From 8de20911a5b2cc7c7c92a0f6fdd158e169b1fad8 Mon Sep 17 00:00:00 2001 From: Daniel Mehrmann Date: Tue, 13 Jan 2004 19:57:48 +0000 Subject: [PATCH] mehrmann wb extensions --- winboard-dm-beta4/Makefile | 118 + winboard-dm-beta4/backend.c |11298 ++++++++++++++++++++++++++++++++++++++++ winboard-dm-beta4/backend.h | 288 + winboard-dm-beta4/backendz.h | 72 + winboard-dm-beta4/common.h | 488 ++ winboard-dm-beta4/config.h | 130 + winboard-dm-beta4/defaults.h | 249 + winboard-dm-beta4/frontend.h | 173 + winboard-dm-beta4/gamelist.c | 305 ++ winboard-dm-beta4/lists.c | 149 + winboard-dm-beta4/lists.h | 66 + winboard-dm-beta4/moves.c | 978 ++++ winboard-dm-beta4/parser.c | 3830 ++++++++++++++ winboard-dm-beta4/parser.h | 59 + winboard-dm-beta4/pgntags.c | 262 + winboard-dm-beta4/wclipbrd.c | 320 ++ winboard-dm-beta4/wclipbrd.h | 32 + winboard-dm-beta4/wedittags.c | 234 + winboard-dm-beta4/wedittags.h | 27 + winboard-dm-beta4/wgamelist.c | 250 + winboard-dm-beta4/winboard.c | 8401 +++++++++++++++++++++++++++++ winboard-dm-beta4/winboard.dsp | 1776 +++++++ winboard-dm-beta4/winboard.dsw | 29 + winboard-dm-beta4/winboard.h | 165 + winboard-dm-beta4/winboard.hpj | 19 + winboard-dm-beta4/winboard.rc | 1526 ++++++ winboard-dm-beta4/winboard.rtf | 1880 +++++++ winboard-dm-beta4/woptions.c | 2763 ++++++++++ winboard-dm-beta4/woptions.h | 35 + winboard-dm-beta4/wsockerr.c | 60 + winboard-dm-beta4/wsockerr.h | 10 + winboard-dm-beta4/zippy.c | 1218 +++++ winboard-dm-beta4/zippy.h | 58 + 33 files changed, 37268 insertions(+), 0 deletions(-) create mode 100755 winboard-dm-beta4/Makefile create mode 100755 winboard-dm-beta4/backend.c create mode 100755 winboard-dm-beta4/backend.h create mode 100755 winboard-dm-beta4/backendz.h create mode 100755 winboard-dm-beta4/common.h create mode 100755 winboard-dm-beta4/config.h create mode 100755 winboard-dm-beta4/defaults.h create mode 100755 winboard-dm-beta4/frontend.h create mode 100755 winboard-dm-beta4/gamelist.c create mode 100755 winboard-dm-beta4/lists.c create mode 100755 winboard-dm-beta4/lists.h create mode 100755 winboard-dm-beta4/moves.c create mode 100755 winboard-dm-beta4/parser.c create mode 100755 winboard-dm-beta4/parser.h create mode 100755 winboard-dm-beta4/pgntags.c create mode 100755 winboard-dm-beta4/wclipbrd.c create mode 100755 winboard-dm-beta4/wclipbrd.h create mode 100755 winboard-dm-beta4/wedittags.c create mode 100755 winboard-dm-beta4/wedittags.h create mode 100755 winboard-dm-beta4/wgamelist.c create mode 100755 winboard-dm-beta4/winboard.c create mode 100755 winboard-dm-beta4/winboard.dsp create mode 100755 winboard-dm-beta4/winboard.dsw create mode 100755 winboard-dm-beta4/winboard.h create mode 100755 winboard-dm-beta4/winboard.hpj create mode 100755 winboard-dm-beta4/winboard.rc create mode 100755 winboard-dm-beta4/winboard.rtf create mode 100755 winboard-dm-beta4/woptions.c create mode 100755 winboard-dm-beta4/woptions.h create mode 100755 winboard-dm-beta4/wsockerr.c create mode 100755 winboard-dm-beta4/wsockerr.h create mode 100755 winboard-dm-beta4/zippy.c create mode 100755 winboard-dm-beta4/zippy.h diff --git a/winboard-dm-beta4/Makefile b/winboard-dm-beta4/Makefile new file mode 100755 index 0000000..1c1816d --- /dev/null +++ b/winboard-dm-beta4/Makefile @@ -0,0 +1,118 @@ +OS=NT +ENV=WIN32 +CPU=i386 + +!include <$(OS)$(ENV).MAK> + +proj = winboard +allobj = winboard.obj backend.obj parser.obj moves.obj lists.obj \ + gamelist.obj pgntags.obj wedittags.obj wgamelist.obj zippy.obj \ + wsockerr.obj wclipbrd.obj woptions.obj + +#### old stuff - disable by Daniel Mehrmann +#cvars = $(cvars) -I. -DWINVER=0x0400 +#cflags = $(cflags) /FR + +# delete .mak file We don't need that ! + +################ Mehrmann stuff ########################### + +### EDIT HERE for compile optimze or debug ;-) + +# new stuff by Daniel Mehrmann + +# need this for a nomal run +# DO NOT CHANGE !! +cflags = -c -W3 -DCRTAPI1=_cdecl -DCRTAPI2=_cdecl -nologo -D_X86_=1 -D_WINNT -D_WIN32_WINNT=0x0400 -D_WIN32_IE=0x0300 -DWINVER=0x0400 /FRwinboard.bsc -DWIN32 + +# optimize here ! +# standard fast und pentium +cflags = $(cflags) -O2 -G5 + + +#!!! disable debug !!! +# comment this out if you want debug ! +cdebug = +linkdebug = + + +############### Mehrmann stuff end ########################## + +all: $(proj).exe + +# Update the help file if necessary +$(proj).hlp : $(proj).rtf + $(hc) $(proj).hpj + cat $(proj).err + +# Update the resource if necessary +$(proj).rbj: $(proj).rc $(proj).h $(proj).res resource.h + $(rc) $(rcvars) -r -fo $(proj).res $(cvars) $(proj).rc + cvtres -$(CPU) $(proj).res -o $(proj).rbj + +# Update the object files if necessary +winboard.obj: winboard.c config.h winboard.h common.h frontend.h backend.h \ + moves.h wgamelist.h defaults.h resource.h wclipbrd.h wedittags.h \ + wsockerr.h lists.h + $(cc) $(cflags) $(cvars) $(cdebug) winboard.c + +backend.obj: backend.c config.h common.h frontend.h backend.h parser.h \ + moves.h zippy.h backendz.h lists.h + $(cc) $(cflags) $(cvars) $(cdebug) backend.c + +parser.obj: parser.c config.h common.h backend.h parser.h frontend.h moves.h \ + lists.h + $(cc) $(cflags) $(cvars) $(cdebug) parser.c + +parser.c: parser.l + flex -L parser.l + del parser.c + rename lex.yy.c parser.c + +moves.obj: moves.c config.h backend.h common.h parser.h moves.h lists.h \ + frontend.h + $(cc) $(cflags) $(cvars) $(cdebug) moves.c + +lists.obj: lists.c config.h lists.h common.h + $(cc) $(cflags) $(cvars) $(cdebug) lists.c + +gamelist.obj: gamelist.c config.h lists.h common.h frontend.h backend.h \ + parser.h lists.h + $(cc) $(cflags) $(cvars) $(cdebug) gamelist.c + +pgntags.obj: pgntags.c config.h common.h frontend.h backend.h parser.h lists.h + $(cc) $(cflags) $(cvars) $(cdebug) pgntags.c + +wclipbrd.obj: wclipbrd.c config.h common.h frontend.h backend.h winboard.h \ + wclipbrd.h lists.h resource.h + $(cc) $(cflags) $(cvars) $(cdebug) wclipbrd.c + +wedittags.obj: wedittags.c config.h common.h winboard.h frontend.h backend.h \ + lists.h resource.h + $(cc) $(cflags) $(cvars) $(cdebug) wedittags.c + +wgamelist.obj: wgamelist.c config.h. common.h winboard.h frontend.h backend.h \ + wgamelist.h lists.h resource.h + $(cc) $(cflags) $(cvars) $(cdebug) wgamelist.c + +woptions.obj: woptions.c config.h common.h frontend.h backend.h lists.h + $(cc) $(cflags) $(cvars) $(cdebug) woptions.c + +wsockerr.obj: wsockerr.c wsockerr.h + $(cc) $(cflags) $(cvars) $(cdebug) wsockerr.c + +zippy.obj: zippy.c config.h common.h zippy.h frontend.h backend.h backendz.h \ + lists.h + $(cc) $(cflags) $(cvars) $(cdebug) zippy.c + +$(proj).exe: $(allobj) $(proj).rbj $(proj).def $(proj).hlp $(proj).rc + $(link) $(linkdebug) $(guiflags) $(allobj) \ + wsock32.lib shell32.lib comctl32.lib winmm.lib libc.lib oldnames.lib kernel32.lib \ + advapi32.lib user32.lib gdi32.lib comdlg32.lib winspool.lib \ + $(proj).rbj -out:$(proj).exe + bscmake *.sbr + +test.exe: test.c + $(cc) $(cflags) $(cvars) $(cdebug) test.c + $(link) $(linkdebug) $(conflags) test.obj $(conlibs) -out:test.exe + diff --git a/winboard-dm-beta4/backend.c b/winboard-dm-beta4/backend.c new file mode 100755 index 0000000..a08ba32 --- /dev/null +++ b/winboard-dm-beta4/backend.c @@ -0,0 +1,11298 @@ +/* + * backend.c -- Common back end for X and Windows NT versions of + * XBoard $Id$ + * + * Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts. + * Enhancements Copyright 1992-2001 Free Software Foundation, Inc. + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * ------------------------------------------------------------------------ + * + * See the file ChangeLog for a revision history. */ + +#include "config.h" + +#include +#include +#include +#include +#include +#include +/* daniel */ +#include + +#if STDC_HEADERS +# include +# include +#else /* not STDC_HEADERS */ +# if HAVE_STRING_H +# include +# else /* not HAVE_STRING_H */ +# include +# endif /* not HAVE_STRING_H */ +#endif /* not STDC_HEADERS */ + +#if HAVE_SYS_FCNTL_H +# include +#else /* not HAVE_SYS_FCNTL_H */ +# if HAVE_FCNTL_H +# include +# endif /* HAVE_FCNTL_H */ +#endif /* not HAVE_SYS_FCNTL_H */ + +#if TIME_WITH_SYS_TIME +# include +# include +#else +# if HAVE_SYS_TIME_H +# include +# else +# include +# endif +#endif + +#if defined(_amigados) && !defined(__GNUC__) +struct timezone { + int tz_minuteswest; + int tz_dsttime; +}; +extern int gettimeofday(struct timeval *, struct timezone *); +#endif + +#if HAVE_UNISTD_H +# include +#endif + +#include "common.h" +#include "frontend.h" +#include "backend.h" +#include "parser.h" +#include "moves.h" +#if ZIPPY +# include "zippy.h" +#endif +#include "backendz.h" +#include "winboard.h" + +/* A point in time */ +typedef struct { + long sec; /* Assuming this is >= 32 bits */ + int ms; /* Assuming this is >= 16 bits */ +} TimeMark; + +int establish P((void)); +void read_from_player P((InputSourceRef isr, VOIDSTAR closure, + char *buf, int count, int error)); +void read_from_ics P((InputSourceRef isr, VOIDSTAR closure, + char *buf, int count, int error)); +void SendToICS P((char *s)); +void SendToICSDelayed P((char *s, long msdelay)); +void SendMoveToICS P((ChessMove moveType, int fromX, int fromY, + int toX, int toY)); +void InitPosition P((int redraw)); +void HandleMachineMove P((char *message, ChessProgramState *cps)); +int AutoPlayOneMove P((void)); +int LoadGameOneMove P((ChessMove readAhead)); +int LoadGameFromFile P((char *filename, int n, char *title, int useList)); +int LoadPositionFromFile P((char *filename, int n, char *title)); +int SavePositionToFile P((char *filename)); +void ApplyMove P((int fromX, int fromY, int toX, int toY, int promoChar, + Board board)); +void MakeMove P((int fromX, int fromY, int toX, int toY, int promoChar)); +void ShowMove P((int fromX, int fromY, int toX, int toY)); +void FinishMove P((ChessMove moveType, int fromX, int fromY, int toX, int toY, + /*char*/int promoChar)); +void BackwardInner P((int target)); +void ForwardInner P((int target)); +void GameEnds P((ChessMove result, char *resultDetails, int whosays)); +void EditPositionDone P((void)); +void PrintOpponents P((FILE *fp)); +void PrintPosition P((FILE *fp, int move)); +void StartChessProgram P((ChessProgramState *cps)); +void GuiCommand P((int command, int param)); +void IcsAnalyzeOutPut P((ChessProgramState *cps, int endThink)); +int SwitchGames P((void)); +void SendToProgram P((char *message, ChessProgramState *cps)); +void SendMoveToProgram P((int moveNum, ChessProgramState *cps)); +void ReceiveFromProgram P((InputSourceRef isr, VOIDSTAR closure, + char *buf, int count, int error)); +void SendTimeControl P((ChessProgramState *cps, + int mps, long tc, int inc, int sd, int st)); +char *TimeControlTagValue P((void)); +void Attention P((ChessProgramState *cps)); +void FeedMovesToProgram P((ChessProgramState *cps, int upto)); +void ResurrectChessProgram P((void)); +void DisplayComment P((int moveNumber, char *text)); +void DisplayMove P((int moveNumber)); +void GetTimeMark P((TimeMark *)); +void ParseGameHistory P((char *game)); +void ParseBoard12 P((char *string)); +void StartClocks P((void)); +void SwitchClocks P((void)); +void StopClocks P((void)); +void ResetClocks P((void)); +char *PGNDate P((void)); +void SetGameInfo P((void)); +Boolean ParseFEN P((Board board, int *blackPlaysFirst, char *fen)); +int RegisterMove P((void)); +void MakeRegisteredMove P((void)); +void TruncateGame P((void)); +int looking_at P((char *, int *, char *)); +void CopyPlayerNameIntoFileName P((char **, char *)); +char *SavePart P((char *)); +int SaveGameOldStyle P((FILE *)); +int SaveGamePGN P((FILE *)); + +long SubtractTimeMarks P((TimeMark *, TimeMark *)); +int CheckFlags P((void)); +long NextTickLength P((long)); +void CheckTimeControl P((void)); +void show_bytes P((FILE *, char *, int)); +int string_to_rating P((char *str)); +void ParseFeatures P((char* args, ChessProgramState *cps)); +void InitBackEnd3 P((void)); +void FeatureDone P((ChessProgramState* cps, int val)); +void InitChessProgram P((ChessProgramState *cps)); +extern int tinyLayout, smallLayout; + +void ParseZippyP3 P((char* data, char* player)); + +/* States for ics_getting_history */ +#define H_FALSE 0 +#define H_REQUESTED 1 +#define H_GOT_REQ_HEADER 2 +#define H_GOT_UNREQ_HEADER 3 +#define H_GETTING_MOVES 4 +#define H_GOT_UNWANTED_HEADER 5 + +/* whosays values for GameEnds */ +#define GE_ICS 0 +#define GE_ENGINE 1 +#define GE_PLAYER 2 +#define GE_FILE 3 +#define GE_XBOARD 4 + +/* Maximum number of games in a cmail message */ +#define CMAIL_MAX_GAMES 20 + +/* Different types of move when calling RegisterMove */ +#define CMAIL_MOVE 0 +#define CMAIL_RESIGN 1 +#define CMAIL_DRAW 2 +#define CMAIL_ACCEPT 3 + +/* Different types of result to remember for each game */ +#define CMAIL_NOT_RESULT 0 +#define CMAIL_OLD_RESULT 1 +#define CMAIL_NEW_RESULT 2 + +/* Telnet protocol constants */ +#define TN_WILL 0373 +#define TN_WONT 0374 +#define TN_DO 0375 +#define TN_DONT 0376 +#define TN_IAC 0377 +#define TN_ECHO 0001 +#define TN_SGA 0003 +#define TN_PORT 23 + +/* Fake up flags for now, as we aren't keeping track of castling + availability yet */ +int +PosFlags(index) +{ + int flags = F_ALL_CASTLE_OK; + if ((index % 2) == 0) flags |= F_WHITE_ON_MOVE; + switch (gameInfo.variant) { + case VariantSuicide: + case VariantGiveaway: + flags |= F_IGNORE_CHECK; + flags &= ~F_ALL_CASTLE_OK; + break; + case VariantAtomic: + flags |= F_IGNORE_CHECK | F_ATOMIC_CAPTURE; + break; + case VariantKriegspiel: + flags |= F_KRIEGSPIEL_CAPTURE; + break; + case VariantNoCastle: + flags &= ~F_ALL_CASTLE_OK; + break; + default: + break; + } + return flags; +} + +FILE *gameFileFP, *debugFP; + +char cmailMove[CMAIL_MAX_GAMES][MOVE_LEN], cmailMsg[MSG_SIZ]; +char bookOutput[MSG_SIZ*10], thinkOutput[MSG_SIZ*10], lastHint[MSG_SIZ]; +char thinkOutput1[MSG_SIZ*10]; + +/*ChessProgramState first, second; */ + +/* premove variables */ +int premoveToX = 0; +int premoveToY = 0; +int premoveFromX = 0; +int premoveFromY = 0; +int premovePromoChar = 0; +int gotPremove = 0; +Boolean alarmSounded; +/* end premove variables */ + +#define ICS_GENERIC 0 +#define ICS_ICC 1 +#define ICS_FICS 2 +#define ICS_CHESSNET 3 /* not really supported */ +int ics_type = ICS_GENERIC; +char *ics_prefix = "$"; + +int currentMove = 0, forwardMostMove = 0, backwardMostMove = 0; +int pauseExamForwardMostMove = 0; +int nCmailGames = 0, nCmailResults = 0, nCmailMovesRegistered = 0; +int cmailMoveRegistered[CMAIL_MAX_GAMES], cmailResult[CMAIL_MAX_GAMES]; +int cmailMsgLoaded = FALSE, cmailMailedMove = FALSE; +int cmailOldMove = -1, firstMove = TRUE, flipView = FALSE; +int blackPlaysFirst = FALSE, startedFromSetupPosition = FALSE; +int searchTime = 0, pausing = FALSE, pauseExamInvalid = FALSE; +int whiteFlag = FALSE, blackFlag = FALSE; +int userOfferedDraw = FALSE; +int ics_user_moved = 0, ics_getting_history = H_FALSE, ics_gamenum = -1; +int matchMode = FALSE, hintRequested = FALSE, bookRequested = FALSE; +int cmailMoveType[CMAIL_MAX_GAMES]; +prefixHint = 0; /* PonderMove true/false */ +long ics_clock_paused = 0; +ProcRef icsPR = NoProc, cmailPR = NoProc; +InputSourceRef telnetISR = NULL, fromUserISR = NULL, cmailISR = NULL; +gameMode = BeginningOfGame; +char moveList[MAX_MOVES][MOVE_LEN], parseList[MAX_MOVES][MOVE_LEN * 2]; +char *commentList[MAX_MOVES], *cmailCommentList[CMAIL_MAX_GAMES]; +char white_holding[64], black_holding[64]; +TimeMark lastNodeCountTime; +long lastNodeCount = 0; +int have_sent_ICS_logon = 0; +int movesPerSession; +long whiteTimeRemaining, blackTimeRemaining, timeControl, timeIncrement; +long timeRemaining[2][MAX_MOVES]; +int matchGame = 0; +TimeMark programStartTime; +char ics_handle[MSG_SIZ]; +int have_set_title = 0; +smartQueue icsQueue[max_gamenum]; + +/* zippypassword3 */ +typedef struct { + char string[512]; +} value[6]; +value command; + +/* Search stats from chessprogram */ +typedef struct { + char movelist[MSG_SIZ]; /* Last PV we were sent */ + char ponderMove[12]; /* Current ponder move */ + int depth; /* Current search depth */ + int nr_moves; /* Total nr of root moves */ + int moves_left; /* Moves remaining to be searched */ + char move_name[MOVE_LEN]; /* Current move being searched, if provided */ + unsigned long nodes; /* # of nodes searched */ + int time; /* Search time (centiseconds) */ + int score; /* Score (centipawns) */ + int got_only_move; /* If last msg was "(only move)" */ + int got_fail; /* 0 - nothing, 1 - got "--", 2 - got "++" */ + int ok_to_send; /* handshaking between send & recv */ + int line_is_book; /* 1 if movelist is book moves */ + int seen_stat; /* 1 if we've seen the stat01: line */ + int GUI_time; /* Time from EngineRoom */ +} ChessProgramStats; + +static ChessProgramStats programStats; + +/* animateTraining preserves the state of appData.animate + * when Training mode is activated. This allows the + * response to be animated when appData.animate == TRUE and + * appData.animateDragging == TRUE. + */ +Boolean animateTraining; + +GameInfo gameInfo; + +AppData appData; + +Board boards[MAX_MOVES]; +Board initialPosition = { + { WhiteRook, WhiteKnight, WhiteBishop, WhiteQueen, + WhiteKing, WhiteBishop, WhiteKnight, WhiteRook }, + { WhitePawn, WhitePawn, WhitePawn, WhitePawn, + WhitePawn, WhitePawn, WhitePawn, WhitePawn }, + { EmptySquare, EmptySquare, EmptySquare, EmptySquare, + EmptySquare, EmptySquare, EmptySquare, EmptySquare }, + { EmptySquare, EmptySquare, EmptySquare, EmptySquare, + EmptySquare, EmptySquare, EmptySquare, EmptySquare }, + { EmptySquare, EmptySquare, EmptySquare, EmptySquare, + EmptySquare, EmptySquare, EmptySquare, EmptySquare }, + { EmptySquare, EmptySquare, EmptySquare, EmptySquare, + EmptySquare, EmptySquare, EmptySquare, EmptySquare }, + { BlackPawn, BlackPawn, BlackPawn, BlackPawn, + BlackPawn, BlackPawn, BlackPawn, BlackPawn }, + { BlackRook, BlackKnight, BlackBishop, BlackQueen, + BlackKing, BlackBishop, BlackKnight, BlackRook } +}; +Board twoKingsPosition = { + { WhiteRook, WhiteKnight, WhiteBishop, WhiteQueen, + WhiteKing, WhiteKing, WhiteKnight, WhiteRook }, + { WhitePawn, WhitePawn, WhitePawn, WhitePawn, + WhitePawn, WhitePawn, WhitePawn, WhitePawn }, + { EmptySquare, EmptySquare, EmptySquare, EmptySquare, + EmptySquare, EmptySquare, EmptySquare, EmptySquare }, + { EmptySquare, EmptySquare, EmptySquare, EmptySquare, + EmptySquare, EmptySquare, EmptySquare, EmptySquare }, + { EmptySquare, EmptySquare, EmptySquare, EmptySquare, + EmptySquare, EmptySquare, EmptySquare, EmptySquare }, + { EmptySquare, EmptySquare, EmptySquare, EmptySquare, + EmptySquare, EmptySquare, EmptySquare, EmptySquare }, + { BlackPawn, BlackPawn, BlackPawn, BlackPawn, + BlackPawn, BlackPawn, BlackPawn, BlackPawn }, + { BlackRook, BlackKnight, BlackBishop, BlackQueen, + BlackKing, BlackKing, BlackKnight, BlackRook } +}; + +/* Convert str to a rating. Checks for special cases of "----", + "++++", etc. Also strips ()'s */ +int +string_to_rating(str) + char *str; +{ + while(*str && !isdigit(*str)) ++str; + if (!*str) + return 0; /* One of the special "no rating" cases */ + else + return atoi(str); +} + +void +ClearProgramStats() +{ + /* Init programStats */ + programStats.movelist[0] = NULLCHAR; + programStats.ponderMove[0] = 0; + programStats.depth = 0; + programStats.nr_moves = 0; + programStats.moves_left = 0; + programStats.nodes = 0; + programStats.time = 100; + programStats.score = 0; + programStats.got_only_move = 0; + programStats.got_fail = 0; + programStats.line_is_book = 0; +} + +void +InitBackEnd1() +{ + int matched, min, sec; + + GetTimeMark(&programStartTime); + + ClearProgramStats(); + programStats.ok_to_send = 1; + programStats.seen_stat = 0; + supportStat = 0; + + /* + * Initialize game list + */ + ListNew(&gameList); + + + /* + * Internet chess server status + */ + if (appData.icsActive) { + appData.matchMode = FALSE; + appData.matchGames = 0; +#if ZIPPY + appData.noChessProgram = !appData.zippyPlay; +#else + appData.zippyPlay = FALSE; + appData.zippyTalk = FALSE; + appData.noChessProgram = TRUE; +#endif + if (*appData.icsHelper != NULLCHAR) { + appData.useTelnet = TRUE; + appData.telnetProgram = appData.icsHelper; + } + } else { + appData.zippyTalk = appData.zippyPlay = FALSE; + } + + /* + * Parse timeControl resource + */ + if (!ParseTimeControl(appData.timeControl, appData.timeIncrement, + appData.movesPerSession)) { + char buf[MSG_SIZ]; + sprintf(buf, "bad timeControl option %s", appData.timeControl); + DisplayFatalError(buf, 0, 2); + } + + /* + * Parse searchTime resource + */ + if (*appData.searchTime != NULLCHAR) { + matched = sscanf(appData.searchTime, "%d:%d", &min, &sec); + if (matched == 1) { + searchTime = min * 60; + } else if (matched == 2) { + searchTime = min * 60 + sec; + } else { + char buf[MSG_SIZ]; + sprintf(buf, "bad searchTime option %s", appData.searchTime); + DisplayFatalError(buf, 0, 2); + } + } + + first.which = "first"; + second.which = "second"; + first.maybeThinking = second.maybeThinking = FALSE; + first.pr = second.pr = NoProc; + first.isr = second.isr = NULL; + first.sendTime = second.sendTime = 2; + first.sendDrawOffers = 1; + if (appData.firstPlaysBlack) { + first.twoMachinesColor = "black\n"; + second.twoMachinesColor = "white\n"; + } else { + first.twoMachinesColor = "white\n"; + second.twoMachinesColor = "black\n"; + } + first.program = appData.firstChessProgram; + second.program = appData.secondChessProgram; + first.host = appData.firstHost; + second.host = appData.secondHost; + first.dir = appData.firstDirectory; + second.dir = appData.secondDirectory; + first.other = &second; + second.other = &first; + first.initString = appData.initString; + second.initString = appData.secondInitString; + first.computerString = appData.firstComputerString; + second.computerString = appData.secondComputerString; + first.useSigint = second.useSigint = TRUE; + first.useSigterm = second.useSigterm = TRUE; + first.reuse = appData.reuseFirst; + second.reuse = appData.reuseSecond; + first.useSetboard = second.useSetboard = FALSE; + first.useSAN = second.useSAN = FALSE; + first.usePing = second.usePing = FALSE; + first.lastPing = second.lastPing = 0; + first.lastPong = second.lastPong = 0; + first.usePlayother = second.usePlayother = FALSE; + first.useColors = second.useColors = TRUE; + first.useUsermove = second.useUsermove = FALSE; + first.sendICS = second.sendICS = FALSE; + first.sendName = second.sendName = appData.icsActive; + first.sdKludge = second.sdKludge = FALSE; + first.stKludge = second.stKludge = FALSE; + TidyProgramName(first.program, first.host, first.tidy); + TidyProgramName(second.program, second.host, second.tidy); + first.matchWins = second.matchWins = 0; + strcpy(first.variants, appData.variant); + strcpy(second.variants, appData.variant); + first.analysisSupport = second.analysisSupport = 2; /* detect */ + first.analyzing = second.analyzing = FALSE; + first.initDone = second.initDone = FALSE; + + if (appData.firstProtocolVersion > PROTOVER || + appData.firstProtocolVersion < 1) { + char buf[MSG_SIZ]; + sprintf(buf, "protocol version %d not supported", + appData.firstProtocolVersion); + DisplayFatalError(buf, 0, 2); + } else { + first.protocolVersion = appData.firstProtocolVersion; + } + + if (appData.secondProtocolVersion > PROTOVER || + appData.secondProtocolVersion < 1) { + char buf[MSG_SIZ]; + sprintf(buf, "protocol version %d not supported", + appData.secondProtocolVersion); + DisplayFatalError(buf, 0, 2); + } else { + second.protocolVersion = appData.secondProtocolVersion; + } + + if (appData.icsActive) { + appData.clockMode = TRUE; /* changes dynamically in ICS mode */ + } else if (*appData.searchTime != NULLCHAR || appData.noChessProgram) { + appData.clockMode = FALSE; + first.sendTime = second.sendTime = 0; + } + +#if ZIPPY + /* Override some settings from environment variables, for backward + compatibility. Unfortunately it's not feasible to have the env + vars just set defaults, at least in xboard. Ugh. + */ + if (appData.icsActive && (appData.zippyPlay || appData.zippyTalk)) { + ZippyInit(); + } +#endif + + if (appData.noChessProgram) { + programVersion = (char*) malloc(5 + strlen(PRODUCT) + strlen(VERSION) + + strlen(PATCHLEVEL)); + sprintf(programVersion, "%s %s.%s", PRODUCT, VERSION, PATCHLEVEL); + } else { + char *p, *q; + q = first.program; + while (*q != ' ' && *q != NULLCHAR) q++; + p = q; + while (p > first.program && *(p-1) != '/') p--; + programVersion = (char*) malloc(8 + strlen(PRODUCT) + strlen(VERSION) + + strlen(PATCHLEVEL) + (q - p)); + sprintf(programVersion, "%s %s.%s + ", PRODUCT, VERSION, PATCHLEVEL); + strncat(programVersion, p, q - p); + } + + if (!appData.icsActive) { + char buf[MSG_SIZ]; + /* Check for variants that are supported only in ICS mode, + or not at all. Some that are accepted here nevertheless + have bugs; see comments below. + */ + VariantClass variant = StringToVariant(appData.variant); + switch (variant) { + case VariantBughouse: /* need four players and two boards */ + case VariantKriegspiel: /* need to hide pieces and move details */ + case VariantFischeRandom: /* castling doesn't work, shuffle not done */ + sprintf(buf, "Variant %s supported only in ICS mode", appData.variant); + DisplayFatalError(buf, 0, 2); + return; + + case VariantUnknown: + case VariantLoadable: + case Variant29: + case Variant30: + case Variant31: + case Variant32: + case Variant33: + case Variant34: + case Variant35: + case Variant36: + default: + sprintf(buf, "Unknown variant name %s", appData.variant); + DisplayFatalError(buf, 0, 2); + return; + + case VariantNormal: /* definitely works! */ + case VariantWildCastle: /* pieces not automatically shuffled */ + case VariantNoCastle: /* pieces not automatically shuffled */ + case VariantCrazyhouse: /* holdings not shown, + offboard interposition not understood */ + case VariantLosers: /* should work except for win condition, + and doesn't know captures are mandatory */ + case VariantSuicide: /* should work except for win condition, + and doesn't know captures are mandatory */ + case VariantGiveaway: /* should work except for win condition, + and doesn't know captures are mandatory */ + case VariantTwoKings: /* should work */ + case VariantAtomic: /* should work except for win condition */ + case Variant3Check: /* should work except for win condition */ + case VariantShatranj: /* might work if TestLegality is off */ + break; + } + } +} + +int +ParseTimeControl(tc, ti, mps) + char *tc; + int ti; + int mps; +{ + int matched, min, sec; + + matched = sscanf(tc, "%d:%d", &min, &sec); + if (matched == 1) { + timeControl = min * 60 * 1000; + } else if (matched == 2) { + timeControl = (min * 60 + sec) * 1000; + } else { + return FALSE; + } + + if (ti >= 0) { + timeIncrement = ti * 1000; /* convert to ms */ + movesPerSession = 0; + } else { + timeIncrement = 0; + movesPerSession = mps; + } + return TRUE; +} + +void +InitBackEnd2() +{ + if (appData.debugMode) { + fprintf(debugFP, "%s\n", programVersion); + } + + if (appData.matchGames > 0) { + appData.matchMode = TRUE; + } else if (appData.matchMode) { + appData.matchGames = 1; + } + Reset(TRUE, FALSE); + if (appData.noChessProgram || first.protocolVersion == 1) { + InitBackEnd3(); + } else { + /* kludge: allow timeout for initial "feature" commands */ + FreezeUI(); + if (appData.icsActive) { + DisplayMessage("", "ICS-Mode: Waiting for chessprogram..."); + } else { + DisplayMessage("", "Starting chessprogram"); + } + ScheduleDelayedEvent(InitBackEnd3, FEATURE_TIMEOUT); + } +} + +void +InitBackEnd3 P((void)) +{ + GameMode initialMode; + char buf[MSG_SIZ]; + int err; + + InitChessProgram(&first); + + /* Make a console window if needed */ + if (appData.icsActive) { + ConsoleCreate(); + } + /* engine Room */ + supportStat = 0; + + if (appData.icsActive) { + err = establish(); + if (err != 0) { + if (*appData.icsCommPort != NULLCHAR) { + sprintf(buf, "Could not open comm port %s", + appData.icsCommPort); + } else { + sprintf(buf, "Could not connect to host %s, port %s", + appData.icsHost, appData.icsPort); + } + DisplayFatalError(buf, err, 1); + return; + } + SetICSMode(); + telnetISR = + AddInputSource(icsPR, FALSE, read_from_ics, &telnetISR); + fromUserISR = + AddInputSource(NoProc, FALSE, read_from_player, &fromUserISR); + } else if (appData.noChessProgram) { + SetNCPMode(); + } else { + SetGNUMode(); + } + + if (*appData.cmailGameName != NULLCHAR) { + SetCmailMode(); + OpenLoopback(&cmailPR); + cmailISR = + AddInputSource(cmailPR, FALSE, CmailSigHandlerCallBack, &cmailISR); + } + + ThawUI(); + DisplayMessage("", ""); + if (StrCaseCmp(appData.initialMode, "") == 0) { + initialMode = BeginningOfGame; + } else if (StrCaseCmp(appData.initialMode, "TwoMachines") == 0) { + initialMode = TwoMachinesPlay; + } else if (StrCaseCmp(appData.initialMode, "AnalyzeFile") == 0) { + initialMode = AnalyzeFile; + } else if (StrCaseCmp(appData.initialMode, "Analysis") == 0) { + initialMode = AnalyzeMode; + } else if (StrCaseCmp(appData.initialMode, "MachineWhite") == 0) { + initialMode = MachinePlaysWhite; + } else if (StrCaseCmp(appData.initialMode, "MachineBlack") == 0) { + initialMode = MachinePlaysBlack; + } else if (StrCaseCmp(appData.initialMode, "EditGame") == 0) { + initialMode = EditGame; + } else if (StrCaseCmp(appData.initialMode, "EditPosition") == 0) { + initialMode = EditPosition; + } else if (StrCaseCmp(appData.initialMode, "Training") == 0) { + initialMode = Training; + } else { + sprintf(buf, "Unknown initialMode %s", appData.initialMode); + DisplayFatalError(buf, 0, 2); + return; + } + + if (appData.matchMode) { + /* Set up machine vs. machine match */ + if (appData.noChessProgram) { + DisplayFatalError("Can't have a match with no chess programs", + 0, 2); + return; + } + matchMode = TRUE; + matchGame = 1; + if (*appData.loadGameFile != NULLCHAR) { + if (!LoadGameFromFile(appData.loadGameFile, + appData.loadGameIndex, + appData.loadGameFile, FALSE)) { + DisplayFatalError("Bad game file", 0, 1); + return; + } + } else if (*appData.loadPositionFile != NULLCHAR) { + if (!LoadPositionFromFile(appData.loadPositionFile, + appData.loadPositionIndex, + appData.loadPositionFile)) { + DisplayFatalError("Bad position file", 0, 1); + return; + } + } + TwoMachinesEvent(); + } else if (*appData.cmailGameName != NULLCHAR) { + /* Set up cmail mode */ + ReloadCmailMsgEvent(TRUE); + } else { + /* Set up other modes */ + if (initialMode == AnalyzeFile) { + if (*appData.loadGameFile == NULLCHAR) { + DisplayFatalError("AnalyzeFile mode requires a game file", 0, 1); + return; + } + } + if (*appData.loadGameFile != NULLCHAR) { + (void) LoadGameFromFile(appData.loadGameFile, + appData.loadGameIndex, + appData.loadGameFile, TRUE); + } else if (*appData.loadPositionFile != NULLCHAR) { + (void) LoadPositionFromFile(appData.loadPositionFile, + appData.loadPositionIndex, + appData.loadPositionFile); + } + if (initialMode == AnalyzeMode) { + if (appData.noChessProgram) { + DisplayFatalError("Analysis mode requires a chess engine", 0, 2); + return; + } + if (appData.icsActive) { + DisplayFatalError("Analysis mode does not work with ICS mode",0,2); + return; + } + AnalyzeModeEvent(); + } else if (initialMode == AnalyzeFile) { + ShowThinkingEvent(TRUE); + AnalyzeFileEvent(); + AnalysisPeriodicEvent(1); + } else if (initialMode == MachinePlaysWhite) { + if (appData.noChessProgram) { + DisplayFatalError("MachineWhite mode requires a chess engine", + 0, 2); + return; + } + if (appData.icsActive) { + DisplayFatalError("MachineWhite mode does not work with ICS mode", + 0, 2); + return; + } + MachineWhiteEvent(); + } else if (initialMode == MachinePlaysBlack) { + if (appData.noChessProgram) { + DisplayFatalError("MachineBlack mode requires a chess engine", + 0, 2); + return; + } + if (appData.icsActive) { + DisplayFatalError("MachineBlack mode does not work with ICS mode", + 0, 2); + return; + } + MachineBlackEvent(); + } else if (initialMode == TwoMachinesPlay) { + if (appData.noChessProgram) { + DisplayFatalError("TwoMachines mode requires a chess engine", + 0, 2); + return; + } + if (appData.icsActive) { + DisplayFatalError("TwoMachines mode does not work with ICS mode", + 0, 2); + return; + } + TwoMachinesEvent(); + } else if (initialMode == EditGame) { + EditGameEvent(); + } else if (initialMode == EditPosition) { + EditPositionEvent(); + } else if (initialMode == Training) { + if (*appData.loadGameFile == NULLCHAR) { + DisplayFatalError("Training mode requires a game file", 0, 2); + return; + } + TrainingEvent(); + } + } + /* If EngineRoom TRUE start */ + if (appData.AnalysisWindow && appData.showThinking && + !appData.noChessProgram) { + if (appData.icsActive && appData.zippyPlay) { + AnalysisPopUp(0,0,0,0,0,0,0,5); + } + if (!appData.icsActive) AnalysisPopUp(0,0,0,0,0,0,0,5); + StartAnalysisClock(); + } +} + +/* + * Establish will establish a contact to a remote host.port. + * Sets icsPR to a ProcRef for a process (or pseudo-process) + * used to talk to the host. + * Returns 0 if okay, error code if not. + */ +int +establish() +{ + char buf[MSG_SIZ]; + + if (*appData.icsCommPort != NULLCHAR) { + /* Talk to the host through a serial comm port */ + return OpenCommPort(appData.icsCommPort, &icsPR); + + } else if (*appData.gateway != NULLCHAR) { + if (*appData.remoteShell == NULLCHAR) { + /* Use the rcmd protocol to run telnet program on a gateway host */ + sprintf(buf, "%s %s %s", + appData.telnetProgram, appData.icsHost, appData.icsPort); + return OpenRcmd(appData.gateway, appData.remoteUser, buf, &icsPR); + + } else { + /* Use the rsh program to run telnet program on a gateway host */ + if (*appData.remoteUser == NULLCHAR) { + sprintf(buf, "%s %s %s %s %s", appData.remoteShell, + appData.gateway, appData.telnetProgram, + appData.icsHost, appData.icsPort); + } else { + sprintf(buf, "%s %s -l %s %s %s %s", + appData.remoteShell, appData.gateway, + appData.remoteUser, appData.telnetProgram, + appData.icsHost, appData.icsPort); + } + return StartChildProcess(buf, "", &icsPR); + + } + } else if (appData.useTelnet) { + return OpenTelnet(appData.icsHost, appData.icsPort, &icsPR); + + } else { + /* TCP socket interface differs somewhat between + Unix and NT; handle details in the front end. + */ + return OpenTCP(appData.icsHost, appData.icsPort, &icsPR); + } +} + +void +show_bytes(fp, buf, count) + FILE *fp; + char *buf; + int count; +{ + while (count--) { + if (*buf < 040 || *(unsigned char *) buf > 0177) { + fprintf(fp, "\\%03o", *buf & 0xff); + } else { + putc(*buf, fp); + } + buf++; + } + fflush(fp); +} + +/* Returns an errno value */ +int +OutputMaybeTelnet(pr, message, count, outError) + ProcRef pr; + char *message; + int count; + int *outError; +{ + char buf[8192], *p, *q, *buflim; + int left, newcount, outcount; + + if (*appData.icsCommPort != NULLCHAR || appData.useTelnet || + *appData.gateway != NULLCHAR) { + if (appData.debugMode) { + fprintf(debugFP, ">ICS: "); + show_bytes(debugFP, message, count); + fprintf(debugFP, "\n"); + } + return OutputToProcess(pr, message, count, outError); + } + + buflim = &buf[sizeof(buf)-1]; /* allow 1 byte for expanding last char */ + p = message; + q = buf; + left = count; + newcount = 0; + while (left) { + if (q >= buflim) { + if (appData.debugMode) { + fprintf(debugFP, ">ICS: "); + show_bytes(debugFP, buf, newcount); + fprintf(debugFP, "\n"); + } + outcount = OutputToProcess(pr, buf, newcount, outError); + if (outcount < newcount) return -1; /* to be sure */ + q = buf; + newcount = 0; + } + if (*p == '\n') { + *q++ = '\r'; + newcount++; + } else if (((unsigned char) *p) == TN_IAC) { + *q++ = (char) TN_IAC; + newcount ++; + } + *q++ = *p++; + newcount++; + left--; + } + if (appData.debugMode) { + fprintf(debugFP, ">ICS: "); + show_bytes(debugFP, buf, newcount); + fprintf(debugFP, "\n"); + } + outcount = OutputToProcess(pr, buf, newcount, outError); + if (outcount < newcount) return -1; /* to be sure */ + return count; +} + +void +read_from_player(isr, closure, message, count, error) + InputSourceRef isr; + VOIDSTAR closure; + char *message; + int count; + int error; +{ + int outError, outCount; + static int gotEof = 0; + + /* Pass data read from player on to ICS */ + if (count > 0) { + gotEof = 0; + outCount = OutputMaybeTelnet(icsPR, message, count, &outError); + if (outCount < count) { + DisplayFatalError("Error writing to ICS", outError, 1); + } + } else if (count < 0) { + RemoveInputSource(isr); + DisplayFatalError("Error reading from keyboard", error, 1); + } else if (gotEof++ > 0) { + RemoveInputSource(isr); + DisplayFatalError("Got end of file from keyboard", 0, 0); + } +} + +void +SendToICS(s) + char *s; +{ + int count, outCount, outError; + + if (icsPR == NULL) return; + + count = strlen(s); + outCount = OutputMaybeTelnet(icsPR, s, count, &outError); + if (outCount < count) { + DisplayFatalError("Error writing to ICS", outError, 1); + } +} + +/* This is used for sending logon scripts to the ICS. Sending + without a delay causes problems when using timestamp on ICC + (at least on my machine). */ +void +SendToICSDelayed(s,msdelay) + char *s; + long msdelay; +{ + int count, outCount, outError; + + if (icsPR == NULL) return; + + count = strlen(s); + if (appData.debugMode) { + fprintf(debugFP, ">ICS: "); + show_bytes(debugFP, s, count); + fprintf(debugFP, "\n"); + } + outCount = OutputToProcessDelayed(icsPR, s, count, &outError, + msdelay); + if (outCount < count) { + DisplayFatalError("Error writing to ICS", outError, 1); + } +} + + +/* Remove all highlighting escape sequences in s + Also deletes any suffix starting with '(' + */ +char * +StripHighlightAndTitle(s) + char *s; +{ + static char retbuf[MSG_SIZ]; + char *p = retbuf; + + while (*s != NULLCHAR) { + while (*s == '\033') { + while (*s != NULLCHAR && !isalpha(*s)) s++; + if (*s != NULLCHAR) s++; + } + while (*s != NULLCHAR && *s != '\033') { + if (*s == '(' || *s == '[') { + *p = NULLCHAR; + return retbuf; + } + *p++ = *s++; + } + } + *p = NULLCHAR; + return retbuf; +} + +/* Remove all highlighting escape sequences in s */ +char * +StripHighlight(s) + char *s; +{ + static char retbuf[MSG_SIZ]; + char *p = retbuf; + + while (*s != NULLCHAR) { + while (*s == '\033') { + while (*s != NULLCHAR && !isalpha(*s)) s++; + if (*s != NULLCHAR) s++; + } + while (*s != NULLCHAR && *s != '\033') { + *p++ = *s++; + } + } + *p = NULLCHAR; + return retbuf; +} + +char *variantNames[] = VARIANT_NAMES; +char * +VariantName(v) + VariantClass v; +{ + return variantNames[v]; +} + + +/* Identify a variant from the strings the chess servers use or the + PGN Variant tag names we use. */ +VariantClass +StringToVariant(e) + char *e; +{ + char *p; + int wnum = -1; + VariantClass v = VariantNormal; + int i, found = FALSE; + char buf[MSG_SIZ]; + + if (!e) return v; + + for (i=0; i%s %s ", ddwwStr, optionStr); + } + msg[0] = TN_IAC; + msg[1] = ddww; + msg[2] = option; + outCount = OutputToProcess(icsPR, (char *)msg, 3, &outError); + if (outCount < 3) { + DisplayFatalError("Error writing to ICS", outError, 1); + } +} + +void +DoEcho() +{ + if (!appData.icsActive) return; + TelnetRequest(TN_DO, TN_ECHO); +} + +void +DontEcho() +{ + if (!appData.icsActive) return; + TelnetRequest(TN_DONT, TN_ECHO); +} + +static int loggedOn = FALSE; + +/*-- Game start info cache: --*/ +int gs_gamenum; +char gs_kind[MSG_SIZ]; +static char player1Name[128] = ""; +static char player2Name[128] = ""; +static int player1Rating = -1; +static int player2Rating = -1; +/*----------------------------*/ + + +/* ICC user send showinfo und we send latest pv */ +/* If username beginn with guest* send advertisement ;-) */ +void +showInfo(data, player) +char* data; +char* player; +{ + char *ptr = data; + char temp[MSG_SIZ]; + char buf[MSG_SIZ]; + int i; + + /* this feature is only for ICC admins or chessprogramer */ + /* You must set commandline /icc to use this */ + if (appData.userVersion == TRUE) return; + if (appData.ICC_feature == FALSE || ics_type != ICS_ICC) return; + while (*ptr == ' ') ptr++; + if (*ptr == 0 || (sizeof(ptr) > MSG_SIZ)) return; + sscanf(ptr, "%s", buf); + + /* showgames command */ + if (strncmp(buf, "showgames", 9) == 0) { + { + int counter; + for (counter = 1; counter <= max_gamenum; counter++) { + if (icsQueue[counter].killPv > 0) { + sprintf(temp, "tell %s I analyze game %d (%s/%s)\n", player, counter, + icsQueue[counter].white, icsQueue[counter].black); + SendToICS(temp); + } + } + return; + } + } + i = atoi(buf); /* security first - user could try to buffer overflow data ! */ + if (i > max_gamenum || icsQueue[i].killPv == 0) { + sprintf(temp, "tell %s I don't analysis this game\n", player); + SendToICS(temp); + sprintf(temp, "tell %s \"tell %s showgames\" to see which games are currently analyzed.\n", player, ics_handle); + SendToICS(temp); + } else if (icsQueue[i].killPv > 0) { + sprintf(temp, "tell %s Hello %s from Winboard-DM\n", player, player); + SendToICS(temp); + /* pos after "Depth " */ + if (icsQueue[i].lastpv[0]) { + sprintf(temp, "tell %s Last analyze of game %d (%s/%s): (%s) Depth=%s\n", + player, i, icsQueue[i].white, icsQueue[i].black, first.tidy, icsQueue[i].lastpv); + } else { + sprintf(temp, "tell %s Sorry, no analysis avaible from game %d at the moment. Please try it later again.\n", + player, i); + } + SendToICS(temp); + /* for ICC guest send member and register info */ + if (strncmp(player, "guest", 5) == 0) { + sprintf(temp, "tell %s Be member of ICC. Get a free 7-days trial membership: \"http://www.chessclub.com/register/english.html\" For more information type: \"help reg\"\n", player); + SendToICS(temp); + } + } +} + +/* ICS-Analyze: + Call this to see if we have a game where we not send a message + for the current move + */ + +int +SwitchGames() +{ + int counter; + char buf[32]; + + for (counter = 1; counter <= max_gamenum; counter++) { + if (icsQueue[counter].killPv > 0 && icsQueue[counter].CurrentMove >= + icsQueue[counter].MessageMove && icsQueue[counter].flag == 0) { + if (appData.debugMode) fprintf(debugFP, "ICS-Analyze: We switch to game %d \n", counter); + sprintf(buf, "refresh %d \n", counter); + SendToICS(buf); + return 0; + break; + } + } + return 1; +} + +/* parse and action from zippy password3 */ +void +ParseZippyP3(data, player) +char* data; +char* player; +{ + int counter = 0; + int forward = 0; + int i, j; + char *ptr = data; + char temp[MSG_SIZ]; + + if (appData.userVersion == TRUE) return; + + for (;;) { + if (counter > 6) { + sprintf(temp, "tell %s Sorry, to many values. Max 6 values each line. Try again.\n", player); + SendToICS(temp); + sprintf(temp, "tell %s Or try send me \"help\"\n", player); + SendToICS(temp); + return; + } + while (*ptr == ' ') ptr++; + if (*ptr == 0) break; + sscanf(ptr, "%s", command[counter].string); + if (appData.debugMode) fprintf(debugFP, "zp3: %s\n", command[counter].string); + ptr = ptr + strlen(command[counter].string); + counter++; + } + if(strncmp(command[forward].string, "help", 4) == 0) { + /* icc don't accept text after new line :((( */ + /* So, we must write every line */ + sprintf(temp, "tell %s Hello %s from %s %s%s\n", player, player, PRODUCT, VERSION, PATCHLEVEL); + SendToICS(temp); + sprintf(temp, "tell %s analyze \n", player); + SendToICS(temp); + sprintf(temp, "tell %s analyze \n", player); + SendToICS(temp); + sprintf(temp, "tell %s analyze output if tell \n", player); + SendToICS(temp); + sprintf(temp, "tell %s analyze killpv \n", player); + SendToICS(temp); + sprintf(temp, "tell %s if you are setup killpv you enable it automaticly\n", player); + SendToICS(temp); + sprintf(temp, "tell %s analyze smartqueue <1|0>\n", player); + SendToICS(temp); + sprintf(temp, "tell %s analyze show \n", player); + SendToICS(temp); + sprintf(temp, "tell %s engine reset\n", player); + SendToICS(temp); + sprintf(temp, "tell %s \n", player); + SendToICS(temp); + return; + } + + if (strncmp(command[forward].string, "engine", 6) == 0) { + if (strncmp(command[forward+1].string, "reset", 5) == 0) { + sprintf(temp, "tell %s reset engine...\n", player); + SendToICS(temp); + ResurrectChessProgram(); + } + return; + } + /* + if (strncmp(command[forward].string, "whisper", 7) == 0) { + sprintf(temp, "tell %s GUI = whisper\n", player); + SendToICS(temp); + appData.SendOutPutToICS = 1; + return; + } else if (trncmp(command[forward].string, "kibitz", 6) == 0) { + sprintf(temp, "tell %s GUI = kibitz\n", player); + SendToICS(temp); + appData.SendOutPutToICS = 2; + return; + } + */ + if(gameMode == IcsPlayingWhite || gameMode == IcsPlayingBlack) { + sprintf(temp, "tell %s Sorry, i'm playing a game!\n", player); + SendToICS(temp); + return; + } + if (strncmp(command[forward].string, "analyze", 10) == 0) { + if (strncmp(command[forward+1].string, "observe", 7) == 0 || + strncmp(command[forward+1].string, "follow", 6) == 0 || + strncmp(command[forward+1].string, "unobserve", 9) == 0 || + strncmp(command[forward+1].string, "unfollow", 8) == 0) { + + /* reset Queue if leave */ + if (strncmp(command[forward+1].string, "unobserve", 9) == 0 || + strncmp(command[forward+1].string, "unfollow", 8) == 0) ResetIcsQueue(ics_gamenum); + + /* secure */ + if(gameMode != IcsPlayingWhite || gameMode != IcsPlayingBlack) { + sprintf(temp, "%s %s\n", command[forward+1].string, + command[forward+2].string); + SendToICS(temp); + sprintf(temp, "tell %s action: %s %s\n", player, command[forward+1].string, + command[forward+2].string); + if (strncmp(command[forward+1].string, "observe", 7) == 0 || + strncmp(command[forward+1].string, "follow", 6) == 0) { + + if (ics_gamenum > max_gamenum) { + sprintf(temp, "tell %s gamenumber to high\n", player); + SendToICS(temp); + return; + } + } + } else { + sprintf(temp, "tell %s Sorry, i'm playing\n", player); + } + SendToICS(temp); + return; + } + + if (strncmp(command[forward+1].string, "start", 5) == 0) { + if (gameMode != IcsObserving) { + sprintf(temp, "tell %s I must observe a game\n", player); + } else if (gameMode == IcsObserving) { + sprintf(temp, "tell %s Starting ICS analyze...\n", player); + appData.icsAnalyze = TRUE; + IcsAnalyze(TRUE); + } + SendToICS(temp); + return; + } + if (strncmp(command[forward+1].string, "stop", 4) == 0) { + if (gameMode != IcsObserving) { + sprintf(temp, "tell %s I must observe a game\n", player); + } else if (gameMode == IcsObserving) { + sprintf(temp, "tell %s Stopping ICS analyze...\n", player); + IcsAnalyze(FALSE); + } + SendToICS(temp); + return; + } + if (strncmp(command[forward+1].string, "output", 6) == 0) { + if(strncmp(command[forward+2].string, "whisper", 7) == 0) { + appData.icsAnalyzeOutPut = 1; + sprintf(temp, "tell %s analyze output is whisper\n", player); + } else if (strncmp(command[forward+2].string, "kibitz", 6) == 0) { + appData.icsAnalyzeOutPut = 2; + sprintf(temp, "tell %s analyze output is kibitz\n", player); + } else if (strncmp(command[forward+2].string, "tell", 4) == 0) { + appData.icsAnalyzeOutPut = 3; + if (command[forward+3].string[0] != NULLCHAR) { + if (strncmp(command[forward+3].string, "none", 4) == 0) { + appData.icsAnalyzeOutPut = 4; + sprintf(temp, "tell %s analyze output is: none\n", player); + SendToICS(temp); + return; + } + strcpy(appData.icsTells, command[forward+3].string); + sprintf(temp, "tell %s analyze output is tell: %s\n", player, + appData.icsTells); + } else { + sprintf(temp, "tell %s Error: I don't know where i should send my analysis\n", player); + appData.icsAnalyzeOutPut = 4; + } + } + SendToICS(temp); + } + if (strncmp(command[forward+1].string, "killpv", 6) == 0) { + i = atoi(command[forward+3].string); + j = atoi(command[forward+2].string); + if (i <= max_gamenum && i != 0) { + if (icsQueue[i].killPv == 0) { + sprintf(temp, "tell %s Error: Mh, killpv is zero. Wrong gamenumber?\n", player); + SendToICS(temp); + } else { + if ( j > 20 || j < 1) { + sprintf(temp, "tell %s Error: killpv must be 1-20\n", player); + } else { + sprintf(temp, "tell %s killpv for game %d is now %d\n", player, i, j); + icsQueue[i].killPv = j; + appData.icsEngineKillPV = TRUE; + } + SendToICS(temp); + } + } else { + sprintf(temp, "tell %s Error: not possible gamenumber\n", player); + SendToICS(temp); + } + return; + } + if (strncmp(command[forward+1].string, "smartqueue", 10) == 0) { + j = atoi(command[forward+2].string); + if (j == 0 || j == 1) { + appData.smartQueue = j; + sprintf(temp, "tell %s smartqueue is now: %d", player, appData.smartQueue); + } else { + sprintf(temp, "tell %s Error: not possible smartquere value\n", player); + } + SendToICS(temp); + return; + } + if (strncmp(command[forward+1].string, "show", 4) == 0) { + i = atoi(command[forward+2].string); + if (i <= max_gamenum && i != 0) { + if (icsQueue[i].killPv == 0) { + sprintf(temp, "tell %s Error: emtpy game slot. Wrong gamenumber?\n", player); + SendToICS(temp); + } else { + sprintf(temp, "tell %s summary information about game: %d\n", player, i); + SendToICS(temp); + sprintf(temp, "tell %s enable killpv: %d, killpv value = %d\n", player, + appData.icsEngineKillPV, icsQueue[i].killPv); + SendToICS(temp); + sprintf(temp, "tell %s enable smartqueue (all games): %d\n", player, appData.smartQueue); + SendToICS(temp); + sprintf(temp, "tell %s analyze output (all games) is %d\n", player, + appData.icsAnalyzeOutPut); + SendToICS(temp); + } + } else { + sprintf(temp, "tell %s Error: not possible gamenumber\n", player); + SendToICS(temp); + } + return; + } + } +} + +void +read_from_ics(isr, closure, data, count, error) + InputSourceRef isr; + VOIDSTAR closure; + char *data; + int count; + int error; +{ +#define BUF_SIZE 8192 +#define STARTED_NONE 0 +#define STARTED_MOVES 1 +#define STARTED_BOARD 2 +#define STARTED_OBSERVE 3 +#define STARTED_HOLDINGS 4 +#define STARTED_CHATTER 5 +#define STARTED_COMMENT 6 +#define STARTED_MOVES_NOHIDE 7 + + static int started = STARTED_NONE; + static char parse[20000]; + static int parse_pos = 0; + static char buf[BUF_SIZE + 1]; + static int firstTime = TRUE, intfSet = FALSE; + static ColorClass curColor = ColorNormal; + static ColorClass prevColor = ColorNormal; + static int savingComment = FALSE; + char str[512]; + int i, oldi; + int buf_len; + int next_out; + int tkind; + /* extra zippy vars */ + int save; + char *q; + char *p = 0; + char *player; + char reply[MSG_SIZ]; + + if (count > 0) { + /* If last read ended with a partial line that we couldn't parse, + prepend it to the new read and try again. */ + if (leftover_len > 0) { + for (i=0; i= 3 && (unsigned char) buf[i] == TN_IAC) { + static int remoteEchoOption = FALSE; /* telnet ECHO option */ + unsigned char option; + oldi = i; + switch ((unsigned char) buf[++i]) { + case TN_WILL: + if (appData.debugMode) + fprintf(debugFP, "\n next_out) + SendToPlayer(&buf[next_out], oldi - next_out); + if (++i > next_out) + next_out = i; + continue; + } + + /* OK, this at least will *usually* work */ + if (!loggedOn && looking_at(buf, &i, "ics%")) { + loggedOn = TRUE; + } + + if (loggedOn && !intfSet) { + if (ics_type == ICS_ICC) { + sprintf(str, + "/set-quietly interface %s\n/set-quietly style 12\n", + programVersion); + + } else if (ics_type == ICS_CHESSNET) { + sprintf(str, "/style 12\n"); + } else { + strcpy(str, "alias $ @\n$set interface "); + strcat(str, programVersion); + strcat(str, "\n$iset startpos 1\n$iset ms 1\n"); +#ifdef WIN32 + strcat(str, "$iset nohighlight 1\n"); +#endif + strcat(str, "$iset lock 1\n$style 12\n"); + } + SendToICS(str); + intfSet = TRUE; + } + + if (started == STARTED_COMMENT) { + /* Accumulate characters in comment */ + parse[parse_pos++] = buf[i]; + if (buf[i] == '\n') { + parse[parse_pos] = NULLCHAR; + AppendComment(forwardMostMove, StripHighlight(parse)); + started = STARTED_NONE; + } else { + /* Don't match patterns against characters in chatter */ + i++; + continue; + } + } + if (started == STARTED_CHATTER) { + if (buf[i] != '\n') { + /* Don't match patterns against characters in chatter */ + i++; + continue; + } + started = STARTED_NONE; + } + + /* Kludge to deal with rcmd protocol */ + if (firstTime && looking_at(buf, &i, "\001*")) { + DisplayFatalError(&buf[1], 0, 1); + continue; + } else { + firstTime = FALSE; + } + + if (!loggedOn && looking_at(buf, &i, "chessclub.com")) { + ics_type = ICS_ICC; + ics_prefix = "/"; + if (appData.debugMode) + fprintf(debugFP, "ics_type %d\n", ics_type); + continue; + } + if (!loggedOn && looking_at(buf, &i, "freechess.org")) { + ics_type = ICS_FICS; + ics_prefix = "$"; + if (appData.debugMode) + fprintf(debugFP, "ics_type %d\n", ics_type); + continue; + } + if (!loggedOn && looking_at(buf, &i, "chess.net")) { + ics_type = ICS_CHESSNET; + ics_prefix = "/"; + if (appData.debugMode) + fprintf(debugFP, "ics_type %d\n", ics_type); + continue; + } + + if (!loggedOn && + (looking_at(buf, &i, "\"*\" is *a registered name") || + looking_at(buf, &i, "Logging you in as \"*\"") || + looking_at(buf, &i, "will be \"*\""))) { + strcpy(ics_handle, star_match[0]); + continue; + } + + if (loggedOn && !have_set_title && ics_handle[0] != NULLCHAR) { + char buf[MSG_SIZ]; + sprintf(buf, "%s@%s", ics_handle, appData.icsHost); + DisplayIcsInteractionTitle(buf); + have_set_title = TRUE; + } + + /* skip finger notes */ + if (started == STARTED_NONE && + ((buf[i] == ' ' && isdigit(buf[i+1])) || + (buf[i] == '1' && buf[i+1] == '0')) && + buf[i+2] == ':' && buf[i+3] == ' ') { + started = STARTED_CHATTER; + i += 3; + continue; + } + + /* skip formula vars */ + if (started == STARTED_NONE && + buf[i] == 'f' && isdigit(buf[i+1]) && buf[i+2] == ':') { + started = STARTED_CHATTER; + i += 3; + continue; + } + oldi = i; + + /* save position of char array pointer for zippy */ + save = i; + /* Try found special things that never works with color */ + /* I really don't know why - code is ok. */ + q = p; + + if (appData.zippyTalk || appData.zippyPlay) { + if (looking_at(buf, &save, "* tells you: *") || + looking_at(buf, &save, "* says: *")) { + player = StripHighlightAndTitle(star_match[0]); + if (appData.zippyPassword[0] != NULLCHAR && + strncmp(star_match[1], appData.zippyPassword, + strlen(appData.zippyPassword)) == 0) { + q = star_match[1] + strlen(appData.zippyPassword); + while (*q == ' ') q++; + fprintf(debugFP, "zippy 1 %s \n", q); + SendToICS(q); + SendToICS("\n"); + } else if(appData.zippyPassword2[0] != NULLCHAR && first.initDone && + strncmp(star_match[1], appData.zippyPassword2, + strlen(appData.zippyPassword2)) == 0) { + fprintf(debugFP, "zippy2vor: %s \n", q); + q = star_match[1] + strlen(appData.zippyPassword2); + while (*q == ' ') q++; + SendToProgram(q, &first); + SendToProgram("\n", &first); + + } else if (appData.zippyPassword3[0] != NULLCHAR && first.initDone && + strncmp(star_match[1], appData.zippyPassword3, + strlen(appData.zippyPassword3)) == 0 && + appData.userVersion == FALSE) { + q = star_match[1] + strlen(appData.zippyPassword3); + ParseZippyP3(q, player); + + } else if (strncmp(star_match[1], "showinfo", 8) == 0 && + appData.userVersion == FALSE && appData.icsAnalyze == TRUE && + appData.icsAnalyzeOutPut == 3 && appData.ICC_feature == TRUE) { + q = star_match[1] + strlen("showinfo"); + showInfo(q, player); + } else if (strncmp(star_match[1], "showgames", 9) == 0 && + appData.userVersion == FALSE && appData.icsAnalyze == TRUE && + appData.icsAnalyzeOutPut == 3 && appData.ICC_feature == TRUE) { + q = star_match[1]; + showInfo(q, player); + + } else if (appData.zippyWrongPassword[0] != NULLCHAR && + strncmp(star_match[1], appData.zippyWrongPassword, + strlen(appData.zippyWrongPassword)) == 0) { + q = star_match[1] + strlen(appData.zippyWrongPassword); + while (*q == ' ') q++; + sprintf(reply, "wrong %s\n", player); + SendToICS(reply); + } + } + /* workaround for icc and freechess.org */ + if (looking_at(buf, &save, "Your opponent offers you a draw") || + looking_at(buf, &save, "offers you a draw") || + looking_at(buf, &save, "* offers you a draw")) { + if (first.sendDrawOffers && first.initDone) { + SendToProgram("draw\n", &first); + /* Handling zippy Draw */ + } else if (appData.zippyDraw && first.initDone) { + //ZippyDraw(1, programStats.score, programStats.depth); + } + } + if (appData.zippyPlay && first.initDone && loggedOn == TRUE) ZippyMatch(buf, &save, player); + } + + /* Make color for all and for zippy */ + if (/* Don't color "message" or "messages" output */ + (tkind = 5, looking_at(buf, &i, "*. * (*:*): ")) || + looking_at(buf, &i, "*. * at *:*: ") || + looking_at(buf, &i, "--* (*:*): ") || + /* Regular tells and says */ + (tkind = 1, looking_at(buf, &i, "* tells you: ")) || + looking_at(buf, &i, "* (your partner) tells you: ") || + looking_at(buf, &i, "* says: ") || + /* Message notifications (same color as tells) */ + looking_at(buf, &i, "* has left a message ") || + looking_at(buf, &i, "* just sent you a message:\n") || + /* Whispers and kibitzes */ + (tkind = 2, looking_at(buf, &i, "* whispers: ")) || + looking_at(buf, &i, "* kibitzes: ") || + /* Channel tells */ + (tkind = 3, looking_at(buf, &i, "*(*: "))) { + + if (tkind == 1 && strchr(star_match[0], ':')) { + /* Avoid "tells you:" spoofs in channels */ + tkind = 3; + } + if (star_match[0][0] == NULLCHAR || + strchr(star_match[0], ' ') || + (tkind == 3 && strchr(star_match[1], ' '))) { + /* Reject bogus matches */ + i = oldi; + } else { + if (appData.colorize) { + if (oldi > next_out) { + SendToPlayer(&buf[next_out], oldi - next_out); + next_out = oldi; + } + switch (tkind) { + case 1: + Colorize(ColorTell, FALSE); + curColor = ColorTell; + break; + case 2: + Colorize(ColorKibitz, FALSE); + curColor = ColorKibitz; + break; + case 3: + p = strrchr(star_match[1], '('); + if (p == NULL) { + p = star_match[1]; + } else { + p++; + } + if (atoi(p) == 1) { + Colorize(ColorChannel1, FALSE); + curColor = ColorChannel1; + } else { + Colorize(ColorChannel, FALSE); + curColor = ColorChannel; + } + break; + case 5: + curColor = ColorNormal; + break; + } + } + if (started == STARTED_NONE && appData.autoComment && + (gameMode == IcsObserving || + gameMode == IcsPlayingWhite || + gameMode == IcsPlayingBlack)) { + parse_pos = i - oldi; + memcpy(parse, &buf[oldi], parse_pos); + parse[parse_pos] = NULLCHAR; + started = STARTED_COMMENT; + savingComment = TRUE; + } else { + started = STARTED_CHATTER; + savingComment = FALSE; + } + loggedOn = TRUE; + continue; + } + } + + if (looking_at(buf, &i, "* s-shouts: ") || + looking_at(buf, &i, "* c-shouts: ")) { + if (appData.colorize) { + if (oldi > next_out) { + SendToPlayer(&buf[next_out], oldi - next_out); + next_out = oldi; + } + Colorize(ColorSShout, FALSE); + curColor = ColorSShout; + } + loggedOn = TRUE; + started = STARTED_CHATTER; + continue; + } + + if (looking_at(buf, &i, "--->")) { + loggedOn = TRUE; + continue; + } + + if (looking_at(buf, &i, "* shouts: ") || + looking_at(buf, &i, "--> ")) { + if (appData.colorize) { + if (oldi > next_out) { + SendToPlayer(&buf[next_out], oldi - next_out); + next_out = oldi; + } + Colorize(ColorShout, FALSE); + curColor = ColorShout; + } + loggedOn = TRUE; + started = STARTED_CHATTER; + continue; + } + + if (looking_at( buf, &i, "Challenge:")) { + if (appData.colorize) { + if (oldi > next_out) { + SendToPlayer(&buf[next_out], oldi - next_out); + next_out = oldi; + } + Colorize(ColorChallenge, FALSE); + curColor = ColorChallenge; + } + loggedOn = TRUE; + continue; + } + + if (looking_at(buf, &i, "* offers you") || + looking_at(buf, &i, "* offers to be") || + looking_at(buf, &i, "* would like to") || + looking_at(buf, &i, "* requests to") || + looking_at(buf, &i, "Your opponent offers") || + looking_at(buf, &i, "Your opponent requests")) { + + if (appData.colorize) { + if (oldi > next_out) { + SendToPlayer(&buf[next_out], oldi - next_out); + next_out = oldi; + } + Colorize(ColorRequest, FALSE); + curColor = ColorRequest; + } + continue; + } + + if (looking_at(buf, &i, "* (*) seeking")) { + if (appData.colorize) { + if (oldi > next_out) { + SendToPlayer(&buf[next_out], oldi - next_out); + next_out = oldi; + } + Colorize(ColorSeek, FALSE); + curColor = ColorSeek; + } + continue; + } + + + if (looking_at(buf, &i, "\\ ")) { + if (prevColor != ColorNormal) { + if (oldi > next_out) { + SendToPlayer(&buf[next_out], oldi - next_out); + next_out = oldi; + } + Colorize(prevColor, TRUE); + curColor = prevColor; + } + if (savingComment) { + parse_pos = i - oldi; + memcpy(parse, &buf[oldi], parse_pos); + parse[parse_pos] = NULLCHAR; + started = STARTED_COMMENT; + } else { + started = STARTED_CHATTER; + } + continue; + } + + if (looking_at(buf, &i, "Black Strength :") || + looking_at(buf, &i, "<<< style 10 board >>>") || + looking_at(buf, &i, "<10>") || + looking_at(buf, &i, "#@#")) { + /* Wrong board style */ + loggedOn = TRUE; + SendToICS(ics_prefix); + SendToICS("set style 12\n"); + SendToICS(ics_prefix); + SendToICS("refresh\n"); + continue; + } + + if (!have_sent_ICS_logon && looking_at(buf, &i, "login:")) { + ICSInitScript(); + have_sent_ICS_logon = 1; + continue; + } + + if (ics_getting_history != H_GETTING_MOVES /*smpos kludge*/ && + (looking_at(buf, &i, "\n<12> ") || + looking_at(buf, &i, "<12> "))) { + loggedOn = TRUE; + if (oldi > next_out) { + SendToPlayer(&buf[next_out], oldi - next_out); + } + next_out = i; + started = STARTED_BOARD; + parse_pos = 0; + continue; + } + + if ((started == STARTED_NONE && looking_at(buf, &i, "\n ")) || + looking_at(buf, &i, " ")) { + if (oldi > next_out) { + SendToPlayer(&buf[next_out], oldi - next_out); + } + next_out = i; + started = STARTED_HOLDINGS; + parse_pos = 0; + continue; + } + + /* Send buf now to zippy */ + if (appData.zippyTalk || appData.zippyPlay) { +#if ZIPPY + if (ZippyControl(buf, &save) || ZippyConverse(buf, &save)) { + loggedOn = TRUE; + continue; + } +#endif + } + + /* ICS: init icsQueue */ + if (appData.zippyPlay && first.initDone && gameMode == IcsObserving) { + if (ics_gamenum > max_gamenum || ics_gamenum == -1) { + if (appData.debugMode) fprintf(debugFP, "To high gamenumber or gamenumber -1 !\n"); + return; + } + if (icsQueue[ics_gamenum].killPv == 0) { + icsQueue[ics_gamenum].move = currentMove; + icsQueue[ics_gamenum].killPv = appData.icsKillPVs; + icsQueue[ics_gamenum].counter = 0; + strcpy(icsQueue[ics_gamenum].white, gameInfo.white); + strcpy(icsQueue[ics_gamenum].black, gameInfo.black); + } + } + + if (looking_at(buf, &i, "* *vs. * *--- *")) { + loggedOn = TRUE; + /* Header for a move list -- first line */ + switch (ics_getting_history) { + case H_FALSE: + switch (gameMode) { + case IcsIdle: + case BeginningOfGame: + /* User typed "moves" or "oldmoves" while we + were idle. Pretend we asked for these + moves and soak them up so user can step + through them and/or save them. + */ + Reset(FALSE, TRUE); + gameMode = IcsObserving; + ModeHighlight(); + ics_gamenum = -1; + ics_getting_history = H_GOT_UNREQ_HEADER; + break; + case EditGame: /*?*/ + case EditPosition: /*?*/ + /* Should above feature work in these modes too? */ + /* For now it doesn't */ + ics_getting_history = H_GOT_UNWANTED_HEADER; + break; + default: + ics_getting_history = H_GOT_UNWANTED_HEADER; + break; + } + break; + case H_REQUESTED: + /* Is this the right one? */ + if (gameInfo.white && gameInfo.black && + strcmp(gameInfo.white, star_match[0]) == 0 && + strcmp(gameInfo.black, star_match[2]) == 0) { + /* All is well */ + ics_getting_history = H_GOT_REQ_HEADER; + } + break; + case H_GOT_REQ_HEADER: + case H_GOT_UNREQ_HEADER: + case H_GOT_UNWANTED_HEADER: + case H_GETTING_MOVES: + /* Should not happen */ + DisplayError("Error gathering move list: two headers", 0); + ics_getting_history = H_FALSE; + break; + } + + /* Save player ratings into gameInfo if needed */ + if ((ics_getting_history == H_GOT_REQ_HEADER || + ics_getting_history == H_GOT_UNREQ_HEADER) && + (gameInfo.whiteRating == -1 || + gameInfo.blackRating == -1)) { + + gameInfo.whiteRating = string_to_rating(star_match[1]); + gameInfo.blackRating = string_to_rating(star_match[3]); + if (appData.debugMode) + fprintf(debugFP, "Ratings from header: W %d, B %d\n", + gameInfo.whiteRating, gameInfo.blackRating); + } + continue; + } + + if (looking_at(buf, &i, + "* * match, initial time: * minute*, increment: * second")) { + /* Header for a move list -- second line */ + /* Initial board will follow if this is a wild game */ + + if (gameInfo.event != NULL) free(gameInfo.event); + sprintf(str, "ICS %s %s match", star_match[0], star_match[1]); + gameInfo.event = StrSave(str); + gameInfo.variant = StringToVariant(gameInfo.event); + continue; + } + + if (looking_at(buf, &i, "Move ")) { + /* Beginning of a move list */ + switch (ics_getting_history) { + case H_FALSE: + /* Normally should not happen */ + /* Maybe user hit reset while we were parsing */ + break; + case H_REQUESTED: + /* Happens if we are ignoring a move list that is not + * the one we just requested. Common if the user + * tries to observe two games without turning off + * getMoveList */ + break; + case H_GETTING_MOVES: + /* Should not happen */ + DisplayError("Error gathering move list: nested", 0); + ics_getting_history = H_FALSE; + break; + case H_GOT_REQ_HEADER: + ics_getting_history = H_GETTING_MOVES; + started = STARTED_MOVES; + parse_pos = 0; + if (oldi > next_out) { + SendToPlayer(&buf[next_out], oldi - next_out); + } + break; + case H_GOT_UNREQ_HEADER: + ics_getting_history = H_GETTING_MOVES; + started = STARTED_MOVES_NOHIDE; + parse_pos = 0; + break; + case H_GOT_UNWANTED_HEADER: + ics_getting_history = H_FALSE; + break; + } + continue; + } + + if (looking_at(buf, &i, "% ") || + ((started == STARTED_MOVES || started == STARTED_MOVES_NOHIDE) + && looking_at(buf, &i, "}*"))) { + savingComment = FALSE; + switch (started) { + case STARTED_MOVES: + case STARTED_MOVES_NOHIDE: + memcpy(&parse[parse_pos], &buf[oldi], i - oldi); + parse[parse_pos + i - oldi] = NULLCHAR; + ParseGameHistory(parse); +#if ZIPPY + if (appData.zippyPlay && first.initDone) { + if (appData.icsAnalyze && gameMode == IcsObserving) { + IcsAnalyze(TRUE); + } + /* icsAnalyze send the moves to engine if we start new */ + if (!appData.icsAnalyze) FeedMovesToProgram(&first, forwardMostMove); + /* Bug 4.2.6: Engine want play, skip that */ + if (gameMode == IcsExamining) { + /* set idle mode */ + SendToProgram("force\n", &first); + } + if (gameMode == IcsPlayingWhite) { + if (appData.icsAnalyze) { + IcsAnalyze(FALSE); + appData.icsAnalyze = FALSE; + + } + if (WhiteOnMove(forwardMostMove)) { + if (first.sendTime) { + if (first.useColors) { + SendToProgram("black\n", &first); + } + SendTimeRemaining(&first, TRUE); + } + if (first.useColors) { + SendToProgram("white\ngo\n", &first); + } else { + SendToProgram("go\n", &first); + } + first.maybeThinking = TRUE; + } else { + if (first.usePlayother) { + if (first.sendTime) { + SendTimeRemaining(&first, TRUE); + } + SendToProgram("playother\n", &first); + firstMove = FALSE; + } else { + firstMove = TRUE; + } + } + } else if (gameMode == IcsPlayingBlack) { + if (appData.icsAnalyze) { + IcsAnalyze(FALSE); + appData.icsAnalyze = FALSE; + SendToICS("refresh\n"); + } + /* engineRoom stay forever */ + if (!WhiteOnMove(forwardMostMove)) { + if (first.sendTime) { + if (first.useColors) { + SendToProgram("white\n", &first); + } + SendTimeRemaining(&first, FALSE); + } + if (first.useColors) { + SendToProgram("black\ngo\n", &first); + } else { + SendToProgram("go\n", &first); + } + first.maybeThinking = TRUE; + } else { + if (first.usePlayother) { + if (first.sendTime) { + SendTimeRemaining(&first, FALSE); + } + SendToProgram("playother\n", &first); + firstMove = FALSE; + } else { + firstMove = TRUE; + } + } + } + +#endif ZIPPY + + } + if (gameMode == IcsObserving && ics_gamenum == -1) { + /* Moves came from oldmoves or moves command + while we weren't doing anything else. + */ + currentMove = forwardMostMove; + ClearHighlights();/*!!could figure this out*/ + flipView = appData.flipView; + DrawPosition(FALSE, boards[currentMove]); + DisplayBothClocks(); + sprintf(str, "%s vs. %s", + gameInfo.white, gameInfo.black); + DisplayTitle(str); + gameMode = IcsIdle; + } else { + /* Moves were history of an active game */ + if (gameInfo.resultDetails != NULL) { + free(gameInfo.resultDetails); + gameInfo.resultDetails = NULL; + } + } + HistorySet(parseList, backwardMostMove, + forwardMostMove, currentMove-1); + DisplayMove(currentMove - 1); + if (started == STARTED_MOVES) next_out = i; + started = STARTED_NONE; + ics_getting_history = H_FALSE; + break; + + case STARTED_OBSERVE: + started = STARTED_NONE; + SendToICS(ics_prefix); + SendToICS("refresh\n"); + break; + + default: + break; + } + continue; + } + + if ((started == STARTED_MOVES || started == STARTED_BOARD || + started == STARTED_HOLDINGS || + started == STARTED_MOVES_NOHIDE) && i >= leftover_len) { + /* Accumulate characters in move list or board */ + parse[parse_pos++] = buf[i]; + } + + /* Start of game messages. Mostly we detect start of game + when the first board image arrives. On some versions + of the ICS, though, we need to do a "refresh" after starting + to observe in order to get the current board right away. */ + if (looking_at(buf, &i, "Adding game * to observation list")) { + started = STARTED_OBSERVE; + continue; + } + + /* Handle auto-observe */ + if (appData.autoObserve && + (gameMode == IcsIdle || gameMode == BeginningOfGame) && + looking_at(buf, &i, "Game notification: * (*) vs. * (*)")) { + char *player; + /* Choose the player that was highlighted, if any. */ + if (star_match[0][0] == '\033' || + star_match[1][0] != '\033') { + player = star_match[0]; + } else { + player = star_match[2]; + } + sprintf(str, "%sobserve %s\n", + ics_prefix, StripHighlightAndTitle(player)); + SendToICS(str); + + /* Save ratings from notify string */ + strcpy(player1Name, star_match[0]); + player1Rating = string_to_rating(star_match[1]); + strcpy(player2Name, star_match[2]); + player2Rating = string_to_rating(star_match[3]); + + if (appData.debugMode) + fprintf(debugFP, + "Ratings from 'Game notification:' %s %d, %s %d\n", + player1Name, player1Rating, + player2Name, player2Rating); + + continue; + } + + /* Deal with automatic examine mode after a game, + and with IcsObserving -> IcsExamining transition */ + if (looking_at(buf, &i, "Entering examine mode for game *") || + looking_at(buf, &i, "has made you an examiner of game *")) { + + int gamenum = atoi(star_match[0]); + if ((gameMode == IcsIdle || gameMode == IcsObserving) && + gamenum == ics_gamenum) { + /* We were already playing or observing this game; + no need to refetch history */ + gameMode = IcsExamining; + if (pausing) { + pauseExamForwardMostMove = forwardMostMove; + } else if (currentMove < forwardMostMove) { + ForwardInner(forwardMostMove); + } + } else { + /* I don't think this case really can happen */ + SendToICS(ics_prefix); + SendToICS("refresh\n"); + } + continue; + } + + /* Error messages */ + if (ics_user_moved) { + if (looking_at(buf, &i, "Illegal move") || + looking_at(buf, &i, "Not a legal move") || + looking_at(buf, &i, "Your king is in check") || + looking_at(buf, &i, "It isn't your turn") || + looking_at(buf, &i, "It is not your move")) { + /* Illegal move */ + ics_user_moved = 0; + if (forwardMostMove > backwardMostMove) { + currentMove = --forwardMostMove; + DisplayMove(currentMove - 1); /* before DMError */ + DisplayMoveError("Illegal move (rejected by ICS)"); + DrawPosition(FALSE, boards[currentMove]); + SwitchClocks(); + DisplayBothClocks(); + } + continue; + } + } + + if (looking_at(buf, &i, "still have time") || + looking_at(buf, &i, "not out of time") || + looking_at(buf, &i, "either player is out of time") || + looking_at(buf, &i, "has timeseal; checking")) { + /* We must have called his flag a little too soon */ + whiteFlag = blackFlag = FALSE; + continue; + } + + if (looking_at(buf, &i, "added * seconds to") || + looking_at(buf, &i, "seconds were added to")) { + /* Update the clocks */ + SendToICS(ics_prefix); + SendToICS("refresh\n"); + continue; + } + + if (!ics_clock_paused && looking_at(buf, &i, "clock paused")) { + ics_clock_paused = TRUE; + StopClocks(); + continue; + } + + if (ics_clock_paused && looking_at(buf, &i, "clock resumed")) { + ics_clock_paused = FALSE; + StartClocks(); + continue; + } + + /* Grab player ratings from the Creating: message. + Note we have to check for the special case when + the ICS inserts things like [white] or [black]. */ + if (looking_at(buf, &i, "Creating: * (*)* * (*)") || + looking_at(buf, &i, "Creating: * (*) [*] * (*)")) { + /* star_matches: + 0 player 1 name (not necessarily white) + 1 player 1 rating + 2 empty, white, or black (IGNORED) + 3 player 2 name (not necessarily black) + 4 player 2 rating + + The names/ratings are sorted out when the game + actually starts (below). + */ + strcpy(player1Name, StripHighlightAndTitle(star_match[0])); + player1Rating = string_to_rating(star_match[1]); + strcpy(player2Name, StripHighlightAndTitle(star_match[3])); + player2Rating = string_to_rating(star_match[4]); + + if (appData.debugMode) + fprintf(debugFP, + "Ratings from 'Creating:' %s %d, %s %d\n", + player1Name, player1Rating, + player2Name, player2Rating); + + continue; + } + + /* Improved generic start/end-of-game messages */ + if (looking_at(buf, &i, "{Game * (* vs. *) *}*")) { + /* star_match[0] is the game number */ + /* [1] is the white player's name */ + /* [2] is the black player's name */ + /* For end-of-game: */ + /* [3] is the reason for the game end */ + /* [4] is a PGN end game-token, preceded by " " */ + /* For start-of-game: */ + /* [3] begins with "Creating" or "Continuing" */ + /* [4] is " *" or empty (don't care). */ + int gamenum = atoi(star_match[0]); + char *why = star_match[3]; + char *endtoken = star_match[4]; + ChessMove endtype = (ChessMove) 0; + + /* Game start messages */ + if (strncmp(why, "Creating ", 9) == 0 || + strncmp(why, "Continuing ", 11) == 0) { + gs_gamenum = gamenum; + strcpy(gs_kind, strchr(why, ' ') + 1); +#if ZIPPY + if (appData.zippyPlay) { + ZippyGameStart(star_match[1], star_match[2]); + } +#endif /*ZIPPY*/ + continue; + } + + /* Game end messages */ + if (gameMode == IcsIdle || gameMode == BeginningOfGame || + ics_gamenum != gamenum) { + continue; + } + while (endtoken[0] == ' ') endtoken++; + switch (endtoken[0]) { + case '*': + default: + endtype = GameUnfinished; + break; + case '0': + endtype = BlackWins; + break; + case '1': + if (endtoken[1] == '/') + endtype = GameIsDrawn; + else + endtype = WhiteWins; + break; + } + GameEnds(endtype, why, GE_ICS); +#if ZIPPY + if (appData.zippyPlay && first.initDone) { + ZippyGameEnd(endtype, why); + if (first.pr == NULL) { + /* Start the next process early so that we'll + be ready for the next challenge */ + StartChessProgram(&first); + } + /* Send "new" early, in case this command takes + a long time to finish, so that we'll be ready + for the next challenge. */ + Reset(TRUE, TRUE); + } +#endif /*ZIPPY*/ + continue; + } + + if (looking_at(buf, &i, "Removing game * from observation") || + looking_at(buf, &i, "no longer observing game *") || + looking_at(buf, &i, "Game * (*) has no examiners")) { + if (gameMode == IcsObserving && + atoi(star_match[0]) == ics_gamenum) + { + if (appData.icsAnalyze) IcsAnalyze(FALSE); + ResetIcsQueue(ics_gamenum); + StopClocks(); + gameMode = IcsIdle; + ics_gamenum = -1; + ics_user_moved = FALSE; + } + continue; + } + + if (looking_at(buf, &i, "no longer examining game *")) { + if (gameMode == IcsExamining && + atoi(star_match[0]) == ics_gamenum) + { + if (appData.icsAnalyze) IcsAnalyze(FALSE); + ResetIcsQueue(ics_gamenum); + gameMode = IcsIdle; + ics_gamenum = -1; + ics_user_moved = FALSE; + } + continue; + } + + /* Advance leftover_start past any newlines we find, + so only partial lines can get reparsed */ + if (looking_at(buf, &i, "\n")) { + prevColor = curColor; + if (curColor != ColorNormal) { + if (oldi > next_out) { + SendToPlayer(&buf[next_out], oldi - next_out); + next_out = oldi; + } + Colorize(ColorNormal, FALSE); + curColor = ColorNormal; + } + if (started == STARTED_BOARD) { + started = STARTED_NONE; + parse[parse_pos] = NULLCHAR; + ParseBoard12(parse); + ics_user_moved = 0; + + /* Send premove here */ + if (appData.premove) { + char str[MSG_SIZ]; + if (currentMove == 0 && + gameMode == IcsPlayingWhite && + appData.premoveWhite) { + sprintf(str, "%s%s\n", ics_prefix, + appData.premoveWhiteText); + if (appData.debugMode) + fprintf(debugFP, "Sending premove:\n"); + SendToICS(str); + } else if (currentMove == 1 && + gameMode == IcsPlayingBlack && + appData.premoveBlack) { + sprintf(str, "%s%s\n", ics_prefix, + appData.premoveBlackText); + if (appData.debugMode) + fprintf(debugFP, "Sending premove:\n"); + SendToICS(str); + } else if (gotPremove) { + gotPremove = 0; + ClearPremoveHighlights(); + if (appData.debugMode) + fprintf(debugFP, "Sending premove:\n"); + UserMoveEvent(premoveFromX, premoveFromY, + premoveToX, premoveToY, + premovePromoChar); + } + } + + /* Usually suppress following prompt */ + if (!(forwardMostMove == 0 && gameMode == IcsExamining)) { + if (looking_at(buf, &i, "*% ")) { + savingComment = FALSE; + } + } + next_out = i; + } else if (started == STARTED_HOLDINGS) { + int gamenum; + char new_piece[MSG_SIZ]; + started = STARTED_NONE; + parse[parse_pos] = NULLCHAR; + if (appData.debugMode) + fprintf(debugFP, "Parsing holdings: %s\n", parse); + if (sscanf(parse, " game %d", &gamenum) == 1 && + gamenum == ics_gamenum) { + if (gameInfo.variant == VariantNormal) { + gameInfo.variant = VariantCrazyhouse; /*temp guess*/ + /* Get a move list just to see the header, which + will tell us whether this is really bug or zh */ + if (ics_getting_history == H_FALSE) { + ics_getting_history = H_REQUESTED; + sprintf(str, "%smoves %d\n", ics_prefix, gamenum); + SendToICS(str); + } + } + new_piece[0] = NULLCHAR; + sscanf(parse, "game %d white [%s black [%s <- %s", + &gamenum, white_holding, black_holding, + new_piece); + white_holding[strlen(white_holding)-1] = NULLCHAR; + black_holding[strlen(black_holding)-1] = NULLCHAR; +#if ZIPPY + if (appData.zippyPlay && first.initDone) { + ZippyHoldings(white_holding, black_holding, + new_piece); + } +#endif /*ZIPPY*/ + if (tinyLayout || smallLayout) { + char wh[16], bh[16]; + PackHolding(wh, white_holding); + PackHolding(bh, black_holding); + sprintf(str, "[%s-%s] %s-%s", wh, bh, + gameInfo.white, gameInfo.black); + } else { + sprintf(str, "%s [%s] vs. %s [%s]", + gameInfo.white, white_holding, + gameInfo.black, black_holding); + } + DrawPosition(FALSE, NULL); + DisplayTitle(str); + } + /* Suppress following prompt */ + if (looking_at(buf, &i, "*% ")) { + savingComment = FALSE; + } + next_out = i; + } + continue; + } + + i++; /* skip unparsed character and loop back */ + } + + if (started != STARTED_MOVES && started != STARTED_BOARD && + started != STARTED_HOLDINGS && i > next_out) { + SendToPlayer(&buf[next_out], i - next_out); + next_out = i; + } + + leftover_len = buf_len - leftover_start; + /* if buffer ends with something we couldn't parse, + reparse it after appending the next read */ + + } else if (count == 0) { + RemoveInputSource(isr); + DisplayFatalError("Connection closed by ICS", 0, 0); + } else { + DisplayFatalError("Error reading from ICS", error, 1); + } +} + + +/* Board style 12 looks like this: + + <12> r-b---k- pp----pp ---bP--- ---p---- q------- ------P- P--Q--BP -----R-K W -1 0 0 0 0 0 0 paf MaxII 0 2 12 21 25 234 174 24 Q/d7-a4 (0:06) Qxa4 0 0 + + * The "<12> " is stripped before it gets to this routine. The two + * trailing 0's (flip state and clock ticking) are later addition, and + * some chess servers may not have them, or may have only the first. + * Additional trailing fields may be added in the future. + */ + +#define PATTERN "%72c%c%d%d%d%d%d%d%d%s%s%d%d%d%d%d%d%d%d%s%s%s%d%d" + +#define RELATION_OBSERVING_PLAYED 0 +#define RELATION_OBSERVING_STATIC -2 /* examined, oldmoves, or smoves */ +#define RELATION_PLAYING_MYMOVE 1 +#define RELATION_PLAYING_NOTMYMOVE -1 +#define RELATION_EXAMINING 2 +#define RELATION_ISOLATED_BOARD -3 +#define RELATION_STARTING_POSITION -4 /* FICS only */ + +void +ParseBoard12(string) + char *string; +{ + GameMode newGameMode; + int gamenum, newGame, newMove, relation, basetime, increment, ics_flip = 0; + int j, k, n, moveNum, white_stren, black_stren, white_time, black_time; + int double_push, castle_ws, castle_wl, castle_bs, castle_bl, irrev_count; + int takeback, i; + char to_play, board_chars[72]; + char move_str[500], str[500], elapsed_time[500]; + char black[32], white[32]; + Board board; + int prevMove = currentMove; + int ticking = 2; + ChessMove moveType; + int fromX, fromY, toX, toY; + char promoChar; + + fromX = fromY = toX = toY = -1; + + newGame = FALSE; + + if (appData.debugMode) + fprintf(debugFP, "Parsing board: %s\n", string); + + move_str[0] = NULLCHAR; + elapsed_time[0] = NULLCHAR; + n = sscanf(string, PATTERN, board_chars, &to_play, &double_push, + &castle_ws, &castle_wl, &castle_bs, &castle_bl, &irrev_count, + &gamenum, white, black, &relation, &basetime, &increment, + &white_stren, &black_stren, &white_time, &black_time, + &moveNum, str, elapsed_time, move_str, &ics_flip, + &ticking); + + if (n < 22) { + sprintf(str, "Failed to parse board string:\n\"%s\"", string); + DisplayError(str, 0); + return; + } + + /* Convert the move number to internal form */ + moveNum = (moveNum - 1) * 2; + if (to_play == 'B') moveNum++; + if (moveNum >= MAX_MOVES) { + DisplayFatalError("Game too long; increase MAX_MOVES and recompile", + 0, 1); + return; + } + + switch (relation) { + case RELATION_OBSERVING_PLAYED: + case RELATION_OBSERVING_STATIC: + if (gamenum == -1) { + /* Old ICC buglet */ + relation = RELATION_OBSERVING_STATIC; + } + newGameMode = IcsObserving; + break; + case RELATION_PLAYING_MYMOVE: + case RELATION_PLAYING_NOTMYMOVE: + newGameMode = + ((relation == RELATION_PLAYING_MYMOVE) == (to_play == 'W')) ? + IcsPlayingWhite : IcsPlayingBlack; + break; + case RELATION_EXAMINING: + newGameMode = IcsExamining; + break; + case RELATION_ISOLATED_BOARD: + default: + /* Just display this board. If user was doing something else, + we will forget about it until the next board comes. */ + newGameMode = IcsIdle; + break; + case RELATION_STARTING_POSITION: + newGameMode = gameMode; + /* if we switch to a new board start IcsAnalyze */ + if(appData.icsAnalyze) IcsAnalyze(TRUE); + break; + } + + /* Modify behavior for initial board display on move listing + of wild games. + */ + switch (ics_getting_history) { + case H_FALSE: + case H_REQUESTED: + break; + case H_GOT_REQ_HEADER: + case H_GOT_UNREQ_HEADER: + /* This is the initial position of the current game */ + gamenum = ics_gamenum; + moveNum = 0; /* old ICS bug workaround */ + if (to_play == 'B') { + startedFromSetupPosition = TRUE; + blackPlaysFirst = TRUE; + moveNum = 1; + if (forwardMostMove == 0) forwardMostMove = 1; + if (backwardMostMove == 0) backwardMostMove = 1; + if (currentMove == 0) currentMove = 1; + } + newGameMode = gameMode; + relation = RELATION_STARTING_POSITION; /* ICC needs this */ + break; + case H_GOT_UNWANTED_HEADER: + /* This is an initial board that we don't want */ + return; + case H_GETTING_MOVES: + /* Should not happen */ + DisplayError("Error gathering move list: extra board", 0); + ics_getting_history = H_FALSE; + return; + } + + /* Take action if this is the first board of a new game, or of a + different game than is currently being displayed. */ + if (gamenum != ics_gamenum || newGameMode != gameMode || + relation == RELATION_ISOLATED_BOARD) { + + /* Forget the old game and get the history (if any) of the new one */ + if (gameMode != BeginningOfGame) { + Reset(FALSE, TRUE); + } + newGame = TRUE; + if (appData.autoRaiseBoard) BoardToTop(); + prevMove = -3; + if (gamenum == -1) { + newGameMode = IcsIdle; + } else if (moveNum > 0 && newGameMode != IcsIdle && + appData.getMoveList) { + /* Need to get game history */ + ics_getting_history = H_REQUESTED; + sprintf(str, "%smoves %d\n", ics_prefix, gamenum); + SendToICS(str); + } + + + /* Initially flip the board to have black on the bottom if playing + black or if the ICS flip flag is set, but let the user change + it with the Flip View button. */ + flipView = appData.autoFlipView ? + (newGameMode == IcsPlayingBlack) || ics_flip : + appData.flipView; + + /* Done with values from previous mode; copy in new ones */ + gameMode = newGameMode; + ModeHighlight(); + ics_gamenum = gamenum; + if (gamenum == gs_gamenum) { + int klen = strlen(gs_kind); + if (gs_kind[klen - 1] == '.') gs_kind[klen - 1] = NULLCHAR; + sprintf(str, "ICS %s", gs_kind); + gameInfo.event = StrSave(str); + } else { + gameInfo.event = StrSave("ICS game"); + } + gameInfo.site = StrSave(appData.icsHost); + gameInfo.date = PGNDate(); + gameInfo.round = StrSave("-"); + gameInfo.white = StrSave(white); + gameInfo.black = StrSave(black); + timeControl = basetime * 60 * 1000; + timeIncrement = increment * 1000; + movesPerSession = 0; + gameInfo.timeControl = TimeControlTagValue(); + gameInfo.variant = StringToVariant(gameInfo.event); + + /* Do we have the ratings? */ + if (strcmp(player1Name, white) == 0 && + strcmp(player2Name, black) == 0) { + if (appData.debugMode) + fprintf(debugFP, "Remembered ratings: W %d, B %d\n", + player1Rating, player2Rating); + gameInfo.whiteRating = player1Rating; + gameInfo.blackRating = player2Rating; + } else if (strcmp(player2Name, white) == 0 && + strcmp(player1Name, black) == 0) { + if (appData.debugMode) + fprintf(debugFP, "Remembered ratings: W %d, B %d\n", + player2Rating, player1Rating); + gameInfo.whiteRating = player2Rating; + gameInfo.blackRating = player1Rating; + } + player1Name[0] = player2Name[0] = NULLCHAR; + + /* Silence shouts if requested */ + if (appData.quietPlay && + (gameMode == IcsPlayingWhite || gameMode == IcsPlayingBlack)) { + SendToICS(ics_prefix); + SendToICS("set shout 0\n"); + } + } + + /* Deal with midgame name changes */ + if (!newGame) { + if (!gameInfo.white || strcmp(gameInfo.white, white) != 0) { + if (gameInfo.white) free(gameInfo.white); + gameInfo.white = StrSave(white); + } + if (!gameInfo.black || strcmp(gameInfo.black, black) != 0) { + if (gameInfo.black) free(gameInfo.black); + gameInfo.black = StrSave(black); + } + } + + /* Throw away game result if anything actually changes in examine mode */ + if (gameMode == IcsExamining && !newGame) { + gameInfo.result = GameUnfinished; + if (gameInfo.resultDetails != NULL) { + free(gameInfo.resultDetails); + gameInfo.resultDetails = NULL; + } + } + + /* In pausing && IcsExamining mode, we ignore boards coming + in if they are in a different variation than we are. */ + if (pauseExamInvalid) return; + if (pausing && gameMode == IcsExamining) { + if (moveNum <= pauseExamForwardMostMove) { + pauseExamInvalid = TRUE; + forwardMostMove = pauseExamForwardMostMove; + return; + } + } + + /* Parse the board */ + for (k = 0; k < 8; k++) + for (j = 0; j < 8; j++) + board[k][j] = CharToPiece(board_chars[(7-k)*9 + j]); + CopyBoard(boards[moveNum], board); + if (moveNum == 0) { + startedFromSetupPosition = + !CompareBoards(board, initialPosition); + } + + if (ics_getting_history == H_GOT_REQ_HEADER || + ics_getting_history == H_GOT_UNREQ_HEADER) { + /* This was an initial position from a move list, not + the current position */ + return; + } + + /* Update currentMove and known move number limits */ + newMove = newGame || moveNum > forwardMostMove; + + + /* If we found takebacks during IcsAnalyze try send to engine */ + if (!newGame && appData.icsAnalyze && first.analyzing && + moveNum < forwardMostMove) { + if (appData.debugMode) fprintf(debugFP, "take back move\n"); + takeback = forwardMostMove - moveNum; + if (!appData.icsWBprotoAgr) { + /* safty first */ + SendToProgram("exit\n", &first); + SendToProgram("force\n", &first); + for (i = 0; i < takeback; i++) { + SendToProgram("undo\n", &first); + /* Some engine need analyze and stat again */ + } + SendToProgram("analyze\n", &first); + } else { + /* hard */ + IcsAnalyze(FALSE); + IcsAnalyze(TRUE); + } + } + if (newGame) { + forwardMostMove = backwardMostMove = currentMove = moveNum; + if (gameMode == IcsExamining && moveNum == 0) { + /* Workaround for ICS limitation: we are not told the wild + type when starting to examine a game. But if we ask for + the move list, the move list header will tell us */ + ics_getting_history = H_REQUESTED; + sprintf(str, "%smoves %d\n", ics_prefix, gamenum); + SendToICS(str); + } + } else if (moveNum == forwardMostMove + 1 || moveNum == forwardMostMove + || (moveNum < forwardMostMove && moveNum >= backwardMostMove)) { + forwardMostMove = moveNum; + if (!pausing || currentMove > forwardMostMove) + currentMove = forwardMostMove; + } else { + /* New part of history that is not contiguous with old part */ + if (pausing && gameMode == IcsExamining) { + pauseExamInvalid = TRUE; + forwardMostMove = pauseExamForwardMostMove; + return; + } + forwardMostMove = backwardMostMove = currentMove = moveNum; + if (gameMode == IcsExamining && moveNum > 0 && appData.getMoveList) { + ics_getting_history = H_REQUESTED; + sprintf(str, "%smoves %d\n", ics_prefix, gamenum); + SendToICS(str); + } + } + + { + int i = 0; + /* Update the clocks */ + if (strchr(elapsed_time, '.')) { + /* Time is in ms */ + timeRemaining[0][moveNum] = whiteTimeRemaining = white_time; + timeRemaining[1][moveNum] = blackTimeRemaining = black_time; + } else { + /* Time is in seconds */ + i = 1; + timeRemaining[0][moveNum] = whiteTimeRemaining = white_time * 1000; + timeRemaining[1][moveNum] = blackTimeRemaining = black_time * 1000; + } + } + + /* Time workaround for ICC - send only sec :( */ + if (ics_type == ICS_ICC) { + if (timeRemaining[0][moveNum] >= 1500) timeRemaining[0][moveNum] = timeRemaining[0][moveNum] - 1500; + if (timeRemaining[1][moveNum] >= 1500) timeRemaining[1][moveNum] = timeRemaining[1][moveNum] - 1500; + + if (timeRemaining[0][moveNum] == 1000) timeRemaining[0][moveNum] = timeRemaining[0][moveNum] - 950; + if (timeRemaining[0][moveNum] == 1000) timeRemaining[1][moveNum] = timeRemaining[1][moveNum] - 950; + + } + +#if ZIPPY + if (appData.zippyPlay && newGame && + gameMode != IcsObserving && gameMode != IcsIdle && + gameMode != IcsExamining) + ZippyFirstBoard(moveNum, basetime, increment); +#endif + + /* Put the move on the move list, first converting + to canonical algebraic form. */ + if (moveNum > 0) { + if (moveNum <= backwardMostMove) { + /* We don't know what the board looked like before + this move. Punt. */ + strcpy(parseList[moveNum - 1], move_str); + strcat(parseList[moveNum - 1], " "); + strcat(parseList[moveNum - 1], elapsed_time); + moveList[moveNum - 1][0] = NULLCHAR; + } else if (ParseOneMove(move_str, moveNum - 1, &moveType, + &fromX, &fromY, &toX, &toY, &promoChar)) { + (void) CoordsToAlgebraic(boards[moveNum - 1], + PosFlags(moveNum - 1), EP_UNKNOWN, + fromY, fromX, toY, toX, promoChar, + parseList[moveNum-1]); + switch (MateTest(boards[moveNum], PosFlags(moveNum), EP_UNKNOWN)){ + case MT_NONE: + case MT_STALEMATE: + default: + break; + case MT_CHECK: + strcat(parseList[moveNum - 1], "+"); + break; + case MT_CHECKMATE: + strcat(parseList[moveNum - 1], "#"); + break; + } + strcat(parseList[moveNum - 1], " "); + strcat(parseList[moveNum - 1], elapsed_time); + /* currentMoveString is set as a side-effect of ParseOneMove */ + strcpy(moveList[moveNum - 1], currentMoveString); + strcat(moveList[moveNum - 1], "\n"); + } else if (strcmp(move_str, "none") == 0) { + /* Again, we don't know what the board looked like; + this is really the start of the game. */ + parseList[moveNum - 1][0] = NULLCHAR; + moveList[moveNum - 1][0] = NULLCHAR; + backwardMostMove = moveNum; + startedFromSetupPosition = TRUE; + fromX = fromY = toX = toY = -1; + } else { + /* Move from ICS was illegal!? Punt. */ +#if 0 + if (appData.testLegality && appData.debugMode) { + sprintf(str, "Illegal move \"%s\" from ICS", move_str); + DisplayError(str, 0); + } +#endif + strcpy(parseList[moveNum - 1], move_str); + strcat(parseList[moveNum - 1], " "); + strcat(parseList[moveNum - 1], elapsed_time); + moveList[moveNum - 1][0] = NULLCHAR; + fromX = fromY = toX = toY = -1; + } + +#if ZIPPY + /* Send move to chess program (BEFORE animating it). */ + if (appData.zippyPlay && !newGame && newMove && + (!appData.getMoveList || backwardMostMove == 0) && first.initDone) { + + if ((gameMode == IcsPlayingWhite && WhiteOnMove(moveNum)) || + (gameMode == IcsPlayingBlack && !WhiteOnMove(moveNum))) { + if (moveList[moveNum - 1][0] == NULLCHAR) { + sprintf(str, "Couldn't parse move \"%s\" from ICS", + move_str); + DisplayError(str, 0); + } else { + if (first.sendTime) { + SendTimeRemaining(&first, gameMode == IcsPlayingWhite); + } + SendMoveToProgram(moveNum - 1, &first); + if (firstMove) { + firstMove = FALSE; + if (first.useColors) { + SendToProgram(gameMode == IcsPlayingWhite ? + "white\ngo\n" : + "black\ngo\n", &first); + } else { + SendToProgram("go\n", &first); + } + first.maybeThinking = TRUE; + } + } + } else if (gameMode == IcsObserving || gameMode == IcsExamining) { + if (moveList[moveNum - 1][0] == NULLCHAR) { + sprintf(str, "Couldn't parse move \"%s\" from ICS", move_str); + DisplayError(str, 0); + } else { + SendMoveToProgram(moveNum - 1, &first); + } + } + } +#endif + } + + if (moveNum > 0 && !gotPremove) { + /* If move comes from a remote source, animate it. If it + isn't remote, it will have already been animated. */ + if (!pausing && !ics_user_moved && prevMove == moveNum - 1) { + AnimateMove(boards[moveNum - 1], fromX, fromY, toX, toY); + } + if (!pausing && appData.highlightLastMove) { + SetHighlights(fromX, fromY, toX, toY); + } + } + + /* Start the clocks */ + whiteFlag = blackFlag = FALSE; + appData.clockMode = !(basetime == 0 && increment == 0); + if (ticking == 0) { + ics_clock_paused = TRUE; + StopClocks(); + } else if (ticking == 1) { + ics_clock_paused = FALSE; + } + if (gameMode == IcsIdle || + relation == RELATION_OBSERVING_STATIC || + relation == RELATION_EXAMINING || + ics_clock_paused) + DisplayBothClocks(); + else + StartClocks(); + + /* Display opponents and material strengths */ + if (gameInfo.variant != VariantBughouse && + gameInfo.variant != VariantCrazyhouse) { + if (tinyLayout || smallLayout) { + sprintf(str, "%s(%d) %s(%d) {%d %d}", + gameInfo.white, white_stren, gameInfo.black, black_stren, + basetime, increment); + } else { + sprintf(str, "%s (%d) vs. %s (%d) {%d %d}", + gameInfo.white, white_stren, gameInfo.black, black_stren, + basetime, increment); + } + DisplayTitle(str); + } + + + /* Display the board */ + if (!pausing) { + + if (appData.premove) + if (!gotPremove || + ((gameMode == IcsPlayingWhite) && (WhiteOnMove(currentMove))) || + ((gameMode == IcsPlayingBlack) && (!WhiteOnMove(currentMove)))) + ClearPremoveHighlights(); + + DrawPosition(FALSE, boards[currentMove]); + DisplayMove(moveNum - 1); + if (appData.ringBellAfterMoves && !ics_user_moved) + RingBell(); + } + + HistorySet(parseList, backwardMostMove, forwardMostMove, currentMove-1); +} + +void +GetMoveListEvent() +{ + char buf[MSG_SIZ]; + if (appData.icsActive && gameMode != IcsIdle && ics_gamenum > 0) { + ics_getting_history = H_REQUESTED; + sprintf(buf, "%smoves %d\n", ics_prefix, ics_gamenum); + SendToICS(buf); + } +} + +void +AnalysisPeriodicEvent(force) + int force; +{ + /* WB engine room */ + if (appData.AnalysisWindow && programStats.depth > 2) { + /* GUI disable send stat ? */ + if (!appData.engineStatLine) SendToProgram(".\n", &first); + /* don't support Stats on game ?*/ + if (supportStat == 0) { + /* call Display every sec for time and nodes */ + DisplayAnalysis(1,0); + } else { + /* GUI makes time ???? */ + /* at the moment: yes! */ + DisplayAnalysis(1,0); + } + } else if (appData.icsAnalyze && programStats.depth > 2) { + SendToProgram(".\n", &first); + DisplayAnalysis(1,0); + } else if (((programStats.ok_to_send == 0 || programStats.line_is_book) + && !force) || !appData.periodicUpdates) + return; + + /* Send . command to Crafty to collect stats */ + if (!appData.AnalysisWindow && (gameMode == AnalyzeMode || + gameMode == AnalyzeFile)) SendToProgram(".\n", &first); + + /* Don't send another until we get a response (this makes + us stop sending to old Crafty's which don't understand + the "." command (sending illegal cmds resets node count & time, + which looks bad)) */ + programStats.ok_to_send = 0; +} + +void +SendMoveToProgram(moveNum, cps) + int moveNum; + ChessProgramState *cps; +{ + char buf[MSG_SIZ]; + if (cps->useUsermove) { + SendToProgram("usermove ", cps); + } + if (cps->useSAN) { + char *space; + if ((space = strchr(parseList[moveNum], ' ')) != NULL) { + int len = space - parseList[moveNum]; + memcpy(buf, parseList[moveNum], len); + buf[len++] = '\n'; + buf[len] = NULLCHAR; + } else { + sprintf(buf, "%s\n", parseList[moveNum]); + } + SendToProgram(buf, cps); + } else { + SendToProgram(moveList[moveNum], cps); + } +} + +void +SendMoveToICS(moveType, fromX, fromY, toX, toY) + ChessMove moveType; + int fromX, fromY, toX, toY; +{ + char user_move[MSG_SIZ]; + + switch (moveType) { + default: + sprintf(user_move, "say Internal error; bad moveType %d (%d,%d-%d,%d)", + (int)moveType, fromX, fromY, toX, toY); + DisplayError(user_move + strlen("say "), 0); + break; + case WhiteKingSideCastle: + case BlackKingSideCastle: + case WhiteQueenSideCastleWild: + case BlackQueenSideCastleWild: + sprintf(user_move, "o-o\n"); + break; + case WhiteQueenSideCastle: + case BlackQueenSideCastle: + case WhiteKingSideCastleWild: + case BlackKingSideCastleWild: + sprintf(user_move, "o-o-o\n"); + break; + case WhitePromotionQueen: + case BlackPromotionQueen: + case WhitePromotionRook: + case BlackPromotionRook: + case WhitePromotionBishop: + case BlackPromotionBishop: + case WhitePromotionKnight: + case BlackPromotionKnight: + case WhitePromotionKing: + case BlackPromotionKing: + sprintf(user_move, "%c%c%c%c=%c\n", + 'a' + fromX, '1' + fromY, 'a' + toX, '1' + toY, + PieceToChar(PromoPiece(moveType))); + break; + case WhiteDrop: + case BlackDrop: + sprintf(user_move, "%c@%c%c\n", + ToUpper(PieceToChar((ChessSquare) fromX)), + 'a' + toX, '1' + toY); + break; + case NormalMove: + case WhiteCapturesEnPassant: + case BlackCapturesEnPassant: + case IllegalMove: /* could be a variant we don't quite understand */ + sprintf(user_move, "%c%c%c%c\n", + 'a' + fromX, '1' + fromY, 'a' + toX, '1' + toY); + break; + } + SendToICS(user_move); +} + +void +CoordsToComputerAlgebraic(rf, ff, rt, ft, promoChar, move) + int rf, ff, rt, ft; + char promoChar; + char move[7]; +{ + if (rf == DROP_RANK) { + sprintf(move, "%c@%c%c\n", + ToUpper(PieceToChar((ChessSquare) ff)), 'a' + ft, '1' + rt); + } else { + if (promoChar == 'x' || promoChar == NULLCHAR) { + sprintf(move, "%c%c%c%c\n", + 'a' + ff, '1' + rf, 'a' + ft, '1' + rt); + } else { + sprintf(move, "%c%c%c%c%c\n", + 'a' + ff, '1' + rf, 'a' + ft, '1' + rt, promoChar); + } + } +} + +void +ProcessICSInitScript(f) + FILE *f; +{ + char buf[MSG_SIZ]; + + while (fgets(buf, MSG_SIZ, f)) { + SendToICSDelayed(buf,(long)appData.msLoginDelay); + } + + fclose(f); +} + + +/* Parser for moves from gnuchess, ICS, or user typein box */ +Boolean +ParseOneMove(move, moveNum, moveType, fromX, fromY, toX, toY, promoChar) + char *move; + int moveNum; + ChessMove *moveType; + int *fromX, *fromY, *toX, *toY; + char *promoChar; +{ + *moveType = yylexstr(moveNum, move); + switch (*moveType) { + case WhitePromotionQueen: + case BlackPromotionQueen: + case WhitePromotionRook: + case BlackPromotionRook: + case WhitePromotionBishop: + case BlackPromotionBishop: + case WhitePromotionKnight: + case BlackPromotionKnight: + case WhitePromotionKing: + case BlackPromotionKing: + case NormalMove: + case WhiteCapturesEnPassant: + case BlackCapturesEnPassant: + case WhiteKingSideCastle: + case WhiteQueenSideCastle: + case BlackKingSideCastle: + case BlackQueenSideCastle: + case WhiteKingSideCastleWild: + case WhiteQueenSideCastleWild: + case BlackKingSideCastleWild: + case BlackQueenSideCastleWild: + case IllegalMove: /* bug or odd chess variant */ + *fromX = currentMoveString[0] - 'a'; + *fromY = currentMoveString[1] - '1'; + *toX = currentMoveString[2] - 'a'; + *toY = currentMoveString[3] - '1'; + *promoChar = currentMoveString[4]; + if (*fromX < 0 || *fromX > 7 || *fromY < 0 || *fromY > 7 || + *toX < 0 || *toX > 7 || *toY < 0 || *toY > 7) { + *fromX = *fromY = *toX = *toY = 0; + return FALSE; + } + if (appData.testLegality) { + return (*moveType != IllegalMove); + } else { + return !(fromX == fromY && toX == toY); + } + + case WhiteDrop: + case BlackDrop: + *fromX = *moveType == WhiteDrop ? + (int) CharToPiece(ToUpper(currentMoveString[0])) : + (int) CharToPiece(ToLower(currentMoveString[0])); + *fromY = DROP_RANK; + *toX = currentMoveString[2] - 'a'; + *toY = currentMoveString[3] - '1'; + *promoChar = NULLCHAR; + return TRUE; + + case AmbiguousMove: + case ImpossibleMove: + case (ChessMove) 0: /* end of file */ + case ElapsedTime: + case Comment: + case PGNTag: + case NAG: + case WhiteWins: + case BlackWins: + case GameIsDrawn: + default: + /* bug? */ + *fromX = *fromY = *toX = *toY = 0; + *promoChar = NULLCHAR; + return FALSE; + } +} + + +void +InitPosition(redraw) + int redraw; +{ + currentMove = forwardMostMove = backwardMostMove = 0; + switch (gameInfo.variant) { + default: + CopyBoard(boards[0], initialPosition); + break; + case VariantTwoKings: + CopyBoard(boards[0], twoKingsPosition); + startedFromSetupPosition = TRUE; + break; + case VariantWildCastle: + CopyBoard(boards[0], initialPosition); + /* !!?shuffle with kings guaranteed to be on d or e file */ + break; + case VariantNoCastle: + CopyBoard(boards[0], initialPosition); + /* !!?unconstrained back-rank shuffle */ + break; + case VariantFischeRandom: + CopyBoard(boards[0], initialPosition); + /* !!shuffle according to FR rules */ + break; + } + if (redraw) + DrawPosition(FALSE, boards[currentMove]); +} + +void +SendBoard(cps, moveNum) + ChessProgramState *cps; + int moveNum; +{ + char message[MSG_SIZ]; + + if (cps->useSetboard) { + char* fen = PositionToFEN(moveNum); + sprintf(message, "setboard %s\n", fen); + SendToProgram(message, cps); + free(fen); + + } else { + ChessSquare *bp; + int i, j; + /* Kludge to set black to move, avoiding the troublesome and now + * deprecated "black" command. + */ + if (!WhiteOnMove(moveNum)) SendToProgram("a2a3\n", cps); + + SendToProgram("edit\n", cps); + SendToProgram("#\n", cps); + for (i = BOARD_SIZE - 1; i >= 0; i--) { + bp = &boards[moveNum][i][0]; + for (j = 0; j < BOARD_SIZE; j++, bp++) { + if ((int) *bp < (int) BlackPawn) { + sprintf(message, "%c%c%c\n", PieceToChar(*bp), + 'a' + j, '1' + i); + SendToProgram(message, cps); + } + } + } + + SendToProgram("c\n", cps); + for (i = BOARD_SIZE - 1; i >= 0; i--) { + bp = &boards[moveNum][i][0]; + for (j = 0; j < BOARD_SIZE; j++, bp++) { + if (((int) *bp != (int) EmptySquare) + && ((int) *bp >= (int) BlackPawn)) { + sprintf(message, "%c%c%c\n", ToUpper(PieceToChar(*bp)), + 'a' + j, '1' + i); + SendToProgram(message, cps); + } + } + } + + SendToProgram(".\n", cps); + } +} + +int +IsPromotion(fromX, fromY, toX, toY) + int fromX, fromY, toX, toY; +{ + return gameMode != EditPosition && + fromX >=0 && fromY >= 0 && toX >= 0 && toY >= 0 && + ((boards[currentMove][fromY][fromX] == WhitePawn && toY == 7) || + (boards[currentMove][fromY][fromX] == BlackPawn && toY == 0)); +} + + +int +PieceForSquare (x, y) + int x; + int y; +{ + if (x < 0 || x >= BOARD_SIZE || y < 0 || y >= BOARD_SIZE) + return -1; + else + return boards[currentMove][y][x]; +} + +int +OKToStartUserMove(x, y) + int x, y; +{ + ChessSquare from_piece; + int white_piece; + + if (matchMode) return FALSE; + if (gameMode == EditPosition) return TRUE; + + if (x >= 0 && y >= 0) + from_piece = boards[currentMove][y][x]; + else + from_piece = EmptySquare; + + if (from_piece == EmptySquare) return FALSE; + + white_piece = (int)from_piece >= (int)WhitePawn && + (int)from_piece <= (int)WhiteKing; + + switch (gameMode) { + case PlayFromGameFile: + case AnalyzeFile: + case TwoMachinesPlay: + case EndOfGame: + return FALSE; + + case IcsObserving: + case IcsIdle: + return FALSE; + + case MachinePlaysWhite: + case IcsPlayingBlack: + if (appData.zippyPlay) return FALSE; + if (white_piece) { + DisplayMoveError("You are playing Black"); + return FALSE; + } + break; + + case MachinePlaysBlack: + case IcsPlayingWhite: + if (appData.zippyPlay) return FALSE; + if (!white_piece) { + DisplayMoveError("You are playing White"); + return FALSE; + } + break; + + case EditGame: + if (!white_piece && WhiteOnMove(currentMove)) { + DisplayMoveError("It is White's turn"); + return FALSE; + } + if (white_piece && !WhiteOnMove(currentMove)) { + DisplayMoveError("It is Black's turn"); + return FALSE; + } + if (cmailMsgLoaded && (currentMove < cmailOldMove)) { + /* Editing correspondence game history */ + /* Could disallow this or prompt for confirmation */ + cmailOldMove = -1; + } + if (currentMove < forwardMostMove) { + /* Discarding moves */ + /* Could prompt for confirmation here, + but I don't think that's such a good idea */ + forwardMostMove = currentMove; + } + break; + + case BeginningOfGame: + if (appData.icsActive) return FALSE; + if (!appData.noChessProgram) { + if (!white_piece) { + DisplayMoveError("You are playing White"); + return FALSE; + } + } + break; + + case Training: + if (!white_piece && WhiteOnMove(currentMove)) { + DisplayMoveError("It is White's turn"); + return FALSE; + } + if (white_piece && !WhiteOnMove(currentMove)) { + DisplayMoveError("It is Black's turn"); + return FALSE; + } + break; + + default: + case IcsExamining: + break; + } + if (currentMove != forwardMostMove && gameMode != AnalyzeMode + && gameMode != AnalyzeFile && gameMode != Training) { + DisplayMoveError("Displayed position is not current"); + return FALSE; + } + return TRUE; +} + +FILE *lastLoadGameFP = NULL, *lastLoadPositionFP = NULL; +int lastLoadGameNumber = 0, lastLoadPositionNumber = 0; +int lastLoadGameUseList = FALSE; +char lastLoadGameTitle[MSG_SIZ], lastLoadPositionTitle[MSG_SIZ]; +ChessMove lastLoadGameStart = (ChessMove) 0; + + +void +UserMoveEvent(fromX, fromY, toX, toY, promoChar) + int fromX, fromY, toX, toY; + int promoChar; +{ + ChessMove moveType; + + if (fromX < 0 || fromY < 0) return; + if ((fromX == toX) && (fromY == toY)) { + return; + } + + /* Check if the user is playing in turn. This is complicated because we + let the user "pick up" a piece before it is his turn. So the piece he + tried to pick up may have been captured by the time he puts it down! + Therefore we use the color the user is supposed to be playing in this + test, not the color of the piece that is currently on the starting + square---except in EditGame mode, where the user is playing both + sides; fortunately there the capture race can't happen. (It can + now happen in IcsExamining mode, but that's just too bad. The user + will get a somewhat confusing message in that case.) + */ + + switch (gameMode) { + case PlayFromGameFile: + case AnalyzeFile: + case TwoMachinesPlay: + case EndOfGame: + case IcsObserving: + case IcsIdle: + /* We switched into a game mode where moves are not accepted, + perhaps while the mouse button was down. */ + return; + + case MachinePlaysWhite: + /* User is moving for Black */ + if (WhiteOnMove(currentMove)) { + DisplayMoveError("It is White's turn"); + return; + } + break; + + case MachinePlaysBlack: + /* User is moving for White */ + if (!WhiteOnMove(currentMove)) { + DisplayMoveError("It is Black's turn"); + return; + } + break; + + case EditGame: + case IcsExamining: + case BeginningOfGame: + case AnalyzeMode: + case Training: + if ((int) boards[currentMove][fromY][fromX] >= (int) BlackPawn && + (int) boards[currentMove][fromY][fromX] <= (int) BlackKing) { + /* User is moving for Black */ + if (WhiteOnMove(currentMove)) { + DisplayMoveError("It is White's turn"); + return; + } + } else { + /* User is moving for White */ + if (!WhiteOnMove(currentMove)) { + DisplayMoveError("It is Black's turn"); + return; + } + } + break; + + case IcsPlayingBlack: + /* User is moving for Black */ + if (WhiteOnMove(currentMove)) { + if (!appData.premove) { + DisplayMoveError("It is White's turn"); + } else if (toX >= 0 && toY >= 0) { + premoveToX = toX; + premoveToY = toY; + premoveFromX = fromX; + premoveFromY = fromY; + premovePromoChar = promoChar; + gotPremove = 1; + if (appData.debugMode) + fprintf(debugFP, "Got premove: fromX %d," + "fromY %d, toX %d, toY %d\n", + fromX, fromY, toX, toY); + } + return; + } + break; + + case IcsPlayingWhite: + /* User is moving for White */ + if (!WhiteOnMove(currentMove)) { + if (!appData.premove) { + DisplayMoveError("It is Black's turn"); + } else if (toX >= 0 && toY >= 0) { + premoveToX = toX; + premoveToY = toY; + premoveFromX = fromX; + premoveFromY = fromY; + premovePromoChar = promoChar; + gotPremove = 1; + if (appData.debugMode) + fprintf(debugFP, "Got premove: fromX %d," + "fromY %d, toX %d, toY %d\n", + fromX, fromY, toX, toY); + } + return; + } + break; + + default: + break; + + case EditPosition: + if (toX == -2 || toY == -2) { + boards[0][fromY][fromX] = EmptySquare; + DrawPosition(FALSE, boards[currentMove]); + } else if (toX >= 0 && toY >= 0) { + boards[0][toY][toX] = boards[0][fromY][fromX]; + boards[0][fromY][fromX] = EmptySquare; + DrawPosition(FALSE, boards[currentMove]); + } + return; + } + + if (toX < 0 || toY < 0) return; + userOfferedDraw = FALSE; + + if (appData.testLegality) { + moveType = LegalityTest(boards[currentMove], PosFlags(currentMove), + EP_UNKNOWN, fromY, fromX, toY, toX, promoChar); + if (moveType == IllegalMove || moveType == ImpossibleMove) { + DisplayMoveError("Illegal move"); + return; + } + } else { + moveType = PromoCharToMoveType(WhiteOnMove(currentMove), promoChar); + } + + if (gameMode == Training) { + /* compare the move played on the board to the next move in the + * game. If they match, display the move and the opponent's response. + * If they don't match, display an error message. + */ + int saveAnimate; + Board testBoard; + CopyBoard(testBoard, boards[currentMove]); + ApplyMove(fromX, fromY, toX, toY, promoChar, testBoard); + + if (CompareBoards(testBoard, boards[currentMove+1])) { + ForwardInner(currentMove+1); + + /* Autoplay the opponent's response. + * if appData.animate was TRUE when Training mode was entered, + * the response will be animated. + */ + saveAnimate = appData.animate; + appData.animate = animateTraining; + ForwardInner(currentMove+1); + appData.animate = saveAnimate; + + /* check for the end of the game */ + if (currentMove >= forwardMostMove) { + gameMode = PlayFromGameFile; + ModeHighlight(); + SetTrainingModeOff(); + DisplayInformation("End of game"); + } + } else { + DisplayError("Incorrect move", 0); + } + return; + } + + FinishMove(moveType, fromX, fromY, toX, toY, promoChar); +} + +/* Common tail of UserMoveEvent and DropMenuEvent */ +void +FinishMove(moveType, fromX, fromY, toX, toY, promoChar) + ChessMove moveType; + int fromX, fromY, toX, toY; + /*char*/int promoChar; +{ + /* Ok, now we know that the move is good, so we can kill + the previous line in Analysis Mode */ + if (gameMode == AnalyzeMode && currentMove < forwardMostMove) { + forwardMostMove = currentMove; + } + + /* If we need the chess program but it's dead, restart it */ + ResurrectChessProgram(); + + /* A user move restarts a paused game*/ + if (pausing) + PauseEvent(); + + thinkOutput[0] = NULLCHAR; + + MakeMove(fromX, fromY, toX, toY, promoChar); /*updates forwardMostMove*/ + + if (gameMode == BeginningOfGame) { + if (appData.noChessProgram) { + gameMode = EditGame; + SetGameInfo(); + } else { + char buf[MSG_SIZ]; + gameMode = MachinePlaysBlack; + SetGameInfo(); + sprintf(buf, "%s vs. %s", gameInfo.white, gameInfo.black); + DisplayTitle(buf); + if (first.sendName) { + sprintf(buf, "name %s\n", gameInfo.white); + SendToProgram(buf, &first); + } + } + ModeHighlight(); + } + + /* Relay move to ICS or chess engine */ + if (appData.icsActive) { + if (gameMode == IcsPlayingWhite || gameMode == IcsPlayingBlack || + gameMode == IcsExamining) { + SendMoveToICS(moveType, fromX, fromY, toX, toY); + ics_user_moved = 1; + } + } else { + if (first.sendTime && (gameMode == BeginningOfGame || + gameMode == MachinePlaysWhite || + gameMode == MachinePlaysBlack)) { + SendTimeRemaining(&first, gameMode != MachinePlaysBlack); + } + + SendMoveToProgram(forwardMostMove-1, &first); + if (gameMode != EditGame && gameMode != PlayFromGameFile) { + first.maybeThinking = TRUE; + } + if (currentMove == cmailOldMove + 1) { + cmailMoveType[lastLoadGameNumber - 1] = CMAIL_MOVE; + } + } + + ShowMove(fromX, fromY, toX, toY); /*updates currentMove*/ + + switch (gameMode) { + case EditGame: + switch (MateTest(boards[currentMove], PosFlags(currentMove), + EP_UNKNOWN)) { + case MT_NONE: + case MT_CHECK: + break; + case MT_CHECKMATE: + if (WhiteOnMove(currentMove)) { + GameEnds(BlackWins, "Black mates", GE_PLAYER); + } else { + GameEnds(WhiteWins, "White mates", GE_PLAYER); + } + break; + case MT_STALEMATE: + GameEnds(GameIsDrawn, "Stalemate", GE_PLAYER); + break; + } + break; + + case MachinePlaysBlack: + case MachinePlaysWhite: + /* disable certain menu options while machine is thinking */ + SetMachineThinkingEnables(); + break; + + default: + break; + } +} + +void +HandleMachineMove(message, cps) + char *message; + ChessProgramState *cps; +{ + char machineMove[MSG_SIZ], buf1[MSG_SIZ*10], buf2[MSG_SIZ]; + char realname[MSG_SIZ]; + int fromX, fromY, toX, toY; + ChessMove moveType; + char promoChar; + char *p; + int machineWhite; + + /* + * Kludge to ignore BEL characters + */ + while (*message == '\007') message++; + + /* + * Look for book output + */ + if (cps == &first && bookRequested) { + if (message[0] == '\t' || message[0] == ' ') { + /* Part of the book output is here; append it */ + strcat(bookOutput, message); + strcat(bookOutput, " \n"); + return; + } else if (bookOutput[0] != NULLCHAR) { + /* All of book output has arrived; display it */ + char *p = bookOutput; + while (*p != NULLCHAR) { + if (*p == '\t') *p = ' '; + p++; + } + DisplayInformation(bookOutput); + bookRequested = FALSE; + /* Fall through to parse the current output */ + } + } + + /* + * Look for machine move. + */ + if ((sscanf(message, "%s %s %s", buf1, buf2, machineMove) == 3 && + strcmp(buf2, "...") == 0) || + (sscanf(message, "%s %s", buf1, machineMove) == 2 && + strcmp(buf1, "move") == 0)) { + /* Save last score befor move for zippy draw handling */ + if (appData.icsActive && appData.zippyDraw) { + // ZippyDraw(0, programStats.score, programStats.depth); + } + /* This method is only useful on engines that support ping */ + if (cps->lastPing != cps->lastPong) { + if (gameMode == BeginningOfGame) { + /* Extra move from before last new; ignore */ + if (appData.debugMode) { + fprintf(debugFP, "Ignoring extra move from %s\n", cps->which); + } + } else { + if (appData.debugMode) { + fprintf(debugFP, "Undoing extra move from %s, gameMode %d\n", + cps->which, gameMode); + } + SendToProgram("undo\n", cps); + } + return; + } + + switch (gameMode) { + case BeginningOfGame: + /* Extra move from before last reset; ignore */ + if (appData.debugMode) { + fprintf(debugFP, "Ignoring extra move from %s\n", cps->which); + } + return; + + case EndOfGame: + case IcsIdle: + default: + /* Extra move after we tried to stop. The mode test is + not a reliable way of detecting this problem, but it's + the best we can do on engines that don't support ping. + */ + if (appData.debugMode) { + fprintf(debugFP, "Undoing extra move from %s, gameMode %d\n", + cps->which, gameMode); + } + SendToProgram("undo\n", cps); + return; + + case MachinePlaysWhite: + case IcsPlayingWhite: + machineWhite = TRUE; + break; + + case MachinePlaysBlack: + case IcsPlayingBlack: + machineWhite = FALSE; + break; + + case TwoMachinesPlay: + machineWhite = (cps->twoMachinesColor[0] == 'w'); + break; + } + if (WhiteOnMove(forwardMostMove) != machineWhite) { + if (appData.debugMode) { + fprintf(debugFP, + "Ignoring move out of turn by %s, gameMode %d" + ", forwardMost %d\n", + cps->which, gameMode, forwardMostMove); + } + return; + } + + if (!ParseOneMove(machineMove, forwardMostMove, &moveType, + &fromX, &fromY, &toX, &toY, &promoChar)) { + /* Machine move could not be parsed; ignore it. */ + sprintf(buf1, "Illegal move \"%s\" from %s machine", + machineMove, cps->which); + /*!!if (appData.debugMode)*/ DisplayError(buf1, 0); + return; + } + + hintRequested = FALSE; + lastHint[0] = NULLCHAR; + bookRequested = FALSE; + /* Program may be pondering now */ + cps->maybeThinking = TRUE; + if (cps->sendTime == 2) cps->sendTime = 1; + if (cps->offeredDraw) cps->offeredDraw--; + +#if ZIPPY + if ((gameMode == IcsPlayingWhite || gameMode == IcsPlayingBlack) && + first.initDone) { + SendMoveToICS(moveType, fromX, fromY, toX, toY); + ics_user_moved = 1; + } +#endif + /* currentMoveString is set as a side-effect of ParseOneMove */ + strcpy(machineMove, currentMoveString); + strcat(machineMove, "\n"); + strcpy(moveList[forwardMostMove], machineMove); + + MakeMove(fromX, fromY, toX, toY, promoChar);/*updates forwardMostMove*/ + + if (gameMode == TwoMachinesPlay) { + if (cps->other->sendTime) { + SendTimeRemaining(cps->other, + cps->other->twoMachinesColor[0] == 'w'); + } + SendMoveToProgram(forwardMostMove-1, cps->other); + if (firstMove) { + firstMove = FALSE; + if (cps->other->useColors) { + SendToProgram(cps->other->twoMachinesColor, cps->other); + } + SendToProgram("go\n", cps->other); + } + cps->other->maybeThinking = TRUE; + } + + ShowMove(fromX, fromY, toX, toY); /*updates currentMove*/ + if (!pausing && appData.ringBellAfterMoves) { + RingBell(); + } + + /* + * Reenable menu items that were disabled while + * machine was thinking + */ + if (gameMode != TwoMachinesPlay) + SetUserThinkingEnables(); + return; + } + + + /* Set special modes for chess engines. Later something general + * could be added here; for now there is just one kludge feature, + * needed because Crafty 15.10 and earlier don't ignore SIGINT + * when "xboard" is given as an interactive command. + */ + if (strncmp(message, "kibitz Hello from Crafty", 24) == 0) { + cps->useSigint = FALSE; + cps->useSigterm = FALSE; + } + + /* + * Look for communication commands + */ + if (!strncmp(message, "telluser ", 9)) { + DisplayInformation(message + 9); + return; + } + if (!strncmp(message, "tellusererror ", 14)) { + DisplayError(message + 14, 0); + return; + } + if (!strncmp(message, "tellopponent ", 13)) { + if (appData.icsActive) { + if (loggedOn) { + sprintf(buf1, "%ssay %s\n", ics_prefix, message + 13); + SendToICS(buf1); + } + } else { + DisplayInformation(message + 13); + } + return; + } + if (!strncmp(message, "tellothers ", 11)) { + if (appData.icsActive) { + if (loggedOn) { + sprintf(buf1, "%swhisper %s\n", ics_prefix, message + 11); + SendToICS(buf1); + } + } + return; + } + if (!strncmp(message, "tellall ", 8)) { + if (appData.icsActive) { + /* daniel*/ + if (loggedOn && !appData.icsAnalyze) { + sprintf(buf1, "%skibitz %s\n", ics_prefix, message + 8); + SendToICS(buf1); + } + } else { + DisplayInformation(message + 8); + } + return; + } + if (strncmp(message, "warning", 7) == 0) { + /* Undocumented feature, use tellusererror in new code */ + DisplayError(message, 0); + return; + } + if (sscanf(message, "askuser %s %[^\n]", buf1, buf2) == 2) { + strcpy(realname, cps->tidy); + strcat(realname, " query"); + AskQuestion(realname, buf2, buf1, cps->pr); + return; + } + /* Commands from the engine directly to ICS. We don't allow these to be + * sent until we are logged on. Crafty kibitzes have been known to + * interfere with the login process. + */ + if (loggedOn) { + if (!strncmp(message, "tellics ", 8)) { + SendToICS(message + 8); + SendToICS("\n"); + return; + } + if (!strncmp(message, "tellicsnoalias ", 15)) { + SendToICS(ics_prefix); + SendToICS(message + 15); + SendToICS("\n"); + return; + } + /* The following are for backward compatibility only */ + if (!strncmp(message,"whisper",7) || !strncmp(message,"kibitz",6) || + !strncmp(message,"draw",4) || !strncmp(message,"tell",3)) { + SendToICS(ics_prefix); + SendToICS(message); + SendToICS("\n"); + return; + } + } + if (strncmp(message, "feature ", 8) == 0) { + ParseFeatures(message+8, cps); + } + if (sscanf(message, "pong %d", &cps->lastPong) == 1) { + return; + } + /* + * If the move is illegal, cancel it and redraw the board. + * Also deal with other error cases. Matching is rather loose + * here to accommodate engines written before the spec. + */ + if (strncmp(message + 1, "llegal move", 11) == 0 || + strncmp(message, "Error", 5) == 0) { + if (StrStr(message, "name") || + StrStr(message, "rating") || StrStr(message, "?") || + StrStr(message, "result") || StrStr(message, "board") || + StrStr(message, "bk") || StrStr(message, "computer") || + StrStr(message, "variant") || StrStr(message, "hint") || + StrStr(message, "random") || StrStr(message, "depth") || + StrStr(message, "accepted")) { + return; + } + if (StrStr(message, "protover")) { + /* Program is responding to input, so it's apparently done + initializing, and this error message indicates it is + protocol version 1. So we don't need to wait any longer + for it to initialize and send feature commands. */ + FeatureDone(cps, 1); + cps->protocolVersion = 1; + return; + } + cps->maybeThinking = FALSE; + + if (StrStr(message, "draw")) { + /* Program doesn't have "draw" command */ + cps->sendDrawOffers = 0; + return; + } + if (cps->sendTime != 1 && + (StrStr(message, "time") || StrStr(message, "otim"))) { + /* Program apparently doesn't have "time" or "otim" command */ + cps->sendTime = 0; + return; + } + if (StrStr(message, "analyze")) { + cps->analysisSupport = FALSE; + cps->analyzing = FALSE; + Reset(FALSE, TRUE); + sprintf(buf2, "%s does not support analysis", cps->tidy); + DisplayError(buf2, 0); + return; + } + if (StrStr(message, "st")) { + cps->stKludge = TRUE; + SendTimeControl(cps, movesPerSession, timeControl, + timeIncrement, appData.searchDepth, + searchTime); + return; + } + if (StrStr(message, "sd")) { + cps->sdKludge = TRUE; + SendTimeControl(cps, movesPerSession, timeControl, + timeIncrement, appData.searchDepth, + searchTime); + return; + } + if (!StrStr(message, "llegal")) return; + if (gameMode == BeginningOfGame || gameMode == EndOfGame || + gameMode == IcsIdle) return; + if (forwardMostMove <= backwardMostMove) return; + if (cps == &first && programStats.ok_to_send == 0) { + /* Bogus message from Crafty responding to "." This filtering + can miss some of the bad messages, but fortunately the bug + is fixed in current Crafty versions, so it doesn't matter. */ + return; + } + if (pausing) PauseEvent(); + if (gameMode == PlayFromGameFile) { + /* Stop reading this game file */ + gameMode = EditGame; + ModeHighlight(); + } + + + currentMove = --forwardMostMove; + DisplayMove(currentMove-1); /* before DisplayMoveError */ + SwitchClocks(); + DisplayBothClocks(); + sprintf(buf1, "Illegal move \"%s\" (rejected by %s chess program)", + parseList[currentMove], cps->which); + DisplayMoveError(buf1); + DrawPosition(FALSE, boards[currentMove]); + return; + } + if (strncmp(message, "time", 4) == 0 && StrStr(message, "Illegal")) { + /* Program has a broken "time" command that + outputs a string not ending in newline. + Don't use it. */ + cps->sendTime = 0; + } + + /* + * If chess program startup fails, exit with an error message. + * Attempts to recover here are futile. + */ + if ((StrStr(message, "unknown host") != NULL) + || (StrStr(message, "No remote directory") != NULL) + || (StrStr(message, "not found") != NULL) + || (StrStr(message, "No such file") != NULL) + || (StrStr(message, "can't alloc") != NULL) + || (StrStr(message, "Permission denied") != NULL)) { + + cps->maybeThinking = FALSE; + sprintf(buf1, "Failed to start %s chess program %s on %s: %s\n", + cps->which, cps->program, cps->host, message); + RemoveInputSource(cps->isr); + DisplayFatalError(buf1, 0, 1); + return; + } + + /* + * Look for hint output + */ + if (sscanf(message, "Hint: %s", buf1) == 1) { + switch (gameMode) { + case IcsPlayingWhite: + case IcsPlayingBlack: + case MachinePlaysWhite: + case MachinePlaysBlack: + strcpy(programStats.ponderMove, buf1); + break; + default: + programStats.ponderMove[0] = NULLCHAR; + break; + } + if (cps == &first && hintRequested) { + hintRequested = FALSE; + if (ParseOneMove(buf1, forwardMostMove, &moveType, + &fromX, &fromY, &toX, &toY, &promoChar)) { + (void) CoordsToAlgebraic(boards[forwardMostMove], + PosFlags(forwardMostMove), EP_UNKNOWN, + fromY, fromX, toY, toX, promoChar, buf1); + sprintf(buf2, "Hint: %s", buf1); + DisplayInformation(buf2); + } else { + /* Hint move could not be parsed!? */ + sprintf(buf2, + "Illegal hint move \"%s\"\nfrom %s chess program", + buf1, cps->which); + DisplayError(buf2, 0); + } + } else { + /* Copy ponder move */ + strcpy(lastHint, buf1); + } + return; + } + + /* + * Ignore other messages if game is not in progress + */ + if (gameMode == BeginningOfGame || gameMode == EndOfGame || + gameMode == IcsIdle || cps->lastPing != cps->lastPong) return; + + /* + * look for win, lose, draw, or draw offer + */ + if (strncmp(message, "1-0", 3) == 0) { + char *p, *q, *r = ""; + p = strchr(message, '{'); + if (p) { + q = strchr(p, '}'); + if (q) { + *q = NULLCHAR; + r = p + 1; + } + } + GameEnds(WhiteWins, r, GE_ENGINE); + return; + } else if (strncmp(message, "0-1", 3) == 0) { + char *p, *q, *r = ""; + p = strchr(message, '{'); + if (p) { + q = strchr(p, '}'); + if (q) { + *q = NULLCHAR; + r = p + 1; + } + } + /* Kludge for Arasan 4.1 bug */ + if (strcmp(r, "Black resigns") == 0) { + GameEnds(WhiteWins, r, GE_ENGINE); + return; + } + GameEnds(BlackWins, r, GE_ENGINE); + return; + } else if (strncmp(message, "1/2", 3) == 0) { + char *p, *q, *r = ""; + p = strchr(message, '{'); + if (p) { + q = strchr(p, '}'); + if (q) { + *q = NULLCHAR; + r = p + 1; + } + } + GameEnds(GameIsDrawn, r, GE_ENGINE); + return; + + } else if (strncmp(message, "White resign", 12) == 0) { + GameEnds(BlackWins, "White resigns", GE_ENGINE); + return; + } else if (strncmp(message, "Black resign", 12) == 0) { + GameEnds(WhiteWins, "Black resigns", GE_ENGINE); + return; + } else if (strncmp(message, "White", 5) == 0 && + message[5] != '(' && + StrStr(message, "Black") == NULL) { + GameEnds(WhiteWins, "White mates", GE_ENGINE); + return; + } else if (strncmp(message, "Black", 5) == 0 && + message[5] != '(') { + GameEnds(BlackWins, "Black mates", GE_ENGINE); + return; + } else if (strcmp(message, "resign") == 0 || + strcmp(message, "computer resigns") == 0) { + switch (gameMode) { + case MachinePlaysBlack: + case IcsPlayingBlack: + GameEnds(WhiteWins, "Black resigns", GE_ENGINE); + break; + case MachinePlaysWhite: + case IcsPlayingWhite: + GameEnds(BlackWins, "White resigns", GE_ENGINE); + break; + case TwoMachinesPlay: + if (cps->twoMachinesColor[0] == 'w') + GameEnds(BlackWins, "White resigns", GE_ENGINE); + else + GameEnds(WhiteWins, "Black resigns", GE_ENGINE); + break; + default: + /* can't happen */ + break; + } + return; + } else if (strncmp(message, "opponent mates", 14) == 0) { + switch (gameMode) { + case MachinePlaysBlack: + case IcsPlayingBlack: + GameEnds(WhiteWins, "White mates", GE_ENGINE); + break; + case MachinePlaysWhite: + case IcsPlayingWhite: + GameEnds(BlackWins, "Black mates", GE_ENGINE); + break; + case TwoMachinesPlay: + if (cps->twoMachinesColor[0] == 'w') + GameEnds(BlackWins, "Black mates", GE_ENGINE); + else + GameEnds(WhiteWins, "White mates", GE_ENGINE); + break; + default: + /* can't happen */ + break; + } + return; + } else if (strncmp(message, "computer mates", 14) == 0) { + switch (gameMode) { + case MachinePlaysBlack: + case IcsPlayingBlack: + GameEnds(BlackWins, "Black mates", GE_ENGINE); + break; + case MachinePlaysWhite: + case IcsPlayingWhite: + GameEnds(WhiteWins, "White mates", GE_ENGINE); + break; + case TwoMachinesPlay: + if (cps->twoMachinesColor[0] == 'w') + GameEnds(WhiteWins, "White mates", GE_ENGINE); + else + GameEnds(BlackWins, "Black mates", GE_ENGINE); + break; + default: + /* can't happen */ + break; + } + return; + } else if (strncmp(message, "checkmate", 9) == 0) { + if (WhiteOnMove(forwardMostMove)) { + GameEnds(BlackWins, "Black mates", GE_ENGINE); + } else { + GameEnds(WhiteWins, "White mates", GE_ENGINE); + } + return; + } else if (strstr(message, "Draw") != NULL || + strstr(message, "game is a draw") != NULL) { + GameEnds(GameIsDrawn, "Draw", GE_ENGINE); + return; + } else if (strstr(message, "offer") != NULL && + strstr(message, "draw") != NULL) { +#if ZIPPY + if (appData.zippyPlay && first.initDone) { + /* Relay offer to ICS */ + SendToICS(ics_prefix); + SendToICS("draw\n"); + } +#endif + cps->offeredDraw = 2; /* valid until this engine moves twice */ + if (gameMode == TwoMachinesPlay) { + if (cps->other->offeredDraw) { + GameEnds(GameIsDrawn, "Draw agreed", GE_XBOARD); + } else { + if (cps->other->sendDrawOffers) { + SendToProgram("draw\n", cps->other); + } + } + } else if (gameMode == MachinePlaysWhite || + gameMode == MachinePlaysBlack) { + if (userOfferedDraw) { + DisplayInformation("Machine accepts your draw offer"); + GameEnds(GameIsDrawn, "Draw agreed", GE_XBOARD); + } else { + DisplayInformation("Machine offers a draw\nSelect Action / Draw to agree"); + } + } + } + + + /* + * Look for thinking output + */ + /* Using icsAnalyze for future function */ + if (appData.showThinking || appData.icsAnalyze) { + int plylev, mvleft, mvtot, curscore, time; + char mvname[MOVE_LEN]; + unsigned long nodes; + char plyext; + int ignore = FALSE; + prefixHint = FALSE; + mvname[0] = NULLCHAR; + + /* reset thinkoutput */ + thinkOutput[0] = NULLCHAR; + + switch (gameMode) { + case MachinePlaysBlack: + case IcsPlayingBlack: + if (WhiteOnMove(forwardMostMove)) prefixHint = TRUE; + break; + case MachinePlaysWhite: + case IcsPlayingWhite: + if (!WhiteOnMove(forwardMostMove)) prefixHint = TRUE; + break; + case AnalyzeMode: + case AnalyzeFile: + break; + case IcsObserving: + ignore = FALSE; + break; + case TwoMachinesPlay: + if ((cps->twoMachinesColor[0] == 'w') != + WhiteOnMove(forwardMostMove)) { + ignore = TRUE; + } + break; + default: + ignore = TRUE; + break; + } + + if (!ignore) { + /* reset ponder move display */ + buf1[0] = NULLCHAR; + if (sscanf(message, "%d%c %d %d %lu %[^\n]\n", + &plylev, &plyext, &curscore, &time, &nodes, buf1) >= 5) { + + if (plyext != ' ' && plyext != '\t') { + time *= 100; + } + programStats.depth = plylev; + programStats.nodes = nodes; + programStats.time = time; + programStats.score = curscore; + programStats.got_only_move = 0; + + /* Buffer overflow protection */ + if (buf1[0] != NULLCHAR) { + if (strlen(buf1) >= MSG_SIZ) { + if (appData.debugMode) fprintf(debugFP, "PV is to long. I use the first %d bytes. \n", MSG_SIZ); + strncpy(programStats.movelist, buf1, MSG_SIZ); + } else { + strcpy(programStats.movelist, buf1); + } + } else { + sprintf(programStats.movelist, " no PV \n"); + if (appData.debugMode) fprintf(debugFP, "I found no PV \n"); + } + + if (programStats.seen_stat) { + programStats.ok_to_send = 1; + } + + if (strchr(programStats.movelist, '(') != NULL) { + programStats.line_is_book = 1; + programStats.nr_moves = 0; + programStats.moves_left = 0; + } else { + programStats.line_is_book = 0; + } + + sprintf(thinkOutput, "%d %c%+.2f %s%s%s", + plylev, + (gameMode == TwoMachinesPlay ? + ToUpper(cps->twoMachinesColor[0]) : ' '), + ((double) programStats.score) / 100.0, + prefixHint ? lastHint : "", + prefixHint ? " " : "", buf1); + /* Using icsAnalyze for future function */ + if (currentMove == forwardMostMove || gameMode==AnalyzeMode || + appData.icsAnalyzeWindow || appData.AnalysisWindow || + gameMode == AnalyzeFile) { + if (appData.icsAnalyzeWindow || + appData.AnalysisWindow) DisplayAnalysis(0,1); + DisplayMove(currentMove - 1); + } else { + if (appData.showThinking) DisplayMove(currentMove - 1); + } + return; + + } else if ((p=StrStr(message, "(only move)")) != NULL) { + /* crafty (9.25+) says "(only move) " + * if there is only 1 legal move + */ + sscanf(p, "(only move) %s", buf1); + sprintf(thinkOutput, "%s (only move)", buf1); + sprintf(programStats.movelist, "%s (only move)", buf1); + programStats.depth = 2; /* don't use 0 or 1 it's book depth */ + programStats.nr_moves = 1; + programStats.moves_left = 1; + programStats.nodes = 1; + programStats.time = 1; + programStats.got_only_move = 1; + + /* Not really, but we also use this member to + mean "line isn't going to change" (Crafty + isn't searching, so stats won't change) */ + programStats.line_is_book = 1; + if (currentMove == forwardMostMove || gameMode==AnalyzeMode || + appData.icsAnalyzeWindow || appData.AnalysisWindow || + gameMode == AnalyzeFile) { + if (appData.icsAnalyzeWindow || + appData.AnalysisWindow) DisplayAnalysis(0,1); + DisplayMove(currentMove - 1); + } else { + if (appData.showThinking) DisplayMove(currentMove - 1); + } + return; + + } else if (sscanf(message,"stat01: %d %lu %d %d %d %s", + &time, &nodes, &plylev, &mvleft, + &mvtot, mvname) >= 5) { + /* The stat01: line is from Crafty (9.29+) in response + to the "." command */ + programStats.seen_stat = 1; + /* for display engine room */ + supportStat = 1; + cps->maybeThinking = TRUE; + + if (programStats.got_only_move || !appData.periodicUpdates) return; + + programStats.depth = plylev; + programStats.time = time; + programStats.nodes = nodes; + programStats.moves_left = mvleft; + programStats.nr_moves = mvtot; + strcpy(programStats.move_name, mvname); + programStats.ok_to_send = 1; + if (appData.icsAnalyzeWindow || + appData.AnalysisWindow) DisplayAnalysis(0,0); + return; + + } else if (strncmp(message,"++",2) == 0) { + /* Crafty 9.29+ outputs this */ + programStats.got_fail = 2; + return; + + } else if (strncmp(message,"--",2) == 0) { + /* Crafty 9.29+ outputs this */ + programStats.got_fail = 1; + return; + + } else if (thinkOutput[0] != NULLCHAR && + strncmp(message, " ", 4) == 0) { + p = message; + while (*p && *p == ' ') p++; + strcat(thinkOutput, " "); + strcat(thinkOutput, p); + strcat(programStats.movelist, " "); + strcat(programStats.movelist, p); + + if (currentMove == forwardMostMove || gameMode==AnalyzeMode || + appData.icsAnalyzeWindow || appData.AnalysisWindow || + gameMode == AnalyzeFile) { + if (appData.icsAnalyzeWindow || + appData.AnalysisWindow) DisplayAnalysis(0,1); + DisplayMove(currentMove - 1); + } else { + if (appData.showThinking) DisplayMove(currentMove - 1); + } + return; + + } + } + } +} + + +/* Parse a game score from the character string "game", and + record it as the history of the current game. The game + score is NOT assumed to start from the standard position. + The display is not updated in any way. + */ +void +ParseGameHistory(game) + char *game; +{ + ChessMove moveType; + int fromX, fromY, toX, toY, boardIndex; + char promoChar; + char *p, *q; + char buf[MSG_SIZ]; + + if (appData.debugMode) + fprintf(debugFP, "Parsing game history: %s\n", game); + + if (gameInfo.event == NULL) gameInfo.event = StrSave("ICS game"); + gameInfo.site = StrSave(appData.icsHost); + gameInfo.date = PGNDate(); + gameInfo.round = StrSave("-"); + + /* Parse out names of players */ + while (*game == ' ') game++; + p = buf; + while (*game != ' ') *p++ = *game++; + *p = NULLCHAR; + gameInfo.white = StrSave(buf); + while (*game == ' ') game++; + p = buf; + while (*game != ' ' && *game != '\n') *p++ = *game++; + *p = NULLCHAR; + gameInfo.black = StrSave(buf); + + /* Parse moves */ + boardIndex = blackPlaysFirst ? 1 : 0; + yynewstr(game); + for (;;) { + yyboardindex = boardIndex; + moveType = (ChessMove) yylex(); + switch (moveType) { + case WhitePromotionQueen: + case BlackPromotionQueen: + case WhitePromotionRook: + case BlackPromotionRook: + case WhitePromotionBishop: + case BlackPromotionBishop: + case WhitePromotionKnight: + case BlackPromotionKnight: + case WhitePromotionKing: + case BlackPromotionKing: + case NormalMove: + case WhiteCapturesEnPassant: + case BlackCapturesEnPassant: + case WhiteKingSideCastle: + case WhiteQueenSideCastle: + case BlackKingSideCastle: + case BlackQueenSideCastle: + case WhiteKingSideCastleWild: + case WhiteQueenSideCastleWild: + case BlackKingSideCastleWild: + case BlackQueenSideCastleWild: + case IllegalMove: /* maybe suicide chess, etc. */ + fromX = currentMoveString[0] - 'a'; + fromY = currentMoveString[1] - '1'; + toX = currentMoveString[2] - 'a'; + toY = currentMoveString[3] - '1'; + promoChar = currentMoveString[4]; + break; + case WhiteDrop: + case BlackDrop: + fromX = moveType == WhiteDrop ? + (int) CharToPiece(ToUpper(currentMoveString[0])) : + (int) CharToPiece(ToLower(currentMoveString[0])); + fromY = DROP_RANK; + toX = currentMoveString[2] - 'a'; + toY = currentMoveString[3] - '1'; + promoChar = NULLCHAR; + break; + case AmbiguousMove: + /* bug? */ + sprintf(buf, "Ambiguous move in ICS output: \"%s\"", yy_text); + DisplayError(buf, 0); + return; + case ImpossibleMove: + /* bug? */ + sprintf(buf, "Illegal move in ICS output: \"%s\"", yy_text); + DisplayError(buf, 0); + return; + case (ChessMove) 0: /* end of file */ + if (boardIndex < backwardMostMove) { + /* Oops, gap. How did that happen? */ + DisplayError("Gap in move list", 0); + return; + } + backwardMostMove = blackPlaysFirst ? 1 : 0; + if (boardIndex > forwardMostMove) { + forwardMostMove = boardIndex; + } + return; + case ElapsedTime: + if (boardIndex > 0) { + strcat(parseList[boardIndex-1], " "); + strcat(parseList[boardIndex-1], yy_text); + } + continue; + case Comment: + case PGNTag: + case NAG: + default: + /* ignore */ + continue; + case WhiteWins: + case BlackWins: + case GameIsDrawn: + case GameUnfinished: + if (gameMode == IcsExamining) { + if (boardIndex < backwardMostMove) { + /* Oops, gap. How did that happen? */ + return; + } + backwardMostMove = blackPlaysFirst ? 1 : 0; + return; + } + gameInfo.result = moveType; + p = strchr(yy_text, '{'); + if (p == NULL) p = strchr(yy_text, '('); + if (p == NULL) { + p = yy_text; + if (p[0] == '0' || p[0] == '1' || p[0] == '*') p = ""; + } else { + q = strchr(p, *p == '{' ? '}' : ')'); + if (q != NULL) *q = NULLCHAR; + p++; + } + gameInfo.resultDetails = StrSave(p); + continue; + } + if (boardIndex >= forwardMostMove && + !(gameMode == IcsObserving && ics_gamenum == -1)) { + backwardMostMove = blackPlaysFirst ? 1 : 0; + return; + } + (void) CoordsToAlgebraic(boards[boardIndex], PosFlags(boardIndex), + EP_UNKNOWN, fromY, fromX, toY, toX, promoChar, + parseList[boardIndex]); + CopyBoard(boards[boardIndex + 1], boards[boardIndex]); + /* currentMoveString is set as a side-effect of yylex */ + strcpy(moveList[boardIndex], currentMoveString); + strcat(moveList[boardIndex], "\n"); + boardIndex++; + ApplyMove(fromX, fromY, toX, toY, promoChar, boards[boardIndex]); + switch (MateTest(boards[boardIndex], + PosFlags(boardIndex), EP_UNKNOWN)) { + case MT_NONE: + case MT_STALEMATE: + default: + break; + case MT_CHECK: + strcat(parseList[boardIndex - 1], "+"); + break; + case MT_CHECKMATE: + strcat(parseList[boardIndex - 1], "#"); + break; + } + } +} + + +/* Apply a move to the given board */ +void +ApplyMove(fromX, fromY, toX, toY, promoChar, board) + int fromX, fromY, toX, toY; + int promoChar; + Board board; +{ + ChessSquare captured = board[toY][toX]; + if (fromY == DROP_RANK) { + /* must be first */ + board[toY][toX] = (ChessSquare) fromX; + } else if (fromX == toX && fromY == toY) { + return; + } else if (fromY == 0 && fromX == 4 + && board[fromY][fromX] == WhiteKing + && toY == 0 && toX == 6) { + board[fromY][fromX] = EmptySquare; + board[toY][toX] = WhiteKing; + board[fromY][7] = EmptySquare; + board[toY][5] = WhiteRook; + } else if (fromY == 0 && fromX == 4 + && board[fromY][fromX] == WhiteKing + && toY == 0 && toX == 2) { + board[fromY][fromX] = EmptySquare; + board[toY][toX] = WhiteKing; + board[fromY][0] = EmptySquare; + board[toY][3] = WhiteRook; + } else if (fromY == 0 && fromX == 3 + && board[fromY][fromX] == WhiteKing + && toY == 0 && toX == 5) { + board[fromY][fromX] = EmptySquare; + board[toY][toX] = WhiteKing; + board[fromY][7] = EmptySquare; + board[toY][4] = WhiteRook; + } else if (fromY == 0 && fromX == 3 + && board[fromY][fromX] == WhiteKing + && toY == 0 && toX == 1) { + board[fromY][fromX] = EmptySquare; + board[toY][toX] = WhiteKing; + board[fromY][0] = EmptySquare; + board[toY][2] = WhiteRook; + } else if (board[fromY][fromX] == WhitePawn + && toY == 7) { + /* white pawn promotion */ + board[7][toX] = CharToPiece(ToUpper(promoChar)); + if (board[7][toX] == EmptySquare) { + board[7][toX] = WhiteQueen; + } + board[fromY][fromX] = EmptySquare; + } else if ((fromY == 4) + && (toX != fromX) + && (board[fromY][fromX] == WhitePawn) + && (board[toY][toX] == EmptySquare)) { + board[fromY][fromX] = EmptySquare; + board[toY][toX] = WhitePawn; + captured = board[toY - 1][toX]; + board[toY - 1][toX] = EmptySquare; + } else if (fromY == 7 && fromX == 4 + && board[fromY][fromX] == BlackKing + && toY == 7 && toX == 6) { + board[fromY][fromX] = EmptySquare; + board[toY][toX] = BlackKing; + board[fromY][7] = EmptySquare; + board[toY][5] = BlackRook; + } else if (fromY == 7 && fromX == 4 + && board[fromY][fromX] == BlackKing + && toY == 7 && toX == 2) { + board[fromY][fromX] = EmptySquare; + board[toY][toX] = BlackKing; + board[fromY][0] = EmptySquare; + board[toY][3] = BlackRook; + } else if (fromY == 7 && fromX == 3 + && board[fromY][fromX] == BlackKing + && toY == 7 && toX == 5) { + board[fromY][fromX] = EmptySquare; + board[toY][toX] = BlackKing; + board[fromY][7] = EmptySquare; + board[toY][4] = BlackRook; + } else if (fromY == 7 && fromX == 3 + && board[fromY][fromX] == BlackKing + && toY == 7 && toX == 1) { + board[fromY][fromX] = EmptySquare; + board[toY][toX] = BlackKing; + board[fromY][0] = EmptySquare; + board[toY][2] = BlackRook; + } else if (board[fromY][fromX] == BlackPawn + && toY == 0) { + /* black pawn promotion */ + board[0][toX] = CharToPiece(ToLower(promoChar)); + if (board[0][toX] == EmptySquare) { + board[0][toX] = BlackQueen; + } + board[fromY][fromX] = EmptySquare; + } else if ((fromY == 3) + && (toX != fromX) + && (board[fromY][fromX] == BlackPawn) + && (board[toY][toX] == EmptySquare)) { + board[fromY][fromX] = EmptySquare; + board[toY][toX] = BlackPawn; + captured = board[toY + 1][toX]; + board[toY + 1][toX] = EmptySquare; + } else { + board[toY][toX] = board[fromY][fromX]; + board[fromY][fromX] = EmptySquare; + } + if (gameInfo.variant == VariantCrazyhouse) { +#if 0 + /* !!A lot more code needs to be written to support holdings */ + if (fromY == DROP_RANK) { + /* Delete from holdings */ + if (holdings[(int) fromX] > 0) holdings[(int) fromX]--; + } + if (captured != EmptySquare) { + /* Add to holdings */ + if (captured < BlackPawn) { + holdings[(int)captured - (int)BlackPawn + (int)WhitePawn]++; + } else { + holdings[(int)captured - (int)WhitePawn + (int)BlackPawn]++; + } + } +#endif + } else if (gameInfo.variant == VariantAtomic) { + if (captured != EmptySquare) { + int y, x; + for (y = toY-1; y <= toY+1; y++) { + for (x = toX-1; x <= toX+1; x++) { + if (y >= 0 && y <= 7 && x >= 0 && x <= 7 && + board[y][x] != WhitePawn && board[y][x] != BlackPawn) { + board[y][x] = EmptySquare; + } + } + } + board[toY][toX] = EmptySquare; + } + } +} + +/* Updates forwardMostMove */ +void +MakeMove(fromX, fromY, toX, toY, promoChar) + int fromX, fromY, toX, toY; + int promoChar; +{ + forwardMostMove++; + if (forwardMostMove >= MAX_MOVES) { + DisplayFatalError("Game too long; increase MAX_MOVES and recompile", + 0, 1); + return; + } + SwitchClocks(); + timeRemaining[0][forwardMostMove] = whiteTimeRemaining; + timeRemaining[1][forwardMostMove] = blackTimeRemaining; + if (commentList[forwardMostMove] != NULL) { + free(commentList[forwardMostMove]); + commentList[forwardMostMove] = NULL; + } + CopyBoard(boards[forwardMostMove], boards[forwardMostMove - 1]); + ApplyMove(fromX, fromY, toX, toY, promoChar, boards[forwardMostMove]); + gameInfo.result = GameUnfinished; + if (gameInfo.resultDetails != NULL) { + free(gameInfo.resultDetails); + gameInfo.resultDetails = NULL; + } + CoordsToComputerAlgebraic(fromY, fromX, toY, toX, promoChar, + moveList[forwardMostMove - 1]); + (void) CoordsToAlgebraic(boards[forwardMostMove - 1], + PosFlags(forwardMostMove - 1), EP_UNKNOWN, + fromY, fromX, toY, toX, promoChar, + parseList[forwardMostMove - 1]); + switch (MateTest(boards[forwardMostMove], + PosFlags(forwardMostMove), EP_UNKNOWN)){ + case MT_NONE: + case MT_STALEMATE: + default: + break; + case MT_CHECK: + strcat(parseList[forwardMostMove - 1], "+"); + break; + case MT_CHECKMATE: + strcat(parseList[forwardMostMove - 1], "#"); + break; + } +} + +/* Updates currentMove if not pausing */ +void +ShowMove(fromX, fromY, toX, toY) +{ + int instant = (gameMode == PlayFromGameFile) ? + (matchMode || (appData.timeDelay == 0 && !pausing)) : pausing; + if (!pausing || gameMode == PlayFromGameFile || gameMode == AnalyzeFile) { + if (!instant) { + if (forwardMostMove == currentMove + 1) { + AnimateMove(boards[forwardMostMove - 1], + fromX, fromY, toX, toY); + } + if (appData.highlightLastMove) { + SetHighlights(fromX, fromY, toX, toY); + } + } + currentMove = forwardMostMove; + } + + if (instant) return; + DisplayMove(currentMove - 1); + DrawPosition(FALSE, boards[currentMove]); + DisplayBothClocks(); + HistorySet(parseList,backwardMostMove,forwardMostMove,currentMove-1); +} + + +void +InitChessProgram(cps) + ChessProgramState *cps; +{ + char buf[MSG_SIZ]; + if (appData.noChessProgram) return; + hintRequested = FALSE; + bookRequested = FALSE; + SendToProgram(cps->initString, cps); + if (gameInfo.variant != VariantNormal && + gameInfo.variant != VariantLoadable) { + char *v = VariantName(gameInfo.variant); + if (StrStr(cps->variants, v) == NULL) { + sprintf(buf, "Variant %s not supported by %s", v, cps->tidy); + DisplayFatalError(buf, 0, 1); + return; + } + sprintf(buf, "variant %s\n", VariantName(gameInfo.variant)); + SendToProgram(buf, cps); + } + if (cps->sendICS) { + sprintf(buf, "ics %s\n", appData.icsActive ? appData.icsHost : "-"); + SendToProgram(buf, cps); + } + cps->maybeThinking = FALSE; + cps->offeredDraw = 0; + if (!appData.icsActive) { + SendTimeControl(cps, movesPerSession, timeControl, + timeIncrement, appData.searchDepth, + searchTime); + } + if (appData.showThinking) { + SendToProgram("post\n", cps); + } + SendToProgram("hard\n", cps); + if (!appData.ponderNextMove) { + /* Warning: "easy" is a toggle in GNU Chess, so don't send + it without being sure what state we are in first. "hard" + is not a toggle, so that one is OK. + */ + SendToProgram("easy\n", cps); + } + if (cps->usePing) { + sprintf(buf, "ping %d\n", ++cps->lastPing); + SendToProgram(buf, cps); + } + cps->initDone = TRUE; +} + + +void +StartChessProgram(cps) + ChessProgramState *cps; +{ + char buf[MSG_SIZ]; + int err; + + if (appData.noChessProgram) return; + cps->initDone = FALSE; + + if (strcmp(cps->host, "localhost") == 0) { + err = StartChildProcess(cps->program, cps->dir, &cps->pr); + } else if (*appData.remoteShell == NULLCHAR) { + err = OpenRcmd(cps->host, appData.remoteUser, cps->program, &cps->pr); + } else { + if (*appData.remoteUser == NULLCHAR) { + sprintf(buf, "%s %s %s", appData.remoteShell, cps->host, + cps->program); + } else { + sprintf(buf, "%s %s -l %s %s", appData.remoteShell, + cps->host, appData.remoteUser, cps->program); + } + err = StartChildProcess(buf, "", &cps->pr); + } + + if (err != 0) { + sprintf(buf, "Startup failure on '%s'", cps->program); + DisplayFatalError(buf, err, 1); + cps->pr = NoProc; + cps->isr = NULL; + return; + } + + cps->isr = AddInputSource(cps->pr, TRUE, ReceiveFromProgram, cps); + if (cps->protocolVersion > 1) { + sprintf(buf, "xboard\nprotover %d\n", cps->protocolVersion); + SendToProgram(buf, cps); + } else { + SendToProgram("xboard\n", cps); + } +} + + +void +TwoMachinesEventIfReady P((void)) +{ + if (first.lastPing != first.lastPong) { + DisplayMessage("", "Waiting for first chess program"); + ScheduleDelayedEvent(TwoMachinesEventIfReady, 1000); + return; + } + if (second.lastPing != second.lastPong) { + DisplayMessage("", "Waiting for second chess program"); + ScheduleDelayedEvent(TwoMachinesEventIfReady, 1000); + return; + } + ThawUI(); + TwoMachinesEvent(); +} + +void +NextMatchGame P((void)) +{ + Reset(FALSE, TRUE); + if (*appData.loadGameFile != NULLCHAR) { + LoadGameFromFile(appData.loadGameFile, + appData.loadGameIndex, + appData.loadGameFile, FALSE); + } else if (*appData.loadPositionFile != NULLCHAR) { + LoadPositionFromFile(appData.loadPositionFile, + appData.loadPositionIndex, + appData.loadPositionFile); + } + TwoMachinesEventIfReady(); +} + +void +GameEnds(result, resultDetails, whosays) + ChessMove result; + char *resultDetails; + int whosays; +{ + GameMode nextGameMode; + int isIcsGame; + + if (appData.debugMode) { + fprintf(debugFP, "GameEnds(%d, %s, %d)\n", + result, resultDetails ? resultDetails : "(null)", whosays); + } + + if (appData.icsAnalyze && gameMode == IcsObserving) ResetIcsQueue(ics_gamenum); + + if (appData.icsActive && whosays == GE_ENGINE) { + /* If we are playing on ICS, the server decides when the + game is over, but the engine can offer to draw, claim + a draw, or resign. + */ +#if ZIPPY + if (appData.zippyPlay && first.initDone) { + if (result == GameIsDrawn) { + /* In case draw still needs to be claimed */ + SendToICS(ics_prefix); + SendToICS("draw\n"); + } else if (StrCaseStr(resultDetails, "resign")) { + SendToICS(ics_prefix); + SendToICS("resign\n"); + } + } +#endif + return; + } + + /* If we're loading the game from a file, stop */ + if (whosays == GE_FILE) { + (void) StopLoadGameTimer(); + gameFileFP = NULL; + } + + /* Cancel draw offers */ + first.offeredDraw = second.offeredDraw = 0; + + /* If this is an ICS game, only ICS can really say it's done; + if not, anyone can. */ + isIcsGame = (gameMode == IcsPlayingWhite || + gameMode == IcsPlayingBlack || + gameMode == IcsObserving || + gameMode == IcsExamining); + + if (!isIcsGame || whosays == GE_ICS) { + /* OK -- not an ICS game, or ICS said it was done */ + StopClocks(); + if (!isIcsGame && !appData.noChessProgram) + SetUserThinkingEnables(); + + if (resultDetails != NULL) { + gameInfo.result = result; + gameInfo.resultDetails = StrSave(resultDetails); + + /* Tell program how game ended in case it is learning */ + if (gameMode == MachinePlaysWhite || + gameMode == MachinePlaysBlack || + gameMode == TwoMachinesPlay || + gameMode == IcsPlayingWhite || + gameMode == IcsPlayingBlack || + gameMode == BeginningOfGame) { + char buf[MSG_SIZ]; + sprintf(buf, "result %s {%s}\n", PGNResult(result), + resultDetails); + if (first.pr != NoProc) { + SendToProgram(buf, &first); + } + if (second.pr != NoProc && + gameMode == TwoMachinesPlay) { + SendToProgram(buf, &second); + } + } + + /* display last move only if game was not loaded from file */ + if ((whosays != GE_FILE) && (currentMove == forwardMostMove)) + DisplayMove(currentMove - 1); + + if (forwardMostMove != 0) { + if (gameMode != PlayFromGameFile && gameMode != EditGame) { + if (*appData.saveGameFile != NULLCHAR) { + SaveGameToFile(appData.saveGameFile, TRUE); + } else if (appData.autoSaveGames) { + AutoSaveGame(); + } + if (*appData.savePositionFile != NULLCHAR) { + SavePositionToFile(appData.savePositionFile); + } + } + } + } + + if (appData.icsActive) { + if (appData.quietPlay && + (gameMode == IcsPlayingWhite || + gameMode == IcsPlayingBlack)) { + SendToICS(ics_prefix); + SendToICS("set shout 1\n"); + } + nextGameMode = IcsIdle; + ics_user_moved = FALSE; + /* clean up premove. It's ugly when the game has ended and the + * premove highlights are still on the board. + */ + if (gotPremove) { + gotPremove = FALSE; + ClearPremoveHighlights(); + DrawPosition(FALSE, boards[currentMove]); + } + if (whosays == GE_ICS) { + switch (result) { + case WhiteWins: + if (gameMode == IcsPlayingWhite) + PlayIcsWinSound(); + else if(gameMode == IcsPlayingBlack) + PlayIcsLossSound(); + break; + case BlackWins: + if (gameMode == IcsPlayingBlack) + PlayIcsWinSound(); + else if(gameMode == IcsPlayingWhite) + PlayIcsLossSound(); + break; + case GameIsDrawn: + PlayIcsDrawSound(); + break; + default: + PlayIcsUnfinishedSound(); + } + } + } else if (gameMode == EditGame || + gameMode == PlayFromGameFile || + gameMode == AnalyzeMode || + gameMode == AnalyzeFile) { + nextGameMode = gameMode; + } else { + nextGameMode = EndOfGame; + } + pausing = FALSE; + ModeHighlight(); + } else { + nextGameMode = gameMode; + } + + if (appData.noChessProgram) { + gameMode = nextGameMode; + ModeHighlight(); + return; + } + + if (first.reuse) { + /* Put first chess program into idle state */ + if (first.pr != NoProc && + (gameMode == MachinePlaysWhite || + gameMode == MachinePlaysBlack || + gameMode == TwoMachinesPlay || + gameMode == IcsPlayingWhite || + gameMode == IcsPlayingBlack || + gameMode == BeginningOfGame)) { + SendToProgram("force\n", &first); + if (first.usePing) { + char buf[MSG_SIZ]; + sprintf(buf, "ping %d\n", ++first.lastPing); + SendToProgram(buf, &first); + } + } + } else if (result != GameUnfinished || nextGameMode == IcsIdle) { + /* Kill off first chess program */ + if (first.isr != NULL) + RemoveInputSource(first.isr); + first.isr = NULL; + + if (first.pr != NoProc) { + ExitAnalyzeMode(); + SendToProgram("quit\n", &first); + DestroyChildProcess(first.pr, first.useSigterm); + } + first.pr = NoProc; + } + if (second.reuse) { + /* Put second chess program into idle state */ + if (second.pr != NoProc && + gameMode == TwoMachinesPlay) { + SendToProgram("force\n", &second); + if (second.usePing) { + char buf[MSG_SIZ]; + sprintf(buf, "ping %d\n", ++second.lastPing); + SendToProgram(buf, &second); + } + } + } else if (result != GameUnfinished || nextGameMode == IcsIdle) { + /* Kill off second chess program */ + if (second.isr != NULL) + RemoveInputSource(second.isr); + second.isr = NULL; + + if (second.pr != NoProc) { + SendToProgram("quit\n", &second); + DestroyChildProcess(second.pr, second.useSigterm); + } + second.pr = NoProc; + } + + if (matchMode && gameMode == TwoMachinesPlay) { + switch (result) { + case WhiteWins: + if (first.twoMachinesColor[0] == 'w') { + first.matchWins++; + } else { + second.matchWins++; + } + break; + case BlackWins: + if (first.twoMachinesColor[0] == 'b') { + first.matchWins++; + } else { + second.matchWins++; + } + break; + default: + break; + } + if (matchGame < appData.matchGames) { + char *tmp; + tmp = first.twoMachinesColor; + first.twoMachinesColor = second.twoMachinesColor; + second.twoMachinesColor = tmp; + gameMode = nextGameMode; + matchGame++; + ScheduleDelayedEvent(NextMatchGame, 10000); + return; + } else { + char buf[MSG_SIZ]; + gameMode = nextGameMode; + sprintf(buf, "Match %s vs. %s: final score %d-%d-%d", + first.tidy, second.tidy, + first.matchWins, second.matchWins, + appData.matchGames - (first.matchWins + second.matchWins)); + DisplayFatalError(buf, 0, 0); + } + } + if ((gameMode == AnalyzeMode || gameMode == AnalyzeFile) && + !(nextGameMode == AnalyzeMode || nextGameMode == AnalyzeFile)) + ExitAnalyzeMode(); + gameMode = nextGameMode; + ModeHighlight(); +} + +/* Assumes program was just initialized (initString sent). + Leaves program in force mode. */ +void +FeedMovesToProgram(cps, upto) + ChessProgramState *cps; + int upto; + +{ + int i; + if (appData.debugMode) + fprintf(debugFP, "Feeding %smoves %d through %d to %s chess program\n", + startedFromSetupPosition ? "position and " : "", + backwardMostMove, upto, cps->which); + /* daniel */ + if(!appData.icsAnalyze) SendToProgram("force\n", cps); + if (startedFromSetupPosition) { + SendBoard(cps, backwardMostMove); + } + for (i = backwardMostMove; i < upto; i++) { + + SendMoveToProgram(i, cps); + } +} + + +void +ResurrectChessProgram() +{ + /* The chess program may have exited. + If so, restart it and feed it all the moves made so far. */ + + if (appData.noChessProgram || first.pr != NoProc) return; + + StartChessProgram(&first); + InitChessProgram(&first); + FeedMovesToProgram(&first, currentMove); + + if (!first.sendTime) { + /* can't tell gnuchess what its clock should read, + so we bow to its notion. */ + ResetClocks(); + timeRemaining[0][currentMove] = whiteTimeRemaining; + timeRemaining[1][currentMove] = blackTimeRemaining; + } + + if ((gameMode == AnalyzeMode || gameMode == AnalyzeFile) && + first.analysisSupport) { + SendToProgram("analyze\n", &first); + first.analyzing = TRUE; + } +} + +/* + * Button procedures + */ +void +Reset(redraw, init) + int redraw, init; +{ + int i; + + if (appData.debugMode) { + fprintf(debugFP, "Reset(%d, %d) from gameMode %d\n", + redraw, init, gameMode); + } + + /* reset send engine output to ics */ + appData.SendOutPutToICS = 1; + + pausing = pauseExamInvalid = FALSE; + startedFromSetupPosition = blackPlaysFirst = FALSE; + firstMove = TRUE; + whiteFlag = blackFlag = FALSE; + userOfferedDraw = FALSE; + hintRequested = bookRequested = FALSE; + first.maybeThinking = FALSE; + second.maybeThinking = FALSE; + thinkOutput[0] = NULLCHAR; + lastHint[0] = NULLCHAR; + ClearGameInfo(&gameInfo); + gameInfo.variant = StringToVariant(appData.variant); + ics_user_moved = ics_clock_paused = FALSE; + ics_getting_history = H_FALSE; + ics_gamenum = -1; + white_holding[0] = black_holding[0] = NULLCHAR; + ClearProgramStats(); + + ResetFrontEnd(); + ClearHighlights(); + flipView = appData.flipView; + ClearPremoveHighlights(); + gotPremove = FALSE; + alarmSounded = FALSE; + + GameEnds((ChessMove) 0, NULL, GE_PLAYER); + ExitAnalyzeMode(); + gameMode = BeginningOfGame; + ModeHighlight(); + InitPosition(redraw); + for (i = 0; i < MAX_MOVES; i++) { + if (commentList[i] != NULL) { + free(commentList[i]); + commentList[i] = NULL; + } + } + ResetClocks(); + timeRemaining[0][0] = whiteTimeRemaining; + timeRemaining[1][0] = blackTimeRemaining; + if (first.pr == NULL) { + StartChessProgram(&first); + } + if (init) InitChessProgram(&first); + DisplayTitle(""); + DisplayMessage("", ""); + HistorySet(parseList, backwardMostMove, forwardMostMove, currentMove-1); +} + +void +AutoPlayGameLoop() +{ + for (;;) { + if (!AutoPlayOneMove()) + return; + if (matchMode || appData.timeDelay == 0) + continue; + if (appData.timeDelay < 0 || gameMode == AnalyzeFile) + return; + StartLoadGameTimer((long)(1000.0 * appData.timeDelay)); + break; + } +} + + +int +AutoPlayOneMove() +{ + int fromX, fromY, toX, toY; + + if (appData.debugMode) { + fprintf(debugFP, "AutoPlayOneMove(): current %d\n", currentMove); + } + + if (gameMode != PlayFromGameFile) + return FALSE; + + if (currentMove >= forwardMostMove) { + gameMode = EditGame; + ModeHighlight(); + return FALSE; + } + + toX = moveList[currentMove][2] - 'a'; + toY = moveList[currentMove][3] - '1'; + + if (moveList[currentMove][1] == '@') { + if (appData.highlightLastMove) { + SetHighlights(-1, -1, toX, toY); + } + } else { + fromX = moveList[currentMove][0] - 'a'; + fromY = moveList[currentMove][1] - '1'; + AnimateMove(boards[currentMove], fromX, fromY, toX, toY); + + if (appData.highlightLastMove) { + SetHighlights(fromX, fromY, toX, toY); + } + } + DisplayMove(currentMove); + SendMoveToProgram(currentMove++, &first); + DisplayBothClocks(); + DrawPosition(FALSE, boards[currentMove]); + if (commentList[currentMove] != NULL) { + DisplayComment(currentMove - 1, commentList[currentMove]); + } + return TRUE; +} + + +int +LoadGameOneMove(readAhead) + ChessMove readAhead; +{ + int fromX = 0, fromY = 0, toX = 0, toY = 0, done; + char promoChar = NULLCHAR; + ChessMove moveType; + char move[MSG_SIZ]; + char *p, *q; + + if (gameMode != PlayFromGameFile && gameMode != AnalyzeFile && + gameMode != AnalyzeMode && gameMode != Training) { + gameFileFP = NULL; + return FALSE; + } + + yyboardindex = forwardMostMove; + if (readAhead != (ChessMove)0) { + moveType = readAhead; + } else { + if (gameFileFP == NULL) + return FALSE; + moveType = (ChessMove) yylex(); + } + + done = FALSE; + switch (moveType) { + case Comment: + if (appData.debugMode) + fprintf(debugFP, "Parsed Comment: %s\n", yy_text); + p = yy_text; + if (*p == '{' || *p == '[' || *p == '(') { + p[strlen(p) - 1] = NULLCHAR; + p++; + } + + /* append the comment but don't display it */ + while (*p == '\n') p++; + AppendComment(currentMove, p); + return TRUE; + + case WhiteCapturesEnPassant: + case BlackCapturesEnPassant: + case WhitePromotionQueen: + case BlackPromotionQueen: + case WhitePromotionRook: + case BlackPromotionRook: + case WhitePromotionBishop: + case BlackPromotionBishop: + case WhitePromotionKnight: + case BlackPromotionKnight: + case WhitePromotionKing: + case BlackPromotionKing: + case NormalMove: + case WhiteKingSideCastle: + case WhiteQueenSideCastle: + case BlackKingSideCastle: + case BlackQueenSideCastle: + case WhiteKingSideCastleWild: + case WhiteQueenSideCastleWild: + case BlackKingSideCastleWild: + case BlackQueenSideCastleWild: + if (appData.debugMode) + fprintf(debugFP, "Parsed %s into %s\n", yy_text, currentMoveString); + fromX = currentMoveString[0] - 'a'; + fromY = currentMoveString[1] - '1'; + toX = currentMoveString[2] - 'a'; + toY = currentMoveString[3] - '1'; + promoChar = currentMoveString[4]; + break; + + case WhiteDrop: + case BlackDrop: + if (appData.debugMode) + fprintf(debugFP, "Parsed %s into %s\n", yy_text, currentMoveString); + fromX = moveType == WhiteDrop ? + (int) CharToPiece(ToUpper(currentMoveString[0])) : + (int) CharToPiece(ToLower(currentMoveString[0])); + fromY = DROP_RANK; + toX = currentMoveString[2] - 'a'; + toY = currentMoveString[3] - '1'; + break; + + case WhiteWins: + case BlackWins: + case GameIsDrawn: + case GameUnfinished: + if (appData.debugMode) + fprintf(debugFP, "Parsed game end: %s\n", yy_text); + p = strchr(yy_text, '{'); + if (p == NULL) p = strchr(yy_text, '('); + if (p == NULL) { + p = yy_text; + if (p[0] == '0' || p[0] == '1' || p[0] == '*') p = ""; + } else { + q = strchr(p, *p == '{' ? '}' : ')'); + if (q != NULL) *q = NULLCHAR; + p++; + } + GameEnds(moveType, p, GE_FILE); + done = TRUE; + if (cmailMsgLoaded) { + ClearHighlights(); + flipView = WhiteOnMove(currentMove); + if (moveType == GameUnfinished) flipView = !flipView; + if (appData.debugMode) + fprintf(debugFP, "Setting flipView to %d\n", flipView) ; + } + break; + + case (ChessMove) 0: /* end of file */ + if (appData.debugMode) + fprintf(debugFP, "Parser hit end of file\n"); + switch (MateTest(boards[currentMove], PosFlags(currentMove), + EP_UNKNOWN)) { + case MT_NONE: + case MT_CHECK: + break; + case MT_CHECKMATE: + if (WhiteOnMove(currentMove)) { + GameEnds(BlackWins, "Black mates", GE_FILE); + } else { + GameEnds(WhiteWins, "White mates", GE_FILE); + } + break; + case MT_STALEMATE: + GameEnds(GameIsDrawn, "Stalemate", GE_FILE); + break; + } + done = TRUE; + break; + + case MoveNumberOne: + if (lastLoadGameStart == GNUChessGame) { + /* GNUChessGames have numbers, but they aren't move numbers */ + if (appData.debugMode) + fprintf(debugFP, "Parser ignoring: '%s' (%d)\n", + yy_text, (int) moveType); + return LoadGameOneMove((ChessMove)0); /* tail recursion */ + } + /* else fall thru */ + + case XBoardGame: + case GNUChessGame: + case PGNTag: + /* Reached start of next game in file */ + if (appData.debugMode) + fprintf(debugFP, "Parsed start of next game: %s\n", yy_text); + switch (MateTest(boards[currentMove], PosFlags(currentMove), + EP_UNKNOWN)) { + case MT_NONE: + case MT_CHECK: + break; + case MT_CHECKMATE: + if (WhiteOnMove(currentMove)) { + GameEnds(BlackWins, "Black mates", GE_FILE); + } else { + GameEnds(WhiteWins, "White mates", GE_FILE); + } + break; + case MT_STALEMATE: + GameEnds(GameIsDrawn, "Stalemate", GE_FILE); + break; + } + done = TRUE; + break; + + case PositionDiagram: /* should not happen; ignore */ + case ElapsedTime: /* ignore */ + case NAG: /* ignore */ + if (appData.debugMode) + fprintf(debugFP, "Parser ignoring: '%s' (%d)\n", + yy_text, (int) moveType); + return LoadGameOneMove((ChessMove)0); /* tail recursion */ + + case IllegalMove: + if (appData.testLegality) { + if (appData.debugMode) + fprintf(debugFP, "Parsed IllegalMove: %s\n", yy_text); + sprintf(move, "Illegal move: %d.%s%s", + (forwardMostMove / 2) + 1, + WhiteOnMove(forwardMostMove) ? " " : ".. ", yy_text); + DisplayError(move, 0); + done = TRUE; + } else { + if (appData.debugMode) + fprintf(debugFP, "Parsed %s into IllegalMove %s\n", + yy_text, currentMoveString); + fromX = currentMoveString[0] - 'a'; + fromY = currentMoveString[1] - '1'; + toX = currentMoveString[2] - 'a'; + toY = currentMoveString[3] - '1'; + promoChar = currentMoveString[4]; + } + break; + + case AmbiguousMove: + if (appData.debugMode) + fprintf(debugFP, "Parsed AmbiguousMove: %s\n", yy_text); + sprintf(move, "Ambiguous move: %d.%s%s", + (forwardMostMove / 2) + 1, + WhiteOnMove(forwardMostMove) ? " " : ".. ", yy_text); + DisplayError(move, 0); + done = TRUE; + break; + + default: + case ImpossibleMove: + if (appData.debugMode) + fprintf(debugFP, "Parsed ImpossibleMove: %s\n", yy_text); + sprintf(move, "Illegal move: %d.%s%s", + (forwardMostMove / 2) + 1, + WhiteOnMove(forwardMostMove) ? " " : ".. ", yy_text); + DisplayError(move, 0); + done = TRUE; + break; + } + + if (done) { + if (appData.matchMode || (appData.timeDelay == 0 && !pausing)) { + DrawPosition(FALSE, boards[currentMove]); + DisplayBothClocks(); + if (!appData.matchMode && commentList[currentMove] != NULL) + DisplayComment(currentMove - 1, commentList[currentMove]); + } + (void) StopLoadGameTimer(); + gameFileFP = NULL; + cmailOldMove = forwardMostMove; + return FALSE; + } else { + /* currentMoveString is set as a side-effect of yylex */ + strcat(currentMoveString, "\n"); + strcpy(moveList[forwardMostMove], currentMoveString); + + thinkOutput[0] = NULLCHAR; + MakeMove(fromX, fromY, toX, toY, promoChar); + currentMove = forwardMostMove; + return TRUE; + } +} + +/* Load the nth game from the given file */ +int +LoadGameFromFile(filename, n, title, useList) + char *filename; + int n; + char *title; + /*Boolean*/ int useList; +{ + FILE *f; + char buf[MSG_SIZ]; + + if (strcmp(filename, "-") == 0) { + f = stdin; + title = "stdin"; + } else { + f = fopen(filename, "rb"); + if (f == NULL) { + sprintf(buf, "Can't open \"%s\"", filename); + DisplayError(buf, errno); + return FALSE; + } + } + if (fseek(f, 0, 0) == -1) { + /* f is not seekable; probably a pipe */ + useList = FALSE; + } + if (useList && n == 0) { + int error = GameListBuild(f); + if (error) { + DisplayError("Cannot build game list", error); + } else if (!ListEmpty(&gameList) && + ((ListGame *) gameList.tailPred)->number > 1) { + GameListPopUp(f, title); + return TRUE; + } + GameListDestroy(); + n = 1; + } + if (n == 0) n = 1; + return LoadGame(f, n, title, FALSE); +} + + +void +MakeRegisteredMove() +{ + int fromX, fromY, toX, toY; + char promoChar; + if (cmailMoveRegistered[lastLoadGameNumber - 1]) { + switch (cmailMoveType[lastLoadGameNumber - 1]) { + case CMAIL_MOVE: + case CMAIL_DRAW: + if (appData.debugMode) + fprintf(debugFP, "Restoring %s for game %d\n", + cmailMove[lastLoadGameNumber - 1], lastLoadGameNumber); + + thinkOutput[0] = NULLCHAR; + strcpy(moveList[currentMove], cmailMove[lastLoadGameNumber - 1]); + fromX = cmailMove[lastLoadGameNumber - 1][0] - 'a'; + fromY = cmailMove[lastLoadGameNumber - 1][1] - '1'; + toX = cmailMove[lastLoadGameNumber - 1][2] - 'a'; + toY = cmailMove[lastLoadGameNumber - 1][3] - '1'; + promoChar = cmailMove[lastLoadGameNumber - 1][4]; + MakeMove(fromX, fromY, toX, toY, promoChar); + ShowMove(fromX, fromY, toX, toY); + + switch (MateTest(boards[currentMove], PosFlags(currentMove), + EP_UNKNOWN)) { + case MT_NONE: + case MT_CHECK: + break; + + case MT_CHECKMATE: + if (WhiteOnMove(currentMove)) { + GameEnds(BlackWins, "Black mates", GE_PLAYER); + } else { + GameEnds(WhiteWins, "White mates", GE_PLAYER); + } + break; + + case MT_STALEMATE: + GameEnds(GameIsDrawn, "Stalemate", GE_PLAYER); + break; + } + + break; + + case CMAIL_RESIGN: + if (WhiteOnMove(currentMove)) { + GameEnds(BlackWins, "White resigns", GE_PLAYER); + } else { + GameEnds(WhiteWins, "Black resigns", GE_PLAYER); + } + break; + + case CMAIL_ACCEPT: + GameEnds(GameIsDrawn, "Draw agreed", GE_PLAYER); + break; + + default: + break; + } + } + + return; +} + +/* Wrapper around LoadGame for use when a Cmail message is loaded */ +int +CmailLoadGame(f, gameNumber, title, useList) + FILE *f; + int gameNumber; + char *title; + int useList; +{ + int retVal; + + if (gameNumber > nCmailGames) { + DisplayError("No more games in this message", 0); + return FALSE; + } + if (f == lastLoadGameFP) { + int offset = gameNumber - lastLoadGameNumber; + if (offset == 0) { + cmailMsg[0] = NULLCHAR; + if (cmailMoveRegistered[lastLoadGameNumber - 1]) { + cmailMoveRegistered[lastLoadGameNumber - 1] = FALSE; + nCmailMovesRegistered--; + } + cmailMoveType[lastLoadGameNumber - 1] = CMAIL_MOVE; + if (cmailResult[lastLoadGameNumber - 1] == CMAIL_NEW_RESULT) { + cmailResult[lastLoadGameNumber - 1] = CMAIL_NOT_RESULT; + } + } else { + if (! RegisterMove()) return FALSE; + } + } + + retVal = LoadGame(f, gameNumber, title, useList); + + /* Make move registered during previous look at this game, if any */ + MakeRegisteredMove(); + + if (cmailCommentList[lastLoadGameNumber - 1] != NULL) { + commentList[currentMove] + = StrSave(cmailCommentList[lastLoadGameNumber - 1]); + DisplayComment(currentMove - 1, commentList[currentMove]); + } + + return retVal; +} + +/* Support for LoadNextGame, LoadPreviousGame, ReloadSameGame */ +int +ReloadGame(offset) + int offset; +{ + int gameNumber = lastLoadGameNumber + offset; + if (lastLoadGameFP == NULL) { + DisplayError("No game has been loaded yet", 0); + return FALSE; + } + if (gameNumber <= 0) { + DisplayError("Can't back up any further", 0); + return FALSE; + } + if (cmailMsgLoaded) { + return CmailLoadGame(lastLoadGameFP, gameNumber, + lastLoadGameTitle, lastLoadGameUseList); + } else { + return LoadGame(lastLoadGameFP, gameNumber, + lastLoadGameTitle, lastLoadGameUseList); + } +} + + + +/* Load the nth game from open file f */ +int +LoadGame(f, gameNumber, title, useList) + FILE *f; + int gameNumber; + char *title; + int useList; +{ + ChessMove cm; + char buf[MSG_SIZ]; + int gn = gameNumber; + ListGame *lg = NULL; + int numPGNTags = 0; + int err; + GameMode oldGameMode; + + if (appData.debugMode) + fprintf(debugFP, "LoadGame(): on entry, gameMode %d\n", gameMode); + + if (gameMode == Training ) + SetTrainingModeOff(); + + oldGameMode = gameMode; + if (gameMode != BeginningOfGame) { + Reset(FALSE, TRUE); + } + + gameFileFP = f; + if (lastLoadGameFP != NULL && lastLoadGameFP != f) { + fclose(lastLoadGameFP); + } + + if (useList) { + lg = (ListGame *) ListElem(&gameList, gameNumber-1); + + if (lg) { + fseek(f, lg->offset, 0); + GameListHighlight(gameNumber); + gn = 1; + } + else { + DisplayError("Game number out of range", 0); + return FALSE; + } + } else { + GameListDestroy(); + if (fseek(f, 0, 0) == -1) { + if (f == lastLoadGameFP ? + gameNumber == lastLoadGameNumber + 1 : + gameNumber == 1) { + gn = 1; + } else { + DisplayError("Can't seek on game file", 0); + return FALSE; + } + } + } + lastLoadGameFP = f; + lastLoadGameNumber = gameNumber; + strcpy(lastLoadGameTitle, title); + lastLoadGameUseList = useList; + + yynewfile(f); + + + if (lg && lg->gameInfo.white && lg->gameInfo.black) { + sprintf(buf, "%s vs. %s", lg->gameInfo.white, + lg->gameInfo.black); + DisplayTitle(buf); + } else if (*title != NULLCHAR) { + if (gameNumber > 1) { + sprintf(buf, "%s %d", title, gameNumber); + DisplayTitle(buf); + } else { + DisplayTitle(title); + } + } + + if (gameMode != AnalyzeFile && gameMode != AnalyzeMode) { + gameMode = PlayFromGameFile; + ModeHighlight(); + } + + currentMove = forwardMostMove = backwardMostMove = 0; + CopyBoard(boards[0], initialPosition); + StopClocks(); + + /* + * Skip the first gn-1 games in the file. + * Also skip over anything that precedes an identifiable + * start of game marker, to avoid being confused by + * garbage at the start of the file. Currently + * recognized start of game markers are the move number "1", + * the pattern "gnuchess .* game", the pattern + * "^[#;%] [^ ]* game file", and a PGN tag block. + * A game that starts with one of the latter two patterns + * will also have a move number 1, possibly + * following a position diagram. + */ + cm = lastLoadGameStart = (ChessMove) 0; + yyskipmoves = TRUE; + while (gn > 0) { + yyboardindex = forwardMostMove; + cm = (ChessMove) yylex(); + yyskipmoves = FALSE; + switch (cm) { + case (ChessMove) 0: + if (cmailMsgLoaded) { + nCmailGames = CMAIL_MAX_GAMES - gn; + } else { + Reset(TRUE, TRUE); + DisplayError("Game not found in file", 0); + } + yyskipmoves = FALSE; + return FALSE; + + case GNUChessGame: + case XBoardGame: + gn--; + lastLoadGameStart = cm; + break; + + case MoveNumberOne: + switch (lastLoadGameStart) { + case GNUChessGame: + case XBoardGame: + case PGNTag: + break; + case MoveNumberOne: + case (ChessMove) 0: + gn--; /* count this game */ + lastLoadGameStart = cm; + break; + default: + /* impossible */ + break; + } + break; + + case PGNTag: + switch (lastLoadGameStart) { + case GNUChessGame: + case PGNTag: + case MoveNumberOne: + case (ChessMove) 0: + gn--; /* count this game */ + lastLoadGameStart = cm; + break; + case XBoardGame: + lastLoadGameStart = cm; /* game counted already */ + break; + default: + /* impossible */ + break; + } + if (gn > 0) { + do { + yyboardindex = forwardMostMove; + cm = (ChessMove) yylex(); + } while (cm == PGNTag || cm == Comment); + } + break; + + case WhiteWins: + case BlackWins: + case GameIsDrawn: + if (cmailMsgLoaded && (CMAIL_MAX_GAMES == lastLoadGameNumber)) { + if ( cmailResult[CMAIL_MAX_GAMES - gn - 1] + != CMAIL_OLD_RESULT) { + nCmailResults ++ ; + cmailResult[ CMAIL_MAX_GAMES + - gn - 1] = CMAIL_OLD_RESULT; + } + } + break; + + default: + break; + } + } + yyskipmoves = FALSE; + + if (appData.debugMode) + fprintf(debugFP, "Parsed game start '%s' (%d)\n", yy_text, (int) cm); + + if (cm == XBoardGame) { + /* Skip any header junk before position diagram and/or move 1 */ + for (;;) { + yyboardindex = forwardMostMove; + cm = (ChessMove) yylex(); + + if (cm == (ChessMove) 0 || + cm == GNUChessGame || cm == XBoardGame) { + /* Empty game; pretend end-of-file and handle later */ + cm = (ChessMove) 0; + break; + } + + if (cm == MoveNumberOne || cm == PositionDiagram || + cm == PGNTag || cm == Comment) + break; + } + } else if (cm == GNUChessGame) { + if (gameInfo.event != NULL) { + free(gameInfo.event); + } + gameInfo.event = StrSave(yy_text); + } + + startedFromSetupPosition = FALSE; + while (cm == PGNTag) { + if (appData.debugMode) + fprintf(debugFP, "Parsed PGNTag: %s\n", yy_text); + err = ParsePGNTag(yy_text, &gameInfo); + if (!err) numPGNTags++; + + if (gameInfo.fen != NULL) { + Board initial_position; + startedFromSetupPosition = TRUE; + if (!ParseFEN(initial_position, &blackPlaysFirst, gameInfo.fen)) { + Reset(TRUE, TRUE); + DisplayError("Bad FEN position in file", 0); + return FALSE; + } + CopyBoard(boards[0], initial_position); + if (blackPlaysFirst) { + currentMove = forwardMostMove = backwardMostMove = 1; + CopyBoard(boards[1], initial_position); + strcpy(moveList[0], ""); + strcpy(parseList[0], ""); + timeRemaining[0][1] = whiteTimeRemaining; + timeRemaining[1][1] = blackTimeRemaining; + if (commentList[0] != NULL) { + commentList[1] = commentList[0]; + commentList[0] = NULL; + } + } else { + currentMove = forwardMostMove = backwardMostMove = 0; + } + yyboardindex = forwardMostMove; + free(gameInfo.fen); + gameInfo.fen = NULL; + } + + yyboardindex = forwardMostMove; + cm = (ChessMove) yylex(); + + /* Handle comments interspersed among the tags */ + while (cm == Comment) { + char *p; + if (appData.debugMode) + fprintf(debugFP, "Parsed Comment: %s\n", yy_text); + p = yy_text; + if (*p == '{' || *p == '[' || *p == '(') { + p[strlen(p) - 1] = NULLCHAR; + p++; + } + while (*p == '\n') p++; + AppendComment(currentMove, p); + yyboardindex = forwardMostMove; + cm = (ChessMove) yylex(); + } + } + + /* don't rely on existence of Event tag since if game was + * pasted from clipboard the Event tag may not exist + */ + if (numPGNTags > 0){ + char *tags; + if (gameInfo.variant == VariantNormal) { + gameInfo.variant = StringToVariant(gameInfo.event); + } + if (!matchMode) { + tags = PGNTags(&gameInfo); + TagsPopUp(tags, CmailMsg()); + free(tags); + } + } else { + /* Make something up, but don't display it now */ + SetGameInfo(); + TagsPopDown(); + } + + if (cm == PositionDiagram) { + int i, j; + char *p; + Board initial_position; + + if (appData.debugMode) + fprintf(debugFP, "Parsed PositionDiagram: %s\n", yy_text); + + if (!startedFromSetupPosition) { + p = yy_text; + for (i = BOARD_SIZE - 1; i >= 0; i--) + for (j = 0; j < BOARD_SIZE; p++) + switch (*p) { + case '[': + case '-': + case ' ': + case '\t': + case '\n': + case '\r': + break; + default: + initial_position[i][j++] = CharToPiece(*p); + break; + } + while (*p == ' ' || *p == '\t' || + *p == '\n' || *p == '\r') p++; + + if (strncmp(p, "black", strlen("black"))==0) + blackPlaysFirst = TRUE; + else + blackPlaysFirst = FALSE; + startedFromSetupPosition = TRUE; + + CopyBoard(boards[0], initial_position); + if (blackPlaysFirst) { + currentMove = forwardMostMove = backwardMostMove = 1; + CopyBoard(boards[1], initial_position); + strcpy(moveList[0], ""); + strcpy(parseList[0], ""); + timeRemaining[0][1] = whiteTimeRemaining; + timeRemaining[1][1] = blackTimeRemaining; + if (commentList[0] != NULL) { + commentList[1] = commentList[0]; + commentList[0] = NULL; + } + } else { + currentMove = forwardMostMove = backwardMostMove = 0; + } + } + yyboardindex = forwardMostMove; + cm = (ChessMove) yylex(); + } + + if (first.pr == NoProc) { + StartChessProgram(&first); + } + InitChessProgram(&first); + SendToProgram("force\n", &first); + if (startedFromSetupPosition) { + SendBoard(&first, forwardMostMove); + DisplayBothClocks(); + } + + while (cm == Comment) { + char *p; + if (appData.debugMode) + fprintf(debugFP, "Parsed Comment: %s\n", yy_text); + p = yy_text; + if (*p == '{' || *p == '[' || *p == '(') { + p[strlen(p) - 1] = NULLCHAR; + p++; + } + while (*p == '\n') p++; + AppendComment(currentMove, p); + yyboardindex = forwardMostMove; + cm = (ChessMove) yylex(); + } + + if (cm == (ChessMove) 0 || cm == WhiteWins || cm == BlackWins || + cm == GameIsDrawn || cm == GameUnfinished) { + DisplayMessage("", "No moves in game"); + if (cmailMsgLoaded) { + if (appData.debugMode) + fprintf(debugFP, "Setting flipView to %d.\n", FALSE); + ClearHighlights(); + flipView = FALSE; + } + DrawPosition(FALSE, boards[currentMove]); + DisplayBothClocks(); + gameMode = EditGame; + ModeHighlight(); + gameFileFP = NULL; + cmailOldMove = 0; + return TRUE; + } + + if (commentList[currentMove] != NULL) { + if (!matchMode && (pausing || appData.timeDelay != 0)) { + DisplayComment(currentMove - 1, commentList[currentMove]); + } + } + if (!matchMode && appData.timeDelay != 0) + DrawPosition(FALSE, boards[currentMove]); + + if (gameMode == AnalyzeFile || gameMode == AnalyzeMode) { + programStats.ok_to_send = 1; + } + + /* if the first token after the PGN tags is a move + * and not move number 1, retrieve it from the parser + */ + if (cm != MoveNumberOne) + LoadGameOneMove(cm); + + /* load the remaining moves from the file */ + while (LoadGameOneMove((ChessMove)0)) { + timeRemaining[0][forwardMostMove] = whiteTimeRemaining; + timeRemaining[1][forwardMostMove] = blackTimeRemaining; + } + + /* rewind to the start of the game */ + currentMove = backwardMostMove; + + HistorySet(parseList, backwardMostMove, forwardMostMove, currentMove-1); + + if (oldGameMode == AnalyzeFile || + oldGameMode == AnalyzeMode) { + AnalyzeFileEvent(); + } + + if (matchMode || appData.timeDelay == 0) { + ToEndEvent(); + gameMode = EditGame; + ModeHighlight(); + } else if (appData.timeDelay > 0) { + AutoPlayGameLoop(); + } + + if (appData.debugMode) + fprintf(debugFP, "LoadGame(): on exit, gameMode %d\n", gameMode); + return TRUE; +} + +/* Support for LoadNextPosition, LoadPreviousPosition, ReloadSamePosition */ +int +ReloadPosition(offset) + int offset; +{ + int positionNumber = lastLoadPositionNumber + offset; + if (lastLoadPositionFP == NULL) { + DisplayError("No position has been loaded yet", 0); + return FALSE; + } + if (positionNumber <= 0) { + DisplayError("Can't back up any further", 0); + return FALSE; + } + return LoadPosition(lastLoadPositionFP, positionNumber, + lastLoadPositionTitle); +} + +/* Load the nth position from the given file */ +int +LoadPositionFromFile(filename, n, title) + char *filename; + int n; + char *title; +{ + FILE *f; + char buf[MSG_SIZ]; + + if (strcmp(filename, "-") == 0) { + return LoadPosition(stdin, n, "stdin"); + } else { + f = fopen(filename, "rb"); + if (f == NULL) { + sprintf(buf, "Can't open \"%s\"", filename); + DisplayError(buf, errno); + return FALSE; + } else { + return LoadPosition(f, n, title); + } + } +} + +/* Load the nth position from the given open file, and close it */ +int +LoadPosition(f, positionNumber, title) + FILE *f; + int positionNumber; + char *title; +{ + char *p, line[MSG_SIZ]; + Board initial_position; + int i, j, fenMode, pn; + + if (gameMode == Training ) + SetTrainingModeOff(); + + if (gameMode != BeginningOfGame) { + Reset(FALSE, TRUE); + } + if (lastLoadPositionFP != NULL && lastLoadPositionFP != f) { + fclose(lastLoadPositionFP); + } + if (positionNumber == 0) positionNumber = 1; + lastLoadPositionFP = f; + lastLoadPositionNumber = positionNumber; + strcpy(lastLoadPositionTitle, title); + if (first.pr == NoProc) { + StartChessProgram(&first); + InitChessProgram(&first); + } + pn = positionNumber; + if (positionNumber < 0) { + /* Negative position number means to seek to that byte offset */ + if (fseek(f, -positionNumber, 0) == -1) { + DisplayError("Can't seek on position file", 0); + return FALSE; + }; + pn = 1; + } else { + if (fseek(f, 0, 0) == -1) { + if (f == lastLoadPositionFP ? + positionNumber == lastLoadPositionNumber + 1 : + positionNumber == 1) { + pn = 1; + } else { + DisplayError("Can't seek on position file", 0); + return FALSE; + } + } + } + /* See if this file is FEN or old-style xboard */ + if (fgets(line, MSG_SIZ, f) == NULL) { + DisplayError("Position not found in file", 0); + return FALSE; + } + switch (line[0]) { + case '#': case 'x': + default: + fenMode = FALSE; + break; + case 'p': case 'n': case 'b': case 'r': case 'q': case 'k': + case 'P': case 'N': case 'B': case 'R': case 'Q': case 'K': + case '1': case '2': case '3': case '4': case '5': case '6': + case '7': case '8': + fenMode = TRUE; + break; + } + + if (pn >= 2) { + if (fenMode || line[0] == '#') pn--; + while (pn > 0) { + /* skip postions before number pn */ + if (fgets(line, MSG_SIZ, f) == NULL) { + DisplayError("Position not found in file", 0); + return FALSE; + } + if (fenMode || line[0] == '#') pn--; + } + } + + if (fenMode) { + if (!ParseFEN(initial_position, &blackPlaysFirst, line)) { + DisplayError("Bad FEN position in file", 0); + return FALSE; + } + } else { + (void) fgets(line, MSG_SIZ, f); + (void) fgets(line, MSG_SIZ, f); + + for (i = BOARD_SIZE - 1; i >= 0; i--) { + (void) fgets(line, MSG_SIZ, f); + for (p = line, j = 0; j < BOARD_SIZE; p++) { + if (*p == ' ') + continue; + initial_position[i][j++] = CharToPiece(*p); + } + } + + blackPlaysFirst = FALSE; + if (!feof(f)) { + (void) fgets(line, MSG_SIZ, f); + if (strncmp(line, "black", strlen("black"))==0) + blackPlaysFirst = TRUE; + } + } + startedFromSetupPosition = TRUE; + + SendToProgram("force\n", &first); + CopyBoard(boards[0], initial_position); + if (blackPlaysFirst) { + currentMove = forwardMostMove = backwardMostMove = 1; + strcpy(moveList[0], ""); + strcpy(parseList[0], ""); + CopyBoard(boards[1], initial_position); + DisplayMessage("", "Black to play"); + } else { + currentMove = forwardMostMove = backwardMostMove = 0; + DisplayMessage("", "White to play"); + } + SendBoard(&first, forwardMostMove); + + if (positionNumber > 1) { + sprintf(line, "%s %d", title, positionNumber); + DisplayTitle(line); + } else { + DisplayTitle(title); + } + gameMode = EditGame; + ModeHighlight(); + ResetClocks(); + timeRemaining[0][1] = whiteTimeRemaining; + timeRemaining[1][1] = blackTimeRemaining; + DrawPosition(FALSE, boards[currentMove]); + + return TRUE; +} + + +void +CopyPlayerNameIntoFileName(dest, src) + char **dest, *src; +{ + while (*src != NULLCHAR && *src != ',') { + if (*src == ' ') { + *(*dest)++ = '_'; + src++; + } else { + *(*dest)++ = *src++; + } + } +} + +char *DefaultFileName(ext) + char *ext; +{ + static char def[MSG_SIZ]; + char *p; + + if (gameInfo.white != NULL && gameInfo.white[0] != '-') { + p = def; + CopyPlayerNameIntoFileName(&p, gameInfo.white); + *p++ = '-'; + CopyPlayerNameIntoFileName(&p, gameInfo.black); + *p++ = '.'; + strcpy(p, ext); + } else { + def[0] = NULLCHAR; + } + return def; +} + +/* Save the current game to the given file */ +int +SaveGameToFile(filename, append) + char *filename; + int append; +{ + FILE *f; + char buf[MSG_SIZ]; + + if (strcmp(filename, "-") == 0) { + return SaveGame(stdout, 0, NULL); + } else { + f = fopen(filename, append ? "a" : "w"); + if (f == NULL) { + sprintf(buf, "Can't open \"%s\"", filename); + DisplayError(buf, errno); + return FALSE; + } else { + return SaveGame(f, 0, NULL); + } + } +} + +char * +SavePart(str) + char *str; +{ + static char buf[MSG_SIZ]; + char *p; + + p = strchr(str, ' '); + if (p == NULL) return str; + strncpy(buf, str, p - str); + buf[p - str] = NULLCHAR; + return buf; +} + +#define PGN_MAX_LINE 75 + +/* Save game in PGN style and close the file */ +int +SaveGamePGN(f) + FILE *f; +{ + int i, offset, linelen, newblock; + time_t tm; + char *movetext; + char numtext[32]; + int movelen, numlen, blank; + + tm = time((time_t *) NULL); + + PrintPGNTags(f, &gameInfo); + + if (backwardMostMove > 0 || startedFromSetupPosition) { + char *fen = PositionToFEN(backwardMostMove); + fprintf(f, "[FEN \"%s\"]\n[SetUp \"1\"]\n", fen); + fprintf(f, "\n{--------------\n"); + PrintPosition(f, backwardMostMove); + fprintf(f, "--------------}\n"); + free(fen); + } else { + fprintf(f, "\n"); + } + + i = backwardMostMove; + offset = backwardMostMove & (~1L); /* output move numbers start at 1 */ + linelen = 0; + newblock = TRUE; + + while (i < forwardMostMove) { + /* Print comments preceding this move */ + if (commentList[i] != NULL) { + if (linelen > 0) fprintf(f, "\n"); + fprintf(f, "{\n%s}\n", commentList[i]); + linelen = 0; + newblock = TRUE; + } + + /* Format move number */ + if ((i % 2) == 0) { + sprintf(numtext, "%d.", (i - offset)/2 + 1); + } else { + if (newblock) { + sprintf(numtext, "%d...", (i - offset)/2 + 1); + } else { + numtext[0] = NULLCHAR; + } + } + numlen = strlen(numtext); + newblock = FALSE; + + /* Print move number */ + blank = linelen > 0 && numlen > 0; + if (linelen + (blank ? 1 : 0) + numlen > PGN_MAX_LINE) { + fprintf(f, "\n"); + linelen = 0; + blank = 0; + } + if (blank) { + fprintf(f, " "); + linelen++; + } + fprintf(f, numtext); + linelen += numlen; + + /* Get move */ + movetext = SavePart(parseList[i]); + movelen = strlen(movetext); + + /* Print move */ + blank = linelen > 0 && movelen > 0; + if (linelen + (blank ? 1 : 0) + movelen > PGN_MAX_LINE) { + fprintf(f, "\n"); + linelen = 0; + blank = 0; + } + if (blank) { + fprintf(f, " "); + linelen++; + } + fprintf(f, movetext); + linelen += movelen; + + i++; + } + + /* Start a new line */ + if (linelen > 0) fprintf(f, "\n"); + + /* Print comments after last move */ + if (commentList[i] != NULL) { + fprintf(f, "{\n%s}\n", commentList[i]); + } + + /* Print result */ + if (gameInfo.resultDetails != NULL && + gameInfo.resultDetails[0] != NULLCHAR) { + fprintf(f, "{%s} %s\n\n", gameInfo.resultDetails, + PGNResult(gameInfo.result)); + } else { + fprintf(f, "%s\n\n", PGNResult(gameInfo.result)); + } + + fclose(f); + return TRUE; +} + +/* Save game in old style and close the file */ +int +SaveGameOldStyle(f) + FILE *f; +{ + int i, offset; + time_t tm; + + tm = time((time_t *) NULL); + + fprintf(f, "# %s game file -- %s", programName, ctime(&tm)); + PrintOpponents(f); + + if (backwardMostMove > 0 || startedFromSetupPosition) { + fprintf(f, "\n[--------------\n"); + PrintPosition(f, backwardMostMove); + fprintf(f, "--------------]\n"); + } else { + fprintf(f, "\n"); + } + + i = backwardMostMove; + offset = backwardMostMove & (~1L); /* output move numbers start at 1 */ + + while (i < forwardMostMove) { + if (commentList[i] != NULL) { + fprintf(f, "[%s]\n", commentList[i]); + } + + if ((i % 2) == 1) { + fprintf(f, "%d. ... %s\n", (i - offset)/2 + 1, parseList[i]); + i++; + } else { + fprintf(f, "%d. %s ", (i - offset)/2 + 1, parseList[i]); + i++; + if (commentList[i] != NULL) { + fprintf(f, "\n"); + continue; + } + if (i >= forwardMostMove) { + fprintf(f, "\n"); + break; + } + fprintf(f, "%s\n", parseList[i]); + i++; + } + } + + if (commentList[i] != NULL) { + fprintf(f, "[%s]\n", commentList[i]); + } + + /* This isn't really the old style, but it's close enough */ + if (gameInfo.resultDetails != NULL && + gameInfo.resultDetails[0] != NULLCHAR) { + fprintf(f, "%s (%s)\n\n", PGNResult(gameInfo.result), + gameInfo.resultDetails); + } else { + fprintf(f, "%s\n\n", PGNResult(gameInfo.result)); + } + + fclose(f); + return TRUE; +} + +/* Save the current game to open file f and close the file */ +int +SaveGame(f, dummy, dummy2) + FILE *f; + int dummy; + char *dummy2; +{ + if (gameMode == EditPosition) EditPositionDone(); + if (appData.oldSaveStyle) + return SaveGameOldStyle(f); + else + return SaveGamePGN(f); +} + +/* Save the current position to the given file */ +int +SavePositionToFile(filename) + char *filename; +{ + FILE *f; + char buf[MSG_SIZ]; + + if (strcmp(filename, "-") == 0) { + return SavePosition(stdout, 0, NULL); + } else { + f = fopen(filename, "a"); + if (f == NULL) { + sprintf(buf, "Can't open \"%s\"", filename); + DisplayError(buf, errno); + return FALSE; + } else { + SavePosition(f, 0, NULL); + return TRUE; + } + } +} + +/* Save the current position to the given open file and close the file */ +int +SavePosition(f, dummy, dummy2) + FILE *f; + int dummy; + char *dummy2; +{ + time_t tm; + char *fen; + + if (appData.oldSaveStyle) { + tm = time((time_t *) NULL); + + fprintf(f, "# %s position file -- %s", programName, ctime(&tm)); + PrintOpponents(f); + fprintf(f, "[--------------\n"); + PrintPosition(f, currentMove); + fprintf(f, "--------------]\n"); + } else { + fen = PositionToFEN(currentMove); + fprintf(f, "%s\n", fen); + free(fen); + } + fclose(f); + return TRUE; +} + +void +ReloadCmailMsgEvent(unregister) + int unregister; +{ + static char *inFilename = NULL; + static char *outFilename; + int i; + struct stat inbuf, outbuf; + int status; + + /* Any registered moves are unregistered if unregister is set, */ + /* i.e. invoked by the signal handler */ + if (unregister) { + for (i = 0; i < CMAIL_MAX_GAMES; i ++) { + cmailMoveRegistered[i] = FALSE; + if (cmailCommentList[i] != NULL) { + free(cmailCommentList[i]); + cmailCommentList[i] = NULL; + } + } + nCmailMovesRegistered = 0; + } + + for (i = 0; i < CMAIL_MAX_GAMES; i ++) { + cmailResult[i] = CMAIL_NOT_RESULT; + } + nCmailResults = 0; + + if (inFilename == NULL) { + /* Because the filenames are static they only get malloced once */ + /* and they never get freed */ + inFilename = (char *) malloc(strlen(appData.cmailGameName) + 9); + sprintf(inFilename, "%s.game.in", appData.cmailGameName); + + outFilename = (char *) malloc(strlen(appData.cmailGameName) + 5); + sprintf(outFilename, "%s.out", appData.cmailGameName); + } + + status = stat(outFilename, &outbuf); + if (status < 0) { + cmailMailedMove = FALSE; + } else { + status = stat(inFilename, &inbuf); + cmailMailedMove = (inbuf.st_mtime < outbuf.st_mtime); + } + + /* LoadGameFromFile(CMAIL_MAX_GAMES) with cmailMsgLoaded == TRUE + counts the games, notes how each one terminated, etc. + + It would be nice to remove this kludge and instead gather all + the information while building the game list. (And to keep it + in the game list nodes instead of having a bunch of fixed-size + parallel arrays.) Note this will require getting each game's + termination from the PGN tags, as the game list builder does + not process the game moves. --mann + */ + cmailMsgLoaded = TRUE; + LoadGameFromFile(inFilename, CMAIL_MAX_GAMES, "", FALSE); + + /* Load first game in the file or popup game menu */ + LoadGameFromFile(inFilename, 0, appData.cmailGameName, TRUE); + + return; +} + +int +RegisterMove() +{ + FILE *f; + char string[MSG_SIZ]; + + if ( cmailMailedMove + || (cmailResult[lastLoadGameNumber - 1] == CMAIL_OLD_RESULT)) { + return TRUE; /* Allow free viewing */ + } + + /* Unregister move to ensure that we don't leave RegisterMove */ + /* with the move registered when the conditions for registering no */ + /* longer hold */ + if (cmailMoveRegistered[lastLoadGameNumber - 1]) { + cmailMoveRegistered[lastLoadGameNumber - 1] = FALSE; + nCmailMovesRegistered --; + + if (cmailCommentList[lastLoadGameNumber - 1] != NULL) + { + free(cmailCommentList[lastLoadGameNumber - 1]); + cmailCommentList[lastLoadGameNumber - 1] = NULL; + } + } + + if (cmailOldMove == -1) { + DisplayError("You have edited the game history.\nUse Reload Same Game and make your move again.", 0); + return FALSE; + } + + if (currentMove > cmailOldMove + 1) { + DisplayError("You have entered too many moves.\nBack up to the correct position and try again.", 0); + return FALSE; + } + + if (currentMove < cmailOldMove) { + DisplayError("Displayed position is not current.\nStep forward to the correct position and try again.", 0); + return FALSE; + } + + if (forwardMostMove > currentMove) { + /* Silently truncate extra moves */ + TruncateGame(); + } + + if ( (currentMove == cmailOldMove + 1) + || ( (currentMove == cmailOldMove) + && ( (cmailMoveType[lastLoadGameNumber - 1] == CMAIL_ACCEPT) + || (cmailMoveType[lastLoadGameNumber - 1] == CMAIL_RESIGN)))) { + if (gameInfo.result != GameUnfinished) { + cmailResult[lastLoadGameNumber - 1] = CMAIL_NEW_RESULT; + } + + if (commentList[currentMove] != NULL) { + cmailCommentList[lastLoadGameNumber - 1] + = StrSave(commentList[currentMove]); + } + strcpy(cmailMove[lastLoadGameNumber - 1], moveList[currentMove - 1]); + + if (appData.debugMode) + fprintf(debugFP, "Saving %s for game %d\n", + cmailMove[lastLoadGameNumber - 1], lastLoadGameNumber); + + sprintf(string, + "%s.game.out.%d", appData.cmailGameName, lastLoadGameNumber); + + f = fopen(string, "w"); + if (appData.oldSaveStyle) { + SaveGameOldStyle(f); /* also closes the file */ + + sprintf(string, "%s.pos.out", appData.cmailGameName); + f = fopen(string, "w"); + SavePosition(f, 0, NULL); /* also closes the file */ + } else { + fprintf(f, "{--------------\n"); + PrintPosition(f, currentMove); + fprintf(f, "--------------}\n\n"); + + SaveGame(f, 0, NULL); /* also closes the file*/ + } + + cmailMoveRegistered[lastLoadGameNumber - 1] = TRUE; + nCmailMovesRegistered ++; + } else if (nCmailGames == 1) { + DisplayError("You have not made a move yet", 0); + return FALSE; + } + + return TRUE; +} + +void +MailMoveEvent() +{ + static char *partCommandString = "cmail -xv%s -remail -game %s 2>&1"; + FILE *commandOutput; + char buffer[MSG_SIZ], msg[MSG_SIZ], string[MSG_SIZ]; + int nBytes = 0; /* Suppress warnings on uninitialized variables */ + int nBuffers; + int i; + int archived; + char *arcDir; + + if (! cmailMsgLoaded) { + DisplayError("The cmail message is not loaded.\nUse Reload CMail Message and make your move again.", 0); + return; + } + + if (nCmailGames == nCmailResults) { + DisplayError("No unfinished games", 0); + return; + } + +#if CMAIL_PROHIBIT_REMAIL + if (cmailMailedMove) { + sprintf(msg, "You have already mailed a move.\nWait until a move arrives from your opponent.\nTo resend the same move, type\n\"cmail -remail -game %s\"\non the command line.", appData.cmailGameName); + DisplayError(msg, 0); + return; + } +#endif + + if (! (cmailMailedMove || RegisterMove())) return; + + if ( cmailMailedMove + || (nCmailMovesRegistered + nCmailResults == nCmailGames)) { + sprintf(string, partCommandString, + appData.debugMode ? " -v" : "", appData.cmailGameName); + commandOutput = popen(string, "r"); + + if (commandOutput == NULL) { + DisplayError("Failed to invoke cmail", 0); + } else { + for (nBuffers = 0; (! feof(commandOutput)); nBuffers ++) { + nBytes = fread(buffer, 1, MSG_SIZ - 1, commandOutput); + } + if (nBuffers > 1) { + (void) memcpy(msg, buffer + nBytes, MSG_SIZ - nBytes - 1); + (void) memcpy(msg + MSG_SIZ - nBytes - 1, buffer, nBytes); + nBytes = MSG_SIZ - 1; + } else { + (void) memcpy(msg, buffer, nBytes); + } + *(msg + nBytes) = '\0'; /* \0 for end-of-string*/ + + if(StrStr(msg, "Mailed cmail message to ") != NULL) { + cmailMailedMove = TRUE; /* Prevent >1 moves */ + + archived = TRUE; + for (i = 0; i < nCmailGames; i ++) { + if (cmailResult[i] == CMAIL_NOT_RESULT) { + archived = FALSE; + } + } + if ( archived + && ( (arcDir = (char *) getenv("CMAIL_ARCDIR")) + != NULL)) { + sprintf(buffer, "%s/%s.%s.archive", + arcDir, + appData.cmailGameName, + gameInfo.date); + LoadGameFromFile(buffer, 1, buffer, FALSE); + cmailMsgLoaded = FALSE; + } + } + + DisplayInformation(msg); + pclose(commandOutput); + } + } else { + if ((*cmailMsg) != '\0') { + DisplayInformation(cmailMsg); + } + } + + return; +} + +char * +CmailMsg() +{ + int prependComma = 0; + char number[5]; + char string[MSG_SIZ]; /* Space for game-list */ + int i; + + if (!cmailMsgLoaded) return ""; + + if (cmailMailedMove) { + sprintf(cmailMsg, "Waiting for reply from opponent\n"); + } else { + /* Create a list of games left */ + sprintf(string, "["); + for (i = 0; i < nCmailGames; i ++) { + if (! ( cmailMoveRegistered[i] + || (cmailResult[i] == CMAIL_OLD_RESULT))) { + if (prependComma) { + sprintf(number, ",%d", i + 1); + } else { + sprintf(number, "%d", i + 1); + prependComma = 1; + } + + strcat(string, number); + } + } + strcat(string, "]"); + + if (nCmailMovesRegistered + nCmailResults == 0) { + switch (nCmailGames) { + case 1: + sprintf(cmailMsg, + "Still need to make move for game\n"); + break; + + case 2: + sprintf(cmailMsg, + "Still need to make moves for both games\n"); + break; + + default: + sprintf(cmailMsg, + "Still need to make moves for all %d games\n", + nCmailGames); + break; + } + } else { + switch (nCmailGames - nCmailMovesRegistered - nCmailResults) { + case 1: + sprintf(cmailMsg, + "Still need to make a move for game %s\n", + string); + break; + + case 0: + if (nCmailResults == nCmailGames) { + sprintf(cmailMsg, "No unfinished games\n"); + } else { + sprintf(cmailMsg, "Ready to send mail\n"); + } + break; + + default: + sprintf(cmailMsg, + "Still need to make moves for games %s\n", + string); + } + } + } + + return cmailMsg; +} + +void +ResetGameEvent() +{ + if (gameMode == Training) + SetTrainingModeOff(); + + Reset(TRUE, TRUE); + cmailMsgLoaded = FALSE; + if (appData.icsActive) { + SendToICS(ics_prefix); + SendToICS("refresh\n"); + } +} + +static int exiting = 0; + +void +ExitEvent(status) + int status; +{ + exiting++; + if (exiting > 2) { + /* Give up on clean exit */ + exit(status); + } + if (exiting > 1) { + /* Keep trying for clean exit */ + return; + } + + if (appData.icsActive && appData.colorize) Colorize(ColorNone, FALSE); + + if (telnetISR != NULL) { + RemoveInputSource(telnetISR); + } + if (icsPR != NoProc) { + DestroyChildProcess(icsPR, TRUE); + } + /* Save game if resource set and not already saved by GameEnds() */ + if (gameInfo.resultDetails == NULL && forwardMostMove > 0) { + if (*appData.saveGameFile != NULLCHAR) { + SaveGameToFile(appData.saveGameFile, TRUE); + } else if (appData.autoSaveGames) { + AutoSaveGame(); + } + if (*appData.savePositionFile != NULLCHAR) { + SavePositionToFile(appData.savePositionFile); + } + } + GameEnds((ChessMove) 0, NULL, GE_PLAYER); + + /* Kill off chess programs */ + if (first.pr != NoProc) { + ExitAnalyzeMode(); + SendToProgram("quit\n", &first); + DestroyChildProcess(first.pr, first.useSigterm); + } + if (second.pr != NoProc) { + SendToProgram("quit\n", &second); + DestroyChildProcess(second.pr, second.useSigterm); + } + if (first.isr != NULL) { + RemoveInputSource(first.isr); + } + if (second.isr != NULL) { + RemoveInputSource(second.isr); + } + + ShutDownFrontEnd(); + exit(status); +} + +void +PauseEvent() +{ + if (appData.debugMode) + fprintf(debugFP, "PauseEvent(): pausing %d\n", pausing); + if (pausing) { + pausing = FALSE; + ModeHighlight(); + if (gameMode == MachinePlaysWhite || + gameMode == MachinePlaysBlack) { + StartClocks(); + } else { + DisplayBothClocks(); + } + if (gameMode == PlayFromGameFile) { + if (appData.timeDelay >= 0) + AutoPlayGameLoop(); + } else if (gameMode == IcsExamining && pauseExamInvalid) { + Reset(FALSE, TRUE); + SendToICS(ics_prefix); + SendToICS("refresh\n"); + } else if (currentMove < forwardMostMove) { + ForwardInner(forwardMostMove); + } + pauseExamInvalid = FALSE; + } else { + switch (gameMode) { + default: + return; + case IcsExamining: + pauseExamForwardMostMove = forwardMostMove; + pauseExamInvalid = FALSE; + /* fall through */ + case IcsObserving: + case IcsPlayingWhite: + case IcsPlayingBlack: + pausing = TRUE; + ModeHighlight(); + return; + case PlayFromGameFile: + (void) StopLoadGameTimer(); + pausing = TRUE; + ModeHighlight(); + break; + case BeginningOfGame: + if (appData.icsActive) return; + /* else fall through */ + case MachinePlaysWhite: + case MachinePlaysBlack: + case TwoMachinesPlay: + if (forwardMostMove == 0) + return; /* don't pause if no one has moved */ + if ((gameMode == MachinePlaysWhite && + !WhiteOnMove(forwardMostMove)) || + (gameMode == MachinePlaysBlack && + WhiteOnMove(forwardMostMove))) { + StopClocks(); + } + pausing = TRUE; + ModeHighlight(); + break; + } + } +} + +void +EditCommentEvent() +{ + char title[MSG_SIZ]; + + if (currentMove < 1 || parseList[currentMove - 1][0] == NULLCHAR) { + strcpy(title, "Edit comment"); + } else { + sprintf(title, "Edit comment on %d.%s%s", (currentMove - 1) / 2 + 1, + WhiteOnMove(currentMove - 1) ? " " : ".. ", + parseList[currentMove - 1]); + } + + EditCommentPopUp(currentMove, title, commentList[currentMove]); +} + + +void +EditTagsEvent() +{ + char *tags = PGNTags(&gameInfo); + EditTagsPopUp(tags); + free(tags); +} + +void +AnalyzeModeEvent() +{ + if (appData.noChessProgram || gameMode == AnalyzeMode) + return; + + /* Engine Room enable */ + /* We need a AnalysisDisplay(TRUE) for timer */ + appData.AnalysisWindow = TRUE; + + if (gameMode != AnalyzeFile) { + EditGameEvent(); + if (gameMode != EditGame) return; + ResurrectChessProgram(); + SendToProgram("analyze\n", &first); + first.analyzing = TRUE; + /*first.maybeThinking = TRUE;*/ + first.maybeThinking = FALSE; /* avoid killing GNU Chess */ + } + gameMode = AnalyzeMode; + pausing = FALSE; + ModeHighlight(); + SetGameInfo(); + StartAnalysisClock(); + GetTimeMark(&lastNodeCountTime); + lastNodeCount = 0; + PeriodicUpdatesEvent(TRUE); +} + +/* daniel */ +void IcsAnalyze(newState) +int newState; + +{ + if (appData.noChessProgram) { + DisplayFatalError("ICS-Analysis requires a chess engine", 0, 1); + return; + } + + if (!newState && first.analyzing) { + if (appData.debugMode) fprintf(debugFP, "ICS-Analyze: Shutting down engine\n"); + ExitAnalyzeMode(); + DisplayMessage("","Close ICS engine analyse..."); + return; + } + + if (gameMode != IcsObserving) { + MessageBox(0,"You are not observing a game", + "ICS Engine Analyse", MB_OK); + appData.icsAnalyze = FALSE; + /* Set state for GUI */ + appData.icsEngineNone = TRUE; + appData.icsEngineWhisper = FALSE; + appData.icsEngineKibitz = FALSE; + appData.icsEngineTell = FALSE; + appData.icsAnalyzeOutPut = 4; + return; + } + + if (first.analysisSupport == FALSE) { + MessageBox(0,"Sorry, this engine does not support analyze", + "ICS Engine Analyse", MB_OK); + return; + } + + if (newState) { + if (appData.debugMode) fprintf(debugFP, "Starting ICS analyze\n"); + DisplayMessage("","Starting ICS engine analyse"); + if (!appData.icsWBprotoAgr) { + /* safty */ + /* Wo do that only if we start new or have a problem */ + SendToProgram("new\n", &first); + SendToProgram("post\n", &first); + SendToProgram("force\n", &first); + FeedMovesToProgram(&first, currentMove); + SendToProgram("analyze\n", &first); + } else { + /* hard */ + SendToProgram("exit\n", &first); + SendToProgram("new\n", &first); + SendToProgram("post\n", &first); + SendToProgram("hart\n", &first); + SendToProgram("force\n", &first); + FeedMovesToProgram(&first, currentMove); + SendToProgram("analyze\n", &first); + SendToProgram(".\n", &first); + } + PeriodicUpdatesEvent(TRUE); /* appData.periodicUpdates */ + first.analyzing = TRUE; /* Used for GUI and other ways */ + } +} + +void +IcsAnalyzeWindowUp() +{ + /* Using allso for startup Engine Room + * So function name looks like mismatch + * Change it for a better program style - + * but this is not crirical + */ + + if (appData.AnalysisWindow) { + ClearProgramStats(); + DisplayAnalysis(0,0); + PeriodicUpdatesEvent(TRUE); + } + /* StartAnalysisClock check gameMode */ + if (gameMode == AnalyzeMode || gameMode == AnalyzeFile || + appData.icsAnalyze || appData.AnalysisWindow) { + StartAnalysisClock(); + } + GetTimeMark(&lastNodeCountTime); + lastNodeCount = 0; /* importent */ +} + +void +AnalyzeFileEvent() +{ + if (appData.noChessProgram || gameMode == AnalyzeFile) + return; + + /* Engine Room */ + /* We need a DisplayAnalysis(TRUE); */ + appData.AnalysisWindow = TRUE; + + if (gameMode != AnalyzeMode) { + EditGameEvent(); + if (gameMode != EditGame) return; + ResurrectChessProgram(); + SendToProgram("analyze\n", &first); + first.analyzing = TRUE; + /*first.maybeThinking = TRUE;*/ + first.maybeThinking = FALSE; /* avoid killing GNU Chess */ + } + gameMode = AnalyzeFile; + pausing = FALSE; + ModeHighlight(); + SetGameInfo(); + + StartAnalysisClock(); + GetTimeMark(&lastNodeCountTime); + lastNodeCount = 0; +} + +void +MachineWhiteEvent() +{ + char buf[MSG_SIZ]; + + if (appData.noChessProgram || (gameMode == MachinePlaysWhite)) + return; + + + if (gameMode == PlayFromGameFile || + gameMode == TwoMachinesPlay || + gameMode == Training || + gameMode == AnalyzeMode || + gameMode == EndOfGame) + EditGameEvent(); + + if (gameMode == EditPosition) + EditPositionDone(); + + if (!WhiteOnMove(currentMove)) { + DisplayError("It is not White's turn", 0); + return; + } + + if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) + ExitAnalyzeMode(); + + + if (gameMode == EditGame || gameMode == AnalyzeMode || + gameMode == AnalyzeFile) + TruncateGame(); + + ResurrectChessProgram(); /* in case it isn't running */ + gameMode = MachinePlaysWhite; + pausing = FALSE; + ModeHighlight(); + SetGameInfo(); + sprintf(buf, "%s vs. %s", gameInfo.white, gameInfo.black); + DisplayTitle(buf); + if (first.sendName) { + sprintf(buf, "name %s\n", gameInfo.black); + SendToProgram(buf, &first); + } + if (first.sendTime) { + if (first.useColors) { + SendToProgram("black\n", &first); /*gnu kludge*/ + } + SendTimeRemaining(&first, TRUE); + } + if (first.useColors) { + SendToProgram("white\ngo\n", &first); + } else { + SendToProgram("go\n", &first); + } + SetMachineThinkingEnables(); + first.maybeThinking = TRUE; + StartClocks(); + + if (appData.autoFlipView && !flipView) { + flipView = !flipView; + DrawPosition(FALSE, NULL); + } + if (appData.AnalysisWindow) appData.periodicUpdates = TRUE; +} + +void +MachineBlackEvent() +{ + char buf[MSG_SIZ]; + + if (appData.noChessProgram || (gameMode == MachinePlaysBlack)) + return; + + + if (gameMode == PlayFromGameFile || + gameMode == TwoMachinesPlay || + gameMode == Training || + gameMode == AnalyzeMode || + gameMode == EndOfGame) + EditGameEvent(); + + if (gameMode == EditPosition) + EditPositionDone(); + + if (WhiteOnMove(currentMove)) { + DisplayError("It is not Black's turn", 0); + return; + } + + if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) + ExitAnalyzeMode(); + + if (gameMode == EditGame || gameMode == AnalyzeMode || + gameMode == AnalyzeFile) + TruncateGame(); + + ResurrectChessProgram(); /* in case it isn't running */ + gameMode = MachinePlaysBlack; + pausing = FALSE; + ModeHighlight(); + SetGameInfo(); + sprintf(buf, "%s vs. %s", gameInfo.white, gameInfo.black); + DisplayTitle(buf); + if (first.sendName) { + sprintf(buf, "name %s\n", gameInfo.white); + SendToProgram(buf, &first); + } + if (first.sendTime) { + if (first.useColors) { + SendToProgram("white\n", &first); /*gnu kludge*/ + } + SendTimeRemaining(&first, FALSE); + } + if (first.useColors) { + SendToProgram("black\ngo\n", &first); + } else { + SendToProgram("go\n", &first); + } + SetMachineThinkingEnables(); + first.maybeThinking = TRUE; + StartClocks(); + + if (appData.autoFlipView && flipView) { + flipView = !flipView; + DrawPosition(FALSE, NULL); + } + if (appData.AnalysisWindow) appData.periodicUpdates = TRUE; +} + + +void +DisplayTwoMachinesTitle() +{ + char buf[MSG_SIZ]; + if (appData.matchGames > 0) { + if (first.twoMachinesColor[0] == 'w') { + sprintf(buf, "%s vs. %s (%d-%d-%d)", + gameInfo.white, gameInfo.black, + first.matchWins, second.matchWins, + matchGame - 1 - (first.matchWins + second.matchWins)); + } else { + sprintf(buf, "%s vs. %s (%d-%d-%d)", + gameInfo.white, gameInfo.black, + second.matchWins, first.matchWins, + matchGame - 1 - (first.matchWins + second.matchWins)); + } + } else { + sprintf(buf, "%s vs. %s", gameInfo.white, gameInfo.black); + } + DisplayTitle(buf); +} + +void +TwoMachinesEvent P((void)) +{ + int i; + char buf[MSG_SIZ]; + ChessProgramState *onmove; + + if (appData.noChessProgram) return; + + switch (gameMode) { + case TwoMachinesPlay: + return; + case MachinePlaysWhite: + case MachinePlaysBlack: + if (WhiteOnMove(forwardMostMove) == (gameMode == MachinePlaysWhite)) { + DisplayError("Wait until your turn,\nor select Move Now", 0); + return; + } + /* fall through */ + case BeginningOfGame: + case PlayFromGameFile: + case EndOfGame: + EditGameEvent(); + if (gameMode != EditGame) return; + break; + case EditPosition: + EditPositionDone(); + break; + case AnalyzeMode: + case AnalyzeFile: + ExitAnalyzeMode(); + break; + case EditGame: + default: + break; + } + + forwardMostMove = currentMove; + ResurrectChessProgram(); /* in case first program isn't running */ + + if (second.pr == NULL) { + StartChessProgram(&second); + if (second.protocolVersion == 1) { + TwoMachinesEventIfReady(); + } else { + /* kludge: allow timeout for initial "feature" command */ + FreezeUI(); + DisplayMessage("", "Starting second chess program"); + ScheduleDelayedEvent(TwoMachinesEventIfReady, FEATURE_TIMEOUT); + } + return; + } + DisplayMessage("", ""); + InitChessProgram(&second); + SendToProgram("force\n", &second); + if (startedFromSetupPosition) { + SendBoard(&second, backwardMostMove); + } + for (i = backwardMostMove; i < forwardMostMove; i++) { + SendMoveToProgram(i, &second); + } + + gameMode = TwoMachinesPlay; + pausing = FALSE; + ModeHighlight(); + SetGameInfo(); + DisplayTwoMachinesTitle(); + firstMove = TRUE; + if ((first.twoMachinesColor[0] == 'w') == WhiteOnMove(forwardMostMove)) { + onmove = &first; + } else { + onmove = &second; + } + + SendToProgram(first.computerString, &first); + if (first.sendName) { + sprintf(buf, "name %s\n", second.tidy); + SendToProgram(buf, &first); + } + SendToProgram(second.computerString, &second); + if (second.sendName) { + sprintf(buf, "name %s\n", first.tidy); + SendToProgram(buf, &second); + } + + if (!first.sendTime || !second.sendTime) { + ResetClocks(); + timeRemaining[0][forwardMostMove] = whiteTimeRemaining; + timeRemaining[1][forwardMostMove] = blackTimeRemaining; + } + if (onmove->sendTime) { + if (onmove->useColors) { + SendToProgram(onmove->other->twoMachinesColor, onmove); /*gnu kludge*/ + } + SendTimeRemaining(onmove, WhiteOnMove(forwardMostMove)); + } + if (onmove->useColors) { + SendToProgram(onmove->twoMachinesColor, onmove); + } + SendToProgram("go\n", onmove); + onmove->maybeThinking = TRUE; + SetMachineThinkingEnables(); + + StartClocks(); +} + +void +TrainingEvent() +{ + if (gameMode == Training) { + SetTrainingModeOff(); + gameMode = PlayFromGameFile; + DisplayMessage("", "Training mode off"); + } else { + gameMode = Training; + animateTraining = appData.animate; + + /* make sure we are not already at the end of the game */ + if (currentMove < forwardMostMove) { + SetTrainingModeOn(); + DisplayMessage("", "Training mode on"); + } else { + gameMode = PlayFromGameFile; + DisplayError("Already at end of game", 0); + } + } + ModeHighlight(); +} + +void +IcsClientEvent() +{ + if (!appData.icsActive) return; + switch (gameMode) { + case IcsPlayingWhite: + case IcsPlayingBlack: + case IcsObserving: + case IcsIdle: + case BeginningOfGame: + case IcsExamining: + return; + + case EditGame: + break; + + case EditPosition: + EditPositionDone(); + break; + + case AnalyzeMode: + case AnalyzeFile: + ExitAnalyzeMode(); + break; + + default: + EditGameEvent(); + break; + } + + gameMode = IcsIdle; + ModeHighlight(); + return; +} + + +void +EditGameEvent() +{ + int i; + + switch (gameMode) { + case Training: + SetTrainingModeOff(); + break; + case MachinePlaysWhite: + case MachinePlaysBlack: + case BeginningOfGame: + SendToProgram("force\n", &first); + SetUserThinkingEnables(); + break; + case PlayFromGameFile: + (void) StopLoadGameTimer(); + if (gameFileFP != NULL) { + gameFileFP = NULL; + } + break; + case EditPosition: + EditPositionDone(); + break; + case AnalyzeMode: + case AnalyzeFile: + ExitAnalyzeMode(); + SendToProgram("force\n", &first); + break; + case TwoMachinesPlay: + GameEnds((ChessMove) 0, NULL, GE_PLAYER); + ResurrectChessProgram(); + SetUserThinkingEnables(); + break; + case EndOfGame: + ResurrectChessProgram(); + break; + case IcsPlayingBlack: + case IcsPlayingWhite: + DisplayError("Warning: You are still playing a game", 0); + break; + case IcsObserving: + break; + case IcsExamining: + DisplayError("Warning: You are still examining a game", 0); + break; + case IcsIdle: + break; + case EditGame: + default: + return; + } + + pausing = FALSE; + /* daniel */ + if (gameMode != IcsObserving) StopClocks(); + + first.offeredDraw = second.offeredDraw = 0; + + if (gameMode == PlayFromGameFile) { + whiteTimeRemaining = timeRemaining[0][currentMove]; + blackTimeRemaining = timeRemaining[1][currentMove]; + DisplayTitle(""); + } + + if (gameMode == MachinePlaysWhite || + gameMode == MachinePlaysBlack || + gameMode == TwoMachinesPlay || + gameMode == EndOfGame) { + i = forwardMostMove; + while (i > currentMove) { + SendToProgram("undo\n", &first); + i--; + } + whiteTimeRemaining = timeRemaining[0][currentMove]; + blackTimeRemaining = timeRemaining[1][currentMove]; + DisplayBothClocks(); + if (whiteFlag || blackFlag) { + whiteFlag = blackFlag = 0; + } + DisplayTitle(""); + } + + gameMode = EditGame; + ModeHighlight(); + SetGameInfo(); +} + + +void +EditPositionEvent() +{ + if (gameMode == EditPosition) { + EditGameEvent(); + return; + } + + EditGameEvent(); + if (gameMode != EditGame) return; + + gameMode = EditPosition; + ModeHighlight(); + SetGameInfo(); + if (currentMove > 0) + CopyBoard(boards[0], boards[currentMove]); + + blackPlaysFirst = !WhiteOnMove(currentMove); + ResetClocks(); + currentMove = forwardMostMove = backwardMostMove = 0; + HistorySet(parseList, backwardMostMove, forwardMostMove, currentMove-1); + DisplayMove(-1); +} + +void +ExitAnalyzeMode() +{ + if (first.analysisSupport && first.analyzing) { + SendToProgram("exit\n", &first); + first.analyzing = FALSE; + } + AnalysisPopDown(); + thinkOutput[0] = NULLCHAR; +} + +void +EditPositionDone() +{ + startedFromSetupPosition = TRUE; + InitChessProgram(&first); + SendToProgram("force\n", &first); + if (blackPlaysFirst) { + strcpy(moveList[0], ""); + strcpy(parseList[0], ""); + currentMove = forwardMostMove = backwardMostMove = 1; + CopyBoard(boards[1], boards[0]); + } else { + currentMove = forwardMostMove = backwardMostMove = 0; + } + SendBoard(&first, forwardMostMove); + DisplayTitle(""); + timeRemaining[0][forwardMostMove] = whiteTimeRemaining; + timeRemaining[1][forwardMostMove] = blackTimeRemaining; + gameMode = EditGame; + ModeHighlight(); + HistorySet(parseList, backwardMostMove, forwardMostMove, currentMove-1); +} + +/* Pause for `ms' milliseconds */ +/* !! Ugh, this is a kludge. Fix it sometime. --tpm */ +void +TimeDelay(ms) + long ms; +{ + TimeMark m1, m2; + + GetTimeMark(&m1); + do { + GetTimeMark(&m2); + } while (SubtractTimeMarks(&m2, &m1) < ms); +} + +/* !! Ugh, this is a kludge. Fix it sometime. --tpm */ +void +SendMultiLineToICS(buf) + char *buf; +{ + char temp[MSG_SIZ+1], *p; + int len; + + len = strlen(buf); + if (len > MSG_SIZ) + len = MSG_SIZ; + + strncpy(temp, buf, len); + temp[len] = 0; + + p = temp; + while (*p) { + if (*p == '\n' || *p == '\r') + *p = ' '; + ++p; + } + + strcat(temp, "\n"); + SendToICS(temp); + SendToPlayer(temp, strlen(temp)); +} + +void +SetWhiteToPlayEvent() +{ + if (gameMode == EditPosition) { + blackPlaysFirst = FALSE; + DisplayBothClocks(); /* works because currentMove is 0 */ + } else if (gameMode == IcsExamining) { + SendToICS(ics_prefix); + SendToICS("tomove white\n"); + } +} + +void +SetBlackToPlayEvent() +{ + if (gameMode == EditPosition) { + blackPlaysFirst = TRUE; + currentMove = 1; /* kludge */ + DisplayBothClocks(); + currentMove = 0; + } else if (gameMode == IcsExamining) { + SendToICS(ics_prefix); + SendToICS("tomove black\n"); + } +} + +void +EditPositionMenuEvent(selection, x, y) + ChessSquare selection; + int x, y; +{ + char buf[MSG_SIZ]; + + if (gameMode != EditPosition && gameMode != IcsExamining) return; + + switch (selection) { + case ClearBoard: + if (gameMode == IcsExamining && ics_type == ICS_FICS) { + SendToICS(ics_prefix); + SendToICS("bsetup clear\n"); + } else if (gameMode == IcsExamining && ics_type == ICS_ICC) { + SendToICS(ics_prefix); + SendToICS("clearboard\n"); + } else { + for (x = 0; x < BOARD_SIZE; x++) { + for (y = 0; y < BOARD_SIZE; y++) { + if (gameMode == IcsExamining) { + if (boards[currentMove][y][x] != EmptySquare) { + sprintf(buf, "%sx@%c%c\n", ics_prefix, + 'a' + x, '1' + y); + SendToICS(buf); + } + } else { + boards[0][y][x] = EmptySquare; + } + } + } + } + if (gameMode == EditPosition) { + DrawPosition(FALSE, boards[0]); + } + break; + + case WhitePlay: + SetWhiteToPlayEvent(); + break; + + case BlackPlay: + SetBlackToPlayEvent(); + break; + + case EmptySquare: + if (gameMode == IcsExamining) { + sprintf(buf, "%sx@%c%c\n", ics_prefix, 'a' + x, '1' + y); + SendToICS(buf); + } else { + boards[0][y][x] = EmptySquare; + DrawPosition(FALSE, boards[0]); + } + break; + + default: + if (gameMode == IcsExamining) { + sprintf(buf, "%s%c@%c%c\n", ics_prefix, + PieceToChar(selection), 'a' + x, '1' + y); + SendToICS(buf); + } else { + boards[0][y][x] = selection; + DrawPosition(FALSE, boards[0]); + } + break; + } +} + + +void +DropMenuEvent(selection, x, y) + ChessSquare selection; + int x, y; +{ + ChessMove moveType; + + switch (gameMode) { + case IcsPlayingWhite: + case MachinePlaysBlack: + if (!WhiteOnMove(currentMove)) { + DisplayMoveError("It is Black's turn"); + return; + } + moveType = WhiteDrop; + break; + case IcsPlayingBlack: + case MachinePlaysWhite: + if (WhiteOnMove(currentMove)) { + DisplayMoveError("It is White's turn"); + return; + } + moveType = BlackDrop; + break; + case EditGame: + moveType = WhiteOnMove(currentMove) ? WhiteDrop : BlackDrop; + break; + default: + return; + } + + if (moveType == BlackDrop && selection < BlackPawn) { + selection = (ChessSquare) ((int) selection + + (int) BlackPawn - (int) WhitePawn); + } + if (boards[currentMove][y][x] != EmptySquare) { + DisplayMoveError("That square is occupied"); + return; + } + + FinishMove(moveType, (int) selection, DROP_RANK, x, y, NULLCHAR); +} + +void +AcceptEvent() +{ + /* Accept a pending offer of any kind from opponent */ + + if (appData.icsActive) { + SendToICS(ics_prefix); + SendToICS("accept\n"); + } else if (cmailMsgLoaded) { + if (currentMove == cmailOldMove && + commentList[cmailOldMove] != NULL && + StrStr(commentList[cmailOldMove], WhiteOnMove(cmailOldMove) ? + "Black offers a draw" : "White offers a draw")) { + TruncateGame(); + GameEnds(GameIsDrawn, "Draw agreed", GE_PLAYER); + cmailMoveType[lastLoadGameNumber - 1] = CMAIL_ACCEPT; + } else { + DisplayError("There is no pending offer on this move", 0); + cmailMoveType[lastLoadGameNumber - 1] = CMAIL_MOVE; + } + } else { + /* Not used for offers from chess program */ + } +} + +void +DeclineEvent() +{ + /* Decline a pending offer of any kind from opponent */ + + if (appData.icsActive) { + SendToICS(ics_prefix); + SendToICS("decline\n"); + } else if (cmailMsgLoaded) { + if (currentMove == cmailOldMove && + commentList[cmailOldMove] != NULL && + StrStr(commentList[cmailOldMove], WhiteOnMove(cmailOldMove) ? + "Black offers a draw" : "White offers a draw")) { +#ifdef NOTDEF + AppendComment(cmailOldMove, "Draw declined"); + DisplayComment(cmailOldMove - 1, "Draw declined"); +#endif /*NOTDEF*/ + } else { + DisplayError("There is no pending offer on this move", 0); + } + } else { + /* Not used for offers from chess program */ + } +} + +void +RematchEvent() +{ + /* Issue ICS rematch command */ + if (appData.icsActive) { + SendToICS(ics_prefix); + SendToICS("rematch\n"); + } +} + +void +CallFlagEvent() +{ + /* Call your opponent's flag (claim a win on time) */ + if (appData.icsActive) { + SendToICS(ics_prefix); + SendToICS("flag\n"); + } else { + switch (gameMode) { + default: + return; + case MachinePlaysWhite: + if (whiteFlag) { + if (blackFlag) + GameEnds(GameIsDrawn, "Both players ran out of time", + GE_PLAYER); + else + GameEnds(BlackWins, "Black wins on time", GE_PLAYER); + } else { + DisplayError("Your opponent is not out of time", 0); + } + break; + case MachinePlaysBlack: + if (blackFlag) { + if (whiteFlag) + GameEnds(GameIsDrawn, "Both players ran out of time", + GE_PLAYER); + else + GameEnds(WhiteWins, "White wins on time", GE_PLAYER); + } else { + DisplayError("Your opponent is not out of time", 0); + } + break; + } + } +} + +void +DrawEvent() +{ + /* Offer draw or accept pending draw offer from opponent */ + + if (appData.icsActive) { + /* Note: tournament rules require draw offers to be + made after you make your move but before you punch + your clock. Currently ICS doesn't let you do that; + instead, you immediately punch your clock after making + a move, but you can offer a draw at any time. */ + + SendToICS(ics_prefix); + SendToICS("draw\n"); + } else if (cmailMsgLoaded) { + if (currentMove == cmailOldMove && + commentList[cmailOldMove] != NULL && + StrStr(commentList[cmailOldMove], WhiteOnMove(cmailOldMove) ? + "Black offers a draw" : "White offers a draw")) { + GameEnds(GameIsDrawn, "Draw agreed", GE_PLAYER); + cmailMoveType[lastLoadGameNumber - 1] = CMAIL_ACCEPT; + } else if (currentMove == cmailOldMove + 1) { + char *offer = WhiteOnMove(cmailOldMove) ? + "White offers a draw" : "Black offers a draw"; + AppendComment(currentMove, offer); + DisplayComment(currentMove - 1, offer); + cmailMoveType[lastLoadGameNumber - 1] = CMAIL_DRAW; + } else { + DisplayError("You must make your move before offering a draw", 0); + cmailMoveType[lastLoadGameNumber - 1] = CMAIL_MOVE; + } + } else if (first.offeredDraw) { + GameEnds(GameIsDrawn, "Draw agreed", GE_XBOARD); + } else { + if (first.sendDrawOffers) { + SendToProgram("draw\n", &first); + userOfferedDraw = TRUE; + } + } +} + +void +AdjournEvent() +{ + /* Offer Adjourn or accept pending Adjourn offer from opponent */ + + if (appData.icsActive) { + SendToICS(ics_prefix); + SendToICS("adjourn\n"); + } else { + /* Currently GNU Chess doesn't offer or accept Adjourns */ + } +} + + +void +AbortEvent() +{ + /* Offer Abort or accept pending Abort offer from opponent */ + + if (appData.icsActive) { + SendToICS(ics_prefix); + SendToICS("abort\n"); + } else { + GameEnds(GameUnfinished, "Game aborted", GE_PLAYER); + } +} + +void +ResignEvent() +{ + /* Resign. You can do this even if it's not your turn. */ + + if (appData.icsActive) { + SendToICS(ics_prefix); + SendToICS("resign\n"); + } else { + switch (gameMode) { + case MachinePlaysWhite: + GameEnds(WhiteWins, "Black resigns", GE_PLAYER); + break; + case MachinePlaysBlack: + GameEnds(BlackWins, "White resigns", GE_PLAYER); + break; + case EditGame: + if (cmailMsgLoaded) { + TruncateGame(); + if (WhiteOnMove(cmailOldMove)) { + GameEnds(BlackWins, "White resigns", GE_PLAYER); + } else { + GameEnds(WhiteWins, "Black resigns", GE_PLAYER); + } + cmailMoveType[lastLoadGameNumber - 1] = CMAIL_RESIGN; + } + break; + default: + break; + } + } +} + + +void +StopObservingEvent() +{ + /* Stop observing current games */ + SendToICS(ics_prefix); + SendToICS("unobserve\n"); +} + +void +StopExaminingEvent() +{ + /* Stop observing current game */ + SendToICS(ics_prefix); + SendToICS("unexamine\n"); +} + +void +ForwardInner(target) + int target; +{ + int limit; + + if (appData.debugMode) + fprintf(debugFP, "ForwardInner(%d), current %d, forward %d\n", + target, currentMove, forwardMostMove); + + if (gameMode == EditPosition) + return; + + if (gameMode == PlayFromGameFile && !pausing) + PauseEvent(); + + if (gameMode == IcsExamining && pausing) + limit = pauseExamForwardMostMove; + else + limit = forwardMostMove; + + if (target > limit) target = limit; + + if (target > 0 && moveList[target - 1][0]) { + int fromX, fromY, toX, toY; + toX = moveList[target - 1][2] - 'a'; + toY = moveList[target - 1][3] - '1'; + if (moveList[target - 1][1] == '@') { + if (appData.highlightLastMove) { + SetHighlights(-1, -1, toX, toY); + } + } else { + fromX = moveList[target - 1][0] - 'a'; + fromY = moveList[target - 1][1] - '1'; + if (target == currentMove + 1) { + AnimateMove(boards[currentMove], fromX, fromY, toX, toY); + } + if (appData.highlightLastMove) { + SetHighlights(fromX, fromY, toX, toY); + } + } + } + if (gameMode == EditGame || gameMode == AnalyzeMode || + gameMode == Training || gameMode == PlayFromGameFile || + gameMode == AnalyzeFile) { + while (currentMove < target) { + SendMoveToProgram(currentMove++, &first); + } + } else { + currentMove = target; + } + + if (gameMode == EditGame || gameMode == EndOfGame) { + whiteTimeRemaining = timeRemaining[0][currentMove]; + blackTimeRemaining = timeRemaining[1][currentMove]; + } + DisplayBothClocks(); + DisplayMove(currentMove - 1); + DrawPosition(FALSE, boards[currentMove]); + HistorySet(parseList,backwardMostMove,forwardMostMove,currentMove-1); + if (commentList[currentMove] && !matchMode && gameMode != Training) { + DisplayComment(currentMove - 1, commentList[currentMove]); + } +} + + +void +ForwardEvent() +{ + if (gameMode == IcsExamining && !pausing) { + SendToICS(ics_prefix); + SendToICS("forward\n"); + } else { + ForwardInner(currentMove + 1); + } +} + +void +ToEndEvent() +{ + if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) { + /* to optimze, we temporarily turn off analysis mode while we feed + * the remaining moves to the engine. Otherwise we get analysis output + * after each move. + */ + if (first.analysisSupport) { + SendToProgram("exit\nforce\n", &first); + first.analyzing = FALSE; + } + } + + if (gameMode == IcsExamining && !pausing) { + SendToICS(ics_prefix); + SendToICS("forward 999999\n"); + } else { + ForwardInner(forwardMostMove); + } + + if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) { + /* we have fed all the moves, so reactivate analysis mode */ + SendToProgram("analyze\n", &first); + first.analyzing = TRUE; + /*first.maybeThinking = TRUE;*/ + first.maybeThinking = FALSE; /* avoid killing GNU Chess */ + } +} + +void +BackwardInner(target) + int target; +{ + if (appData.debugMode) + fprintf(debugFP, "BackwardInner(%d), current %d, forward %d\n", + target, currentMove, forwardMostMove); + + if (gameMode == EditPosition) return; + if (currentMove <= backwardMostMove) { + ClearHighlights(); + DrawPosition(FALSE, boards[currentMove]); + return; + } + if (gameMode == PlayFromGameFile && !pausing) + PauseEvent(); + + if (moveList[target][0]) { + int fromX, fromY, toX, toY; + toX = moveList[target][2] - 'a'; + toY = moveList[target][3] - '1'; + if (moveList[target][1] == '@') { + if (appData.highlightLastMove) { + SetHighlights(-1, -1, toX, toY); + } + } else { + fromX = moveList[target][0] - 'a'; + fromY = moveList[target][1] - '1'; + if (target == currentMove - 1) { + AnimateMove(boards[currentMove], toX, toY, fromX, fromY); + } + if (appData.highlightLastMove) { + SetHighlights(fromX, fromY, toX, toY); + } + } + } + if (gameMode == EditGame || gameMode==AnalyzeMode || + gameMode == PlayFromGameFile || gameMode == AnalyzeFile) { + while (currentMove > target) { + SendToProgram("undo\n", &first); + currentMove--; + } + } else { + currentMove = target; + } + + if (gameMode == EditGame || gameMode == EndOfGame) { + whiteTimeRemaining = timeRemaining[0][currentMove]; + blackTimeRemaining = timeRemaining[1][currentMove]; + } + DisplayBothClocks(); + DisplayMove(currentMove - 1); + DrawPosition(FALSE, boards[currentMove]); + HistorySet(parseList,backwardMostMove,forwardMostMove,currentMove-1); + if (commentList[currentMove] != NULL) { + DisplayComment(currentMove - 1, commentList[currentMove]); + } +} + +void +BackwardEvent() +{ + if (gameMode == IcsExamining && !pausing) { + SendToICS(ics_prefix); + SendToICS("backward\n"); + } else { + BackwardInner(currentMove - 1); + } +} + +void +ToStartEvent() +{ + if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) { + /* to optimze, we temporarily turn off analysis mode while we undo + * all the moves. Otherwise we get analysis output after each undo. + */ + if (first.analysisSupport) { + SendToProgram("exit\nforce\n", &first); + first.analyzing = FALSE; + } + } + + if (gameMode == IcsExamining && !pausing) { + SendToICS(ics_prefix); + SendToICS("backward 999999\n"); + } else { + BackwardInner(backwardMostMove); + } + + if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) { + /* we have fed all the moves, so reactivate analysis mode */ + SendToProgram("analyze\n", &first); + first.analyzing = TRUE; + /*first.maybeThinking = TRUE;*/ + first.maybeThinking = FALSE; /* avoid killing GNU Chess */ + } +} + +void +ToNrEvent(int to) +{ + if (gameMode == PlayFromGameFile && !pausing) PauseEvent(); + if (to >= forwardMostMove) to = forwardMostMove; + if (to <= backwardMostMove) to = backwardMostMove; + if (to < currentMove) { + BackwardInner(to); + } else { + ForwardInner(to); + } +} + +void +RevertEvent() +{ + if (gameMode != IcsExamining) { + DisplayError("You are not examining a game", 0); + return; + } + if (pausing) { + DisplayError("You can't revert while pausing", 0); + return; + } + SendToICS(ics_prefix); + SendToICS("revert\n"); +} + +void +RetractMoveEvent() +{ + switch (gameMode) { + case MachinePlaysWhite: + case MachinePlaysBlack: + if (WhiteOnMove(forwardMostMove) == (gameMode == MachinePlaysWhite)) { + DisplayError("Wait until your turn,\nor select Move Now", 0); + return; + } + if (forwardMostMove < 2) return; + currentMove = forwardMostMove = forwardMostMove - 2; + whiteTimeRemaining = timeRemaining[0][currentMove]; + blackTimeRemaining = timeRemaining[1][currentMove]; + DisplayBothClocks(); + DisplayMove(currentMove - 1); + ClearHighlights();/*!! could figure this out*/ + DrawPosition(FALSE, boards[currentMove]); + SendToProgram("remove\n", &first); + /*first.maybeThinking = TRUE;*/ /* GNU Chess does not ponder here */ + break; + + case BeginningOfGame: + default: + break; + + case IcsPlayingWhite: + case IcsPlayingBlack: + if (WhiteOnMove(forwardMostMove) == (gameMode == IcsPlayingWhite)) { + SendToICS(ics_prefix); + SendToICS("takeback 2\n"); + } else { + SendToICS(ics_prefix); + SendToICS("takeback 1\n"); + } + break; + } +} + +void +MoveNowEvent() +{ + ChessProgramState *cps; + + switch (gameMode) { + case MachinePlaysWhite: + if (!WhiteOnMove(forwardMostMove)) { + DisplayError("It is your turn", 0); + return; + } + cps = &first; + break; + case MachinePlaysBlack: + if (WhiteOnMove(forwardMostMove)) { + DisplayError("It is your turn", 0); + return; + } + cps = &first; + break; + case TwoMachinesPlay: + if (WhiteOnMove(forwardMostMove) == + (first.twoMachinesColor[0] == 'w')) { + cps = &first; + } else { + cps = &second; + } + break; + case BeginningOfGame: + default: + return; + } + SendToProgram("?\n", cps); +} + +void +TruncateGameEvent() +{ + EditGameEvent(); + if (gameMode != EditGame) return; + TruncateGame(); +} + +void +TruncateGame() +{ + if (forwardMostMove > currentMove) { + if (gameInfo.resultDetails != NULL) { + free(gameInfo.resultDetails); + gameInfo.resultDetails = NULL; + gameInfo.result = GameUnfinished; + } + forwardMostMove = currentMove; + HistorySet(parseList, backwardMostMove, forwardMostMove, + currentMove-1); + } +} + +void +HintEvent() +{ + if (appData.noChessProgram) return; + switch (gameMode) { + case MachinePlaysWhite: + if (WhiteOnMove(forwardMostMove)) { + DisplayError("Wait until your turn", 0); + return; + } + break; + case BeginningOfGame: + case MachinePlaysBlack: + if (!WhiteOnMove(forwardMostMove)) { + DisplayError("Wait until your turn", 0); + return; + } + break; + default: + DisplayError("No hint available", 0); + return; + } + SendToProgram("hint\n", &first); + hintRequested = TRUE; +} + +void +BookEvent() +{ + if (appData.noChessProgram) return; + switch (gameMode) { + case MachinePlaysWhite: + if (WhiteOnMove(forwardMostMove)) { + DisplayError("Wait until your turn", 0); + return; + } + break; + case BeginningOfGame: + case MachinePlaysBlack: + if (!WhiteOnMove(forwardMostMove)) { + DisplayError("Wait until your turn", 0); + return; + } + break; + case EditPosition: + EditPositionDone(); + break; + case TwoMachinesPlay: + return; + default: + break; + } + SendToProgram("bk\n", &first); + bookOutput[0] = NULLCHAR; + bookRequested = TRUE; +} + +void +AboutGameEvent() +{ + char *tags = PGNTags(&gameInfo); + TagsPopUp(tags, CmailMsg()); + free(tags); +} + +/* end button procedures */ + +void +PrintPosition(fp, move) + FILE *fp; + int move; +{ + int i, j; + + for (i = BOARD_SIZE - 1; i >= 0; i--) { + for (j = 0; j < BOARD_SIZE; j++) { + char c = PieceToChar(boards[move][i][j]); + fputc(c == 'x' ? '.' : c, fp); + fputc(j == BOARD_SIZE - 1 ? '\n' : ' ', fp); + } + } + if ((gameMode == EditPosition) ? !blackPlaysFirst : (move % 2 == 0)) + fprintf(fp, "white to play\n"); + else + fprintf(fp, "black to play\n"); +} + +void +PrintOpponents(fp) + FILE *fp; +{ + if (gameInfo.white != NULL) { + fprintf(fp, "\t%s vs. %s\n", gameInfo.white, gameInfo.black); + } else { + fprintf(fp, "\n"); + } +} + +/* Find last component of program's own name, using some heuristics */ +void +TidyProgramName(prog, host, buf) + char *prog, *host, buf[MSG_SIZ]; +{ + char *p, *q; + int local = (strcmp(host, "localhost") == 0); + while (!local && (p = strchr(prog, ';')) != NULL) { + p++; + while (*p == ' ') p++; + prog = p; + } + if (*prog == '"' || *prog == '\'') { + q = strchr(prog + 1, *prog); + } else { + q = strchr(prog, ' '); + } + if (q == NULL) q = prog + strlen(prog); + p = q; + while (p >= prog && *p != '/' && *p != '\\') p--; + p++; + if (q - p >= 4 && StrCaseCmp(q - 4, ".exe") == 0) q -= 4; + memcpy(buf, p, q - p); + buf[q - p] = NULLCHAR; + if (!local) { + strcat(buf, "@"); + strcat(buf, host); + } +} + +char * +TimeControlTagValue() +{ + char buf[MSG_SIZ]; + if (!appData.clockMode) { + strcpy(buf, "-"); + } else if (movesPerSession > 0) { + sprintf(buf, "%d/%ld", movesPerSession, timeControl/1000); + } else if (timeIncrement == 0) { + sprintf(buf, "%ld", timeControl/1000); + } else { + sprintf(buf, "%ld+%ld", timeControl/1000, timeIncrement/1000); + } + return StrSave(buf); +} + +void +SetGameInfo() +{ + /* This routine is used only for certain modes */ + VariantClass v = gameInfo.variant; + ClearGameInfo(&gameInfo); + gameInfo.variant = v; + + switch (gameMode) { + case MachinePlaysWhite: + gameInfo.event = StrSave("Computer chess game"); + gameInfo.site = StrSave(HostName()); + gameInfo.date = PGNDate(); + gameInfo.round = StrSave("-"); + gameInfo.white = StrSave(first.tidy); + gameInfo.black = StrSave(UserName()); + gameInfo.timeControl = TimeControlTagValue(); + break; + + case MachinePlaysBlack: + gameInfo.event = StrSave("Computer chess game"); + gameInfo.site = StrSave(HostName()); + gameInfo.date = PGNDate(); + gameInfo.round = StrSave("-"); + gameInfo.white = StrSave(UserName()); + gameInfo.black = StrSave(first.tidy); + gameInfo.timeControl = TimeControlTagValue(); + break; + + case TwoMachinesPlay: + gameInfo.event = StrSave("Computer chess game"); + gameInfo.site = StrSave(HostName()); + gameInfo.date = PGNDate(); + if (matchGame > 0) { + char buf[MSG_SIZ]; + sprintf(buf, "%d", matchGame); + gameInfo.round = StrSave(buf); + } else { + gameInfo.round = StrSave("-"); + } + if (first.twoMachinesColor[0] == 'w') { + gameInfo.white = StrSave(first.tidy); + gameInfo.black = StrSave(second.tidy); + } else { + gameInfo.white = StrSave(second.tidy); + gameInfo.black = StrSave(first.tidy); + } + gameInfo.timeControl = TimeControlTagValue(); + break; + + case EditGame: + gameInfo.event = StrSave("Edited game"); + gameInfo.site = StrSave(HostName()); + gameInfo.date = PGNDate(); + gameInfo.round = StrSave("-"); + gameInfo.white = StrSave("-"); + gameInfo.black = StrSave("-"); + break; + + case EditPosition: + gameInfo.event = StrSave("Edited position"); + gameInfo.site = StrSave(HostName()); + gameInfo.date = PGNDate(); + gameInfo.round = StrSave("-"); + gameInfo.white = StrSave("-"); + gameInfo.black = StrSave("-"); + break; + + case IcsPlayingWhite: + case IcsPlayingBlack: + case IcsObserving: + case IcsExamining: + break; + + case PlayFromGameFile: + gameInfo.event = StrSave("Game from non-PGN file"); + gameInfo.site = StrSave(HostName()); + gameInfo.date = PGNDate(); + gameInfo.round = StrSave("-"); + gameInfo.white = StrSave("?"); + gameInfo.black = StrSave("?"); + break; + + default: + break; + } +} + +void +ReplaceComment(index, text) + int index; + char *text; +{ + int len; + + while (*text == '\n') text++; + len = strlen(text); + while (len > 0 && text[len - 1] == '\n') len--; + + if (commentList[index] != NULL) + free(commentList[index]); + + if (len == 0) { + commentList[index] = NULL; + return; + } + commentList[index] = (char *) malloc(len + 2); + strncpy(commentList[index], text, len); + commentList[index][len] = '\n'; + commentList[index][len + 1] = NULLCHAR; +} + +void +AppendComment(index, text) + int index; + char *text; +{ + int oldlen, len; + char *old; + + while (*text == '\n') text++; + len = strlen(text); + while (len > 0 && text[len - 1] == '\n') len--; + + if (len == 0) return; + + if (commentList[index] != NULL) { + old = commentList[index]; + oldlen = strlen(old); + commentList[index] = (char *) malloc(oldlen + len + 2); + strcpy(commentList[index], old); + free(old); + strncpy(&commentList[index][oldlen], text, len); + commentList[index][oldlen + len] = '\n'; + commentList[index][oldlen + len + 1] = NULLCHAR; + } else { + commentList[index] = (char *) malloc(len + 2); + strncpy(commentList[index], text, len); + commentList[index][len] = '\n'; + commentList[index][len + 1] = NULLCHAR; + } +} + +void +SendToProgram(message, cps) + char *message; + ChessProgramState *cps; +{ + int count, outCount, error; + char buf[MSG_SIZ]; + + if (cps->pr == NULL) return; + Attention(cps); + + if (appData.debugMode) { + TimeMark now; + GetTimeMark(&now); + fprintf(debugFP, "%ld >%-6s: %s", + SubtractTimeMarks(&now, &programStartTime), + cps->which, message); + } + + count = strlen(message); + outCount = OutputToProcess(cps->pr, message, count, &error); + if (outCount < count && !exiting) { + sprintf(buf, "Error writing to %s chess program", cps->which); + DisplayFatalError(buf, error, 1); + } +} + +void +ReceiveFromProgram(isr, closure, message, count, error) + InputSourceRef isr; + VOIDSTAR closure; + char *message; + int count; + int error; +{ + char *end_str; + char buf[MSG_SIZ]; + ChessProgramState *cps = (ChessProgramState *)closure; + + if (isr != cps->isr) return; /* Killed intentionally */ + if (count <= 0) { + if (count == 0) { + sprintf(buf, + "Error: %s chess program (%s) exited unexpectedly", + cps->which, cps->program); + RemoveInputSource(cps->isr); + DisplayFatalError(buf, 0, 1); + } else { + sprintf(buf, + "Error reading from %s chess program (%s)", + cps->which, cps->program); + RemoveInputSource(cps->isr); + DisplayFatalError(buf, error, 1); + } + GameEnds((ChessMove) 0, NULL, GE_PLAYER); + return; + } + + if ((end_str = strchr(message, '\r')) != NULL) + *end_str = NULLCHAR; + if ((end_str = strchr(message, '\n')) != NULL) + *end_str = NULLCHAR; + + if (appData.debugMode) { + TimeMark now; + GetTimeMark(&now); + fprintf(debugFP, "%ld <%-6s: %s\n", + SubtractTimeMarks(&now, &programStartTime), + cps->which, message); + } + + if (appData.icsAnalyze) { + /* wb2 - can reset a setting - we are in possible ics mode - drop */ + if (strstr(message, "whisper") != NULL || + strstr(message, "kibitz") != NULL || + strstr(message, "set 1") != NULL) { + if (appData.debugMode) fprintf(debugFP, "ICS Analyze: Drop engine output\n"); + } else { + HandleMachineMove(message, cps); + } + } else { + HandleMachineMove(message, cps); + } +} + + +void +SendTimeControl(cps, mps, tc, inc, sd, st) + ChessProgramState *cps; + int mps, inc, sd, st; + long tc; +{ + char buf[MSG_SIZ]; + int seconds = (tc / 1000) % 60; + + if (st > 0) { + /* Set exact time per move, normally using st command */ + if (cps->stKludge) { + /* GNU Chess 4 has no st command; uses level in a nonstandard way */ + seconds = st % 60; + if (seconds == 0) { + sprintf(buf, "level 1 %d\n", st/60); + } else { + sprintf(buf, "level 1 %d:%02d\n", st/60, seconds); + } + } else { + sprintf(buf, "st %d\n", st); + } + } else { + /* Set conventional or incremental time control, using level command */ + if (seconds == 0) { + /* Note old gnuchess bug -- minutes:seconds used to not work. + Fixed in later versions, but still avoid :seconds + when seconds is 0. */ + sprintf(buf, "level %d %ld %d\n", mps, tc/60000, inc/1000); + } else { + sprintf(buf, "level %d %ld:%02d %d\n", mps, tc/60000, + seconds, inc/1000); + } + } + SendToProgram(buf, cps); + + /* Orthoganally (except for GNU Chess 4), limit time to st seconds */ + /* Orthogonally, limit search to given depth */ + if (sd > 0) { + if (cps->sdKludge) { + sprintf(buf, "depth\n%d\n", sd); + } else { + sprintf(buf, "sd %d\n", sd); + } + SendToProgram(buf, cps); + } +} + +void +SendTimeRemaining(cps, machineWhite) + ChessProgramState *cps; + int /*boolean*/ machineWhite; +{ + char message[MSG_SIZ]; + long time, otime; + + /* Note: this routine must be called when the clocks are stopped + or when they have *just* been set or switched; otherwise + it will be off by the time since the current tick started. + */ + if (machineWhite) { + time = whiteTimeRemaining / 10; + otime = blackTimeRemaining / 10; + } else { + time = blackTimeRemaining / 10; + otime = whiteTimeRemaining / 10; + } + if (time <= 0) time = 1; + if (otime <= 0) otime = 1; + + sprintf(message, "time %ld\notim %ld\n", time, otime); + SendToProgram(message, cps); +} + +int +BoolFeature(p, name, loc, cps) + char **p; + char *name; + int *loc; + ChessProgramState *cps; +{ + char buf[MSG_SIZ]; + int len = strlen(name); + int val; + if (strncmp((*p), name, len) == 0 && (*p)[len] == '=') { + (*p) += len + 1; + sscanf(*p, "%d", &val); + *loc = (val != 0); + while (**p && **p != ' ') (*p)++; + sprintf(buf, "accepted %s\n", name); + SendToProgram(buf, cps); + return TRUE; + } + return FALSE; +} + +int +IntFeature(p, name, loc, cps) + char **p; + char *name; + int *loc; + ChessProgramState *cps; +{ + char buf[MSG_SIZ]; + int len = strlen(name); + if (strncmp((*p), name, len) == 0 && (*p)[len] == '=') { + (*p) += len + 1; + sscanf(*p, "%d", loc); + while (**p && **p != ' ') (*p)++; + sprintf(buf, "accepted %s\n", name); + SendToProgram(buf, cps); + return TRUE; + } + return FALSE; +} + +int +StringFeature(p, name, loc, cps) + char **p; + char *name; + char loc[]; + ChessProgramState *cps; +{ + char buf[MSG_SIZ]; + int len = strlen(name); + if (strncmp((*p), name, len) == 0 + && (*p)[len] == '=' && (*p)[len+1] == '\"') { + (*p) += len + 2; + sscanf(*p, "%[^\"]", loc); + while (**p && **p != '\"') (*p)++; + if (**p == '\"') (*p)++; + sprintf(buf, "accepted %s\n", name); + SendToProgram(buf, cps); + return TRUE; + } + return FALSE; +} + +void +FeatureDone(cps, val) + ChessProgramState* cps; + int val; +{ + DelayedEventCallback cb = GetDelayedEvent(); + if ((cb == InitBackEnd3 && cps == &first) || + (cb == TwoMachinesEventIfReady && cps == &second)) { + CancelDelayedEvent(); + ScheduleDelayedEvent(cb, val ? 1 : 3600000); + } + cps->initDone = val; +} + +/* Parse feature command from engine */ +void +ParseFeatures(args, cps) + char* args; + ChessProgramState *cps; +{ + char *p = args; + char *q; + int val; + char buf[MSG_SIZ]; + + for (;;) { + while (*p == ' ') p++; + if (*p == NULLCHAR) return; + + if (BoolFeature(&p, "setboard", &cps->useSetboard, cps)) continue; + if (BoolFeature(&p, "time", &cps->sendTime, cps)) continue; + if (BoolFeature(&p, "draw", &cps->sendDrawOffers, cps)) continue; + if (BoolFeature(&p, "sigint", &cps->useSigint, cps)) continue; + if (BoolFeature(&p, "sigterm", &cps->useSigterm, cps)) continue; + if (BoolFeature(&p, "reuse", &val, cps)) { + /* Engine can disable reuse, but can't enable it if user said no */ + if (!val) cps->reuse = FALSE; + continue; + } + if (BoolFeature(&p, "analyze", &cps->analysisSupport, cps)) continue; + if (StringFeature(&p, "myname", &cps->tidy, cps)) { + if (gameMode == TwoMachinesPlay) { + DisplayTwoMachinesTitle(); + } else { + DisplayTitle(""); + } + continue; + } + if (StringFeature(&p, "variants", &cps->variants, cps)) continue; + if (BoolFeature(&p, "san", &cps->useSAN, cps)) continue; + if (BoolFeature(&p, "ping", &cps->usePing, cps)) continue; + if (BoolFeature(&p, "playother", &cps->usePlayother, cps)) continue; + if (BoolFeature(&p, "colors", &cps->useColors, cps)) continue; + if (BoolFeature(&p, "usermove", &cps->useUsermove, cps)) continue; + if (BoolFeature(&p, "ics", &cps->sendICS, cps)) continue; + if (BoolFeature(&p, "name", &cps->sendName, cps)) continue; + if (BoolFeature(&p, "pause", &val, cps)) continue; /* unused at present */ + if (IntFeature(&p, "done", &val, cps)) { + FeatureDone(cps, val); + continue; + } + + /* unknown feature: complain and skip */ + q = p; + while (*q && *q != '=') q++; + sprintf(buf, "rejected %.*s\n", q-p, p); + SendToProgram(buf, cps); + p = q; + if (*p == '=') { + p++; + if (*p == '\"') { + p++; + while (*p && *p != '\"') p++; + if (*p == '\"') p++; + } else { + while (*p && *p != ' ') p++; + } + } + } + +} + +void +PeriodicUpdatesEvent(newState) + int newState; +{ + if (newState == appData.periodicUpdates) + return; + + appData.periodicUpdates=newState; + + /* Display type changes, so update it now */ + DisplayAnalysis(0,0); + + /* Get the ball rolling again... */ + if (newState) { + if (gameMode == AnalyzeMode || gameMode == AnalyzeFile || + appData.icsAnalyze || appData.AnalysisWindow) { + AnalysisPeriodicEvent(1); + StartAnalysisClock(); + } + } +} + +void +PonderNextMoveEvent(newState) + int newState; +{ + if (newState == appData.ponderNextMove) return; + if (gameMode == EditPosition) EditPositionDone(); + if (newState) { + SendToProgram("hard\n", &first); + if (gameMode == TwoMachinesPlay) { + SendToProgram("hard\n", &second); + } + } else { + SendToProgram("easy\n", &first); + thinkOutput[0] = NULLCHAR; + if (gameMode == TwoMachinesPlay) { + SendToProgram("easy\n", &second); + } + } + appData.ponderNextMove = newState; +} + +void +ShowThinkingEvent(newState) + int newState; +{ + if (newState == appData.showThinking) return; + if (gameMode == EditPosition) EditPositionDone(); + if (newState) { + SendToProgram("post\n", &first); + if (gameMode == TwoMachinesPlay) { + SendToProgram("post\n", &second); + } + } else { + if (appData.AnalysisWindow) { + AnalysisPopDown(); + appData.AnalysisWindow = FALSE; + } + SendToProgram("nopost\n", &first); + thinkOutput[0] = NULLCHAR; + if (gameMode == TwoMachinesPlay) { + SendToProgram("nopost\n", &second); + } + } + appData.showThinking = newState; +} + +void +AskQuestionEvent(title, question, replyPrefix, which) + char *title; char *question; char *replyPrefix; char *which; +{ + ProcRef pr = (which[0] == '1') ? first.pr : second.pr; + if (pr == NoProc) return; + AskQuestion(title, question, replyPrefix, pr); +} + +void +DisplayMove(moveNumber) + int moveNumber; +{ + char message[MSG_SIZ]; + char res[MSG_SIZ]; + char cpThinkOutput[MSG_SIZ]; + static char last[1024]; + + int i = 0; + + if (moveNumber == forwardMostMove - 1 || + gameMode == AnalyzeMode || gameMode == AnalyzeFile) { + + strcpy(cpThinkOutput, thinkOutput); + if (strchr(cpThinkOutput, '\n')) + *strchr(cpThinkOutput, '\n') = NULLCHAR; + } else { + *cpThinkOutput = NULLCHAR; + } + + if (moveNumber == forwardMostMove - 1 && + gameInfo.resultDetails != NULL) { + if (gameInfo.resultDetails[0] == NULLCHAR) { + sprintf(res, " %s", PGNResult(gameInfo.result)); + } else { + sprintf(res, " {%s} %s", + gameInfo.resultDetails, PGNResult(gameInfo.result)); + } + + } else { + res[0] = NULLCHAR; + } + + if (moveNumber < 0 || parseList[moveNumber][0] == NULLCHAR) { + /* Output to ICC if IcsAnalyze */ + if(appData.icsAnalyze) IcsAnalyzeOutPut(&first, TRUE); + DisplayMessage(res, cpThinkOutput); + } else { + sprintf(message, "%d.%s%s%s", moveNumber / 2 + 1, + WhiteOnMove(moveNumber) ? " " : ".. ", + parseList[moveNumber], res); + if(appData.icsAnalyze) IcsAnalyzeOutPut(&first, FALSE); + DisplayMessage(message, cpThinkOutput); + } + + /* Send Engine output to ICS */ + if (appData.icsActive && appData.ButtonSendOutPutToICS + && appData.AnalysisWindow) { + + /* only send on move */ + switch (gameMode) { + case IcsPlayingWhite: + if(WhiteOnMove(currentMove)) i = 1; + break; + case IcsPlayingBlack: + if(!WhiteOnMove(currentMove)) i = 1; + break; + } + + if (i == 0 || programStats.depth <= 1 || programStats.depth >= 30 || + programStats.GUI_time <= 3) return; + + if (strcmp(programStats.movelist, last) == 0) return; + strcpy(last, programStats.movelist); + + switch (appData.SendOutPutToICS) { + + case 1: + sprintf(res, "whisper time: %d sec %+.2f/%d %s \n", programStats.GUI_time, + (((float)programStats.score)/100.0), programStats.depth, programStats.movelist); + SendToICS(res); + break; + case 2: + sprintf(res, "kibitz time: %d sec %+.2f/%d %s \n", programStats.GUI_time, + (((float)programStats.score)/100.0), programStats.depth, programStats.movelist); + SendToICS(res); + break; + + default: + break; + } + } +} + + +void +IcsAnalyzeOutPut(cps, endThink) +ChessProgramState *cps; +int endThink; +{ + char cpIcsThinkOutput[MSG_SIZ], icsOutput[32], str[8192]; + static char last[MSG_SIZ]; + long currentTime; + int diff, s, h, m, wait, info; + static int lastGame, lastMove, firstRun, say, lastdepth, sec; + double nps; + + if (appData.icsAnalyzeOutPut == 4 || !appData.icsAnalyze || + gameMode != IcsObserving) return; + + if (appData.icsSmartQueue == 0) { + wait = 60; + } else { + wait = 5; + } + + currentTime = programStats.time; + + /* calculate some infos */ + s = currentTime / 100; + sec = s; /* save complete sec */ + h = (s / (60*60)); + s = s - h*60*60; + m = (s/60); + s = s - m*60; + if (programStats.time == 0) programStats.time = 1; + nps = ((((double)programStats.nodes) / + (((double)programStats.time)/100.0)) /1000); + + if (ics_gamenum > max_gamenum || ics_gamenum == -1) { + DisplayFatalError("ICS-Analysis: Fatal array error - Please make a bugreport.", 0, 1); + return; + } + + /* init ICS gamequeue - safty */ + /* normaly we do that with read_from_ics() */ + if (icsQueue[ics_gamenum].killPv == 0) { + icsQueue[ics_gamenum].move = currentMove; + icsQueue[ics_gamenum].killPv = appData.icsKillPVs; + icsQueue[ics_gamenum].counter = 0; + icsQueue[ics_gamenum].lastpv[0] = NULLCHAR; + } + + /* for chess.fm on ICC we must copy player names each move */ + strcpy(icsQueue[ics_gamenum].white, gameInfo.white); + strcpy(icsQueue[ics_gamenum].black, gameInfo.black); + + if (appData.smartQueue) { + if (lastGame == 0) lastGame = ics_gamenum; + if (lastMove == 0) lastMove = currentMove; + if (ics_gamenum != lastGame || lastMove != currentMove) { + firstRun = 1; + icsQueue[ics_gamenum].counter = 0; + } + } + + /* checking other games - only for live broadcasting */ + /* init on a new move */ + if (appData.icsAnalyzeOutPut != 4) { + if (icsQueue[ics_gamenum].CurrentMove != currentMove) { + icsQueue[ics_gamenum].CurrentMove = currentMove; + icsQueue[ics_gamenum].flag = 0; /* we have not send */ + icsQueue[ics_gamenum].counter = 0; + } + } + + strcpy(cpIcsThinkOutput, thinkOutput); + if (strchr(cpIcsThinkOutput, '\n')) { + *strchr(cpIcsThinkOutput, '\n') = NULLCHAR; + } + if (cpIcsThinkOutput[0] == NULLCHAR) return; + + /* Special ICC fetures - works only with param /icc */ + if (ics_type == ICS_ICC && appData.ICC_feature == TRUE && + appData.userVersion == FALSE) { + if (appData.icsAnalyzeOutPut == 3) { + /* If we start a new broadcast analyse we inform user */ + if (icsQueue[ics_gamenum].lastpv[0] == NULLCHAR) { + sprintf(str, "whisperto %d Hello from Winboard-DM \n", ics_gamenum); + SendToICS(str); + } + + /* If long tourney games >= 120 0 */ + if (appData.icsSmartQueue == 0) { + switch (currentMove) { + case 20: case 40: case 60: case 80: case 100: case 135: case 160: + if (icsQueue[ics_gamenum].event == 0) { + sprintf(str, "whisperto %d Hello, i'm an analysis engine.\n", ics_gamenum); + SendToICS(str); + sprintf(str, "whisperto %d If you want my last analysis of this game, just type \"tell %s showinfo %d\"\n", + ics_gamenum, ics_handle, ics_gamenum); + SendToICS(str); + if (strcmp(appData.icsTells, "211") == 0) { + sprintf(str, "whisperto %d and/or type \"+ch 211\" for a ICC channel analysis\n", ics_gamenum); + SendToICS(str); + } + icsQueue[ics_gamenum].event = 1; + + /* channel 165 on ICC */ + if (currentMove == 20 && chessfm == 0) { + info = 1; + chessfm = 1; + } else if (currentMove == 40 && (chessfm == 1 || chessfm == 0)) { + info = 1; + chessfm = 2; + } else if (currentMove == 60 && (chessfm == 2 || chessfm == 0)) { + info = 1; + chessfm = 3; + } else if (currentMove == 80 && (chessfm == 3 || chessfm == 0)) { + info = 1; + chessfm = 4; + } else if (currentMove == 100 && (chessfm == 4 || chessfm == 0)) { + info = 1; + chessfm = 5; + } else { + info = 0; + } + + if (info == 1) { + sprintf(str, "tell 165 Hi, i'm analyzing live broadcast games. \"tell %s showgames \" to see which games are currently analyzed.\n", ics_handle); + SendToICS(str); + sprintf(str, "tell 165 \"finger %s\" and \"finger live\" for more details \n", ics_handle); + SendToICS(str); + } + } + break; + default: + icsQueue[ics_gamenum].event = 0; + } + } else { + switch (currentMove) { + case 20: case 60: case 100: + if (icsQueue[ics_gamenum].event == 0) { + sprintf(str, "whisperto %d Hello, i'm an analysis engine.\n", ics_gamenum); + SendToICS(str); + sprintf(str, "whisperto %d If you want my last analysis of this game, just type \"tell %s showinfo %d\"\n", + ics_gamenum, ics_handle, ics_gamenum); + SendToICS(str); + if (strcmp(appData.icsTells, "211") == 0) { + sprintf(str, "whisperto %d and/or type \"+ch 211\" for a ICC channel analysis\n", ics_gamenum); + SendToICS(str); + } + icsQueue[ics_gamenum].event = 1; + } + break; + default: + icsQueue[ics_gamenum].event = 0; + } + + } + /* save last game pv for user request */ + sprintf(icsQueue[ics_gamenum].lastpv, "%s time: %02d:%02d min nps: %dK \n", cpIcsThinkOutput, m, s, (int)nps); + } + } + + switch(appData.icsAnalyzeOutPut) { + case 1: + switch (ics_type) { + case ICS_ICC: strcpy(icsOutput, "whisperto"); + break; + case ICS_FICS: strcpy(icsOutput, "xwhisper"); + break; + case ICS_GENERIC: + case ICS_CHESSNET: + default: + DisplayFatalError("ICS-Analysis: Sorry, this Serverprotocoll is not supported",0,2); + break; + } + break; + case 2: + switch (ics_type) { + case ICS_ICC: strcpy(icsOutput, "kibitzto"); + break; + case ICS_FICS: strcpy(icsOutput, "xkibitz"); + break; + case ICS_GENERIC: + case ICS_CHESSNET: + default: + DisplayFatalError("ICS-Analysis: Sorry, this Serverprotocoll is not supported",0,2); + break; + } + break; + case 3: + strcpy(icsOutput, "tell"); + break; + default: + /* could't happen */ + return; + } + + /* Drop double output - example Crafty */ + if (strcmp(cpIcsThinkOutput, last) == 0) { + /* Check again if we can switch game - that will be faster as we wait for next ply */ + if (icsQueue[ics_gamenum].flag == 1) { + if (SwitchGames() == 0) return; + } + /* special crafty feature - let interation pass */ + if (strncmp(cps->tidy, "Crafty", 6) != 0) return; + } + + /* if skip high/fail low active we only send every complete interation from engine */ + if (lastdepth == 0 || lastdepth > programStats.depth) lastdepth = programStats.depth; + + + /* Drop all about 25 plys - could be egtb output */ + if (programStats.depth > 25) { + if (appData.icsAnalyzeOutPut == 3) { + /* We don't stay longer on this game - just try to switching other games */ + icsQueue[ics_gamenum].flag = 1; /* done */ + icsQueue[ics_gamenum].MessageMove = currentMove; + if (SwitchGames() == 0) return; + } + return; + } + + /* Drop score above 10.0 - many engines send to many lines if mate */ + if ((programStats.score / 100) > 10 || (programStats.score / 100) < -10) { + if (appData.icsAnalyzeOutPut == 3) { + /* We don't stay longer on this game - just switching to other games */ + icsQueue[ics_gamenum].flag = 1; /* done */ + icsQueue[ics_gamenum].MessageMove = currentMove; + if (SwitchGames() == 0) return; + } + return; + } + /* tell ICC fail high move if possible */ + if (ics_type == ICS_ICC && appData.ICC_feature == TRUE && appData.userVersion == FALSE && + appData.icsAnalyzeOutPut == 3 && programStats.depth >= icsQueue[ics_gamenum].killPv) { + //if (strchr(cpIcsThinkOutput, '!!') != NULL && strncmp(cps->tidy, "Yace" , 4) != 0) { + //sprintf(str, "whisperto %d Analysis: Something happened - Side on move maybe looks better as before. \n", ics_gamenum); + //SendToICS(str); + //} else if (strchr(cpIcsThinkOutput, '(++)') != NULL && strncmp(cps->tidy, "Yace" , 4) == 0) { + //sprintf(str, "whisperto %d Analysis: Something happened - Side on move maybe looks better as before. \n", ics_gamenum); + //SendToICS(str); + //} + } + + /* Drop fail high/low moves from engines */ + if (appData.windowMove) { + if (strchr(cpIcsThinkOutput, '?') != NULL || strchr(cpIcsThinkOutput, '!') != NULL || + strchr(cpIcsThinkOutput, 't') != NULL || strchr(cpIcsThinkOutput, 'u') != NULL) { + if (appData.debugMode) fprintf(debugFP, "ICS-Analyze: Drop move with string \n"); + return; + } + } + + /* smart Queue fast down handling */ + if (sec > wait && programStats.depth <= (icsQueue[ics_gamenum].killPv - 1) && + appData.smartQueue) { + if (icsQueue[ics_gamenum].killPv > 8) { + if (!appData.icsEngineKillPV) appData.icsEngineKillPV = TRUE; + if (lastMove == currentMove) icsQueue[ics_gamenum].killPv--; + if (appData.debugMode) fprintf(debugFP, "icsQueue[%d].killPv-- \n", + icsQueue[ics_gamenum].killPv); + } + } + /* smart Queue fast up handling */ + if (sec < 30 && programStats.depth >= icsQueue[ics_gamenum].killPv && + appData.smartQueue) { + if (!appData.icsEngineKillPV) appData.icsEngineKillPV = TRUE; + if (lastMove == currentMove ) { + /* Crafty send 2x string so this is a importent reason */ + if (strncmp(cps->tidy, "Crafty", 6) == 0 && + strcmp(cpIcsThinkOutput, last) != 0) { + icsQueue[ics_gamenum].killPv++; + } else if (strncmp(cps->tidy, "Crafty", 6) != 0) { + /* other programs */ + icsQueue[ics_gamenum].killPv++; + } + } + if (appData.debugMode) fprintf(debugFP, "icsQueue[%d].killPv++ \n", + icsQueue[ics_gamenum].killPv); + } + /* smart Queue handling */ + if (appData.smartQueue && programStats.depth >= icsQueue[ics_gamenum].killPv) { + diff = ((int)currentTime / 100) - ((int)icsQueue[ics_gamenum].time / 100); + if ((diff < 7 && diff != 0) && icsQueue[ics_gamenum].counter > 3 && + icsQueue[ics_gamenum].move <= currentMove) { + if (!appData.icsEngineKillPV) appData.icsEngineKillPV = TRUE; + appData.icsEngineKillPV = TRUE; + icsQueue[ics_gamenum].killPv++; + icsQueue[ics_gamenum].move = currentMove + 1; + icsQueue[ics_gamenum].counter = 0; + if (appData.debugMode) fprintf(debugFP, "icsQueue[%d].killPv++ \n", + icsQueue[ics_gamenum].killPv); + /* normal down */ + } else if (diff > wait && icsQueue[ics_gamenum].counter < 2 && + icsQueue[ics_gamenum].move <= currentMove && firstRun == 1 && + lastMove != currentMove) { + if(icsQueue[ics_gamenum].killPv > 8) { + if (!appData.icsEngineKillPV) appData.icsEngineKillPV = TRUE; + if (lastMove == currentMove) icsQueue[ics_gamenum].killPv--; + firstRun = 0; + if (appData.debugMode) fprintf(debugFP, "icsQueue[%d].killPv-- \n", + icsQueue[ics_gamenum].killPv); + } + icsQueue[ics_gamenum].move = currentMove + 1; + icsQueue[ics_gamenum].counter = 0; + } else { + icsQueue[ics_gamenum].counter++; + lastGame = ics_gamenum; + lastMove = currentMove; + } + } + icsQueue[ics_gamenum].time = currentTime; + + /* Check other games part 2 */ + if (appData.icsAnalyzeOutPut != 4) { + /* if no other games avaible we coming back */ + if (icsQueue[ics_gamenum].flag == 1) { + if (SwitchGames() == 0) return; + } + } + + /* kill PV here */ + if (programStats.line_is_book != 1 || programStats.depth != 0) { + if (appData.icsEngineKillPV || appData.smartQueue) { + if(programStats.depth < icsQueue[ics_gamenum].killPv || + programStats.depth < appData.icsKillPVs && programStats.depth != 0) return; + } + } + + /* send information */ + if (programStats.line_is_book == 1 && programStats.depth < 2 || + programStats.depth == 0) { + if (appData.icsAnalyzeOutPut != 3) { + /* We must whisperto if we follow someone */ + /* on FCIS we need xwhisper */ + sprintf(str, "%s %d %s: Book depth=%s \n", icsOutput, ics_gamenum, + cps->tidy, cpIcsThinkOutput); + } else { + if (currentMove > -1) { + sprintf(str, "%s %s %s: (%s/%s) Book %d.%s depth=%s (game \"observe %d\")\n", icsOutput, + appData.icsTells, cps->tidy, gameInfo.white, gameInfo.black, + currentMove / 2 + 1, WhiteOnMove(currentMove) ? " " : "... ", + cpIcsThinkOutput, ics_gamenum); + + icsQueue[ics_gamenum].MessageMove = currentMove; + } + icsQueue[ics_gamenum].flag = 1; /* we send */ + } + SendToICS(str); + } else { + /* interation check */ + /* special crafty interation */ + if (appData.windowMove && strncmp(cps->tidy, "Crafty" , 6) == 0 && + strcmp(cpIcsThinkOutput, last) != 0) { + strcpy(last,cpIcsThinkOutput); + return; + } + /* normal interation check */ + if (appData.windowMove && programStats.depth <= lastdepth) return; + + if (appData.icsAnalyzeOutPut != 3) { + if (endThink == TRUE) { + sprintf(str, "%s %d %s: first move (Depth=%s time: %02d:%02d min nps: %dK \n", icsOutput, + ics_gamenum, cps->tidy, cpIcsThinkOutput, m, s, (int)nps); + } else { + sprintf(str, "%s %d %s: Depth=%s time: %02d:%02d min nps: %dK \n", icsOutput, ics_gamenum, + cps->tidy, cpIcsThinkOutput, m, s, (int)nps); + } + icsQueue[ics_gamenum].flag = 1; /* we send */ + SendToICS(str); + } else { + if (endThink == TRUE) { + sprintf(str, "%s %s %s: (%s/%s) first move (Depth=%s time: %02d:%02d min nps: %dK (game \"observe %d\")\n", icsOutput, + appData.icsTells, cps->tidy, gameInfo.white, gameInfo.black, + cpIcsThinkOutput, m, s, (int)nps, ics_gamenum); + } else { + sprintf(str, "%s %s %s: (%s/%s) Depth=%s time: %02d:%02d min nps: %dK (game \"observe %d\")\n", icsOutput, + appData.icsTells, cps->tidy, gameInfo.white, gameInfo.black, + cpIcsThinkOutput, m, s, (int)nps, ics_gamenum); + } + icsQueue[ics_gamenum].flag = 1; /* we send */ + icsQueue[ics_gamenum].MessageMove = currentMove; + SendToICS(str); + } + } + strcpy(last,cpIcsThinkOutput); + lastdepth = programStats.depth; + + /* At least we search for a open game once more */ + if (icsQueue[ics_gamenum].flag == 1) { + if (SwitchGames() == 0 && appData.debugMode) { + fprintf(debugFP, "Switch was at end of produce \n"); + } + } +} + + +/* Reset icsGameQueue if game ends or user abort */ +void +ResetIcsQueue(gamenumber) +{ + icsQueue[gamenumber].black[0] = NULLCHAR; + icsQueue[gamenumber].white[0] = NULLCHAR; + icsQueue[gamenumber].counter = 0; + icsQueue[gamenumber].currentGame = 0; + icsQueue[gamenumber].CurrentMove = 0; + icsQueue[gamenumber].event = 0; + icsQueue[gamenumber].killPv = 0; + icsQueue[gamenumber].lastpv[0] = NULLCHAR; + icsQueue[gamenumber].MessageMove = 0; + icsQueue[gamenumber].move = 0; + icsQueue[gamenumber].time = 0; +} + +/* GUI -> engine */ +void +GuiCommand(command, param) +int command; +int param; /* reserved */ +{ + switch (command) { + case 1: + switch (gameMode) { + case MachinePlaysWhite: + case MachinePlaysBlack: + SendToProgram("?\n", &first); + break; + } + break; + case 2: + switch (gameMode) { + case AnalyzeMode: + case AnalyzeFile: + if (first.analyzing == TRUE) { + /* don't send stat */ + appData.engineStatLine = TRUE; + SendToProgram("exit\n", &first); + SendToProgram("force\n", &first); + first.analyzing = FALSE; + PeriodicUpdatesEvent(FALSE); + DisplayAnalysis(6,0); + } else { + /* safty with force */ + /* send stat */ + appData.engineStatLine = FALSE; + SendToProgram("analyze\n", &first); + first.analyzing = TRUE; + PeriodicUpdatesEvent(TRUE); + } + break; + /* a lot of engine makes probs if we switch from + * normal Mode to analyzeMode :( */ + case MachinePlaysWhite: + case MachinePlaysBlack: + case EditGame: + if (first.maybeThinking == TRUE) { + /* don't send stat */ + appData.engineStatLine = TRUE; + EditGameEvent(); + first.maybeThinking = FALSE; + } else { + /* get latest state */ + if (supportStat == 1) appData.engineStatLine = FALSE; + if (WhiteOnMove(currentMove)) { + MachineWhiteEvent(); + } else { + MachineBlackEvent(); + } + } + break; + case BeginningOfGame: + MachineWhiteEvent(); + break; + default: + break; + } + } +} + +static int +only_one_move(str) + char *str; +{ + while (*str && isspace(*str)) ++str; + while (*str && !isspace(*str)) ++str; + if (!*str) return 1; + while (*str && isspace(*str)) ++str; + if (!*str) return 1; + return 0; +} + +void +DisplayAnalysis(newState, pv) +int newState; /* int newState: + * 1 = timer++ + * 0 = do nothing + * --- WB bootup (start) --- + * 5 = WB startup if EngineRoom true: popup + * --- GUI Action --- + * 6 = Start button + * hold/reset time + * 7 = Stop button */ + + +int pv; /* only pv comes 1 = TRUE */ +{ + /* newState True = call from timer - see dirty hack */ + char buf[2048]; + char buf2[32]; + char buf3[32]; + char buf4[32]; + char buf5[32]; + static char buf6[64]; /* static need if pv only */ + static char lastline[1024]; + static int lastdepth, last_icsgamenum; + int currentdepth; + char currentline[1024]; + char buf7[128]; + double nps; + int h, m, s; + static char *xtra[] = { "", " (--)", " (++)" }; + static int oldGameMode; /* on the fly switch gameMode ? */ + static int StatLine_autodetect; /* Autodetect only first move out of book */ + /* 0 = should detect + * 1 = done + */ + int diff; + int state; /* Using for ponder, opponent time action and + * using for color engine name + * --- move statment (adv color)--- + * 0 = we have the move and stanard color + * 1 = opponent have the move and opponent color + * --- only color statement--- + * 2 = AnalyzeMode + * 3 = IcsObserving + * --- special things ---- + * 4 = Two engines - we don't support that + */ + static long timer; /* hack without a stat line */ + static int move; /* detect new move */ + + strcpy(currentline, programStats.movelist); + currentdepth = programStats.depth; + + if (appData.noChessProgram) return; + /* if goes up to the end of this function */ + if (appData.icsAnalyzeWindow || appData.AnalysisWindow + || gameMode == AnalyzeMode || gameMode == AnalyzeFile) { + /* stop analysis */ + if (newState == 6) timer = 0; + + /* use for no stat support */ + /* If user switch on the fly gameMode we must know that */ + if (move != currentMove || oldGameMode != gameMode) { + timer = 0; + if (oldGameMode != gameMode) { + /* clear pv screen */ + sprintf(buf, "changing mode..."); + sprintf(buf2, "wait"); + sprintf(buf3, "0kN/s"); + sprintf(buf4, "Nodes=0"); + sprintf(buf5, "0.00"); + sprintf(buf6, "wait..."); + sprintf(buf7, "------------ "); + AnalysisPopUp(buf, buf2, buf3, buf4, buf5, buf6, buf7, 0); + oldGameMode = gameMode; + } + if (move > currentMove) { + supportStat = 0; /* new Game ? */ + StatLine_autodetect = 0; + } + move = currentMove; + lastdepth = 0; + } + + /* ICS Analyze more then one game - check if new game */ + if (appData.icsActive && ics_gamenum != last_icsgamenum) { + timer = 0; + last_icsgamenum = ics_gamenum; + } + + if (gameMode == EditGame) timer = 0; /* no clock if edit */ + + /* hope a lot of programmer will add a stat line - easy to make */ + /* at the moment a dirty(!!) hack with time_id */ + /* calculate some infos */ + if (programStats.time == 0) programStats.time = 1; + if (newState && gameMode != EditGame) timer++; + s = timer; + h = (s / (60*60)); + s = s - h*60*60; + m = (s/60); + s = s - m*60; + + /* save time */ + programStats.GUI_time = timer; + + /* Who is on move or which mode ?*/ + /* Need for colorize EngineName */ + /* Check gameMode for Stat support */ + switch (gameMode) { + case MachinePlaysWhite: + case IcsPlayingWhite: + if (WhiteOnMove(currentMove)) state = 0; + if (!WhiteOnMove(currentMove)) state = 1; + break; + case MachinePlaysBlack: + case IcsPlayingBlack: + if (WhiteOnMove(currentMove)) state = 1; + if (!WhiteOnMove(currentMove)) state = 0; + break; + case AnalyzeMode: + case AnalyzeFile: + appData.engineStatLine = FALSE; + StatLine_autodetect = 0; /* switch back to play is a prob */ + state = 2; + break; + case IcsObserving: + state = 3; + break; + /* not really a support for engine war - wait for war room */ + case TwoMachinesPlay: + state = 4; + break; + default: + appData.engineStatLine = FALSE; + state = 0; /* green */ + } + nps = ((((double)programStats.nodes) / + (((double)programStats.time)/100.0)) /1000); + + if (programStats.nodes > 0 && pv == 1) { + if (strcmp(lastline, currentline) != 0) { + if (prefixHint == TRUE && programStats.ponderMove[0] != NULLCHAR) { + if (programStats.score == 0 || programStats.score > 0) { + /* format arial set */ + sprintf(buf, " d->%02d %+.2f (%s) %s", programStats.depth, + (((float)programStats.score)/100.0), + programStats.ponderMove, currentline); + } else if (programStats.score < 0) { + sprintf(buf, " d->%02d %+.2f (%s) %s", programStats.depth, + (((float)programStats.score)/100.0), + programStats.ponderMove, currentline); + } + strcpy(lastline, currentline); + } else { + /* format arial set */ + if (programStats.score == 0 || programStats.score > 0) { + sprintf(buf, " d->%02d %+.2f %s", programStats.depth, + (((float)programStats.score)/100.0), currentline); + } else if (programStats.score < 0) { + sprintf(buf, " d->%02d %+.2f %s", programStats.depth, + (((float)programStats.score)/100.0), currentline); + } + strcpy(lastline, currentline); + } + lastdepth = currentdepth; + } else { + if (lastdepth < currentdepth) { + if (prefixHint == TRUE && programStats.ponderMove[0] != NULLCHAR) { + if (programStats.score == 0 || programStats.score > 0) { + /* format arial set */ + sprintf(buf, " d->%02d %+.2f (%s) %s", programStats.depth, + (((float)programStats.score)/100.0), + programStats.ponderMove, currentline); + } else if (programStats.score < 0) { + sprintf(buf, " d->%02d %+.2f (%s) %s", programStats.depth, + (((float)programStats.score)/100.0), + programStats.ponderMove, currentline); + } + } else { + /* format arial set */ + if (programStats.score == 0 || programStats.score > 0) { + sprintf(buf, " d->%02d %+.2f %s", programStats.depth, + (((float)programStats.score)/100.0), currentline); + } else if (programStats.score < 0) { + sprintf(buf, " d->%02d %+.2f %s", programStats.depth, + (((float)programStats.score)/100.0), currentline); + } + } + lastdepth = currentdepth; + } else { + buf[0] = NULLCHAR; + } + } + } else { + buf[0] = NULLCHAR; + } + + /* remove Bookline - never works correct */ + /* dirty hack with wb2 proto :((*/ + if (programStats.depth == 0 || programStats.depth == 1) { + sprintf(buf2, "Book"); + sprintf(buf3, "0kN/s"); + sprintf(buf4, "Nodes=0"); + sprintf(buf5, "0.00"); + sprintf(buf6, "wait..."); + } else { + sprintf(buf2, "Depth=%d", programStats.depth); + sprintf(buf3, "%dkN/s", (int)nps); + sprintf(buf4, "Nodes=%lu", programStats.nodes); + sprintf(buf5, "%+.2f", (((float)programStats.score)/100.0)); + } + sprintf(buf7, "%02d:%02d:%02d ", h, m, s); + /* only pv */ + if (pv == 1 && strcmp(lastline, currentline) != 0) { + AnalysisPopUp(buf, buf2, buf3, buf4, buf5, buf6, buf7, state); + return; + } else if (pv == 1 && strcmp(lastline, currentline) == 0 && + lastdepth < currentdepth) { + AnalysisPopUp(buf, buf2, buf3, buf4, buf5, buf6, buf7, state); + return; + } + + /* remove Bookline - never works correct */ + if (programStats.depth == 0 || programStats.depth == 1) { + sprintf(buf6, "wait..."); + } else { + if (supportStat == 0 && StatLine_autodetect == 0 && + timer > 20) { + /* we should disable sending "." now and tell GUI */ + /* Do that here only after first move out of book */ + appData.engineStatLine = TRUE; /* enable checkbox */ + StatLine_autodetect = 1; /* done */ + } + if (programStats.depth > 1) { + if (supportStat == 0) { + sprintf(buf6, "no support"); + } else { + diff = (programStats.nr_moves-programStats.moves_left); + if (diff < 0) { + sprintf(buf6, "Error!"); + } else { + if (programStats.moves_left > 0) { + if (programStats.move_name[0] != NULLCHAR) { + sprintf(buf6, "%d/%d %s", diff, + programStats.nr_moves, programStats.move_name); + } else { + /* without move. e.g. crafty */ + sprintf(buf6, "%d/%d", diff, + programStats.nr_moves, only_one_move(programStats.movelist)? + xtra[programStats.got_fail] : ""); + } + } + } + } + } + } + AnalysisPopUp(buf, buf2, buf3, buf4, buf5, buf6, buf7, state); + + } +} + +void +DisplayComment(moveNumber, text) + int moveNumber; + char *text; +{ + char title[MSG_SIZ]; + + if (moveNumber < 0 || parseList[moveNumber][0] == NULLCHAR) { + strcpy(title, "Comment"); + } else { + sprintf(title, "Comment on %d.%s%s", moveNumber / 2 + 1, + WhiteOnMove(moveNumber) ? " " : ".. ", + parseList[moveNumber]); + } + + CommentPopUp(title, text); +} + +/* This routine sends a ^C interrupt to gnuchess, to awaken it if it + * might be busy thinking or pondering. It can be omitted if your + * gnuchess is configured to stop thinking immediately on any user + * input. However, that gnuchess feature depends on the FIONREAD + * ioctl, which does not work properly on some flavors of Unix. + */ +void +Attention(cps) + ChessProgramState *cps; +{ +#if ATTENTION + if (!cps->useSigint) return; + if (appData.noChessProgram || (cps->pr == NoProc)) return; + switch (gameMode) { + case MachinePlaysWhite: + case MachinePlaysBlack: + case TwoMachinesPlay: + case IcsPlayingWhite: + case IcsPlayingBlack: + case AnalyzeMode: + case AnalyzeFile: + /* Skip if we know it isn't thinking */ + if (!cps->maybeThinking) return; + if (appData.debugMode) + fprintf(debugFP, "Interrupting %s\n", cps->which); + InterruptChildProcess(cps->pr); + cps->maybeThinking = FALSE; + break; + default: + break; + } +#endif /*ATTENTION*/ +} + +int +CheckFlags() +{ + if (whiteTimeRemaining <= 0) { + if (!whiteFlag) { + whiteFlag = TRUE; + if (appData.icsActive) { + if (appData.autoCallFlag && + gameMode == IcsPlayingBlack && !blackFlag) { + SendToICS(ics_prefix); + SendToICS("flag\n"); + } + } else { + if (blackFlag) { + DisplayTitle("Both flags fell"); + } else { + DisplayTitle("White's flag fell"); + if (appData.autoCallFlag) { + GameEnds(BlackWins, "Black wins on time", GE_XBOARD); + return TRUE; + } + } + } + } + } + if (blackTimeRemaining <= 0) { + if (!blackFlag) { + blackFlag = TRUE; + if (appData.icsActive) { + if (appData.autoCallFlag && + gameMode == IcsPlayingWhite && !whiteFlag) { + SendToICS(ics_prefix); + SendToICS("flag\n"); + } + } else { + if (whiteFlag) { + DisplayTitle("Both flags fell"); + } else { + DisplayTitle("Black's flag fell"); + if (appData.autoCallFlag) { + GameEnds(WhiteWins, "White wins on time", GE_XBOARD); + return TRUE; + } + } + } + } + } + return FALSE; +} + +void +CheckTimeControl() +{ + if (!appData.clockMode || appData.icsActive || + gameMode == PlayFromGameFile || forwardMostMove == 0) return; + + if (timeIncrement >= 0) { + if (WhiteOnMove(forwardMostMove)) { + blackTimeRemaining += timeIncrement; + } else { + whiteTimeRemaining += timeIncrement; + } + } + /* + * add time to clocks when time control is achieved + */ + if (movesPerSession) { + switch ((forwardMostMove + 1) % (movesPerSession * 2)) { + case 0: + /* White made time control */ + whiteTimeRemaining += timeControl; + break; + case 1: + /* Black made time control */ + blackTimeRemaining += timeControl; + break; + default: + break; + } + } +} + +void +DisplayBothClocks() +{ + int wom = gameMode == EditPosition ? + !blackPlaysFirst : WhiteOnMove(currentMove); + DisplayWhiteClock(whiteTimeRemaining, wom); + DisplayBlackClock(blackTimeRemaining, !wom); +} + + +/* Timekeeping seems to be a portability nightmare. I think everyone + has ftime(), but I'm really not sure, so I'm including some ifdefs + to use other calls if you don't. Clocks will be less accurate if + you have neither ftime nor gettimeofday. +*/ + +/* Get the current time as a TimeMark */ +void +GetTimeMark(tm) + TimeMark *tm; +{ +#if HAVE_GETTIMEOFDAY + + struct timeval timeVal; + struct timezone timeZone; + + gettimeofday(&timeVal, &timeZone); + tm->sec = (long) timeVal.tv_sec; + tm->ms = (int) (timeVal.tv_usec / 1000L); + +#else /*!HAVE_GETTIMEOFDAY*/ +#if HAVE_FTIME + +#include + struct timeb timeB; + + ftime(&timeB); + tm->sec = (long) timeB.time; + tm->ms = (int) timeB.millitm; + +#else /*!HAVE_FTIME && !HAVE_GETTIMEOFDAY*/ + tm->sec = (long) time(NULL); + tm->ms = 0; +#endif +#endif +} + +/* Return the difference in milliseconds between two + time marks. We assume the difference will fit in a long! +*/ +long +SubtractTimeMarks(tm2, tm1) + TimeMark *tm2, *tm1; +{ + return 1000L*(tm2->sec - tm1->sec) + + (long) (tm2->ms - tm1->ms); +} + + +/* + * Code to manage the game clocks. + * + * In tournament play, black starts the clock and then white makes a move. + * We give the human user a slight advantage if he is playing white---the + * clocks don't run until he makes his first move, so it takes zero time. + * Also, we don't account for network lag, so we could get out of sync + * with GNU Chess's clock -- but then, referees are always right. + */ + +static TimeMark tickStartTM; +static long intendedTickLength; + +long +NextTickLength(timeRemaining) + long timeRemaining; +{ + long nominalTickLength, nextTickLength; + + if (timeRemaining > 0L && timeRemaining <= 10000L) + nominalTickLength = 100L; + else + nominalTickLength = 1000L; + nextTickLength = timeRemaining % nominalTickLength; + if (nextTickLength <= 0) nextTickLength += nominalTickLength; + + return nextTickLength; +} + +/* Stop clocks and reset to a fresh time control */ +void +ResetClocks() +{ + (void) StopClockTimer(); + if (appData.icsActive) { + whiteTimeRemaining = blackTimeRemaining = 0; + } else { + whiteTimeRemaining = blackTimeRemaining = timeControl; + } + if (whiteFlag || blackFlag) { + DisplayTitle(""); + whiteFlag = blackFlag = FALSE; + } + DisplayBothClocks(); +} + +#define FUDGE 25 /* 25ms = 1/40 sec; should be plenty even for 50 Hz clocks */ + +/* Decrement running clock by amount of time that has passed */ +void +DecrementClocks() +{ + long timeRemaining; + long lastTickLength, fudge; + TimeMark now; + + if (!appData.clockMode) return; + if (gameMode==AnalyzeMode || gameMode == AnalyzeFile) return; + + GetTimeMark(&now); + + lastTickLength = SubtractTimeMarks(&now, &tickStartTM); + + /* Fudge if we woke up a little too soon */ + fudge = intendedTickLength - lastTickLength; + if (fudge < 0 || fudge > FUDGE) fudge = 0; + + if (WhiteOnMove(forwardMostMove)) { + timeRemaining = whiteTimeRemaining -= lastTickLength; + DisplayWhiteClock(whiteTimeRemaining - fudge, + WhiteOnMove(currentMove)); + } else { + timeRemaining = blackTimeRemaining -= lastTickLength; + DisplayBlackClock(blackTimeRemaining - fudge, + !WhiteOnMove(currentMove)); + } + + if (CheckFlags()) return; + + tickStartTM = now; + intendedTickLength = NextTickLength(timeRemaining - fudge) + fudge; + StartClockTimer(intendedTickLength); + + /* if the time remaining has fallen below the alarm threshold, sound the + * alarm. if the alarm has sounded and (due to a takeback or time control + * with increment) the time remaining has increased to a level above the + * threshold, reset the alarm so it can sound again. + */ + + if (appData.icsActive && appData.icsAlarm) { + + /* make sure we are dealing with the user's clock */ + if (!( ((gameMode == IcsPlayingWhite) && WhiteOnMove(currentMove)) || + ((gameMode == IcsPlayingBlack) && !WhiteOnMove(currentMove)) + )) return; + + if (alarmSounded && (timeRemaining > appData.icsAlarmTime)) { + alarmSounded = FALSE; + } else if (!alarmSounded && (timeRemaining <= appData.icsAlarmTime)) { + PlayAlarmSound(); + alarmSounded = TRUE; + } + } +} + + +/* A player has just moved, so stop the previously running + clock and (if in clock mode) start the other one. + We redisplay both clocks in case we're in ICS mode, because + ICS gives us an update to both clocks after every move. + Note that this routine is called *after* forwardMostMove + is updated, so the last fractional tick must be subtracted + from the color that is *not* on move now. +*/ +void +SwitchClocks() +{ + long lastTickLength; + TimeMark now; + int flagged = FALSE; + + GetTimeMark(&now); + + if (StopClockTimer() && appData.clockMode) { + lastTickLength = SubtractTimeMarks(&now, &tickStartTM); + if (WhiteOnMove(forwardMostMove)) { + blackTimeRemaining -= lastTickLength; + } else { + whiteTimeRemaining -= lastTickLength; + } + flagged = CheckFlags(); + } + CheckTimeControl(); + + if (flagged || !appData.clockMode) return; + + switch (gameMode) { + case MachinePlaysBlack: + case MachinePlaysWhite: + case BeginningOfGame: + if (pausing) return; + break; + + case EditGame: + case PlayFromGameFile: + case IcsExamining: + return; + + default: + break; + } + + tickStartTM = now; + intendedTickLength = NextTickLength(WhiteOnMove(forwardMostMove) ? + whiteTimeRemaining : blackTimeRemaining); + StartClockTimer(intendedTickLength); +} + + +/* Stop both clocks */ +void +StopClocks() +{ + long lastTickLength; + TimeMark now; + + if (!StopClockTimer()) return; + if (!appData.clockMode) return; + + GetTimeMark(&now); + + lastTickLength = SubtractTimeMarks(&now, &tickStartTM); + if (WhiteOnMove(forwardMostMove)) { + whiteTimeRemaining -= lastTickLength; + DisplayWhiteClock(whiteTimeRemaining, WhiteOnMove(currentMove)); + } else { + blackTimeRemaining -= lastTickLength; + DisplayBlackClock(blackTimeRemaining, !WhiteOnMove(currentMove)); + } + CheckFlags(); +} + +/* Start clock of player on move. Time may have been reset, so + if clock is already running, stop and restart it. */ +void +StartClocks() +{ + (void) StopClockTimer(); /* in case it was running already */ + DisplayBothClocks(); + if (CheckFlags()) return; + + if (!appData.clockMode) return; + if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) return; + + GetTimeMark(&tickStartTM); + intendedTickLength = NextTickLength(WhiteOnMove(forwardMostMove) ? + whiteTimeRemaining : blackTimeRemaining); + StartClockTimer(intendedTickLength); +} + +char * +TimeString(ms) + long ms; +{ + long second, minute, hour, day; + char *sign = ""; + static char buf[32]; + + if (ms > 0 && ms <= 9900) { + /* convert milliseconds to tenths, rounding up */ + double tenths = floor( ((double)(ms + 99L)) / 100.00 ); + + sprintf(buf, " %03.1f ", tenths/10.0); + return buf; + } + + /* convert milliseconds to seconds, rounding up */ + /* use floating point to avoid strangeness of integer division + with negative dividends on many machines */ + second = (long) floor(((double) (ms + 999L)) / 1000.0); + + if (second < 0) { + sign = "-"; + second = -second; + } + + day = second / (60 * 60 * 24); + second = second % (60 * 60 * 24); + hour = second / (60 * 60); + second = second % (60 * 60); + minute = second / 60; + second = second % 60; + + if (day > 0) + sprintf(buf, " %s%ld:%02ld:%02ld:%02ld ", + sign, day, hour, minute, second); + else if (hour > 0) + sprintf(buf, " %s%ld:%02ld:%02ld ", sign, hour, minute, second); + else + sprintf(buf, " %s%2ld:%02ld ", sign, minute, second); + + return buf; +} + + +/* + * This is necessary because some C libraries aren't ANSI C compliant yet. + */ +char * +StrStr(string, match) + char *string, *match; +{ + int i, length; + + length = strlen(match); + + for (i = strlen(string) - length; i >= 0; i--, string++) + if (!strncmp(match, string, length)) + return string; + + return NULL; +} + +char * +StrCaseStr(string, match) + char *string, *match; +{ + int i, j, length; + + length = strlen(match); + + for (i = strlen(string) - length; i >= 0; i--, string++) { + for (j = 0; j < length; j++) { + if (ToLower(match[j]) != ToLower(string[j])) + break; + } + if (j == length) return string; + } + + return NULL; +} + +#ifndef _amigados +int +StrCaseCmp(s1, s2) + char *s1, *s2; +{ + char c1, c2; + + for (;;) { + c1 = ToLower(*s1++); + c2 = ToLower(*s2++); + if (c1 > c2) return 1; + if (c1 < c2) return -1; + if (c1 == NULLCHAR) return 0; + } +} + + +int +ToLower(c) + int c; +{ + return isupper(c) ? tolower(c) : c; +} + + +int +ToUpper(c) + int c; +{ + return islower(c) ? toupper(c) : c; +} +#endif /* !_amigados */ + +char * +StrSave(s) + char *s; +{ + char *ret; + + if ((ret = (char *) malloc(strlen(s) + 1))) { + strcpy(ret, s); + } + return ret; +} + +char * +StrSavePtr(s, savePtr) + char *s, **savePtr; +{ + if (*savePtr) { + free(*savePtr); + } + if ((*savePtr = (char *) malloc(strlen(s) + 1))) { + strcpy(*savePtr, s); + } + return(*savePtr); +} + +char * +PGNDate() +{ + time_t clock; + struct tm *tm; + char buf[MSG_SIZ]; + + clock = time((time_t *)NULL); + tm = localtime(&clock); + sprintf(buf, "%04d.%02d.%02d", + tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday); + return StrSave(buf); +} + + +char * +PositionToFEN(move) + int move; +{ + int i, j, fromX, fromY, toX, toY; + int whiteToPlay; + char buf[128]; + char *p, *q; + int emptycount; + + whiteToPlay = (gameMode == EditPosition) ? + !blackPlaysFirst : (move % 2 == 0); + p = buf; + + /* Piece placement data */ + for (i = BOARD_SIZE - 1; i >= 0; i--) { + emptycount = 0; + for (j = 0; j < BOARD_SIZE; j++) { + if (boards[move][i][j] == EmptySquare) { + emptycount++; + } else { + if (emptycount > 0) { + *p++ = '0' + emptycount; + emptycount = 0; + } + *p++ = PieceToChar(boards[move][i][j]); + } + } + if (emptycount > 0) { + *p++ = '0' + emptycount; + emptycount = 0; + } + *p++ = '/'; + } + *(p - 1) = ' '; + + /* Active color */ + *p++ = whiteToPlay ? 'w' : 'b'; + *p++ = ' '; + + /* !!We don't keep track of castling availability, so fake it */ + q = p; + if (boards[move][0][4] == WhiteKing) { + if (boards[move][0][7] == WhiteRook) *p++ = 'K'; + if (boards[move][0][0] == WhiteRook) *p++ = 'Q'; + } + if (boards[move][7][4] == BlackKing) { + if (boards[move][7][7] == BlackRook) *p++ = 'k'; + if (boards[move][7][0] == BlackRook) *p++ = 'q'; + } + if (q == p) *p++ = '-'; + *p++ = ' '; + + /* En passant target square */ + if (move > backwardMostMove) { + fromX = moveList[move - 1][0] - 'a'; + fromY = moveList[move - 1][1] - '1'; + toX = moveList[move - 1][2] - 'a'; + toY = moveList[move - 1][3] - '1'; + if (fromY == (whiteToPlay ? 6 : 1) && + toY == (whiteToPlay ? 4 : 3) && + boards[move][toY][toX] == (whiteToPlay ? BlackPawn : WhitePawn) && + fromX == toX) { + /* 2-square pawn move just happened */ + *p++ = toX + 'a'; + *p++ = whiteToPlay ? '6' : '3'; + } else { + *p++ = '-'; + } + } else { + *p++ = '-'; + } + + /* !!We don't keep track of halfmove clock for 50-move rule */ + strcpy(p, " 0 "); + p += 3; + + /* Fullmove number */ + sprintf(p, "%d", (move / 2) + 1); + + return StrSave(buf); +} + +Boolean +ParseFEN(board, blackPlaysFirst, fen) + Board board; + int *blackPlaysFirst; + char *fen; +{ + int i, j; + char *p; + int emptycount; + + p = fen; + + /* Piece placement data */ + for (i = BOARD_SIZE - 1; i >= 0; i--) { + j = 0; + for (;;) { + if (*p == '/' || *p == ' ') { + if (*p == '/') p++; + emptycount = BOARD_SIZE - j; + while (emptycount--) board[i][j++] = EmptySquare; + break; + } else if (isdigit(*p)) { + emptycount = *p++ - '0'; + if (j + emptycount > BOARD_SIZE) return FALSE; + while (emptycount--) board[i][j++] = EmptySquare; + } else if (isalpha(*p)) { + if (j >= BOARD_SIZE) return FALSE; + board[i][j++] = CharToPiece(*p++); + } else { + return FALSE; + } + } + } + while (*p == '/' || *p == ' ') p++; + + /* Active color */ + switch (*p) { + case 'w': + *blackPlaysFirst = FALSE; + break; + case 'b': + *blackPlaysFirst = TRUE; + break; + default: + return FALSE; + } + /* !!We ignore the rest of the FEN notation */ + return TRUE; +} + +void +EditPositionPasteFEN(char *fen) +{ + if (fen != NULL) { + Board initial_position; + + if (!ParseFEN(initial_position, &blackPlaysFirst, fen)) { + DisplayError("Bad FEN position in clipboard", 0); + return ; + } else { + int savedBlackPlaysFirst = blackPlaysFirst; + EditPositionEvent(); + blackPlaysFirst = savedBlackPlaysFirst; + CopyBoard(boards[0], initial_position); + EditPositionDone(); + DisplayBothClocks(); + DrawPosition(FALSE, boards[currentMove]); + } + } +} diff --git a/winboard-dm-beta4/backend.h b/winboard-dm-beta4/backend.h new file mode 100755 index 0000000..6e6aee2 --- /dev/null +++ b/winboard-dm-beta4/backend.h @@ -0,0 +1,288 @@ +/* + * backend.h -- Interface exported by XBoard back end + * $Id$ + * + * Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts. + * Enhancements Copyright 1992-95 Free Software Foundation, Inc. + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * ------------------------------------------------------------------------ + */ +#ifndef _BACKEND +#define _BACKEND + +#include "lists.h" +#include "frontend.h" + +extern int gotPremove; +extern int pausing, cmailMsgLoaded, flipView; +extern char white_holding[], black_holding[]; +extern int currentMove, backwardMostMove, forwardMostMove; +extern int blackPlaysFirst; +extern FILE *debugFP; +extern char* programVersion; +extern ProcRef firstProgramPR, secondProgramPR; +extern Board boards[]; + +char *CmailMsg P((void)); +char *PositionToFEN P((int move)); +void EditPositionPasteFEN P((char *fen)); +void TimeDelay P((long ms)); +void SendMultiLineToICS P(( char *text )); +void AnalysisPeriodicEvent P((int force)); +void SetWhiteToPlayEvent P((void)); +void SetBlackToPlayEvent P((void)); +void InitBackEnd1 P((void)); +void InitBackEnd2 P((void)); +void ConsoleCreate P((void)); +void DisplayAnalysis P((int NewState, int pv)); +int IsPromotion P((int fromX, int fromY, int toX, int toY)); +int PieceForSquare P((int x, int y)); +int OKToStartUserMove P((int x, int y)); +void Reset P((int redraw, int init)); +void ResetGameEvent P((void)); +int LoadGame P((FILE *f, int n, char *title, int useList)); +int LoadGameFromFile P((char *filename, int n, char *title, int useList)); +int CmailLoadGame P((FILE *f, int n, char *title, int useList)); +int ReloadGame P((int offset)); +int SaveGame P((FILE *f, int dummy, char *dummy2)); +int SaveGameToFile P((char *filename, int append)); +int LoadPosition P((FILE *f, int n, char *title)); +int ReloadPosition P((int offset)); +int SavePosition P((FILE *f, int dummy, char *dummy2)); +void EditPositionEvent P((void)); +void FlipViewEvent P((void)); +void MachineWhiteEvent P((void)); +void MachineBlackEvent P((void)); +void TwoMachinesEvent P((void)); +void EditGameEvent P((void)); +void TrainingEvent P((void)); +void IcsClientEvent P((void)); +void ForwardEvent P((void)); +void BackwardEvent P((void)); +void ToEndEvent P((void)); +void ToStartEvent P((void)); +void ToNrEvent P((int to)); +void RevertEvent P((void)); +void RetractMoveEvent P((void)); +void MoveNowEvent P((void)); +void TruncateGameEvent P((void)); +void ResetIcsQueue P((int gamenumber)); +void PauseEvent P((void)); +void CallFlagEvent P((void)); +void AcceptEvent P((void)); +void DeclineEvent P((void)); +void RematchEvent P((void)); +void DrawEvent P((void)); +void AbortEvent P((void)); +void AdjournEvent P((void)); +void ResignEvent P((void)); +void StopObservingEvent P((void)); +void StopExaminingEvent P((void)); +void PonderNextMoveEvent P((int newState)); +void ShowThinkingEvent P((int newState)); +void IcsAnalyze P((int newState)); +void IcsAnalyzeWindowUp P((void)); +void PeriodicUpdatesEvent P((int newState)); +void HintEvent P((void)); +void BookEvent P((void)); +void AboutGameEvent P((void)); +void ExitEvent P((int status)); +char *DefaultFileName P((char *)); +void UserMoveEvent P((int fromX, int fromY, int toX, int toY, int promoChar)); +void DecrementClocks P((void)); +char *TimeString P((long millisec)); +void AutoPlayGameLoop P((void)); +void DisplayBothClocks P((void)); +void EditPositionMenuEvent P((ChessSquare selection, int x, int y)); +void DropMenuEvent P((ChessSquare selection, int x, int y)); +int ParseTimeControl P((char *tc, int ti, int mps)); +void ProcessICSInitScript P((FILE * f)); +void EditCommentEvent P((void)); +void ReplaceComment P((int index, char *text)); +int ReplaceTags P((char *tags, GameInfo *gi));/* returns nonzero on error */ +void AppendComment P((int index, char *text)); +void ReloadCmailMsgEvent P((int unregister)); +void MailMoveEvent P((void)); +void EditTagsEvent P((void)); +void GetMoveListEvent P((void)); +void ExitAnalyzeMode P((void)); +void AnalyzeModeEvent P((void)); +void AnalyzeFileEvent P((void)); +void DoEcho P((void)); +void DontEcho P((void)); +void TidyProgramName P((char *prog, char *host, char *buf)); +void AskQuestionEvent P((char *title, char *question, + char *replyPrefix, char *which)); +Boolean ParseOneMove P((char *move, int moveNum, + ChessMove *moveType, int *fromX, int *fromY, + int *toX, int *toY, char *promoChar)); +char *VariantName P((VariantClass v)); +VariantClass StringToVariant P((char *e)); + +char *StrStr P((char *string, char *match)); +char *StrCaseStr P((char *string, char *match)); +char *StrSave P((char *s)); +char *StrSavePtr P((char *s, char **savePtr)); + +#ifndef _amigados +int StrCaseCmp P((char *s1, char *s2)); +int ToLower P((int c)); +int ToUpper P((int c)); +#else +#define StrCaseCmp Stricmp /* Use utility.library functions */ +#include +#endif + +extern GameInfo gameInfo; + + +/* pgntags.c prototypes + */ +char *PGNTags P((GameInfo *)); +void PrintPGNTags P((FILE *f, GameInfo *)); +int ParsePGNTag P((char *, GameInfo *)); +char *PGNResult P((ChessMove result)); + + +/* gamelist.c prototypes + */ +/* A game node in the double linked list of games. + */ +typedef struct _ListGame { + ListNode node; + int number; + unsigned long offset; /* Byte offset of game within file. */ + GameInfo gameInfo; /* Note that some entries may be NULL. */ +} ListGame; + +extern List gameList; +void ClearGameInfo P((GameInfo *)); +int GameListBuild P((FILE *)); +void GameListInitGameInfo P((GameInfo *)); +char *GameListLine P((int, GameInfo *)); + +extern char* StripHighlight P((char *)); /* returns static data */ +extern char* StripHighlightAndTitle P((char *)); /* returns static data */ + + +typedef struct _CPS { + char *which; + int maybeThinking; + ProcRef pr; + InputSourceRef isr; + char *twoMachinesColor; /* "white\n" or "black\n" */ + char *program; + char *host; + char *dir; + struct _CPS *other; + char *initString; + char *computerString; + int sendTime; /* 0=don't, 1=do, 2=test */ + int sendDrawOffers; + int useSigint; + int useSigterm; + int offeredDraw; /* countdown */ + int reuse; + int useSetboard; /* 0=use "edit"; 1=use "setboard" */ + int useSAN; /* 0=use coordinate notation; 1=use SAN */ + int usePing; /* 0=not OK to use ping; 1=OK */ + int lastPing; + int lastPong; + int usePlayother;/* 0=not OK to use playother; 1=OK */ + int useColors; /* 0=avoid obsolete white/black commands; 1=use them */ + int useUsermove; /* 0=just send move; 1=send "usermove move" */ + int sendICS; /* 0=don't use "ics" command; 1=do */ + int sendName; /* 0=don't use "name" command; 1=do */ + int sdKludge; /* 0=use "sd DEPTH" command; 1=use "depth\nDEPTH" */ + int stKludge; /* 0=use "st TIME" command; 1=use "level 1 TIME" */ + char tidy[MSG_SIZ]; + int matchWins; + char variants[MSG_SIZ]; + int analysisSupport; + int analyzing; + int protocolVersion; + int initDone; +} ChessProgramState; + +ChessProgramState first, second; + +/* max gamenumber on ICS + * i don't know the real value + * but i think 1500 is enought + * edit here if you want change + * if we over max value we break all + * action and make a fatal error + */ +#define max_gamenum 1500 + +/* Smart ICS outut Queue */ +typedef struct { + int counter; + long time; + int killPv; + int move; /* only for for killpv++ and -- + give not the realstic move number back !! + */ + int MessageMove; /* Last played move where we send a message */ + int CurrentMove; /* current movenumber on observing board */ + int flag; /* 0= we never send a message for this move 1= We send it */ + int event; /* Send event message to board "Hello, i'm..." */ + int gameNum; /* reserved */ + int currentGame; /* reserved */ + char lastpv[1024]; /* save last pv */ + char white[128]; /* white player name */ + char black[128]; /* black player name */ +} smartQueue; + +extern smartQueue icsQueue[max_gamenum]; + +int chessfm; + +/* rember if engine send a "stat01:" line for display */ +static int supportStat; /* 0 = false 1 = true */ + +/* save pv - reserved for future */ +typedef struct { + char mainline[1024]; +} PV[512]; +PV engineRoom, *er; + +#endif /* _BACKEND */ diff --git a/winboard-dm-beta4/backendz.h b/winboard-dm-beta4/backendz.h new file mode 100755 index 0000000..3bab93f --- /dev/null +++ b/winboard-dm-beta4/backendz.h @@ -0,0 +1,72 @@ +/* + * backendz.h -- Internal interface exported by XBoard backend.c to zippy.c + * $Id$ + * + * Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts. + * Enhancements Copyright 1992-95 Free Software Foundation, Inc. + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * ------------------------------------------------------------------------ + */ + +#ifndef _BACKENDZ +#define _BACKENDZ + +#include "common.h" +#include "frontend.h" + +extern long whiteTimeRemaining, blackTimeRemaining; +extern int forwardMostMove; +extern char star_match[STAR_MATCH_N][MSG_SIZ]; +extern ProcRef firstProgramPR; +extern int startedFromSetupPosition; +extern int firstMove; +extern GameInfo gameInfo; +extern void SendToICS P((char *s)); +extern int looking_at P((char *, int *, char *)); +extern void SendToProgram P((char *message, ChessProgramState *cps)); +extern void SendBoard P((ChessProgramState *cps, int moveNum)); +void SendTimeRemaining P((ChessProgramState *cps, + int/*boolean*/ machineWhite)); + +extern char ics_handle[]; +extern char *ics_prefix; + +#endif diff --git a/winboard-dm-beta4/common.h b/winboard-dm-beta4/common.h new file mode 100755 index 0000000..1a0e658 --- /dev/null +++ b/winboard-dm-beta4/common.h @@ -0,0 +1,488 @@ +/* + * common.h -- Common definitions for X and Windows NT versions of XBoard + * $Id$ + * + * Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts. + * Enhancements Copyright 1992-95 Free Software Foundation, Inc. + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * ------------------------------------------------------------------------ + */ + +#ifndef _COMMON +#define _COMMON + +/* Begin compatibility grunge */ + +#if defined(__STDC__) || defined(WIN32) || defined(_amigados) +#define P(args) args +typedef void *VOIDSTAR; +#else +#define P(args) () +typedef char *VOIDSTAR; +#endif + +#ifdef WIN32 +typedef char Boolean; +typedef char *String; +#define popen _popen +#define pclose _pclose + +#else +#ifdef _amigados /* It is important, that these types have */ +typedef int Boolean; /* a length of 4 bytes each, as we are */ +typedef char *String; /* using ReadArgs() for argument parsing. */ +#ifdef _DCC +FILE *popen(const char *, const char *); +int pclose(FILE *); +#endif + +#else +#include +#endif +#endif + + +#ifndef TRUE +#define TRUE 1 +#define FALSE 0 +#endif + +#if !HAVE_RANDOM +# if HAVE_RAND48 +# define srandom srand48 +# define random lrand48 +# else /* not HAVE_RAND48 */ +# define srandom srand +# define random rand +# endif /* not HAVE_RAND48 */ +#endif /* !HAVE_RANDOM */ + +/* End compatibility grunge */ + +#define PROTOVER 2 /* engine protocol version */ + +#define BOARD_SIZE 8 +#define DROP_RANK -3 +#define MAX_MOVES 1000 +#define MSG_SIZ 2048 +#define DIALOG_SIZE 256 +#define STAR_MATCH_N 16 +#define MOVE_LEN 32 +#define TIME_CONTROL "5" /* in minutes */ +#define TIME_DELAY_QUOTE "1.0" /* seconds between moves */ +#define TIME_DELAY ((float) 1.0) +#define MOVES_PER_SESSION 40 /* moves per TIME_CONTROL */ +#define TIME_INCREMENT -1 /* if >= 0, MOVES_PER_SESSION unused */ +#define WhiteOnMove(move) (((move) % 2) == 0) +#define ICS_HOST "chessclub.com" +#define ICS_PORT "5000" +#define ICS_COMM_PORT "" +#define FIRST_HOST "localhost" +#define SECOND_HOST "localhost" +#define TELNET_PROGRAM "telnet" +#define MATCH_MODE "False" +#define INIT_STRING "new\nrandom\n" +#define WHITE_STRING "white\ngo\n" +#define BLACK_STRING "black\ngo\n" +#define COMPUTER_STRING "computer\n" +#define REUSE_CHESS_PROGRAMS 1 +#define WHITE_PIECE_COLOR "#FFFFCC" +#define BLACK_PIECE_COLOR "#202020" +#define LIGHT_SQUARE_COLOR "#C8C365" +#define DARK_SQUARE_COLOR "#77A26D" +#define JAIL_SQUARE_COLOR "#808080" +#define HIGHLIGHT_SQUARE_COLOR "#FFFF00" +#define PREMOVE_HIGHLIGHT_COLOR "#FF0000" +#define BELLCHAR '\007' +#define NULLCHAR '\000' +#define FEATURE_TIMEOUT 10000 /*ms*/ + +/* Zippy defaults */ +#define ZIPPY_TALK FALSE +#define ZIPPY_PLAY FALSE +#define ZIPPY_LINES "yow.lines" +#define ZIPPY_PINHEAD "" +#define ZIPPY_PASSWORD "" +#define ZIPPY_PASSWORD2 "" +#define ZIPPY_PASSWORD3 "" +#define ZIPPY_WRONG_PASSWORD "" +#define ZIPPY_ACCEPT_ONLY "" +#define ZIPPY_USE_I TRUE +#define ZIPPY_BUGHOUSE 0 +#define ZIPPY_NOPLAY_CRAFTY FALSE +#define ZIPPY_GAME_END "gameend\n" +#define ZIPPY_GAME_START "" +#define ZIPPY_ADJOURN FALSE +#define ZIPPY_ABORT FALSE +#define ZIPPY_VARIANTS "normal" +#define ZIPPY_MAX_GAMES 0 +#define ZIPPY_REPLAY_TIMEOUT 120 + +typedef enum { + BeginningOfGame, MachinePlaysWhite, MachinePlaysBlack, + AnalyzeMode, AnalyzeFile, TwoMachinesPlay, + EditGame, PlayFromGameFile, EndOfGame, EditPosition, Training, + IcsIdle, IcsPlayingWhite, IcsPlayingBlack, IcsObserving, + IcsExamining + } GameMode; + +GameMode gameMode; + +typedef enum { + WhitePawn, WhiteKnight, WhiteBishop, WhiteRook, WhiteQueen, WhiteKing, + BlackPawn, BlackKnight, BlackBishop, BlackRook, BlackQueen, BlackKing, + EmptySquare, + ClearBoard, WhitePlay, BlackPlay /*for use on EditPosition menus*/ + } ChessSquare; + +typedef ChessSquare Board[BOARD_SIZE][BOARD_SIZE]; + +typedef enum { + WhiteKingSideCastle = 1, WhiteQueenSideCastle, + WhiteKingSideCastleWild, WhiteQueenSideCastleWild, + WhiteHSideCastleFR, WhiteASideCastleFR, + BlackKingSideCastle, BlackQueenSideCastle, + BlackKingSideCastleWild, BlackQueenSideCastleWild, + BlackHSideCastleFR, BlackASideCastleFR, + WhitePromotionKnight, WhitePromotionBishop, + WhitePromotionRook, WhitePromotionQueen, WhitePromotionKing, + BlackPromotionKnight, BlackPromotionBishop, + BlackPromotionRook, BlackPromotionQueen, BlackPromotionKing, + WhiteCapturesEnPassant, BlackCapturesEnPassant, + WhiteDrop, BlackDrop, + NormalMove, AmbiguousMove, IllegalMove, ImpossibleMove, + WhiteWins, BlackWins, GameIsDrawn, GameUnfinished, + GNUChessGame, XBoardGame, MoveNumberOne, + Comment, PositionDiagram, ElapsedTime, PGNTag, NAG + } ChessMove; + +typedef enum { + ColorShout, ColorSShout, ColorChannel1, ColorChannel, ColorKibitz, + ColorTell, ColorChallenge, ColorRequest, ColorSeek, ColorNormal, + ColorNone, NColorClasses +} ColorClass; + +typedef enum { + SoundMove, SoundBell, SoundAlarm, SoundIcsWin, SoundIcsLoss, + SoundIcsDraw, SoundIcsUnfinished, NSoundClasses +} SoundClass; + +/* Names for chess variants, not necessarily supported */ +typedef enum { + VariantNormal, /* Normal chess */ + VariantLoadable, /* "loadgame" command allowed (not really a variant)*/ + VariantWildCastle, /* Shuffle chess where king can castle from d file */ + VariantNoCastle, /* Shuffle chess with no castling at all */ + VariantFischeRandom, /* FischeRandom */ + VariantBughouse, /* Bughouse, ICC/FICS rules */ + VariantCrazyhouse, /* Crazyhouse, ICC/FICS rules */ + VariantLosers, /* Try to lose all pieces or get mated (ICC wild 17)*/ + VariantSuicide, /* Try to lose all pieces incl. king (FICS) */ + VariantGiveaway, /* Try to have no legal moves left (ICC wild 26) */ + VariantTwoKings, /* Weird ICC wild 9 */ + VariantKriegspiel, /* Kriegspiel; pawns can capture invisible pieces */ + VariantAtomic, /* Capturing piece explodes (ICC wild 27) */ + Variant3Check, /* Win by giving check 3 times (ICC wild 25) */ + VariantShatranj, /* Unsupported (ICC wild 28) */ + Variant29, /* Temporary name for possible future ICC wild 29 */ + Variant30, /* Temporary name for possible future ICC wild 30 */ + Variant31, /* Temporary name for possible future ICC wild 31 */ + Variant32, /* Temporary name for possible future ICC wild 32 */ + Variant33, /* Temporary name for possible future ICC wild 33 */ + Variant34, /* Temporary name for possible future ICC wild 34 */ + Variant35, /* Temporary name for possible future ICC wild 35 */ + Variant36, /* Temporary name for possible future ICC wild 36 */ + VariantUnknown /* Catchall for other unknown variants */ +} VariantClass; + +#define VARIANT_NAMES { \ + "normal", \ + "normal", \ + "wildcastle", \ + "nocastle", \ + "fischerandom", \ + "bughouse", \ + "crazyhouse", \ + "losers", \ + "suicide", \ + "giveaway", \ + "twokings", \ + "kriegspiel", \ + "atomic", \ + "3check", \ + "shatranj", \ + "wild29", \ + "wild30", \ + "wild31", \ + "wild32", \ + "wild33", \ + "wild34", \ + "wild35", \ + "wild36", \ + "unknown" \ +} + +typedef struct { +#if !defined(_amigados) + char *whitePieceColor; + char *blackPieceColor; + char *lightSquareColor; + char *darkSquareColor; + char *jailSquareColor; + char *highlightSquareColor; + char *premoveHighlightColor; +#else + int whitePieceColor; + int blackPieceColor; + int lightSquareColor; + int darkSquareColor; + int jailSquareColor; + int highlightSquareColor; + int premoveHighlightColor; +#endif + int movesPerSession; + int timeIncrement; + char *initString; + char *secondInitString; + char *firstComputerString; + char *secondComputerString; + char *firstChessProgram; + char *secondChessProgram; + char *firstDirectory; + char *secondDirectory; + Boolean firstPlaysBlack; + Boolean noChessProgram; + char *firstHost; + char *secondHost; + char *bitmapDirectory; + char *remoteShell; + char *remoteUser; + float timeDelay; + char *timeControl; + Boolean icsActive; + char *icsHost; + char *icsPort; + char *icsCommPort; /* if set, use serial port instead of tcp host/port */ + char *icsLogon; /* Hack to permit variable logon scripts. */ + char *icsHelper; + Boolean icsInputBox; + Boolean useTelnet; + char *telnetProgram; + char *gateway; + char *loadGameFile; + int loadGameIndex; /* game # within file */ + char *saveGameFile; + Boolean autoSaveGames; + char *loadPositionFile; + int loadPositionIndex; /* position # within file */ + char *savePositionFile; + Boolean matchMode; + int matchGames; + Boolean monoMode; + Boolean debugMode; + Boolean clockMode; + /* daniel */ + Boolean userVersion; /* programmer version */ + Boolean icsAnalyze; + Boolean icsEngineKillPV; + Boolean icsEngineWhisper; + Boolean icsEngineKibitz; + Boolean icsEngineTell; + Boolean icsEngineNone; + Boolean icsAnalyzeWindow; + Boolean smartQueue; /* Live broadcast quere */ + Boolean ICC_feature; /* Enable special ICC fetures */ + Boolean windowMove; /* Drop fail high/low moves at icsAnalyzeOutPut */ + int icsAnalyzeOutPut; /* 1=whisper 2=kibitz 3=tell 4=none */ + int icsKillPVs; + char icsTells[MSG_SIZ]; /* handle/channel do we tell somthing */ + Boolean icsWBprotoNorm; + Boolean icsWBprotoAgr; + int icsWBproto; /* dummy */ + int icsSmartQueue; /* 0 = standard game 1 = Blitzgame */ + /* Split smartQueue with int because i want more for the future */ + Boolean icsSmartQueueStd; + Boolean icsSmartQueueBlitz; + Boolean icsShowBook; /* True = show book False = disable */ + Boolean AnalysisWindow; /* Engine Room */ + Boolean engineStart; /* EngineRoom Button */ + Boolean engineTourneyMode; /* EngineRoom checkbox tourneyMode */ + Boolean engineStatLine; /* EngineRoom Statline disable */ + Boolean zippyDraw; /* active zippy draw Handling ? */ + int SendOutPutToICS; /* Analysis window: Send thinking lines to ICS */ + /* 0 none 1 whisper 2 kibitz */ + Boolean ButtonSendOutPutToICS; /* Checkbox analysis window */ + char *boardSize; + Boolean Iconic; + char *searchTime; + int searchDepth; + Boolean showCoords; + char *clockFont; + char *messageFont; /* WinBoard only */ + char *coordFont; + char *font; /* xboard only: all other fonts */ + char *tagsFont; /* WinBoard only */ + char *commentFont; /* WinBoard only */ + char *icsFont; /* WinBoard only */ + Boolean ringBellAfterMoves; + Boolean autoCallFlag; + Boolean flipView; + Boolean autoFlipView; + char *cmailGameName; /* xboard only */ + Boolean alwaysPromoteToQueen; + Boolean oldSaveStyle; + Boolean quietPlay; + Boolean showThinking; + Boolean ponderNextMove; + Boolean periodicUpdates; + Boolean autoObserve; + Boolean autoComment; + Boolean getMoveList; + Boolean testLegality; + int borderXoffset; /* xboard only */ + int borderYoffset; /* xboard only */ + Boolean titleInWindow; /* xboard only */ + Boolean localLineEditing; /* WinBoard only */ + Boolean zippyTalk; + Boolean zippyPlay; + int flashCount; /* Number of times to flash (xboard only) */ + int flashRate; /* Flashes per second (xboard only) */ + char *pixmapDirectory; /* Path to XPM/XIM files to use (xboard only) */ + int msLoginDelay; /* Delay per character (in msec) while sending + ICS logon script (xboard only) */ + Boolean colorize; /* If True, use the following colors to color text */ + /* Strings for colors, as "fg, bg, bold" (strings used in xboard only) */ + char *colorShout; + char *colorSShout; + char *colorChannel1; + char *colorChannel; + char *colorKibitz; + char *colorTell; + char *colorChallenge; + char *colorRequest; + char *colorSeek; + char *colorNormal; + char *soundProgram; /* sound-playing program */ + char *soundShout; + char *soundSShout; + char *soundChannel1; + char *soundChannel; + char *soundKibitz; + char *soundTell; + char *soundChallenge; + char *soundRequest; + char *soundSeek; + char *soundMove; + char *soundIcsWin; + char *soundIcsLoss; + char *soundIcsDraw; + char *soundIcsUnfinished; + char *soundIcsAlarm; + Boolean reuseFirst; + Boolean reuseSecond; + Boolean animateDragging; /* If True, animate mouse dragging of pieces */ + Boolean animate; /* If True, animate non-mouse moves */ + int animSpeed; /* Delay in milliseconds between animation frames */ + Boolean popupMoveErrors; + Boolean popupExitMessage; + int showJail; + Boolean highlightLastMove; + Boolean highlightDragging; + Boolean blindfold; /* if true, no pieces are drawn */ + Boolean premove; /* true if premove feature enabled */ + Boolean premoveWhite; /* true if premoving White first move */ + char *premoveWhiteText; /* text of White premove 1 */ + Boolean premoveBlack; /* true if premoving Black first move */ + char *premoveBlackText; /* text of Black premove 1 */ + Boolean icsAlarm; /* true if sounding alarm at a certain time */ + int icsAlarmTime; /* time to sound alarm, in milliseconds */ + Boolean autoRaiseBoard; + int fontSizeTolerance; /* xboard only */ + char *initialMode; + char *variant; + int firstProtocolVersion; + int secondProtocolVersion; + Boolean showButtonBar; +#if ZIPPY + char *zippyLines; + char *zippyPinhead; + char *zippyPassword; + char *zippyPassword2; + char *zippyPassword3; + char *zippyWrongPassword; + char *zippyAcceptOnly; + int zippyUseI; + int zippyBughouse; + int zippyNoplayCrafty; + char *zippyGameEnd; + char *zippyGameStart; + int zippyAdjourn; + int zippyAbort; + char *zippyVariants; + int zippyMaxGames; + int zippyReplayTimeout; /*seconds*/ +#endif +} AppData, *AppDataPtr; + +extern AppData appData; + +typedef struct { + /* PGN 7-tag info */ + char *event; + char *site; + char *date; + char *round; + char *white; + char *black; + ChessMove result; + /* Additional info */ + char *fen; /* NULL or FEN for starting position; input only */ + char *resultDetails; + char *timeControl; + char *extraTags; /* NULL or "[Tag \"Value\"]\n", etc. */ + int whiteRating; /* -1 if unknown */ + int blackRating; /* -1 if unknown */ + VariantClass variant; +} GameInfo; + + + +#endif diff --git a/winboard-dm-beta4/config.h b/winboard-dm-beta4/config.h new file mode 100755 index 0000000..3f3bf18 --- /dev/null +++ b/winboard-dm-beta4/config.h @@ -0,0 +1,130 @@ +/* config.h.in. Generated automatically from configure.in by autoheader. */ + +/* Define if you have that is POSIX.1 compatible. */ +/*#undef HAVE_SYS_WAIT_H*/ + +/* Define if you need to in order for stat and other things to work. */ +/*#undef _POSIX_SOURCE*/ + +/* Define as the return type of signal handlers (int or void). */ +/*#undef RETSIGTYPE*/ + +/* Define if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define if you can safely include both and . */ +/*#undef TIME_WITH_SYS_TIME*/ + +/* Define if lex declares yytext as a char * by default, not a char[]. */ +/*#undef YYTEXT_POINTER*/ + +/*#define FIRST_PTY_LETTER 'p'*/ + +#define HAVE_FCNTL_H 1 + +#define HAVE_GETHOSTNAME 0 + +#define HAVE_GETTIMEOFDAY 0 + +#define HAVE_RANDOM 0 + +#define HAVE_SYS_SOCKET_H 0 + +/*#undef IBMRTAIX*/ + +#define LAST_PTY_LETTER 'q' + +#define PATCHLEVEL "6-dm-beta4" + +#define PRODUCT "WinBoard" + +#define PTY_ITERATION + +#define PTY_NAME_SPRINTF + +#define PTY_TTY_NAME_SPRINTF + +#define REMOTE_SHELL "" + +/*#undef RTU*/ + +/*#undef UNIPLUS*/ + +#define USE_PTYS 0 + +#define VERSION "4.2" + +/*#undef X_WCHAR*/ + +#ifndef __BORLANDC__ +#define WIN32 1 +#else +#define WIN32 +#endif + +#define ZIPPY 1 + +/* Define if you have the _getpty function. */ +/*#undef HAVE__GETPTY*/ + +/* Define if you have the ftime function. */ +#define HAVE_FTIME 1 + +/* Define if you have the grantpt function. */ +/*#undef HAVE_GRANTPT*/ + +/* Define if you have the rand48 function. */ +/*#undef HAVE_RAND48*/ + +/* Define if you have the sysinfo function. */ +/*#undef HAVE_SYSINFO*/ + +/* Define if you have the header file. */ +/*#undef HAVE_LAN_SOCKET_H*/ + +/* Define if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define if you have the header file. */ +/*#undef HAVE_STROPTS_H*/ + +/* Define if you have the header file. */ +#define HAVE_SYS_FCNTL_H 0 + +/* Define if you have the header file. */ +/*#undef HAVE_SYS_SYSTEMINFO_H*/ + +/* Define if you have the header file. */ +/*#undef HAVE_SYS_TIME_H*/ + +/* Define if you have the header file. */ +/*#undef HAVE_UNISTD_H*/ + +/* Define if you have the i library (-li). */ +/*#undef HAVE_LIBI*/ + +/* Define if you have the seq library (-lseq). */ +/*#undef HAVE_LIBSEQ*/ + +/* + Options + -DEMULATE_RSH -DREMOTE_SHELL=\"\" is necessary on Windows 95, because it + does not have its own rsh command. It works better this way on NT too, + because the NT rsh does not propagate signals to the remote process. + -DATTENTION is included even though I haven't been able to send signals to + child processes on Windows, because at least I can send them over rsh to + Unix programs. On Windows I send a newline instead, which wakes up the + chess program if it's polling. On my GNU Chess port the newline actually + works even for Move Now. +*/ +#define EMULATE_RSH 1 +#define ATTENTION 1 + +#ifdef __BORLANDC__ +#define _strdup(x) strdup(x) +#define STRICT +#define _winmajor 3 /* windows 95 */ +#define SCF_DEFAULT 0x0000 +#define SCF_ALL 0x0004 +#endif + diff --git a/winboard-dm-beta4/defaults.h b/winboard-dm-beta4/defaults.h new file mode 100755 index 0000000..f5ea885 --- /dev/null +++ b/winboard-dm-beta4/defaults.h @@ -0,0 +1,249 @@ +/* + * defaults.h -- Default settings for Windows NT front end to XBoard + * + * Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts. + * Enhancements Copyright 1992-97 Free Software Foundation, Inc. + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * ------------------------------------------------------------------------ + */ + +/* Static */ +#define POSITION_FILT "Position files (*.fen,*.epd,*.pos)\0*.fen;*.epd;*.pos\0All files (*.*)\0*.*\0" +#define GAME_FILT "Game files (*.pgn,*.gam)\0*.pgn;*.gam\0All files (*.*)\0*.*\0" +#define SOUND_FILT "Wave files (*.wav)\0*.wav\0All files (*.*)\0*.*\0" +#define OUTER_MARGIN (tinyLayout ? 0 : 4) +#define INNER_MARGIN (tinyLayout ? 0 : 2) +#define MESSAGE_LINE_LEFTMARGIN 2 +#define MESSAGE_TEXT_MAX 256 +/*#define COLOR_ECHOOFF RGB(192,192,192)*/ +#define COLOR_ECHOOFF consoleBackgroundColor +#define WRAP_INDENT 200 + +/* Settable */ +#define FIRST_CHESS_PROGRAM "" +#define FIRST_DIRECTORY "" +#define SECOND_CHESS_PROGRAM "" +#define SECOND_DIRECTORY "" + +#define CLOCK_FONT_TINY "Arial:9.0 b" +#define CLOCK_FONT_TEENY "Arial:9.0 b" +#define CLOCK_FONT_DINKY "Arial:10.0 b" +#define CLOCK_FONT_PETITE "Arial:10.0 b" +#define CLOCK_FONT_SLIM "Arial:12.0 b" +#define CLOCK_FONT_SMALL "Arial:14.0 b" +#define CLOCK_FONT_MEDIOCRE "Arial:14.0 b" +#define CLOCK_FONT_MIDDLING "Arial:14.0 b" +#define CLOCK_FONT_AVERAGE "Arial:15.0 b" +#define CLOCK_FONT_MODERATE "Arial:16.0 b" +#define CLOCK_FONT_MEDIUM "Arial:16.0 b" +#define CLOCK_FONT_BULKY "Arial:17.0 b" +#define CLOCK_FONT_LARGE "Arial:19.0 b" +#define CLOCK_FONT_BIG "Arial:20.0 b" +#define CLOCK_FONT_HUGE "Arial:21.0 b" +#define CLOCK_FONT_GIANT "Arial:22.0 b" +#define CLOCK_FONT_COLOSSAL "Arial:23.0 b" +#define CLOCK_FONT_TITANIC "Arial:24.0 b" + +#define MESSAGE_FONT_TINY "Small Fonts:6.0" +#define MESSAGE_FONT_TEENY "Small Fonts:6.0" +#define MESSAGE_FONT_DINKY "Small Fonts:7.0" +#define MESSAGE_FONT_PETITE "Small Fonts:7.0" +#define MESSAGE_FONT_SLIM "Arial:8.0 b" +#define MESSAGE_FONT_SMALL "Arial:9.0 b" +#define MESSAGE_FONT_MEDIOCRE "Arial:9.0 b" +#define MESSAGE_FONT_MIDDLING "Arial:9.0 b" +#define MESSAGE_FONT_AVERAGE "Arial:10.0 b" +#define MESSAGE_FONT_MODERATE "Arial:10.0 b" +#define MESSAGE_FONT_MEDIUM "Arial:10.0 b" +#define MESSAGE_FONT_BULKY "Arial:10.0 b" +#define MESSAGE_FONT_LARGE "Arial:10.0 b" +#define MESSAGE_FONT_BIG "Arial:11.0 b" +#define MESSAGE_FONT_HUGE "Arial:11.0 b" +#define MESSAGE_FONT_GIANT "Arial:11.0 b" +#define MESSAGE_FONT_COLOSSAL "Arial:12.0 b" +#define MESSAGE_FONT_TITANIC "Arial:12.0 b" + +#define COORD_FONT_TINY "Small Fonts:4.0" +#define COORD_FONT_TEENY "Small Fonts:4.0" +#define COORD_FONT_DINKY "Small Fonts:5.0" +#define COORD_FONT_PETITE "Small Fonts:5.0" +#define COORD_FONT_SLIM "Small Fonts:6.0" +#define COORD_FONT_SMALL "Small Fonts:7.0" +#define COORD_FONT_MEDIOCRE "Small Fonts:7.0" +#define COORD_FONT_MIDDLING "Small Fonts:7.0" +#define COORD_FONT_AVERAGE "Arial:7.0 b" +#define COORD_FONT_MODERATE "Arial:7.0 b" +#define COORD_FONT_MEDIUM "Arial:7.0 b" +#define COORD_FONT_BULKY "Arial:7.0 b" +#define COORD_FONT_LARGE "Arial:7.0 b" +#define COORD_FONT_BIG "Arial:8.0 b" +#define COORD_FONT_HUGE "Arial:8.0 b" +#define COORD_FONT_GIANT "Arial:8.0 b" +#define COORD_FONT_COLOSSAL "Arial:9.0 b" +#define COORD_FONT_TITANIC "Arial:9.0 b" + +#define CONSOLE_FONT_TINY "Courier New:8.0" +#define CONSOLE_FONT_TEENY "Courier New:8.0" +#define CONSOLE_FONT_DINKY "Courier New:8.0" +#define CONSOLE_FONT_PETITE "Courier New:8.0" +#define CONSOLE_FONT_SLIM "Courier New:8.0" +#define CONSOLE_FONT_SMALL "Courier New:8.0" +#define CONSOLE_FONT_MEDIOCRE "Courier New:8.0" +#define CONSOLE_FONT_MIDDLING "Courier New:8.0" +#define CONSOLE_FONT_AVERAGE "Courier New:8.0" +#define CONSOLE_FONT_MODERATE "Courier New:8.0" +#define CONSOLE_FONT_MEDIUM "Courier New:8.0" +#define CONSOLE_FONT_BULKY "Courier New:8.0" +#define CONSOLE_FONT_LARGE "Courier New:8.0" +#define CONSOLE_FONT_BIG "Courier New:8.0" +#define CONSOLE_FONT_HUGE "Courier New:8.0" +#define CONSOLE_FONT_GIANT "Courier New:8.0" +#define CONSOLE_FONT_COLOSSAL "Courier New:8.0" +#define CONSOLE_FONT_TITANIC "Courier New:8.0" + +#define COMMENT_FONT_TINY "Arial:9.0" +#define COMMENT_FONT_TEENY "Arial:9.0" +#define COMMENT_FONT_DINKY "Arial:9.0" +#define COMMENT_FONT_PETITE "Arial:9.0" +#define COMMENT_FONT_SLIM "Arial:9.0" +#define COMMENT_FONT_SMALL "Arial:9.0" +#define COMMENT_FONT_MEDIOCRE "Arial:9.0" +#define COMMENT_FONT_MIDDLING "Arial:9.0" +#define COMMENT_FONT_AVERAGE "Arial:9.0" +#define COMMENT_FONT_MODERATE "Arial:9.0" +#define COMMENT_FONT_MEDIUM "Arial:9.0" +#define COMMENT_FONT_BULKY "Arial:9.0" +#define COMMENT_FONT_LARGE "Arial:9.0" +#define COMMENT_FONT_BIG "Arial:9.0" +#define COMMENT_FONT_HUGE "Arial:9.0" +#define COMMENT_FONT_GIANT "Arial:9.0" +#define COMMENT_FONT_COLOSSAL "Arial:9.0" +#define COMMENT_FONT_TITANIC "Arial:9.0" + +#define EDITTAGS_FONT_TINY "Courier New:8.0" +#define EDITTAGS_FONT_TEENY "Courier New:8.0" +#define EDITTAGS_FONT_DINKY "Courier New:8.0" +#define EDITTAGS_FONT_PETITE "Courier New:8.0" +#define EDITTAGS_FONT_SLIM "Courier New:8.0" +#define EDITTAGS_FONT_SMALL "Courier New:8.0" +#define EDITTAGS_FONT_MEDIUM "Courier New:8.0" +#define EDITTAGS_FONT_MEDIOCRE "Courier New:8.0" +#define EDITTAGS_FONT_MIDDLING "Courier New:8.0" +#define EDITTAGS_FONT_AVERAGE "Courier New:8.0" +#define EDITTAGS_FONT_MODERATE "Courier New:8.0" +#define EDITTAGS_FONT_BULKY "Courier New:8.0" +#define EDITTAGS_FONT_LARGE "Courier New:8.0" +#define EDITTAGS_FONT_BIG "Courier New:8.0" +#define EDITTAGS_FONT_HUGE "Courier New:8.0" +#define EDITTAGS_FONT_GIANT "Courier New:8.0" +#define EDITTAGS_FONT_COLOSSAL "Courier New:8.0" +#define EDITTAGS_FONT_TITANIC "Courier New:8.0" + +#define COLOR_SHOUT "#209000" +#define COLOR_SSHOUT "b #289808" +#define COLOR_CHANNEL1 "#2020E0" +#define COLOR_CHANNEL "b #4040FF" +#define COLOR_KIBITZ "b #FF00FF" +#define COLOR_TELL "b #FF0000" +#define COLOR_CHALLENGE "bi #FF0000" +#define COLOR_REQUEST "bi #FF0000" +#define COLOR_SEEK "#980808" +#define COLOR_NORMAL "#000000" +#define COLOR_NONE "#000000" +#define COLOR_BKGD "#FFFFFF" + +#define SOUND_BELL "$" + +#define BUILT_IN_SOUND_NAMES {\ + "Beepbeep", "Ching", "Click", "Cymbal", "Ding", "Drip", \ + "Gong", "Laser", "Move", "Penalty", "Phone", "Pop", "Pop2", \ + "Slap", "Squeak", "Swish", "Thud", "Whipcrack", \ + "Alarm", "Challenge", "Channel", "Channel1", "Draw", "Kibitz", \ + "Lose", "Request", "Seek", "Shout", "SShout", "Tell", "Unfinished", \ + "Win", NULL \ +} + +#define SETTINGS_FILE "winboard.ini" + +#define ICS_LOGON "ics.ini" + +#define ICS_NAMES "\ +chessclub.com /icsport=5000 /icshelper=timestamp\n\ +freechess.org /icsport=5000 /icshelper=timeseal\n\ +global.chessparlor.com /icsport=6000 /icshelper=timeseal\n\ +chess.net /icsport=5000\n\ +chess-square.com /icsport=5000\n\ +icchess.net /icsport=5000\n\ +zics.org /icsport=5000\n\ +jogo.cex.org.br /icsport=5000\n\ +ajedrez.cec.uchile.cl /icsport=5000\n\ +fly.cc.fer.hr /icsport=7890\n\ +freechess.nl /icsport=5000 /icshelper=timeseal\n\ +jeu.echecs.com /icsport=5000\n\ +chess.unix-ag.uni-kl.de /icsport=5000 /icshelper=timeseal\n\ +chess.mds.mdh.se /icsport=5000\n\ +" + +#define ICS_TEXT_MENU_DEFAULT "\ +-\n\ +&Who,who,0,1\n\ +Playe&rs,players,0,1\n\ +&Games,games,0,1\n\ +&Sought,sought,0,1\n\ +|&Tell (name),tell,1,0\n\ +M&essage (name),message,1,0\n\ +-\n\ +&Finger (name),finger,1,1\n\ +&Vars (name),vars,1,1\n\ +&Observe (name),observe,1,1\n\ +&Match (name),match,1,1\n\ +Pl&ay (name),play,1,1\n\ +" + +#define FCP_NAMES "\ +GNUChess\n\ +\"GNUChes5 xboard\"\n\ +" + +#define SCP_NAMES "\ +GNUChess\n\ +\"GNUChes5 xboard\"\n\ +" diff --git a/winboard-dm-beta4/frontend.h b/winboard-dm-beta4/frontend.h new file mode 100755 index 0000000..bc55c10 --- /dev/null +++ b/winboard-dm-beta4/frontend.h @@ -0,0 +1,173 @@ +/* + * frontend.h -- Interface exported by all XBoard front ends + * $Id$ + * + * Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts. + * Enhancements Copyright 1992-95 Free Software Foundation, Inc. + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * ------------------------------------------------------------------------ + */ + +#ifndef _FRONTEND +#define _FRONTEND + +#include + +typedef VOIDSTAR ProcRef; +#define NoProc ((ProcRef) 0) +typedef VOIDSTAR InputSourceRef; + +void ModeHighlight P((void)); +void SetICSMode P((void)); +void SetGNUMode P((void)); +void SetNCPMode P((void)); +void SetCmailMode P((void)); +void SetTrainingModeOn P((void)); +void SetTrainingModeOff P((void)); +void SetUserThinkingEnables P((void)); +void SetMachineThinkingEnables P((void)); +void DisplayTitle P((String title)); +void DisplayMessage P((String message, String extMessage)); +void DisplayError P((String message, int error)); +void DisplayMoveError P((String message)); + +/* If status == 0, we are exiting with a benign message, not an error */ +void DisplayFatalError P((String message, int error, int status)); + +void DisplayInformation P((String message)); +void AskQuestion P((String title, String question, String replyPrefix, + ProcRef pr)); +void DisplayIcsInteractionTitle P((String title)); +void DrawPosition P((int fullRedraw, Board board)); +void ResetFrontEnd P((void)); +void CommentPopUp P((String title, String comment)); +void CommentPopDown P((void)); +void EditCommentPopUp P((int index, String title, String text)); + +void RingBell P((void)); +void PlayIcsWinSound P((void)); +void PlayIcsLossSound P((void)); +void PlayIcsDrawSound P((void)); +void PlayIcsUnfinishedSound P((void)); +void PlayAlarmSound P((void)); +void EchoOn P((void)); +void EchoOff P((void)); +void Raw P((void)); +void Colorize P((ColorClass cc, int continuation)); + +char *UserName P((void)); +char *HostName P((void)); + +int ClockTimerRunning P((void)); +int StopClockTimer P((void)); +void StartClockTimer P((long millisec)); +void DisplayWhiteClock P((long timeRemaining, int highlight)); +void DisplayBlackClock P((long timeRemaining, int highlight)); + +int LoadGameTimerRunning P((void)); +int StopLoadGameTimer P((void)); +void StartLoadGameTimer P((long millisec)); +void AutoSaveGame P((void)); + +typedef void (*DelayedEventCallback) P((void)); +void ScheduleDelayedEvent P((DelayedEventCallback cb, long millisec)); +DelayedEventCallback GetDelayedEvent P((void)); +void CancelDelayedEvent P((void)); + +int StartChildProcess P((char *cmdLine, char *dir, ProcRef *pr)); +void DestroyChildProcess P((ProcRef pr, int/*boolean*/ signal)); +void InterruptChildProcess P((ProcRef pr)); + +int OpenTelnet P((char *host, char *port, ProcRef *pr)); +int OpenTCP P((char *host, char *port, ProcRef *pr)); +int OpenCommPort P((char *name, ProcRef *pr)); +int OpenLoopback P((ProcRef *pr)); +int OpenRcmd P((char *host, char *user, char *cmd, ProcRef *pr)); + +typedef void (*InputCallback) P((InputSourceRef isr, VOIDSTAR closure, + char *buf, int count, int error)); +/* pr == NoProc means the local keyboard */ +InputSourceRef AddInputSource P((ProcRef pr, int lineByLine, + InputCallback func, VOIDSTAR closure)); +void RemoveInputSource P((InputSourceRef isr)); + +/* pr == NoProc means the local display */ +int OutputToProcess P((ProcRef pr, char *message, int count, int *outError)); +int OutputToProcessDelayed P((ProcRef pr, char *message, int count, + int *outError, long msdelay)); + +void CmailSigHandlerCallBack P((InputSourceRef isr, VOIDSTAR closure, + char *buf, int count, int error)); + +extern ProcRef cmailPR; + +/* these are in wgamelist.c */ +void GameListPopUp P((FILE *fp, char *filename)); +void GameListPopDown P((void)); +void GameListHighlight P((int index)); +void GameListDestroy P((void)); + +/* these are in wedittags.c */ +void EditTagsPopUp P((char *tags)); +void TagsPopUp P((char *tags, char *msg)); +void TagsPopDown P((void)); + +void ICSInitScript P((void)); +void StartAnalysisClock P((void)); +void AnalysisPopUp P((char *pv, char *depth, char *nps, + char *nodes, char *score, char *move_nr, char *time, int state)); +void AnalysisPopDown P((void)); + +void SetHighlights P((int fromX, int fromY, int toX, int toY)); +void ClearHighlights P((void)); +void SetPremoveHighlights P((int fromX, int fromY, int toX, int toY)); +void ClearPremoveHighlights P((void)); + +void ShutDownFrontEnd P((void)); +void BoardToTop P((void)); +void AnimateMove P((Board board, int fromX, int fromY, int toX, int toY)); +void HistorySet P((char movelist[][2*MOVE_LEN], + int first, int last, int current)); +void FreezeUI P((void)); +void ThawUI P((void)); +extern char *programName; + +#endif diff --git a/winboard-dm-beta4/gamelist.c b/winboard-dm-beta4/gamelist.c new file mode 100755 index 0000000..0df36b6 --- /dev/null +++ b/winboard-dm-beta4/gamelist.c @@ -0,0 +1,305 @@ +/* + * gamelist.c -- Functions to manage a gamelist + * XBoard $Id$ + * + * Copyright 1995 Free Software Foundation, Inc. + * + * ------------------------------------------------------------------------ + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA. + * ------------------------------------------------------------------------ + */ + +#include "config.h" + +#include +#include +#if STDC_HEADERS +# include +# include +#else /* not STDC_HEADERS */ +# if HAVE_STRING_H +# include +# else /* not HAVE_STRING_H */ +# include +# endif /* not HAVE_STRING_H */ +#endif /* not STDC_HEADERS */ + +#include "common.h" +#include "frontend.h" +#include "backend.h" +#include "parser.h" + + +/* Variables + */ +List gameList; + + +/* Local function prototypes + */ +static void GameListDeleteGame P((ListGame *)); +static ListGame *GameListCreate P((void)); +static void GameListFree P((List *)); +static int GameListNewGame P((ListGame **)); + +/* Delete a ListGame; implies removint it from a list. + */ +static void GameListDeleteGame(listGame) + ListGame *listGame; +{ + if (listGame) { + if (listGame->gameInfo.event) free(listGame->gameInfo.event); + if (listGame->gameInfo.site) free(listGame->gameInfo.site); + if (listGame->gameInfo.date) free(listGame->gameInfo.date); + if (listGame->gameInfo.round) free(listGame->gameInfo.round); + if (listGame->gameInfo.white) free(listGame->gameInfo.white); + if (listGame->gameInfo.black) free(listGame->gameInfo.black); + if (listGame->gameInfo.fen) free(listGame->gameInfo.fen); + if (listGame->gameInfo.resultDetails) free(listGame->gameInfo.resultDetails); + if (listGame->gameInfo.timeControl) free(listGame->gameInfo.timeControl); + if (listGame->gameInfo.extraTags) free(listGame->gameInfo.extraTags); + ListNodeFree((ListNode *) listGame); + } +} + + +/* Free the previous list of games. + */ +static void GameListFree(gameList) + List *gameList; +{ + while (!ListEmpty(gameList)) + { + GameListDeleteGame((ListGame *) gameList->head); + } +} + + + +/* Initialize a new GameInfo structure. + */ +void GameListInitGameInfo(gameInfo) + GameInfo *gameInfo; +{ + gameInfo->event = NULL; + gameInfo->site = NULL; + gameInfo->date = NULL; + gameInfo->round = NULL; + gameInfo->white = NULL; + gameInfo->black = NULL; + gameInfo->result = GameUnfinished; + gameInfo->fen = NULL; + gameInfo->resultDetails = NULL; + gameInfo->timeControl = NULL; + gameInfo->extraTags = NULL; + gameInfo->whiteRating = -1; /* unknown */ + gameInfo->blackRating = -1; /* unknown */ + gameInfo->variant = VariantNormal; +} + + +/* Create empty ListGame; returns ListGame or NULL, if out of memory. + * + * Note, that the ListGame is *not* added to any list + */ +static ListGame *GameListCreate() + +{ + ListGame *listGame; + + if ((listGame = (ListGame *) ListNodeCreate(sizeof(*listGame)))) { + GameListInitGameInfo(&listGame->gameInfo); + } + return(listGame); +} + + +/* Creates a new game for the gamelist. + */ +static int GameListNewGame(listGamePtr) + ListGame **listGamePtr; +{ + if (!(*listGamePtr = (ListGame *) GameListCreate())) { + GameListFree(&gameList); + return(ENOMEM); + } + ListAddTail(&gameList, (ListNode *) *listGamePtr); + return(0); +} + + +/* Build the list of games in the open file f. + * Returns 0 for success or error number. + */ +int GameListBuild(f) + FILE *f; +{ + ChessMove cm, lastStart; + int gameNumber; + ListGame *currentListGame = NULL; + int error; + int offset; + + GameListFree(&gameList); + yynewfile(f); + gameNumber = 0; + + lastStart = (ChessMove) 0; + yyskipmoves = TRUE; + do { + yyboardindex = 1; + offset = yyoffset(); + cm = (ChessMove) yylex(); + switch (cm) { + case GNUChessGame: + if ((error = GameListNewGame(¤tListGame))) { + rewind(f); + yyskipmoves = FALSE; + return(error); + } + currentListGame->number = ++gameNumber; + currentListGame->offset = offset; + if (currentListGame->gameInfo.event != NULL) { + free(currentListGame->gameInfo.event); + } + currentListGame->gameInfo.event = StrSave(yy_text); + lastStart = cm; + break; + case XBoardGame: + lastStart = cm; + break; + case MoveNumberOne: + switch (lastStart) { + case GNUChessGame: + break; /* ignore */ + case PGNTag: + lastStart = cm; + break; /* Already started */ + case (ChessMove) 0: + case MoveNumberOne: + case XBoardGame: + if ((error = GameListNewGame(¤tListGame))) { + rewind(f); + yyskipmoves = FALSE; + return(error); + } + currentListGame->number = ++gameNumber; + currentListGame->offset = offset; + lastStart = cm; + break; + default: + break; /* impossible */ + } + break; + case PGNTag: + lastStart = cm; + if ((error = GameListNewGame(¤tListGame))) { + rewind(f); + yyskipmoves = FALSE; + return(error); + } + currentListGame->number = ++gameNumber; + currentListGame->offset = offset; + ParsePGNTag(yy_text, ¤tListGame->gameInfo); + do { + yyboardindex = 1; + offset = yyoffset(); + cm = (ChessMove) yylex(); + if (cm == PGNTag) { + ParsePGNTag(yy_text, ¤tListGame->gameInfo); + } + } while (cm == PGNTag || cm == Comment); + break; + default: + break; + } + } + while (cm != (ChessMove) 0); + + + if (appData.debugMode) { + for (currentListGame = (ListGame *) gameList.head; + currentListGame->node.succ; + currentListGame = (ListGame *) currentListGame->node.succ) { + + fprintf(debugFP, "Parsed game number %d, offset %ld:\n", + currentListGame->number, currentListGame->offset); + PrintPGNTags(debugFP, ¤tListGame->gameInfo); + } + } + + rewind(f); + yyskipmoves = FALSE; + return 0; +} + + +/* Clear an existing GameInfo structure. + */ +void ClearGameInfo(gameInfo) + GameInfo *gameInfo; +{ + if (gameInfo->event != NULL) { + free(gameInfo->event); + } + if (gameInfo->site != NULL) { + free(gameInfo->site); + } + if (gameInfo->date != NULL) { + free(gameInfo->date); + } + if (gameInfo->round != NULL) { + free(gameInfo->round); + } + if (gameInfo->white != NULL) { + free(gameInfo->white); + } + if (gameInfo->black != NULL) { + free(gameInfo->black); + } + if (gameInfo->resultDetails != NULL) { + free(gameInfo->resultDetails); + } + if (gameInfo->fen != NULL) { + free(gameInfo->fen); + } + if (gameInfo->timeControl != NULL) { + free(gameInfo->timeControl); + } + if (gameInfo->extraTags != NULL) { + free(gameInfo->extraTags); + } + + GameListInitGameInfo(gameInfo); +} + +char * +GameListLine(number, gameInfo) + int number; + GameInfo *gameInfo; +{ + char *event = (gameInfo->event && strcmp(gameInfo->event, "?") != 0) ? + gameInfo->event : gameInfo->site ? gameInfo->site : "?"; + char *white = gameInfo->white ? gameInfo->white : "?"; + char *black = gameInfo->black ? gameInfo->black : "?"; + char *date = gameInfo->date ? gameInfo->date : "?"; + int len = 10 + strlen(event) + 2 + strlen(white) + 1 + + strlen(black) + 11 + strlen(date) + 1; + char *ret = (char *) malloc(len); + sprintf(ret, "%d. %s, %s-%s, %s, %s", + number, event, white, black, PGNResult(gameInfo->result), date); + return ret; +} + diff --git a/winboard-dm-beta4/lists.c b/winboard-dm-beta4/lists.c new file mode 100755 index 0000000..9f6d4b5 --- /dev/null +++ b/winboard-dm-beta4/lists.c @@ -0,0 +1,149 @@ +/* + * lists.c -- Functions to implement a double linked list + * XBoard $Id$ + * + * Copyright 1995 Free Software Foundation, Inc. + * + * ------------------------------------------------------------------------ + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA. + * ------------------------------------------------------------------------ + * + * This file could well be a part of backend.c, but I prefer it this + * way. + */ + +#include "config.h" + +#include +#if STDC_HEADERS +# include +#endif /* not STDC_HEADERS */ + +#include "common.h" +#include "lists.h" + + + +/* Check, if List l is empty; returns TRUE, if it is, FALSE + * otherwise. + */ +int ListEmpty(l) + List *l; +{ + return(l->head == (ListNode *) &l->tail); +} + + +/* Initialize a list. Must be executed before list is used. + */ +void ListNew(l) + List *l; +{ + l->head = (ListNode *) &l->tail; + l->tail = NULL; + l->tailPred = (ListNode *) l; +} + + +/* Remove node n from the list it is inside. + */ +void ListRemove(n) + ListNode *n; +{ + if (n->succ != NULL) { /* Be safe */ + n->pred->succ = n->succ; + n->succ->pred = n->pred; + n->succ = NULL; /* Mark node as no longer being member */ + n->pred = NULL; /* of a list. */ + } +} + + +/* Delete node n. + */ +void ListNodeFree(n) + ListNode *n; +{ + if (n) { + ListRemove(n); + free(n); + } +} + + +/* Create a list node with size s. Returns NULL, if out of memory. + */ +ListNode *ListNodeCreate(s) + size_t s; +{ + ListNode *n; + + if ((n = (ListNode*) malloc(s))) { + n->succ = NULL; /* Mark node as not being member of a list. */ + n->pred = NULL; + } + return(n); +} + + +/* Insert node n into the list of node m after m. + */ +void ListInsert(m, n) + ListNode *m, *n; +{ + n->succ = m->succ; + n->pred = m; + m->succ = n; + n->succ->pred = n; +} + + +/* Add node n to the head of list l. + */ +void ListAddHead(l, n) + List *l; + ListNode *n; +{ + ListInsert((ListNode *) &l->head, n); +} + + +/* Add node n to the tail of list l. + */ +void ListAddTail(l, n) + List *l; + ListNode *n; +{ + ListInsert((ListNode *) l->tailPred, n); +} + + +/* Return element with number n of list l. (NULL, if n doesn't exist.) + * Counting starts with 0. + */ +ListNode *ListElem(l, n) + List *l; + int n; +{ + ListNode *ln; + + for (ln = l->head; ln->succ; ln = ln->succ) { + if (!n--) { + return (ln); + } + } + + return(NULL); +} diff --git a/winboard-dm-beta4/lists.h b/winboard-dm-beta4/lists.h new file mode 100755 index 0000000..780f6c2 --- /dev/null +++ b/winboard-dm-beta4/lists.h @@ -0,0 +1,66 @@ +/* + * lists.c -- Includefile of lists.c + * XBoard $Id$ + * + * Copyright 1995 Free Software Foundation, Inc. + * + * ------------------------------------------------------------------------ + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA. + * ------------------------------------------------------------------------ + * + * This file could well be a part of backend.c, but I prefer it this + * way. + */ + +#ifndef _LISTS_H +#define _LISTS_H + + +/* Type definition: Node of a double linked list. + */ +typedef struct _ListNode { + struct _ListNode *succ; + struct _ListNode *pred; +} ListNode; + + +/* Type definition: Double linked list. + * + * The list structure consists of two ListNode's: The pred entry of + * the head being the succ entry of the tail. Thus a list is empty + * if and only if it consists of 2 nodes. :-) + */ +typedef struct { + struct _ListNode *head; /* The list structure consists of two */ + struct _ListNode *tail; /* ListNode's: The pred entry of the */ + struct _ListNode *tailPred; /* head being the succ entry of the */ +} List; /* tail. */ + + + +/* Function prototypes + */ +extern int ListEmpty P((List *)); +void ListNew P((List *)); +void ListRemove P((ListNode *)); +void ListNodeFree P((ListNode *)); +ListNode *ListNodeCreate P((size_t)); +void ListInsert P((ListNode *, ListNode *)); +void ListAddHead P((List *, ListNode *)); +void ListAddTail P((List *, ListNode *)); +ListNode *ListElem P((List *, int)); + + +#endif diff --git a/winboard-dm-beta4/moves.c b/winboard-dm-beta4/moves.c new file mode 100755 index 0000000..bed2064 --- /dev/null +++ b/winboard-dm-beta4/moves.c @@ -0,0 +1,978 @@ +/* + * moves.c - Move generation and checking + * $Id$ + * + * Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts. + * Enhancements Copyright 1992-95 Free Software Foundation, Inc. + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * ------------------------------------------------------------------------ + */ + +#include "config.h" + +#include +#if HAVE_STRING_H +# include +#else /* not HAVE_STRING_H */ +# include +#endif /* not HAVE_STRING_H */ +#include "common.h" +#include "backend.h" +#include "moves.h" +#include "parser.h" + +int WhitePiece P((ChessSquare)); +int BlackPiece P((ChessSquare)); +int SameColor P((ChessSquare, ChessSquare)); + + +int WhitePiece(piece) + ChessSquare piece; +{ + return (int) piece >= (int) WhitePawn && (int) piece <= (int) WhiteKing; +} + +int BlackPiece(piece) + ChessSquare piece; +{ + return (int) piece >= (int) BlackPawn && (int) piece <= (int) BlackKing; +} + +int SameColor(piece1, piece2) + ChessSquare piece1, piece2; +{ + return ((int) piece1 >= (int) WhitePawn && + (int) piece1 <= (int) WhiteKing && + (int) piece2 >= (int) WhitePawn && + (int) piece2 <= (int) WhiteKing) + || ((int) piece1 >= (int) BlackPawn && + (int) piece1 <= (int) BlackKing && + (int) piece2 >= (int) BlackPawn && + (int) piece2 <= (int) BlackKing); +} + +ChessSquare PromoPiece(moveType) + ChessMove moveType; +{ + switch (moveType) { + default: + return EmptySquare; + case WhitePromotionQueen: + return WhiteQueen; + case BlackPromotionQueen: + return BlackQueen; + case WhitePromotionRook: + return WhiteRook; + case BlackPromotionRook: + return BlackRook; + case WhitePromotionBishop: + return WhiteBishop; + case BlackPromotionBishop: + return BlackBishop; + case WhitePromotionKnight: + return WhiteKnight; + case BlackPromotionKnight: + return BlackKnight; + case WhitePromotionKing: + return WhiteKing; + case BlackPromotionKing: + return BlackKing; + } +} + +ChessMove PromoCharToMoveType(whiteOnMove, promoChar) + int whiteOnMove; + int promoChar; +{ + if (whiteOnMove) { + switch (promoChar) { + case 'n': + case 'N': + return WhitePromotionKnight; + case 'b': + case 'B': + return WhitePromotionBishop; + case 'r': + case 'R': + return WhitePromotionRook; + case 'q': + case 'Q': + return WhitePromotionQueen; + case 'k': + case 'K': + return WhitePromotionKing; + case NULLCHAR: + default: + return NormalMove; + } + } else { + switch (promoChar) { + case 'n': + case 'N': + return BlackPromotionKnight; + case 'b': + case 'B': + return BlackPromotionBishop; + case 'r': + case 'R': + return BlackPromotionRook; + case 'q': + case 'Q': + return BlackPromotionQueen; + case 'k': + case 'K': + return BlackPromotionKing; + case NULLCHAR: + default: + return NormalMove; + } + } +} + +char pieceToChar[] = { + 'P', 'N', 'B', 'R', 'Q', 'K', + 'p', 'n', 'b', 'r', 'q', 'k', 'x' + }; + +char PieceToChar(p) + ChessSquare p; +{ + return pieceToChar[(int) p]; +} + +ChessSquare CharToPiece(c) + int c; +{ + switch (c) { + default: + case 'x': return EmptySquare; + case 'P': return WhitePawn; + case 'R': return WhiteRook; + case 'N': return WhiteKnight; + case 'B': return WhiteBishop; + case 'Q': return WhiteQueen; + case 'K': return WhiteKing; + case 'p': return BlackPawn; + case 'r': return BlackRook; + case 'n': return BlackKnight; + case 'b': return BlackBishop; + case 'q': return BlackQueen; + case 'k': return BlackKing; + } +} + +void CopyBoard(to, from) + Board to, from; +{ + int i, j; + + for (i = 0; i < BOARD_SIZE; i++) + for (j = 0; j < BOARD_SIZE; j++) + to[i][j] = from[i][j]; +} + +int CompareBoards(board1, board2) + Board board1, board2; +{ + int i, j; + + for (i = 0; i < BOARD_SIZE; i++) + for (j = 0; j < BOARD_SIZE; j++) { + if (board1[i][j] != board2[i][j]) + return FALSE; + } + return TRUE; +} + + +/* Call callback once for each pseudo-legal move in the given + position, except castling moves. A move is pseudo-legal if it is + legal, or if it would be legal except that it leaves the king in + check. In the arguments, epfile is EP_NONE if the previous move + was not a double pawn push, or the file 0..7 if it was, or + EP_UNKNOWN if we don't know and want to allow all e.p. captures. + Promotion moves generated are to Queen only. +*/ +void GenPseudoLegal(board, flags, epfile, callback, closure) + Board board; + int flags; + int epfile; + MoveCallback callback; + VOIDSTAR closure; +{ + int rf, ff; + int i, j, d, s, fs, rs, rt, ft; + + for (rf = 0; rf <= 7; rf++) + for (ff = 0; ff <= 7; ff++) { + if (flags & F_WHITE_ON_MOVE) { + if (!WhitePiece(board[rf][ff])) continue; + } else { + if (!BlackPiece(board[rf][ff])) continue; + } + switch (board[rf][ff]) { + case EmptySquare: + default: + /* can't happen */ + break; + + case WhitePawn: + if (rf < 7 && board[rf + 1][ff] == EmptySquare) { + callback(board, flags, + rf == 6 ? WhitePromotionQueen : NormalMove, + rf, ff, rf + 1, ff, closure); + } + if (rf == 1 && board[2][ff] == EmptySquare && + board[3][ff] == EmptySquare) { + callback(board, flags, NormalMove, + rf, ff, 3, ff, closure); + } + for (s = -1; s <= 1; s += 2) { + if (rf < 7 && ff + s >= 0 && ff + s <= 7 && + ((flags & F_KRIEGSPIEL_CAPTURE) || + BlackPiece(board[rf + 1][ff + s]))) { + callback(board, flags, + rf == 6 ? WhitePromotionQueen : NormalMove, + rf, ff, rf + 1, ff + s, closure); + } + if (rf == 4) { + if (ff + s >= 0 && ff + s <= 7 && + (epfile == ff + s || epfile == EP_UNKNOWN) && + board[4][ff + s] == BlackPawn && + board[5][ff + s] == EmptySquare) { + callback(board, flags, WhiteCapturesEnPassant, + rf, ff, 5, ff + s, closure); + } + } + } + break; + + case BlackPawn: + if (rf > 0 && board[rf - 1][ff] == EmptySquare) { + callback(board, flags, + rf == 1 ? BlackPromotionQueen : NormalMove, + rf, ff, rf - 1, ff, closure); + } + if (rf == 6 && board[5][ff] == EmptySquare && + board[4][ff] == EmptySquare) { + callback(board, flags, NormalMove, + rf, ff, 4, ff, closure); + } + for (s = -1; s <= 1; s += 2) { + if (rf > 0 && ff + s >= 0 && ff + s <= 7 && + ((flags & F_KRIEGSPIEL_CAPTURE) || + WhitePiece(board[rf - 1][ff + s]))) { + callback(board, flags, + rf == 1 ? BlackPromotionQueen : NormalMove, + rf, ff, rf - 1, ff + s, closure); + } + if (rf == 3) { + if (ff + s >= 0 && ff + s <= 7 && + (epfile == ff + s || epfile == EP_UNKNOWN) && + board[3][ff + s] == WhitePawn && + board[2][ff + s] == EmptySquare) { + callback(board, flags, BlackCapturesEnPassant, + rf, ff, 2, ff + s, closure); + } + } + } + break; + + case WhiteKnight: + case BlackKnight: + for (i = -1; i <= 1; i += 2) + for (j = -1; j <= 1; j += 2) + for (s = 1; s <= 2; s++) { + rt = rf + i*s; + ft = ff + j*(3-s); + if (rt < 0 || rt > 7 || ft < 0 || ft > 7) continue; + if (SameColor(board[rf][ff], board[rt][ft])) continue; + callback(board, flags, NormalMove, + rf, ff, rt, ft, closure); + } + break; + + case WhiteBishop: + case BlackBishop: + for (rs = -1; rs <= 1; rs += 2) + for (fs = -1; fs <= 1; fs += 2) + for (i = 1;; i++) { + rt = rf + (i * rs); + ft = ff + (i * fs); + if (rt < 0 || rt > 7 || ft < 0 || ft > 7) break; + if (SameColor(board[rf][ff], board[rt][ft])) break; + callback(board, flags, NormalMove, + rf, ff, rt, ft, closure); + if (board[rt][ft] != EmptySquare) break; + } + break; + + case WhiteRook: + case BlackRook: + for (d = 0; d <= 1; d++) + for (s = -1; s <= 1; s += 2) + for (i = 1;; i++) { + rt = rf + (i * s) * d; + ft = ff + (i * s) * (1 - d); + if (rt < 0 || rt > 7 || ft < 0 || ft > 7) break; + if (SameColor(board[rf][ff], board[rt][ft])) break; + callback(board, flags, NormalMove, + rf, ff, rt, ft, closure); + if (board[rt][ft] != EmptySquare) break; + } + break; + + case WhiteQueen: + case BlackQueen: + for (rs = -1; rs <= 1; rs++) + for (fs = -1; fs <= 1; fs++) { + if (rs == 0 && fs == 0) continue; + for (i = 1;; i++) { + rt = rf + (i * rs); + ft = ff + (i * fs); + if (rt < 0 || rt > 7 || ft < 0 || ft > 7) break; + if (SameColor(board[rf][ff], board[rt][ft])) break; + callback(board, flags, NormalMove, + rf, ff, rt, ft, closure); + if (board[rt][ft] != EmptySquare) break; + } + } + break; + + case WhiteKing: + case BlackKing: + for (i = -1; i <= 1; i++) + for (j = -1; j <= 1; j++) { + if (i == 0 && j == 0) continue; + rt = rf + i; + ft = ff + j; + if (rt < 0 || rt > 7 || ft < 0 || ft > 7) continue; + if (SameColor(board[rf][ff], board[rt][ft])) continue; + callback(board, flags, NormalMove, + rf, ff, rt, ft, closure); + } + break; + } + } +} + + +typedef struct { + MoveCallback cb; + VOIDSTAR cl; +} GenLegalClosure; + +extern void GenLegalCallback P((Board board, int flags, ChessMove kind, + int rf, int ff, int rt, int ft, + VOIDSTAR closure)); + +void GenLegalCallback(board, flags, kind, rf, ff, rt, ft, closure) + Board board; + int flags; + ChessMove kind; + int rf, ff, rt, ft; + VOIDSTAR closure; +{ + register GenLegalClosure *cl = (GenLegalClosure *) closure; + + if (!(flags & F_IGNORE_CHECK) && + CheckTest(board, flags, rf, ff, rt, ft, + kind == WhiteCapturesEnPassant || + kind == BlackCapturesEnPassant)) return; + if (flags & F_ATOMIC_CAPTURE) { + if (board[rt][ft] != EmptySquare || + kind == WhiteCapturesEnPassant || kind == BlackCapturesEnPassant) { + int r, f; + ChessSquare king = (flags & F_WHITE_ON_MOVE) ? WhiteKing : BlackKing; + if (board[rf][ff] == king) return; + for (r = rt-1; r <= rt+1; r++) { + for (f = ft-1; f <= ft+1; f++) { + if (r >= 0 && r <= 7 && f >= 0 && f <= 7 && + board[r][f] == king) return; + } + } + } + } + cl->cb(board, flags, kind, rf, ff, rt, ft, cl->cl); +} + + +/* Like GenPseudoLegal, but (1) include castling moves, (2) unless + F_IGNORE_CHECK is set in the flags, omit moves that would leave the + king in check, and (3) if F_ATOMIC_CAPTURE is set in the flags, omit + moves that would destroy your own king. The CASTLE_OK flags are + true if castling is not yet ruled out by a move of the king or + rook. Return TRUE if the player on move is currently in check and + F_IGNORE_CHECK is not set. */ +int GenLegal(board, flags, epfile, callback, closure) + Board board; + int flags; + int epfile; + MoveCallback callback; + VOIDSTAR closure; +{ + GenLegalClosure cl; + int ff; + int ignoreCheck = (flags & F_IGNORE_CHECK) != 0; + + cl.cb = callback; + cl.cl = closure; + GenPseudoLegal(board, flags, epfile, GenLegalCallback, (VOIDSTAR) &cl); + + if (!ignoreCheck && + CheckTest(board, flags, -1, -1, -1, -1, FALSE)) return TRUE; + + /* Generate castling moves */ + for (ff = 4; ff >= 3; ff-- /*ics wild 1*/) { + if ((flags & F_WHITE_ON_MOVE) && + (flags & F_WHITE_KCASTLE_OK) && + board[0][ff] == WhiteKing && + board[0][ff + 1] == EmptySquare && + board[0][ff + 2] == EmptySquare && + board[0][6] == EmptySquare && + board[0][7] == WhiteRook && + (ignoreCheck || + (!CheckTest(board, flags, 0, ff, 0, ff + 1, FALSE) && + !CheckTest(board, flags, 0, ff, 0, ff + 2, FALSE)))) { + + callback(board, flags, + ff==4 ? WhiteKingSideCastle : WhiteKingSideCastleWild, + 0, ff, 0, ff + 2, closure); + } + if ((flags & F_WHITE_ON_MOVE) && + (flags & F_WHITE_QCASTLE_OK) && + board[0][ff] == WhiteKing && + board[0][ff - 1] == EmptySquare && + board[0][ff - 2] == EmptySquare && + board[0][1] == EmptySquare && + board[0][0] == WhiteRook && + (ignoreCheck || + (!CheckTest(board, flags, 0, ff, 0, ff - 1, FALSE) && + !CheckTest(board, flags, 0, ff, 0, ff - 2, FALSE)))) { + + callback(board, flags, + ff==4 ? WhiteQueenSideCastle : WhiteQueenSideCastleWild, + 0, ff, 0, ff - 2, closure); + } + if (!(flags & F_WHITE_ON_MOVE) && + (flags & F_BLACK_KCASTLE_OK) && + board[7][ff] == BlackKing && + board[7][ff + 1] == EmptySquare && + board[7][ff + 2] == EmptySquare && + board[7][6] == EmptySquare && + board[7][7] == BlackRook && + (ignoreCheck || + (!CheckTest(board, flags, 7, ff, 7, ff + 1, FALSE) && + !CheckTest(board, flags, 7, ff, 7, ff + 2, FALSE)))) { + + callback(board, flags, + ff==4 ? BlackKingSideCastle : BlackKingSideCastleWild, + 7, ff, 7, ff + 2, closure); + } + if (!(flags & F_WHITE_ON_MOVE) && + (flags & F_BLACK_QCASTLE_OK) && + board[7][ff] == BlackKing && + board[7][ff - 1] == EmptySquare && + board[7][ff - 2] == EmptySquare && + board[7][1] == EmptySquare && + board[7][0] == BlackRook && + (ignoreCheck || + (!CheckTest(board, flags, 7, ff, 7, ff - 1, FALSE) && + !CheckTest(board, flags, 7, ff, 7, ff - 1, FALSE)))) { + + callback(board, flags, + ff==4 ? BlackQueenSideCastle : BlackQueenSideCastleWild, + 7, ff, 7, ff - 2, closure); + } + } + + return FALSE; +} + + +typedef struct { + int rking, fking; + int check; +} CheckTestClosure; + + +extern void CheckTestCallback P((Board board, int flags, ChessMove kind, + int rf, int ff, int rt, int ft, + VOIDSTAR closure)); + + +void CheckTestCallback(board, flags, kind, rf, ff, rt, ft, closure) + Board board; + int flags; + ChessMove kind; + int rf, ff, rt, ft; + VOIDSTAR closure; +{ + register CheckTestClosure *cl = (CheckTestClosure *) closure; + + if (rt == cl->rking && ft == cl->fking) cl->check++; +} + + +/* If the player on move were to move from (rf, ff) to (rt, ft), would + he leave himself in check? Or if rf == -1, is the player on move + in check now? enPassant must be TRUE if the indicated move is an + e.p. capture. The possibility of castling out of a check along the + back rank is not accounted for (i.e., we still return nonzero), as + this is illegal anyway. Return value is the number of times the + king is in check. */ +int CheckTest(board, flags, rf, ff, rt, ft, enPassant) + Board board; + int flags; + int rf, ff, rt, ft, enPassant; +{ + CheckTestClosure cl; + ChessSquare king = flags & F_WHITE_ON_MOVE ? WhiteKing : BlackKing; + ChessSquare captured = EmptySquare; + /* Suppress warnings on uninitialized variables */ + + if (rf >= 0) { + if (enPassant) { + captured = board[rf][ft]; + board[rf][ft] = EmptySquare; + } else { + captured = board[rt][ft]; + } + board[rt][ft] = board[rf][ff]; + board[rf][ff] = EmptySquare; + } + + /* For compatibility with ICS wild 9, we scan the board in the + order a1, a2, a3, ... b1, b2, ..., h8 to find the first king, + and we test only whether that one is in check. */ + cl.check = 0; + for (cl.fking = 0; cl.fking <= 7; cl.fking++) + for (cl.rking = 0; cl.rking <= 7; cl.rking++) { + if (board[cl.rking][cl.fking] == king) { + GenPseudoLegal(board, flags ^ F_WHITE_ON_MOVE, -1, + CheckTestCallback, (VOIDSTAR) &cl); + goto undo_move; /* 2-level break */ + } + } + + undo_move: + + if (rf >= 0) { + board[rf][ff] = board[rt][ft]; + if (enPassant) { + board[rf][ft] = captured; + board[rt][ft] = EmptySquare; + } else { + board[rt][ft] = captured; + } + } + + return cl.check; +} + + +typedef struct { + int rf, ff, rt, ft; + ChessMove kind; +} LegalityTestClosure; + +extern void LegalityTestCallback P((Board board, int flags, ChessMove kind, + int rf, int ff, int rt, int ft, + VOIDSTAR closure)); + +void LegalityTestCallback(board, flags, kind, rf, ff, rt, ft, closure) + Board board; + int flags; + ChessMove kind; + int rf, ff, rt, ft; + VOIDSTAR closure; +{ + register LegalityTestClosure *cl = (LegalityTestClosure *) closure; + + if (rf == cl->rf && ff == cl->ff && rt == cl->rt && ft == cl->ft) + cl->kind = kind; +} + +ChessMove LegalityTest(board, flags, epfile, rf, ff, rt, ft, promoChar) + Board board; + int flags, epfile; + int rf, ff, rt, ft, promoChar; +{ + LegalityTestClosure cl; + + cl.rf = rf; + cl.ff = ff; + cl.rt = rt; + cl.ft = ft; + cl.kind = IllegalMove; + GenLegal(board, flags, epfile, LegalityTestCallback, (VOIDSTAR) &cl); + if (promoChar != NULLCHAR && promoChar != 'x') { + if (cl.kind == WhitePromotionQueen || cl.kind == BlackPromotionQueen) { + cl.kind = + PromoCharToMoveType((flags & F_WHITE_ON_MOVE) != 0, promoChar); + } else { + cl.kind = IllegalMove; + } + } + return cl.kind; +} + +typedef struct { + int count; +} MateTestClosure; + +extern void MateTestCallback P((Board board, int flags, ChessMove kind, + int rf, int ff, int rt, int ft, + VOIDSTAR closure)); + +void MateTestCallback(board, flags, kind, rf, ff, rt, ft, closure) + Board board; + int flags; + ChessMove kind; + int rf, ff, rt, ft; + VOIDSTAR closure; +{ + register MateTestClosure *cl = (MateTestClosure *) closure; + + cl->count++; +} + +/* Return MT_NONE, MT_CHECK, MT_CHECKMATE, or MT_STALEMATE */ +int MateTest(board, flags, epfile) + Board board; + int flags, epfile; +{ + MateTestClosure cl; + int inCheck; + + cl.count = 0; + inCheck = GenLegal(board, flags, epfile, MateTestCallback, (VOIDSTAR) &cl); + if (cl.count > 0) { + return inCheck ? MT_CHECK : MT_NONE; + } else { + return inCheck ? MT_CHECKMATE : MT_STALEMATE; + } +} + + +extern void DisambiguateCallback P((Board board, int flags, ChessMove kind, + int rf, int ff, int rt, int ft, + VOIDSTAR closure)); + +void DisambiguateCallback(board, flags, kind, rf, ff, rt, ft, closure) + Board board; + int flags; + ChessMove kind; + int rf, ff, rt, ft; + VOIDSTAR closure; +{ + register DisambiguateClosure *cl = (DisambiguateClosure *) closure; + + if ((cl->pieceIn == EmptySquare || cl->pieceIn == board[rf][ff]) && + (cl->rfIn == -1 || cl->rfIn == rf) && + (cl->ffIn == -1 || cl->ffIn == ff) && + (cl->rtIn == -1 || cl->rtIn == rt) && + (cl->ftIn == -1 || cl->ftIn == ft)) { + + cl->count++; + cl->piece = board[rf][ff]; + cl->rf = rf; + cl->ff = ff; + cl->rt = rt; + cl->ft = ft; + cl->kind = kind; + } +} + +void Disambiguate(board, flags, epfile, closure) + Board board; + int flags, epfile; + DisambiguateClosure *closure; +{ + int illegal = 0; + closure->count = 0; + closure->rf = closure->ff = closure->rt = closure->ft = 0; + closure->kind = ImpossibleMove; + GenLegal(board, flags, epfile, DisambiguateCallback, (VOIDSTAR) closure); + if (closure->count == 0) { + /* See if it's an illegal move due to check */ + illegal = 1; + GenLegal(board, flags|F_IGNORE_CHECK, epfile, DisambiguateCallback, + (VOIDSTAR) closure); + if (closure->count == 0) { + /* No, it's not even that */ + return; + } + } + if (closure->promoCharIn != NULLCHAR && closure->promoCharIn != 'x') { + if (closure->kind == WhitePromotionQueen + || closure->kind == BlackPromotionQueen) { + closure->kind = + PromoCharToMoveType((flags & F_WHITE_ON_MOVE) != 0, + closure->promoCharIn); + } else { + closure->kind = IllegalMove; + } + } + closure->promoChar = ToLower(PieceToChar(PromoPiece(closure->kind))); + if (closure->promoChar == 'x') closure->promoChar = NULLCHAR; + if (closure->count > 1) { + closure->kind = AmbiguousMove; + } + if (illegal) { + /* Note: If more than one illegal move matches, but no legal + moves, we return IllegalMove, not AmbiguousMove. Caller + can look at closure->count to detect this. + */ + closure->kind = IllegalMove; + } +} + + +typedef struct { + /* Input */ + ChessSquare piece; + int rf, ff, rt, ft; + /* Output */ + ChessMove kind; + int rank; + int file; + int either; +} CoordsToAlgebraicClosure; + +extern void CoordsToAlgebraicCallback P((Board board, int flags, + ChessMove kind, int rf, int ff, + int rt, int ft, VOIDSTAR closure)); + +void CoordsToAlgebraicCallback(board, flags, kind, rf, ff, rt, ft, closure) + Board board; + int flags; + ChessMove kind; + int rf, ff, rt, ft; + VOIDSTAR closure; +{ + register CoordsToAlgebraicClosure *cl = + (CoordsToAlgebraicClosure *) closure; + + if (rt == cl->rt && ft == cl->ft && + board[rf][ff] == cl->piece) { + if (rf == cl->rf) { + if (ff == cl->ff) { + cl->kind = kind; /* this is the move we want */ + } else { + cl->file++; /* need file to rule out this move */ + } + } else { + if (ff == cl->ff) { + cl->rank++; /* need rank to rule out this move */ + } else { + cl->either++; /* rank or file will rule out this move */ + } + } + } +} + +/* Convert coordinates to normal algebraic notation. + promoChar must be NULLCHAR or 'x' if not a promotion. +*/ +ChessMove CoordsToAlgebraic(board, flags, epfile, + rf, ff, rt, ft, promoChar, out) + Board board; + int flags, epfile; + int rf, ff, rt, ft; + int promoChar; + char out[MOVE_LEN]; +{ + ChessSquare piece; + ChessMove kind; + char *outp = out; + CoordsToAlgebraicClosure cl; + + if (rf == DROP_RANK) { + /* Bughouse piece drop */ + *outp++ = ToUpper(PieceToChar((ChessSquare) ff)); + *outp++ = '@'; + *outp++ = ft + 'a'; + *outp++ = rt + '1'; + *outp = NULLCHAR; + return (flags & F_WHITE_ON_MOVE) ? WhiteDrop : BlackDrop; + } + + if (promoChar == 'x') promoChar = NULLCHAR; + piece = board[rf][ff]; + switch (piece) { + case WhitePawn: + case BlackPawn: + kind = LegalityTest(board, flags, epfile, rf, ff, rt, ft, promoChar); + if (kind == IllegalMove && !(flags&F_IGNORE_CHECK)) { + /* Keep short notation if move is illegal only because it + leaves the player in check, but still return IllegalMove */ + kind = LegalityTest(board, flags|F_IGNORE_CHECK, epfile, + rf, ff, rt, ft, promoChar); + if (kind == IllegalMove) break; + kind = IllegalMove; + } + /* Pawn move */ + *outp++ = ff + 'a'; + if (ff == ft) { + /* Non-capture; use style "e5" */ + *outp++ = rt + '1'; + } else { + /* Capture; use style "exd5" */ + *outp++ = 'x'; + *outp++ = ft + 'a'; + *outp++ = rt + '1'; + } + /* Use promotion suffix style "=Q" */ + if (promoChar != NULLCHAR && promoChar != 'x') { + *outp++ = '='; + *outp++ = ToUpper(promoChar); + } + *outp = NULLCHAR; + return kind; + + + case WhiteKing: + case BlackKing: + /* Test for castling or ICS wild castling */ + /* Use style "O-O" (oh-oh) for PGN compatibility */ + if (rf == rt && + rf == ((piece == WhiteKing) ? 0 : 7) && + ((ff == 4 && (ft == 2 || ft == 6)) || + (ff == 3 && (ft == 1 || ft == 5)))) { + switch (ft) { + case 1: + case 6: + strcpy(out, "O-O"); + break; + case 2: + case 5: + strcpy(out, "O-O-O"); + break; + } + /* This notation is always unambiguous, unless there are + kings on both the d and e files, with "wild castling" + possible for the king on the d file and normal castling + possible for the other. ICS rules for wild 9 + effectively make castling illegal for either king in + this situation. So I am not going to worry about it; + I'll just generate an ambiguous O-O in this case. + */ + return LegalityTest(board, flags, epfile, + rf, ff, rt, ft, promoChar); + } + /* else fall through */ + + default: + /* Piece move */ + cl.rf = rf; + cl.ff = ff; + cl.rt = rt; + cl.ft = ft; + cl.piece = piece; + cl.kind = IllegalMove; + cl.rank = cl.file = cl.either = 0; + GenLegal(board, flags, epfile, + CoordsToAlgebraicCallback, (VOIDSTAR) &cl); + + if (cl.kind == IllegalMove && !(flags&F_IGNORE_CHECK)) { + /* Generate pretty moves for moving into check, but + still return IllegalMove. + */ + GenLegal(board, flags|F_IGNORE_CHECK, epfile, + CoordsToAlgebraicCallback, (VOIDSTAR) &cl); + if (cl.kind == IllegalMove) break; + cl.kind = IllegalMove; + } + + /* Style is "Nf3" or "Nxf7" if this is unambiguous, + else "Ngf3" or "Ngxf7", + else "N1f3" or "N5xf7", + else "Ng1f3" or "Ng5xf7". + */ + *outp++ = ToUpper(PieceToChar(piece)); + + if (cl.file || (cl.either && !cl.rank)) { + *outp++ = ff + 'a'; + } + if (cl.rank) { + *outp++ = rf + '1'; + } + + if(board[rt][ft] != EmptySquare) + *outp++ = 'x'; + + *outp++ = ft + 'a'; + *outp++ = rt + '1'; + *outp = NULLCHAR; + return cl.kind; + + case EmptySquare: + /* Moving a nonexistent piece */ + break; + } + + /* Not a legal move, even ignoring check. + If there was a piece on the from square, + use style "Ng1g3" or "Ng1xe8"; + if there was a pawn or nothing (!), + use style "g1g3" or "g1xe8". Use "x" + if a piece was on the to square, even + a piece of the same color. + */ + outp = out; + if (piece != EmptySquare && piece != WhitePawn && piece != BlackPawn) { + *outp++ = ToUpper(PieceToChar(piece)); + } + *outp++ = ff + 'a'; + *outp++ = rf + '1'; + if (board[rt][ft] != EmptySquare) *outp++ = 'x'; + *outp++ = ft + 'a'; + *outp++ = rt + '1'; + /* Use promotion suffix style "=Q" */ + if (promoChar != NULLCHAR && promoChar != 'x') { + *outp++ = '='; + *outp++ = ToUpper(promoChar); + } + *outp = NULLCHAR; + + return IllegalMove; +} diff --git a/winboard-dm-beta4/parser.c b/winboard-dm-beta4/parser.c new file mode 100755 index 0000000..e9ec033 --- /dev/null +++ b/winboard-dm-beta4/parser.c @@ -0,0 +1,3830 @@ +/* A lexical scanner generated by flex */ + +/* Scanner skeleton version: + * $Header$ + */ + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 5 + +#include + + +/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */ +#ifdef c_plusplus +#ifndef __cplusplus +#define __cplusplus +#endif +#endif + + +#ifdef __cplusplus + +#include +#include + +/* Use prototypes in function declarations. */ +#define YY_USE_PROTOS + +/* The "const" storage-class-modifier is valid. */ +#define YY_USE_CONST + +#else /* ! __cplusplus */ + +#if __STDC__ + +#define YY_USE_PROTOS +#define YY_USE_CONST + +#endif /* __STDC__ */ +#endif /* ! __cplusplus */ + +#ifdef __TURBOC__ + #pragma warn -rch + #pragma warn -use +#include +#include +#define YY_USE_CONST +#define YY_USE_PROTOS +#endif + +#ifdef YY_USE_CONST +#define yyconst const +#else +#define yyconst +#endif + + +#ifdef YY_USE_PROTOS +#define YY_PROTO(proto) proto +#else +#define YY_PROTO(proto) () +#endif + +/* Returned upon end-of-file. */ +#define YY_NULL 0 + +/* Promotes a possibly negative, possibly signed char to an unsigned + * integer for use as an array index. If the signed char is negative, + * we want to instead treat it as an 8-bit unsigned char, hence the + * double cast. + */ +#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) + +/* Enter a start condition. This macro really ought to take a parameter, + * but we do it the disgusting crufty way forced on us by the ()-less + * definition of BEGIN. + */ +#define BEGIN yy_start = 1 + 2 * + +/* Translate the current start state into a value that can be later handed + * to BEGIN to return to the state. The YYSTATE alias is for lex + * compatibility. + */ +#define YY_START ((yy_start - 1) / 2) +#define YYSTATE YY_START + +/* Action number for EOF rule of a given start state. */ +#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) + +/* Special action meaning "start processing a new file". */ +#define YY_NEW_FILE yyrestart( yyin ) + +#define YY_END_OF_BUFFER_CHAR 0 + +/* Size of default input buffer. */ +#define YY_BUF_SIZE 16384 + +typedef struct yy_buffer_state *YY_BUFFER_STATE; + +extern int yyleng; +extern FILE *yyin, *yyout; + +#define EOB_ACT_CONTINUE_SCAN 0 +#define EOB_ACT_END_OF_FILE 1 +#define EOB_ACT_LAST_MATCH 2 + +/* The funky do-while in the following #define is used to turn the definition + * int a single C statement (which needs a semi-colon terminator). This + * avoids problems with code like: + * + * if ( condition_holds ) + * yyless( 5 ); + * else + * do_something_else(); + * + * Prior to using the do-while the compiler would get upset at the + * "else" because it interpreted the "if" statement as being all + * done when it reached the ';' after the yyless() call. + */ + +/* Return all but the first 'n' matched characters back to the input stream. */ + +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + *yy_cp = yy_hold_char; \ + YY_RESTORE_YY_MORE_OFFSET \ + yy_c_buf_p = yy_cp = yy_bp + n - YY_MORE_ADJ; \ + YY_DO_BEFORE_ACTION; /* set up yytext again */ \ + } \ + while ( 0 ) + +#define unput(c) yyunput( c, yytext_ptr ) + +/* The following is because we cannot portably get our hands on size_t + * (without autoconf's help, which isn't available because we want + * flex-generated scanners to compile on their own). + */ +typedef unsigned int yy_size_t; + + +struct yy_buffer_state + { + FILE *yy_input_file; + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + yy_size_t yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + int yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; +#define YY_BUFFER_NEW 0 +#define YY_BUFFER_NORMAL 1 + /* When an EOF's been seen but there's still some text to process + * then we mark the buffer as YY_EOF_PENDING, to indicate that we + * shouldn't try reading from the input source any more. We might + * still have a bunch of tokens to match, though, because of + * possible backing-up. + * + * When we actually see the EOF, we change the status to "new" + * (via yyrestart()), so that the user can continue scanning by + * just pointing yyin at a new input file. + */ +#define YY_BUFFER_EOF_PENDING 2 + }; + +static YY_BUFFER_STATE yy_current_buffer = 0; + +/* We provide macros for accessing buffer states in case in the + * future we want to put the buffer states in a more general + * "scanner state". + */ +#define YY_CURRENT_BUFFER yy_current_buffer + + +/* yy_hold_char holds the character lost when yytext is formed. */ +static char yy_hold_char; + +static int yy_n_chars; /* number of characters read into yy_ch_buf */ + + +int yyleng; + +/* Points to current character in buffer. */ +static char *yy_c_buf_p = (char *) 0; +static int yy_init = 1; /* whether we need to initialize */ +static int yy_start = 0; /* start state number */ + +/* Flag which is used to allow yywrap()'s to do buffer switches + * instead of setting up a fresh yyin. A bit of a hack ... + */ +static int yy_did_buffer_switch_on_eof; + +void yyrestart YY_PROTO(( FILE *input_file )); + +void yy_switch_to_buffer YY_PROTO(( YY_BUFFER_STATE new_buffer )); +void yy_load_buffer_state YY_PROTO(( void )); +YY_BUFFER_STATE yy_create_buffer YY_PROTO(( FILE *file, int size )); +void yy_delete_buffer YY_PROTO(( YY_BUFFER_STATE b )); +void yy_init_buffer YY_PROTO(( YY_BUFFER_STATE b, FILE *file )); +void yy_flush_buffer YY_PROTO(( YY_BUFFER_STATE b )); +#define YY_FLUSH_BUFFER yy_flush_buffer( yy_current_buffer ) + +YY_BUFFER_STATE yy_scan_buffer YY_PROTO(( char *base, yy_size_t size )); +YY_BUFFER_STATE yy_scan_string YY_PROTO(( yyconst char *yy_str )); +YY_BUFFER_STATE yy_scan_bytes YY_PROTO(( yyconst char *bytes, int len )); + +static void *yy_flex_alloc YY_PROTO(( yy_size_t )); +static void *yy_flex_realloc YY_PROTO(( void *, yy_size_t )); +static void yy_flex_free YY_PROTO(( void * )); + +#define yy_new_buffer yy_create_buffer + +#define yy_set_interactive(is_interactive) \ + { \ + if ( ! yy_current_buffer ) \ + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ + yy_current_buffer->yy_is_interactive = is_interactive; \ + } + +#define yy_set_bol(at_bol) \ + { \ + if ( ! yy_current_buffer ) \ + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ + yy_current_buffer->yy_at_bol = at_bol; \ + } + +#define YY_AT_BOL() (yy_current_buffer->yy_at_bol) + + +#define YY_USES_REJECT +typedef unsigned char YY_CHAR; +FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0; +typedef int yy_state_type; +extern char *yytext; +#define yytext_ptr yytext + +static yy_state_type yy_get_previous_state YY_PROTO(( void )); +static yy_state_type yy_try_NUL_trans YY_PROTO(( yy_state_type current_state )); +static int yy_get_next_buffer YY_PROTO(( void )); +static void yy_fatal_error YY_PROTO(( yyconst char msg[] )); + +/* Done after the current pattern has been matched and before the + * corresponding action - sets up yytext. + */ +#define YY_DO_BEFORE_ACTION \ + yytext_ptr = yy_bp; \ + yyleng = (int) (yy_cp - yy_bp); \ + yy_hold_char = *yy_cp; \ + *yy_cp = '\0'; \ + yy_c_buf_p = yy_cp; + +#define YY_NUM_RULES 42 +#define YY_END_OF_BUFFER 43 +static yyconst short int yy_acclist[661] = + { 0, + 43, 41, 42, 41, 42, 41, 42, 40, 41, 42, + 41, 42, 25, 41, 42, 41, 42, 40, 41, 42, + 40, 41, 42,16410, 40, 41, 42,16410, 41, 42, + 40, 41, 42, 40, 41, 42, 40, 41, 42, 40, + 41, 42, 40, 41, 42, 40, 41, 42, 40, 41, + 42, 40, 41, 42, 40, 41, 42, 40, 41, 42, + 40, 41, 42, 40, 41, 42, 40, 41, 42, 41, + 42, 40, 41, 42, 40, 41, 42, 40, 41, 42, + 40, 41, 42, 40, 41, 42, 40, 41, 42, 40, + 41, 42, 40, 41, 42, 40, 41, 42, 41, 42, + + 41, 42, 40, 41, 42, 40, 41, 42, 40, 41, + 42,16410, 40, 41, 42,16410, 41, 42, 40, 41, + 42, 40, 41, 42, 40, 41, 42, 40, 41, 42, + 40, 41, 42, 40, 41, 42, 40, 41, 42, 40, + 41, 42, 40, 41, 42, 40, 41, 42, 40, 41, + 42, 40, 41, 42, 40, 41, 42, 40, 41, 42, + 40, 41, 42, 40, 41, 42, 40, 41, 42, 40, + 41, 42, 40, 41, 42, 40, 41, 42, 40, 41, + 42, 40, 41, 42, 41, 42, 33, 40, 17, 40, + 9, 40, 40, 40,16410, 8218, 40, 35, 40, 40, + + 40, 40, 40, 40, 40, 40, 40, 40, 40, 9, + 40, 40, 40, 40, 40, 40, 36, 40, 3, 40, + 40, 40, 4, 40, 40, 3, 40, 40, 4, 40, + 40, 40, 40, 9, 40, 34, 40, 40, 9, 40, + 40, 40,16410, 8218, 40, 40, 40, 40, 40, 40, + 40, 40, 40, 40, 40, 40, 9, 40, 40, 40, + 40, 40, 40, 40, 3, 40, 40, 40, 4, 40, + 40, 3, 40, 40, 4, 40, 40, 40, 40, 9, + 40, 15, 9, 40, 23, 40, 23, 8, 40, 8218, + 22, 40, 22, 24, 40, 40, 40, 6, 40, 40, + + 40, 40, 40, 40, 40, 9, 40, 40, 40, 40, + 40, 20, 40, 4, 40, 40, 3, 40, 40, 3, + 40, 4, 5, 40, 4, 40, 40, 4, 40, 40, + 40, 3, 40, 4, 4, 40, 5, 6, 40, 4, + 40, 40, 9, 40, 34, 39, 9, 40, 23, 40, + 8, 40, 22, 40, 35, 40, 40, 40, 6, 40, + 40, 40, 40, 40, 40, 40, 9, 40, 40, 40, + 40, 40, 20, 40, 4, 40, 40, 3, 40, 40, + 3, 40, 5, 40, 4, 40, 40, 4, 40, 40, + 40, 3, 40, 4, 40, 5, 6, 40, 4, 40, + + 40, 9, 40, 38, 38, 37, 25, 25, 40, 6, + 40, 7, 40, 6, 10, 40, 40, 40, 40, 19, + 40, 40, 21, 40, 16, 40, 40, 40, 40, 40, + 20, 20, 40, 20, 40, 36, 3, 3, 2, 40, + 5, 4, 5, 40, 40, 4, 4, 40, 2, 7, + 40, 5, 6, 5, 6, 40, 5, 40, 40, 40, + 25, 39, 40, 6, 40, 7, 40, 40, 40, 40, + 40, 19, 40, 40, 21, 40, 16, 40, 40, 40, + 40, 40, 20, 40, 20, 20, 40, 2, 40, 5, + 40, 40, 4, 40, 2, 7, 40, 5, 6, 40, + + 5, 40, 40, 40, 7, 1, 40, 40, 40, 19, + 40, 40, 40, 21, 21, 40, 21, 40, 40, 40, + 40, 30, 36, 2, 2, 40, 5, 4, 5, 5, + 40, 2, 7, 39, 1, 40, 40, 40, 19, 40, + 40, 40, 21, 40, 21, 21, 40, 40, 40, 40, + 20, 39, 2, 40, 5, 40, 27, 38, 23, 23, + 22, 22, 24, 24, 20, 21, 1, 1, 40, 40, + 40, 40, 11, 40, 40, 28, 36, 30, 2, 2, + 5, 27, 34, 39, 39, 1, 40, 40, 40, 40, + 21, 39, 11, 40, 40, 20, 39, 18, 24, 20, + + 21, 1, 1, 19, 40, 40, 40, 11, 40, 40, + 40, 40, 21, 39, 40, 11, 40, 40, 12, 40, + 40, 40, 40, 12, 40, 40, 14, 40, 40, 40, + 14, 40, 40, 40, 39, 40, 40, 40, 40, 39, + 39, 40, 40, 31, 40, 39, 39, 31, 40, 13, + 31, 32, 32, 35, 39, 39, 31, 39, 34, 29 + } ; + +static yyconst short int yy_accept[712] = + { 0, + 1, 1, 1, 2, 4, 6, 8, 11, 13, 16, + 18, 21, 25, 29, 31, 34, 37, 40, 43, 46, + 49, 52, 55, 58, 61, 64, 67, 70, 72, 75, + 78, 81, 84, 87, 90, 93, 96, 99, 101, 103, + 106, 109, 113, 117, 119, 122, 125, 128, 131, 134, + 137, 140, 143, 146, 149, 152, 155, 158, 161, 164, + 167, 170, 173, 176, 179, 182, 185, 187, 187, 188, + 189, 189, 189, 189, 189, 190, 190, 190, 191, 191, + 193, 193, 193, 193, 194, 194, 194, 196, 196, 198, + 198, 199, 199, 200, 200, 201, 201, 201, 202, 203, + + 204, 205, 206, 207, 208, 209, 210, 212, 213, 214, + 215, 216, 217, 217, 217, 217, 217, 218, 219, 221, + 221, 222, 223, 225, 226, 228, 228, 229, 231, 232, + 233, 234, 236, 236, 236, 236, 237, 237, 238, 238, + 239, 241, 241, 242, 244, 244, 246, 246, 247, 248, + 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, + 259, 260, 261, 262, 263, 264, 265, 267, 267, 268, + 269, 271, 272, 274, 274, 275, 277, 278, 279, 280, + 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, + 282, 282, 283, 283, 283, 283, 285, 287, 288, 290, + + 291, 291, 291, 291, 293, 294, 295, 295, 295, 295, + 295, 296, 296, 297, 297, 298, 298, 298, 300, 301, + 302, 303, 304, 305, 306, 308, 309, 310, 311, 312, + 314, 314, 314, 314, 314, 316, 316, 317, 317, 317, + 319, 320, 322, 323, 325, 325, 325, 327, 328, 330, + 331, 331, 332, 334, 335, 337, 340, 342, 343, 345, + 346, 346, 346, 346, 346, 347, 349, 351, 353, 355, + 355, 356, 356, 357, 358, 358, 359, 361, 362, 363, + 364, 365, 366, 367, 369, 370, 371, 372, 373, 375, + 377, 378, 378, 380, 381, 383, 385, 387, 388, 390, + + 391, 391, 392, 394, 396, 399, 401, 402, 404, 404, + 404, 405, 406, 406, 406, 407, 407, 407, 408, 408, + 409, 409, 409, 409, 410, 410, 410, 410, 410, 410, + 410, 410, 410, 410, 410, 410, 412, 412, 412, 414, + 415, 416, 417, 417, 418, 419, 420, 422, 422, 423, + 425, 427, 428, 429, 430, 431, 432, 434, 436, 436, + 436, 436, 436, 437, 438, 438, 439, 441, 442, 443, + 443, 443, 443, 445, 446, 447, 447, 449, 449, 452, + 454, 457, 459, 460, 461, 461, 462, 462, 462, 462, + 462, 463, 463, 464, 464, 464, 466, 468, 469, 469, + + 470, 471, 472, 474, 475, 477, 479, 480, 481, 482, + 483, 485, 486, 488, 490, 492, 493, 495, 498, 501, + 503, 504, 505, 505, 505, 505, 505, 505, 505, 505, + 505, 505, 505, 505, 505, 505, 505, 505, 505, 505, + 506, 508, 509, 510, 510, 512, 512, 513, 514, 515, + 517, 519, 520, 521, 522, 522, 522, 524, 524, 524, + 525, 525, 525, 527, 528, 528, 529, 530, 530, 532, + 532, 534, 534, 534, 534, 534, 534, 534, 535, 535, + 535, 537, 538, 539, 541, 542, 543, 545, 546, 548, + 549, 550, 551, 553, 555, 557, 557, 557, 559, 559, + + 559, 560, 560, 561, 561, 562, 562, 563, 563, 564, + 564, 565, 565, 565, 565, 565, 567, 567, 568, 568, + 568, 570, 571, 571, 571, 571, 571, 571, 572, 573, + 575, 576, 578, 578, 579, 580, 581, 582, 582, 582, + 584, 584, 584, 585, 586, 586, 586, 588, 589, 590, + 591, 593, 595, 596, 598, 598, 599, 599, 599, 599, + 600, 600, 600, 600, 602, 602, 603, 604, 604, 605, + 605, 605, 605, 605, 606, 607, 608, 610, 611, 611, + 611, 611, 611, 611, 612, 613, 615, 616, 618, 619, + 619, 619, 619, 619, 619, 619, 620, 620, 620, 620, + + 620, 621, 622, 622, 622, 622, 622, 623, 624, 624, + 624, 624, 624, 625, 625, 625, 625, 626, 627, 629, + 629, 629, 629, 629, 630, 630, 631, 633, 633, 633, + 633, 633, 634, 635, 635, 635, 635, 635, 636, 637, + 638, 638, 638, 638, 638, 638, 639, 640, 640, 640, + 640, 640, 641, 642, 643, 644, 644, 644, 644, 644, + 644, 646, 646, 646, 646, 646, 647, 648, 650, 650, + 650, 651, 651, 652, 652, 653, 653, 653, 655, 655, + 656, 657, 657, 657, 657, 657, 659, 659, 659, 659, + 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, + + 659, 659, 659, 659, 659, 659, 659, 659, 660, 661, + 661 + } ; + +static yyconst int yy_ec[256] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 4, 1, 5, 6, 7, 8, 1, 9, 10, + 11, 12, 13, 1, 14, 15, 16, 17, 18, 19, + 20, 20, 20, 20, 20, 20, 21, 22, 23, 1, + 24, 1, 1, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 34, 44, 34, 45, 46, 34, 34, + 47, 1, 48, 1, 49, 1, 50, 51, 52, 53, + + 54, 55, 56, 57, 58, 34, 59, 60, 61, 62, + 63, 64, 41, 65, 66, 67, 68, 34, 69, 46, + 70, 34, 71, 1, 72, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1 + } ; + +static yyconst int yy_meta[73] = + { 0, + 1, 2, 3, 2, 1, 1, 1, 1, 4, 5, + 6, 1, 1, 7, 1, 1, 4, 8, 8, 8, + 4, 9, 1, 10, 1, 4, 11, 4, 4, 4, + 4, 4, 4, 4, 11, 4, 4, 11, 12, 12, + 11, 11, 4, 4, 4, 7, 1, 1, 1, 13, + 14, 13, 13, 15, 13, 13, 13, 4, 11, 4, + 4, 11, 12, 12, 11, 4, 4, 4, 4, 4, + 1, 1 + } ; + +static yyconst short int yy_base[787] = + { 0, + 0, 72, 2588, 4394, 119, 129, 0, 141, 2583, 139, + 150, 171, 238, 2583, 257, 2527, 2518, 117, 159, 2518, + 2530, 190, 142, 233, 191, 2512, 239, 317, 376, 420, + 125, 205, 193, 114, 243, 120, 204, 331, 2574, 174, + 353, 476, 258, 260, 543, 244, 282, 346, 311, 334, + 256, 312, 365, 595, 331, 351, 354, 644, 688, 242, + 348, 327, 365, 386, 303, 392, 552, 2521, 432, 0, + 2566, 258, 557, 282, 4394, 2562, 393, 320, 2556, 2554, + 2552, 342, 442, 2551, 457, 364, 605, 2550, 0, 2562, + 4394, 576, 530, 617, 732, 625, 661, 449, 2514, 2509, + + 2512, 2517, 2492, 2493, 2490, 2517, 2515, 463, 572, 2503, + 2494, 2489, 2502, 789, 372, 861, 4394, 669, 924, 705, + 713, 468, 980, 765, 1032, 773, 789, 1076, 481, 637, + 2486, 2485, 390, 2475, 830, 2542, 2541, 383, 2540, 617, + 593, 546, 858, 874, 406, 579, 432, 865, 1120, 1005, + 505, 683, 726, 727, 621, 872, 870, 876, 603, 873, + 905, 665, 891, 884, 882, 973, 1168, 1013, 1049, 936, + 1225, 1057, 1277, 1093, 1101, 1321, 641, 983, 928, 930, + 896, 2478, 538, 543, 612, 2531, 622, 1030, 1221, 2528, + 2466, 4394, 2532, 2531, 2529, 2518, 2527, 2526, 0, 4394, + + 2525, 2524, 2523, 2521, 2520, 443, 2465, 2459, 2471, 2466, + 668, 709, 594, 1218, 732, 753, 756, 1365, 2467, 2466, + 2446, 803, 906, 2460, 2498, 0, 2453, 2449, 2441, 1422, + 689, 1069, 172, 1494, 790, 1251, 1294, 1302, 1415, 2496, + 838, 976, 1288, 1557, 1413, 1449, 678, 629, 910, 1338, + 1346, 992, 1105, 1502, 1057, 1609, 1182, 1100, 2492, 4394, + 1510, 996, 2501, 191, 2501, 1172, 960, 962, 1158, 831, + 2499, 1132, 1237, 889, 1482, 1300, 1653, 1176, 1228, 1010, + 1273, 1315, 1175, 1190, 0, 1204, 1531, 1071, 1710, 1774, + 1550, 1582, 1242, 1443, 1551, 1830, 1272, 1239, 1121, 1493, + + 1590, 1606, 1659, 1141, 1882, 1673, 1721, 1427, 1504, 2447, + 4394, 843, 1025, 2489, 4394, 1727, 2487, 2485, 2423, 2422, + 2475, 2474, 2473, 2473, 1010, 2472, 539, 2471, 1290, 1541, + 610, 2421, 2421, 2414, 2414, 0, 939, 1197, 0, 4394, + 4394, 1699, 1710, 1344, 2420, 2419, 885, 879, 1130, 1939, + 0, 2438, 2420, 2421, 2420, 0, 2011, 2083, 733, 949, + 1131, 1410, 2468, 2461, 1365, 4394, 2146, 1356, 1154, 689, + 1752, 1796, 1157, 715, 2417, 2406, 0, 1386, 0, 1564, + 2202, 1802, 1633, 2406, 1857, 2464, 1571, 1672, 2417, 2403, + 2462, 1187, 1451, 1003, 894, 1295, 1470, 1718, 1855, 1823, + + 1555, 1665, 1782, 1796, 2267, 1574, 1588, 1826, 1647, 1674, + 2339, 2460, 2411, 2475, 1840, 1858, 1608, 0, 2531, 1905, + 1956, 1857, 1728, 2409, 2451, 1639, 2450, 2385, 2445, 2383, + 2443, 2381, 2434, 1281, 2399, 2395, 2395, 2390, 1389, 4394, + 2587, 2443, 1146, 1916, 2442, 1281, 2415, 2390, 0, 2652, + 2724, 2378, 2378, 2428, 1322, 1883, 4394, 2426, 1966, 1457, + 2002, 2076, 2419, 1428, 952, 4394, 2375, 2364, 0, 2410, + 1544, 1774, 2396, 1877, 2392, 2347, 2341, 1521, 1030, 1255, + 2787, 1676, 1881, 1788, 1891, 1861, 2852, 2402, 2924, 1963, + 1841, 1944, 2402, 1691, 1649, 1816, 1235, 4394, 1979, 2393, + + 2392, 2330, 2329, 2389, 2388, 2326, 2325, 2385, 2381, 2319, + 2318, 2366, 2362, 2315, 2323, 1377, 2320, 1778, 2004, 2102, + 2355, 2310, 2348, 2304, 2287, 2326, 2288, 2289, 2264, 1524, + 2279, 4394, 1980, 4394, 2317, 4394, 4394, 2312, 2053, 2319, + 2268, 2261, 2315, 1999, 1555, 548, 1908, 1982, 1951, 1786, + 2301, 2043, 2029, 2297, 2054, 4394, 2243, 2158, 2289, 2284, + 2219, 2205, 2209, 4394, 2198, 2239, 4394, 2235, 2228, 2174, + 2228, 2182, 2157, 2174, 2105, 2086, 0, 2061, 2130, 2120, + 2054, 1040, 358, 2032, 2091, 2073, 2093, 1970, 2136, 2120, + 1988, 2029, 1542, 1985, 1941, 1941, 1923, 884, 1858, 1831, + + 2996, 1815, 1772, 1768, 1617, 651, 3068, 2150, 2149, 1757, + 1745, 1725, 4394, 1623, 1924, 2045, 3140, 2054, 0, 1631, + 1594, 1302, 1202, 3212, 2158, 2066, 2040, 2177, 1577, 1531, + 2110, 1524, 1496, 1455, 1427, 1308, 1895, 2162, 1448, 1422, + 2179, 1319, 1298, 2163, 2154, 1285, 1115, 1083, 1117, 1726, + 1576, 2196, 2198, 1062, 984, 2193, 2056, 930, 2153, 2166, + 0, 902, 804, 803, 1618, 2210, 2238, 0, 2213, 583, + 4394, 497, 2199, 486, 4394, 426, 460, 4394, 2116, 2203, + 2254, 2231, 392, 317, 1804, 2255, 2281, 239, 2027, 829, + 2006, 2117, 2293, 2295, 2298, 2299, 2303, 2317, 2321, 2322, + + 2323, 2365, 2366, 2369, 2370, 2371, 2233, 154, 4394, 4394, + 3281, 3296, 3311, 3326, 3341, 3353, 3368, 3383, 3397, 3412, + 3427, 3442, 3457, 3472, 3487, 3502, 3517, 3532, 3547, 3562, + 3577, 3592, 3607, 3622, 3633, 3648, 3663, 3678, 3693, 3708, + 3723, 3738, 3753, 3768, 3783, 3792, 3807, 3822, 3837, 3852, + 3867, 3882, 3897, 3908, 3923, 3938, 3953, 3968, 3983, 3998, + 4013, 4028, 4043, 4058, 4073, 4088, 4103, 4118, 4133, 4148, + 4163, 4174, 4188, 4203, 4218, 4233, 4244, 4258, 4273, 4288, + 4303, 4318, 4333, 4348, 4363, 4378 + } ; + +static yyconst short int yy_def[787] = + { 0, + 710, 710, 710, 710, 710, 710, 711, 712, 710, 710, + 711, 710, 12, 713, 711, 711, 711, 711, 15, 711, + 711, 15, 711, 711, 15, 711, 711, 714, 711, 15, + 29, 29, 29, 29, 29, 29, 711, 715, 710, 716, + 716, 710, 42, 713, 716, 716, 716, 716, 45, 716, + 716, 45, 716, 716, 45, 716, 716, 716, 45, 58, + 58, 58, 58, 58, 58, 716, 715, 710, 710, 711, + 717, 718, 717, 710, 710, 710, 710, 711, 710, 711, + 710, 719, 719, 711, 719, 710, 12, 710, 711, 713, + 710, 710, 711, 710, 711, 710, 710, 95, 711, 711, + + 711, 711, 711, 711, 711, 711, 711, 711, 95, 711, + 711, 711, 720, 714, 720, 721, 710, 711, 711, 710, + 711, 711, 711, 711, 119, 710, 711, 123, 95, 711, + 711, 711, 715, 722, 715, 710, 723, 716, 710, 716, + 716, 710, 716, 42, 710, 716, 724, 716, 148, 710, + 149, 716, 716, 716, 716, 716, 716, 716, 716, 716, + 716, 149, 716, 716, 716, 148, 148, 710, 148, 716, + 716, 148, 167, 710, 148, 171, 149, 716, 716, 716, + 715, 710, 717, 725, 725, 726, 727, 717, 717, 728, + 729, 710, 710, 710, 710, 711, 711, 710, 711, 710, + + 710, 710, 710, 711, 710, 710, 710, 710, 710, 710, + 711, 710, 95, 710, 711, 710, 710, 711, 711, 711, + 711, 711, 711, 711, 711, 218, 711, 711, 711, 730, + 731, 732, 733, 734, 123, 710, 711, 710, 710, 711, + 711, 711, 735, 711, 710, 710, 711, 711, 123, 711, + 710, 711, 711, 735, 123, 244, 711, 711, 711, 710, + 715, 710, 736, 710, 737, 716, 716, 716, 716, 738, + 736, 739, 716, 149, 710, 716, 149, 716, 716, 716, + 716, 716, 716, 716, 277, 716, 716, 716, 740, 716, + 716, 710, 716, 716, 716, 290, 716, 716, 290, 291, + + 710, 716, 716, 290, 296, 716, 716, 716, 715, 710, + 710, 741, 741, 742, 710, 743, 744, 744, 745, 745, + 710, 710, 710, 711, 710, 710, 710, 710, 710, 710, + 710, 710, 710, 710, 710, 711, 746, 710, 711, 710, + 710, 711, 710, 711, 711, 711, 711, 710, 711, 747, + 711, 711, 711, 711, 711, 748, 749, 749, 750, 750, + 751, 752, 753, 710, 710, 710, 711, 754, 710, 710, + 710, 710, 711, 711, 710, 710, 711, 710, 367, 754, + 367, 711, 711, 711, 715, 710, 710, 710, 710, 710, + 755, 710, 716, 756, 756, 716, 716, 291, 710, 716, + + 716, 716, 716, 716, 757, 716, 716, 716, 716, 716, + 758, 748, 758, 716, 716, 716, 716, 414, 414, 716, + 716, 716, 715, 710, 759, 760, 761, 762, 763, 764, + 765, 766, 710, 710, 710, 710, 710, 710, 710, 710, + 711, 711, 711, 710, 711, 710, 711, 711, 767, 768, + 768, 711, 711, 711, 769, 770, 710, 771, 710, 772, + 710, 710, 711, 710, 710, 710, 710, 710, 711, 710, + 772, 715, 710, 710, 710, 710, 710, 773, 774, 774, + 414, 716, 716, 716, 716, 716, 775, 767, 775, 716, + 716, 716, 776, 716, 716, 715, 710, 710, 760, 761, + + 761, 762, 762, 763, 763, 764, 764, 765, 765, 766, + 766, 710, 710, 710, 710, 710, 710, 777, 710, 710, + 711, 711, 778, 710, 710, 710, 710, 711, 711, 711, + 711, 710, 710, 710, 710, 710, 710, 710, 715, 710, + 710, 710, 773, 773, 774, 774, 716, 716, 716, 716, + 779, 716, 716, 776, 715, 710, 710, 760, 710, 710, + 710, 710, 710, 710, 710, 710, 710, 778, 778, 710, + 710, 710, 710, 711, 711, 711, 711, 711, 715, 710, + 710, 774, 774, 716, 716, 779, 716, 716, 716, 715, + 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, + + 780, 711, 710, 710, 774, 774, 781, 716, 715, 710, + 710, 710, 710, 710, 782, 782, 780, 617, 711, 710, + 710, 774, 774, 781, 782, 624, 716, 715, 710, 710, + 782, 617, 617, 710, 710, 774, 774, 783, 624, 624, + 715, 710, 710, 782, 782, 617, 617, 710, 710, 774, + 774, 783, 783, 624, 624, 715, 710, 710, 782, 782, + 617, 784, 710, 785, 774, 783, 783, 624, 715, 710, + 710, 710, 782, 784, 710, 710, 785, 710, 774, 783, + 783, 715, 710, 710, 774, 783, 715, 710, 774, 715, + 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, + + 786, 786, 786, 786, 786, 786, 786, 710, 710, 0, + 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, + 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, + 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, + 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, + 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, + 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, + 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, + 710, 710, 710, 710, 710, 710 + } ; + +static yyconst short int yy_nxt[4467] = + { 0, + 4, 4, 4, 5, 4, 4, 6, 4, 7, 8, + 4, 9, 10, 7, 4, 4, 11, 12, 13, 13, + 13, 4, 14, 4, 4, 7, 15, 16, 17, 7, + 7, 18, 7, 7, 19, 20, 21, 22, 23, 24, + 22, 25, 26, 7, 27, 7, 28, 4, 4, 29, + 30, 31, 32, 33, 34, 35, 36, 7, 19, 20, + 21, 22, 37, 24, 25, 26, 7, 7, 27, 7, + 38, 4, 4, 4, 4, 5, 4, 39, 6, 39, + 7, 8, 4, 9, 10, 40, 4, 4, 41, 42, + 43, 43, 43, 4, 44, 4, 4, 40, 45, 46, + + 47, 40, 40, 48, 40, 40, 49, 50, 51, 52, + 53, 54, 52, 55, 56, 40, 57, 40, 28, 4, + 4, 58, 59, 60, 61, 62, 63, 64, 65, 40, + 49, 50, 51, 52, 66, 54, 55, 56, 40, 40, + 57, 40, 67, 4, 68, 69, 69, 69, 69, 69, + 72, 75, 76, 77, 102, 106, 709, 73, 73, 73, + 73, 73, 710, 78, 122, 79, 80, 123, 68, 123, + 122, 81, 82, 82, 83, 123, 362, 123, 103, 70, + 107, 130, 70, 710, 84, 85, 86, 87, 87, 87, + 87, 87, 88, 710, 710, 139, 70, 89, 70, 70, + + 70, 70, 70, 70, 70, 89, 70, 70, 89, 89, + 89, 89, 89, 70, 70, 70, 70, 131, 70, 363, + 89, 89, 89, 89, 89, 89, 89, 89, 70, 89, + 70, 70, 89, 89, 89, 89, 70, 70, 70, 70, + 70, 82, 92, 122, 109, 123, 389, 123, 94, 70, + 70, 70, 70, 710, 390, 122, 123, 97, 123, 710, + 92, 82, 91, 147, 70, 139, 132, 186, 187, 101, + 93, 138, 94, 710, 95, 95, 95, 139, 96, 139, + 102, 97, 108, 108, 108, 108, 108, 108, 108, 108, + 70, 190, 662, 122, 171, 111, 112, 123, 178, 123, + + 153, 112, 93, 139, 103, 158, 98, 98, 98, 98, + 98, 98, 98, 98, 710, 710, 99, 113, 114, 114, + 114, 113, 113, 113, 113, 113, 113, 113, 113, 113, + 115, 113, 113, 134, 710, 710, 196, 197, 113, 113, + 113, 113, 70, 82, 82, 82, 154, 135, 135, 135, + 135, 135, 191, 170, 70, 139, 77, 92, 171, 70, + 91, 70, 70, 113, 117, 113, 140, 139, 79, 141, + 138, 138, 139, 70, 142, 139, 688, 170, 159, 171, + 205, 171, 206, 155, 162, 231, 139, 113, 113, 118, + 138, 70, 134, 119, 119, 119, 157, 120, 170, 171, + + 70, 171, 136, 160, 139, 179, 193, 156, 194, 265, + 164, 165, 154, 139, 195, 170, 165, 163, 171, 117, + 171, 121, 205, 155, 606, 122, 123, 122, 122, 122, + 122, 122, 122, 124, 271, 272, 170, 125, 125, 125, + 171, 126, 171, 82, 82, 82, 330, 156, 69, 69, + 69, 69, 69, 556, 180, 201, 331, 202, 82, 82, + 82, 136, 678, 203, 331, 127, 218, 218, 218, 128, + 129, 128, 129, 129, 129, 129, 129, 82, 82, 83, + 226, 226, 226, 684, 70, 244, 244, 244, 675, 143, + 85, 86, 144, 144, 144, 144, 144, 145, 256, 256, + + 256, 138, 146, 138, 138, 138, 138, 138, 138, 138, + 146, 138, 138, 146, 146, 146, 146, 146, 138, 138, + 138, 138, 277, 277, 277, 146, 146, 146, 146, 146, + 146, 146, 146, 138, 146, 138, 138, 146, 146, 146, + 146, 138, 138, 138, 138, 138, 92, 184, 311, 265, + 91, 70, 186, 312, 134, 205, 148, 206, 94, 683, + 149, 149, 149, 198, 150, 181, 184, 97, 135, 135, + 135, 135, 135, 188, 188, 188, 188, 188, 189, 211, + 211, 211, 211, 211, 211, 211, 211, 70, 148, 218, + 218, 218, 151, 151, 151, 151, 151, 151, 151, 151, + + 139, 70, 152, 70, 207, 583, 208, 70, 82, 268, + 94, 70, 209, 433, 139, 710, 139, 210, 70, 97, + 710, 186, 312, 136, 139, 70, 710, 434, 207, 70, + 208, 314, 315, 266, 267, 671, 209, 227, 139, 70, + 210, 284, 139, 376, 161, 161, 161, 161, 161, 161, + 161, 161, 70, 91, 244, 244, 244, 166, 305, 305, + 305, 167, 167, 167, 281, 168, 212, 212, 212, 212, + 212, 212, 212, 212, 216, 216, 216, 216, 216, 216, + 216, 216, 277, 277, 277, 336, 336, 336, 375, 169, + 220, 70, 377, 170, 171, 170, 170, 170, 170, 170, + + 170, 172, 360, 376, 139, 173, 173, 173, 623, 174, + 217, 217, 217, 217, 217, 217, 217, 217, 235, 235, + 235, 235, 235, 235, 235, 235, 337, 337, 337, 468, + 286, 248, 278, 175, 70, 70, 117, 176, 177, 176, + 177, 177, 177, 177, 177, 213, 360, 139, 139, 339, + 339, 339, 466, 214, 243, 243, 243, 243, 243, 243, + 243, 243, 123, 123, 123, 123, 123, 123, 123, 123, + 340, 340, 340, 341, 341, 341, 280, 213, 469, 279, + 117, 215, 215, 215, 215, 215, 215, 215, 215, 113, + 114, 114, 114, 113, 113, 113, 113, 113, 113, 113, + + 113, 113, 113, 113, 113, 678, 348, 70, 70, 70, + 113, 113, 113, 113, 249, 249, 249, 249, 249, 249, + 249, 249, 254, 254, 254, 254, 254, 254, 254, 254, + 349, 691, 134, 271, 272, 113, 117, 113, 255, 255, + 255, 255, 255, 255, 255, 255, 135, 135, 135, 135, + 135, 261, 314, 315, 349, 367, 367, 367, 676, 113, + 113, 113, 232, 232, 232, 233, 70, 113, 113, 113, + 113, 113, 113, 70, 269, 113, 113, 82, 70, 139, + 70, 70, 113, 113, 70, 113, 139, 138, 444, 710, + 70, 139, 70, 139, 139, 139, 91, 139, 134, 70, + + 136, 136, 138, 139, 675, 139, 446, 113, 117, 309, + 139, 268, 139, 70, 273, 273, 273, 273, 273, 273, + 273, 273, 285, 285, 285, 524, 139, 336, 336, 336, + 446, 113, 113, 236, 138, 282, 70, 237, 70, 281, + 287, 288, 283, 289, 70, 238, 445, 239, 524, 139, + 240, 139, 343, 296, 296, 296, 480, 139, 240, 350, + 343, 240, 455, 325, 240, 240, 468, 136, 70, 237, + 70, 350, 350, 241, 242, 241, 241, 241, 241, 241, + 241, 139, 240, 139, 343, 240, 366, 672, 240, 245, + 308, 70, 268, 367, 367, 367, 117, 244, 244, 244, + + 296, 296, 296, 246, 139, 91, 247, 386, 265, 379, + 379, 379, 387, 388, 247, 537, 265, 247, 70, 427, + 247, 247, 290, 290, 290, 290, 290, 290, 290, 290, + 247, 139, 91, 248, 314, 315, 279, 668, 247, 184, + 311, 247, 91, 605, 247, 250, 188, 188, 188, 188, + 188, 189, 479, 251, 216, 216, 216, 216, 216, 216, + 216, 216, 243, 243, 243, 243, 243, 243, 243, 243, + 232, 232, 232, 233, 381, 381, 381, 250, 403, 70, + 428, 252, 253, 252, 252, 252, 252, 252, 252, 213, + 545, 668, 139, 256, 256, 256, 265, 214, 171, 171, + + 171, 171, 171, 171, 171, 171, 299, 299, 299, 299, + 299, 299, 299, 299, 376, 366, 117, 339, 339, 339, + 663, 213, 379, 379, 379, 215, 257, 215, 215, 258, + 215, 215, 215, 274, 91, 362, 662, 410, 396, 396, + 396, 275, 254, 254, 254, 254, 254, 254, 254, 254, + 304, 304, 304, 304, 304, 304, 304, 304, 419, 419, + 419, 329, 447, 377, 375, 274, 70, 467, 661, 276, + 276, 276, 276, 276, 276, 276, 276, 236, 363, 139, + 70, 291, 522, 70, 70, 393, 448, 394, 478, 292, + 478, 239, 375, 139, 293, 395, 139, 139, 70, 339, + + 339, 339, 293, 407, 91, 293, 522, 370, 293, 293, + 374, 139, 70, 291, 440, 440, 440, 294, 295, 294, + 294, 294, 294, 294, 294, 139, 293, 401, 406, 293, + 184, 311, 293, 70, 245, 248, 70, 316, 316, 316, + 316, 316, 296, 296, 296, 70, 139, 70, 246, 139, + 70, 297, 366, 376, 396, 396, 396, 91, 139, 297, + 139, 408, 297, 139, 637, 297, 297, 338, 338, 338, + 338, 338, 338, 338, 338, 297, 348, 364, 298, 402, + 70, 70, 375, 297, 512, 364, 297, 556, 364, 297, + 300, 364, 364, 139, 139, 557, 513, 245, 301, 429, + + 404, 364, 417, 70, 91, 368, 368, 368, 70, 364, + 91, 246, 364, 526, 661, 364, 139, 397, 397, 397, + 546, 139, 300, 70, 404, 298, 302, 303, 302, 302, + 302, 302, 302, 302, 274, 455, 139, 527, 305, 305, + 305, 370, 275, 241, 241, 241, 241, 241, 241, 241, + 241, 365, 365, 365, 365, 365, 365, 365, 365, 636, + 430, 441, 441, 441, 658, 371, 274, 650, 405, 532, + 276, 306, 276, 276, 307, 276, 276, 276, 342, 372, + 405, 405, 460, 460, 460, 657, 343, 252, 252, 252, + 252, 252, 252, 252, 252, 378, 378, 378, 378, 378, + + 378, 378, 378, 471, 471, 471, 518, 518, 518, 465, + 342, 456, 456, 456, 344, 344, 344, 344, 344, 344, + 344, 344, 356, 356, 236, 356, 356, 356, 356, 356, + 563, 356, 356, 356, 356, 70, 356, 356, 467, 369, + 422, 364, 564, 356, 356, 356, 356, 369, 139, 364, + 369, 70, 364, 369, 369, 364, 364, 457, 245, 70, + 414, 414, 414, 369, 139, 364, 461, 268, 356, 356, + 356, 369, 139, 364, 369, 369, 364, 369, 70, 364, + 462, 465, 655, 369, 654, 265, 369, 358, 649, 369, + 369, 139, 356, 356, 113, 232, 232, 232, 233, 369, + + 113, 113, 113, 113, 113, 113, 134, 369, 113, 113, + 369, 245, 134, 369, 648, 113, 113, 423, 113, 380, + 380, 380, 544, 392, 544, 246, 385, 385, 385, 385, + 385, 338, 338, 338, 338, 338, 338, 338, 338, 70, + 113, 117, 302, 302, 302, 302, 302, 302, 302, 302, + 431, 431, 139, 461, 331, 370, 647, 91, 70, 70, + 646, 366, 331, 70, 113, 113, 371, 462, 414, 414, + 414, 139, 139, 371, 77, 136, 139, 576, 91, 665, + 372, 136, 70, 373, 473, 265, 79, 372, 643, 577, + 409, 373, 81, 265, 373, 139, 70, 373, 373, 294, + + 294, 294, 294, 294, 294, 294, 294, 373, 582, 139, + 374, 432, 432, 482, 70, 373, 70, 465, 373, 91, + 91, 373, 342, 418, 418, 418, 268, 139, 642, 139, + 343, 365, 365, 365, 365, 365, 365, 365, 365, 378, + 378, 378, 378, 378, 378, 378, 378, 468, 184, 498, + 441, 441, 441, 499, 342, 70, 635, 70, 344, 382, + 344, 344, 383, 344, 344, 344, 398, 70, 139, 366, + 139, 622, 679, 70, 399, 474, 418, 418, 418, 92, + 139, 70, 70, 375, 70, 475, 139, 86, 634, 630, + 397, 397, 397, 88, 139, 139, 469, 139, 398, 70, + + 491, 536, 400, 400, 400, 400, 400, 400, 400, 400, + 356, 356, 139, 356, 356, 356, 356, 356, 357, 356, + 356, 356, 356, 483, 356, 356, 298, 492, 91, 70, + 134, 412, 356, 356, 356, 376, 184, 311, 397, 397, + 397, 496, 139, 426, 426, 426, 426, 426, 344, 344, + 344, 344, 344, 344, 344, 344, 356, 356, 356, 439, + 439, 439, 439, 439, 439, 439, 439, 400, 400, 400, + 400, 400, 400, 400, 400, 413, 134, 613, 464, 664, + 356, 356, 70, 245, 417, 444, 464, 519, 539, 464, + 70, 444, 464, 464, 70, 139, 70, 246, 629, 136, + + 297, 520, 464, 139, 70, 371, 91, 139, 297, 139, + 464, 297, 467, 464, 297, 297, 464, 139, 134, 441, + 441, 441, 464, 556, 297, 621, 620, 298, 485, 555, + 464, 70, 297, 464, 70, 297, 464, 464, 297, 371, + 481, 481, 481, 484, 139, 540, 464, 139, 70, 70, + 467, 585, 486, 372, 464, 374, 415, 464, 265, 134, + 464, 139, 139, 689, 415, 70, 70, 415, 619, 70, + 415, 415, 468, 472, 472, 472, 472, 472, 139, 139, + 415, 490, 139, 416, 456, 456, 456, 136, 415, 70, + 201, 415, 202, 416, 415, 398, 615, 91, 203, 70, + + 615, 553, 139, 399, 439, 439, 439, 439, 439, 439, + 439, 439, 139, 70, 550, 467, 70, 548, 567, 268, + 549, 495, 481, 481, 481, 523, 139, 398, 136, 139, + 457, 400, 420, 400, 400, 421, 400, 400, 400, 449, + 449, 548, 449, 449, 449, 449, 449, 92, 449, 449, + 449, 449, 70, 449, 449, 631, 651, 524, 416, 70, + 449, 449, 449, 449, 70, 139, 525, 533, 533, 533, + 468, 70, 139, 481, 481, 481, 614, 139, 70, 631, + 524, 533, 533, 533, 139, 449, 449, 449, 184, 311, + 70, 139, 451, 584, 612, 558, 558, 558, 558, 558, + + 544, 392, 544, 139, 451, 451, 613, 596, 693, 449, + 449, 356, 356, 534, 356, 356, 356, 356, 356, 495, + 356, 356, 356, 356, 552, 356, 356, 534, 535, 91, + 566, 158, 356, 356, 356, 356, 535, 70, 566, 535, + 70, 566, 535, 535, 566, 566, 611, 560, 70, 610, + 139, 70, 535, 139, 566, 134, 134, 356, 356, 356, + 535, 139, 566, 535, 139, 566, 535, 590, 566, 579, + 579, 579, 579, 579, 607, 392, 631, 260, 589, 632, + 664, 356, 356, 356, 356, 461, 356, 356, 356, 356, + 356, 639, 356, 356, 356, 356, 587, 356, 356, 70, + + 631, 70, 535, 633, 356, 356, 356, 356, 588, 670, + 535, 519, 139, 535, 139, 640, 535, 535, 91, 693, + 604, 671, 134, 603, 136, 136, 535, 602, 566, 356, + 356, 356, 134, 609, 535, 644, 566, 535, 577, 566, + 535, 631, 566, 566, 70, 588, 579, 579, 579, 579, + 579, 134, 566, 356, 356, 461, 607, 139, 70, 645, + 566, 638, 628, 566, 392, 631, 566, 184, 498, 462, + 601, 139, 463, 685, 558, 558, 558, 558, 558, 134, + 463, 134, 673, 463, 631, 631, 463, 463, 260, 631, + 641, 136, 656, 653, 631, 134, 463, 631, 392, 659, + + 392, 540, 608, 627, 463, 392, 669, 463, 631, 631, + 463, 371, 392, 631, 660, 134, 601, 653, 631, 673, + 136, 631, 600, 666, 599, 372, 682, 653, 373, 653, + 631, 598, 686, 134, 653, 693, 373, 597, 569, 373, + 392, 653, 373, 373, 687, 569, 680, 667, 136, 567, + 136, 653, 373, 653, 631, 374, 392, 392, 653, 596, + 373, 564, 595, 373, 136, 653, 373, 449, 449, 653, + 449, 449, 449, 449, 449, 450, 449, 449, 449, 449, + 594, 449, 449, 134, 136, 653, 653, 593, 488, 449, + 449, 449, 592, 653, 690, 693, 591, 693, 681, 392, + + 693, 693, 136, 392, 708, 693, 694, 686, 695, 653, + 653, 696, 697, 449, 449, 449, 698, 392, 581, 693, + 489, 580, 262, 693, 693, 693, 537, 536, 578, 575, + 699, 574, 489, 489, 700, 701, 702, 449, 449, 356, + 356, 573, 356, 356, 356, 356, 356, 357, 356, 356, + 356, 356, 136, 356, 356, 572, 571, 570, 569, 105, + 412, 356, 356, 356, 260, 567, 260, 693, 693, 260, + 260, 693, 693, 693, 260, 565, 562, 561, 703, 704, + 560, 559, 705, 706, 707, 356, 356, 356, 260, 511, + 511, 509, 260, 260, 260, 509, 507, 507, 505, 505, + + 503, 503, 501, 501, 392, 551, 542, 541, 205, 356, + 356, 356, 356, 198, 356, 356, 356, 356, 356, 357, + 356, 356, 356, 356, 466, 356, 356, 538, 465, 536, + 459, 92, 412, 356, 356, 356, 260, 260, 531, 530, + 260, 260, 260, 529, 528, 444, 92, 517, 516, 515, + 514, 434, 511, 509, 507, 505, 503, 356, 356, 356, + 501, 187, 497, 493, 392, 477, 476, 74, 199, 470, + 370, 366, 459, 454, 453, 452, 199, 443, 442, 438, + 437, 356, 356, 70, 461, 436, 435, 205, 205, 199, + 198, 198, 198, 320, 320, 318, 139, 318, 462, 187, + + 424, 494, 264, 392, 264, 384, 366, 355, 354, 494, + 353, 352, 494, 351, 347, 494, 494, 346, 345, 335, + 334, 333, 332, 329, 329, 494, 328, 327, 326, 325, + 325, 324, 323, 494, 322, 321, 494, 320, 318, 494, + 371, 311, 310, 265, 264, 262, 260, 199, 259, 117, + 230, 229, 228, 199, 372, 225, 224, 415, 223, 222, + 222, 221, 220, 219, 91, 415, 205, 204, 415, 198, + 199, 415, 415, 198, 192, 184, 182, 137, 110, 105, + 104, 415, 101, 100, 416, 91, 74, 710, 710, 415, + 710, 710, 415, 710, 710, 415, 519, 710, 710, 710, + + 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, + 520, 710, 710, 521, 710, 710, 710, 710, 710, 710, + 710, 521, 710, 710, 521, 710, 710, 521, 521, 710, + 710, 710, 710, 710, 710, 710, 710, 521, 710, 710, + 710, 710, 710, 710, 710, 521, 710, 710, 521, 710, + 710, 521, 449, 449, 710, 449, 449, 449, 449, 449, + 710, 449, 449, 449, 449, 710, 449, 449, 710, 710, + 710, 710, 710, 449, 449, 449, 449, 710, 710, 710, + 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, + 710, 710, 710, 710, 710, 710, 710, 710, 449, 449, + + 449, 710, 710, 710, 710, 710, 710, 710, 710, 710, + 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, + 710, 710, 449, 449, 449, 449, 710, 449, 449, 449, + 449, 449, 710, 449, 449, 449, 449, 710, 449, 449, + 710, 710, 710, 710, 710, 449, 449, 449, 449, 710, + 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, + 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, + 449, 449, 449, 710, 710, 710, 710, 451, 710, 710, + 710, 710, 710, 710, 710, 710, 710, 710, 710, 451, + 451, 710, 710, 710, 449, 449, 519, 710, 710, 710, + + 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, + 520, 710, 710, 547, 710, 710, 710, 710, 710, 710, + 710, 547, 710, 710, 547, 710, 710, 547, 547, 710, + 710, 710, 710, 710, 710, 710, 710, 547, 710, 710, + 710, 710, 710, 710, 710, 547, 710, 710, 547, 710, + 710, 547, 449, 449, 710, 449, 449, 449, 449, 449, + 450, 449, 449, 449, 449, 710, 449, 449, 710, 710, + 710, 710, 710, 488, 449, 449, 449, 710, 710, 710, + 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, + 710, 710, 710, 710, 710, 710, 710, 710, 449, 449, + + 449, 710, 710, 710, 710, 710, 710, 710, 710, 710, + 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, + 710, 710, 449, 449, 449, 449, 710, 449, 449, 449, + 449, 449, 450, 449, 449, 449, 449, 710, 449, 449, + 710, 710, 710, 710, 710, 488, 449, 449, 449, 710, + 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, + 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, + 449, 449, 449, 710, 710, 710, 710, 489, 710, 710, + 710, 710, 710, 710, 710, 710, 710, 710, 710, 489, + 489, 710, 710, 710, 449, 449, 616, 616, 710, 616, + + 616, 616, 616, 616, 710, 616, 616, 616, 616, 710, + 616, 616, 710, 710, 710, 710, 710, 616, 616, 616, + 616, 710, 710, 710, 710, 710, 710, 618, 710, 710, + 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, + 710, 710, 616, 616, 616, 710, 710, 710, 710, 710, + 710, 618, 710, 710, 710, 710, 710, 710, 710, 710, + 710, 710, 710, 710, 710, 710, 616, 616, 616, 616, + 710, 616, 616, 616, 616, 616, 617, 616, 616, 616, + 616, 710, 616, 616, 710, 710, 710, 710, 710, 625, + 616, 616, 616, 710, 710, 710, 710, 710, 710, 626, + + 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, + 710, 710, 710, 710, 616, 616, 616, 710, 710, 710, + 710, 710, 710, 626, 710, 710, 710, 710, 710, 710, + 710, 710, 710, 710, 710, 710, 710, 710, 616, 616, + 616, 616, 710, 616, 616, 616, 616, 616, 710, 616, + 616, 616, 616, 710, 616, 616, 710, 710, 710, 710, + 710, 616, 616, 616, 616, 710, 710, 710, 710, 710, + 710, 618, 710, 710, 710, 710, 710, 710, 710, 710, + 710, 710, 710, 710, 710, 710, 616, 616, 616, 710, + 710, 710, 710, 710, 710, 618, 710, 710, 710, 710, + + 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, + 616, 616, 616, 616, 710, 616, 616, 616, 616, 616, + 617, 616, 616, 616, 616, 710, 616, 616, 710, 710, + 710, 710, 710, 625, 616, 616, 616, 710, 710, 710, + 710, 710, 710, 626, 710, 710, 710, 710, 710, 710, + 710, 710, 710, 710, 710, 710, 710, 710, 616, 616, + 616, 710, 710, 710, 710, 710, 710, 626, 710, 710, + 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, + 710, 710, 616, 616, 70, 710, 710, 70, 70, 710, + 710, 70, 70, 70, 70, 70, 71, 71, 71, 71, + + 71, 710, 71, 71, 71, 71, 71, 71, 71, 71, + 71, 90, 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 116, 116, 116, 116, + 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, + 116, 133, 133, 133, 133, 133, 133, 133, 133, 133, + 133, 133, 133, 133, 133, 133, 138, 710, 710, 138, + 138, 138, 710, 138, 138, 138, 138, 138, 183, 183, + 183, 183, 183, 710, 183, 183, 183, 183, 183, 183, + 183, 183, 183, 185, 185, 185, 185, 185, 185, 185, + 185, 185, 185, 185, 185, 185, 185, 185, 200, 200, + + 710, 710, 710, 710, 710, 710, 710, 200, 200, 200, + 200, 200, 113, 113, 113, 113, 113, 113, 113, 113, + 113, 113, 113, 113, 113, 113, 113, 234, 234, 234, + 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, + 234, 234, 134, 134, 134, 134, 134, 134, 134, 134, + 134, 134, 134, 134, 134, 134, 134, 263, 263, 263, + 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, + 263, 263, 270, 270, 270, 270, 270, 270, 270, 270, + 270, 270, 270, 270, 270, 270, 270, 185, 185, 185, + 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, + + 185, 185, 186, 186, 186, 186, 186, 186, 186, 186, + 186, 186, 186, 186, 186, 186, 186, 313, 313, 313, + 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, + 313, 313, 317, 317, 710, 317, 317, 317, 317, 317, + 317, 317, 317, 317, 317, 317, 317, 319, 319, 710, + 319, 319, 319, 319, 319, 319, 319, 319, 319, 319, + 319, 319, 357, 357, 710, 357, 357, 357, 357, 357, + 357, 357, 357, 357, 357, 357, 357, 359, 359, 359, + 359, 359, 359, 359, 359, 359, 359, 359, 359, 359, + 359, 359, 113, 113, 113, 113, 113, 113, 113, 113, + + 113, 113, 113, 113, 113, 113, 113, 361, 361, 361, + 361, 361, 361, 361, 361, 361, 361, 361, 361, 361, + 361, 361, 234, 234, 234, 234, 234, 234, 234, 234, + 234, 234, 234, 234, 234, 234, 234, 369, 710, 710, + 369, 710, 369, 369, 710, 710, 369, 369, 263, 263, + 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, + 263, 263, 263, 391, 391, 391, 391, 391, 391, 391, + 391, 391, 391, 391, 391, 391, 391, 391, 270, 270, + 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, + 270, 270, 270, 90, 90, 90, 90, 90, 90, 90, + + 90, 90, 90, 90, 90, 90, 90, 90, 411, 411, + 710, 411, 411, 411, 411, 411, 411, 411, 411, 411, + 411, 411, 411, 313, 313, 313, 313, 313, 313, 313, + 313, 313, 313, 313, 313, 313, 313, 313, 425, 425, + 425, 425, 710, 425, 425, 425, 425, 425, 425, 425, + 425, 425, 425, 183, 183, 183, 183, 183, 183, 183, + 183, 183, 183, 183, 183, 183, 183, 183, 317, 317, + 710, 317, 317, 317, 317, 317, 317, 317, 317, 317, + 317, 317, 317, 319, 319, 710, 319, 319, 319, 319, + 319, 319, 319, 319, 319, 319, 319, 319, 439, 710, + + 439, 710, 710, 710, 439, 439, 439, 450, 450, 710, + 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, + 450, 450, 356, 356, 710, 356, 356, 356, 356, 356, + 356, 356, 356, 356, 356, 356, 356, 357, 357, 710, + 357, 357, 357, 357, 357, 357, 357, 357, 357, 357, + 357, 357, 359, 359, 359, 359, 359, 359, 359, 359, + 359, 359, 359, 359, 359, 359, 359, 361, 361, 361, + 361, 361, 361, 361, 361, 361, 361, 361, 361, 361, + 361, 361, 113, 113, 113, 113, 113, 113, 113, 113, + 113, 113, 113, 113, 113, 113, 113, 458, 458, 458, + + 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, + 458, 458, 464, 710, 710, 710, 710, 464, 464, 710, + 710, 464, 464, 391, 391, 391, 391, 391, 391, 391, + 391, 391, 391, 391, 391, 391, 391, 391, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 487, 487, 710, 487, 487, 487, 487, + 487, 487, 487, 487, 487, 487, 487, 487, 411, 411, + 710, 411, 411, 411, 411, 411, 411, 411, 411, 411, + 411, 411, 411, 425, 425, 425, 425, 710, 425, 425, + 425, 425, 425, 425, 425, 425, 425, 425, 183, 183, + + 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, + 183, 183, 183, 500, 500, 710, 500, 500, 500, 500, + 500, 500, 500, 500, 500, 500, 500, 500, 502, 502, + 710, 502, 502, 502, 502, 502, 502, 502, 502, 502, + 502, 502, 502, 504, 504, 710, 504, 504, 504, 504, + 504, 504, 504, 504, 504, 504, 504, 504, 506, 506, + 710, 506, 506, 506, 506, 506, 506, 506, 506, 506, + 506, 506, 506, 508, 508, 710, 508, 508, 508, 508, + 508, 508, 508, 508, 508, 508, 508, 508, 510, 510, + 710, 510, 510, 510, 510, 510, 510, 510, 510, 510, + + 510, 510, 510, 449, 449, 710, 449, 449, 449, 449, + 449, 449, 449, 449, 449, 449, 449, 449, 450, 450, + 710, 450, 450, 450, 450, 450, 450, 450, 450, 450, + 450, 450, 450, 359, 359, 359, 359, 359, 359, 359, + 359, 359, 359, 359, 359, 359, 359, 359, 113, 113, + 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, + 113, 113, 113, 458, 458, 458, 458, 458, 458, 458, + 458, 458, 458, 458, 458, 458, 458, 458, 535, 710, + 710, 710, 710, 535, 535, 710, 710, 535, 543, 543, + 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, + + 543, 543, 543, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, 487, 487, + 710, 487, 487, 487, 487, 487, 487, 487, 487, 487, + 487, 487, 487, 554, 554, 554, 554, 554, 554, 554, + 554, 554, 554, 554, 554, 554, 554, 554, 566, 710, + 710, 710, 710, 566, 566, 710, 710, 566, 568, 568, + 710, 568, 568, 568, 568, 568, 568, 568, 568, 568, + 568, 568, 568, 586, 586, 586, 586, 586, 586, 586, + 586, 586, 586, 586, 586, 586, 586, 586, 617, 617, + 710, 617, 617, 617, 617, 617, 617, 617, 617, 617, + + 617, 617, 617, 624, 624, 710, 624, 624, 624, 624, + 624, 624, 624, 624, 624, 624, 624, 624, 616, 616, + 710, 616, 616, 616, 616, 616, 616, 616, 616, 616, + 616, 616, 616, 652, 652, 652, 652, 652, 652, 652, + 652, 652, 652, 652, 652, 652, 652, 652, 674, 674, + 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, + 674, 674, 674, 677, 677, 677, 677, 677, 677, 677, + 677, 677, 677, 677, 677, 677, 677, 677, 692, 692, + 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, + 692, 692, 692, 3, 710, 710, 710, 710, 710, 710, + + 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, + 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, + 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, + 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, + 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, + 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, + 710, 710, 710, 710, 710, 710 + } ; + +static yyconst short int yy_chk[4467] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 5, 6, 6, 6, 6, 6, + 8, 10, 10, 11, 18, 23, 708, 8, 8, 8, + 8, 8, 19, 11, 34, 11, 11, 34, 5, 34, + 36, 11, 12, 12, 12, 36, 233, 31, 18, 12, + 23, 31, 40, 19, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 22, 25, 40, 12, 12, 12, 12, + + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 37, 19, 233, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 13, 27, 33, 25, 33, 264, 33, 24, 22, + 25, 13, 46, 13, 264, 32, 32, 24, 32, 13, + 15, 43, 44, 44, 51, 46, 37, 72, 72, 32, + 15, 43, 15, 43, 15, 15, 15, 51, 15, 43, + 35, 15, 24, 24, 24, 24, 24, 24, 24, 24, + 47, 74, 688, 35, 60, 27, 27, 35, 60, 35, + + 46, 27, 15, 47, 35, 51, 15, 15, 15, 15, + 15, 15, 15, 15, 49, 52, 15, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 38, 55, 49, 78, 78, 28, 28, + 28, 28, 50, 82, 82, 82, 47, 38, 38, 38, + 38, 38, 74, 65, 48, 50, 41, 57, 65, 56, + 583, 41, 57, 28, 28, 28, 41, 48, 41, 41, + 49, 52, 56, 53, 41, 57, 684, 62, 53, 62, + 86, 62, 86, 48, 55, 115, 53, 28, 28, 29, + 55, 138, 133, 29, 29, 29, 50, 29, 61, 61, + + 66, 61, 38, 53, 138, 66, 77, 48, 77, 145, + 57, 57, 61, 66, 77, 63, 57, 56, 63, 115, + 63, 29, 145, 64, 583, 29, 29, 29, 29, 29, + 29, 29, 29, 30, 147, 147, 64, 30, 30, 30, + 64, 30, 64, 83, 83, 83, 206, 64, 69, 69, + 69, 69, 69, 683, 66, 83, 206, 83, 85, 85, + 85, 133, 677, 83, 206, 30, 98, 98, 98, 30, + 30, 30, 30, 30, 30, 30, 30, 42, 42, 42, + 108, 108, 108, 676, 42, 122, 122, 122, 674, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 129, 129, + + 129, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 151, 151, 151, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 45, 183, 183, 142, + 546, 45, 184, 184, 67, 327, 45, 327, 45, 672, + 45, 45, 45, 142, 45, 67, 73, 45, 67, 67, + 67, 67, 67, 73, 73, 73, 73, 73, 73, 93, + 93, 93, 93, 93, 93, 93, 93, 146, 45, 109, + 109, 109, 45, 45, 45, 45, 45, 45, 45, 45, + + 146, 141, 45, 54, 92, 546, 92, 213, 87, 141, + 54, 159, 92, 331, 141, 213, 54, 92, 87, 54, + 87, 185, 185, 67, 159, 140, 87, 331, 92, 155, + 92, 187, 187, 140, 140, 670, 92, 109, 140, 213, + 92, 159, 155, 248, 54, 54, 54, 54, 54, 54, + 54, 54, 58, 606, 130, 130, 130, 58, 177, 177, + 177, 58, 58, 58, 155, 58, 94, 94, 94, 94, + 94, 94, 94, 94, 96, 96, 96, 96, 96, 96, + 96, 96, 162, 162, 162, 211, 211, 211, 247, 58, + 130, 152, 248, 58, 58, 58, 58, 58, 58, 58, + + 58, 59, 231, 370, 152, 59, 59, 59, 606, 59, + 97, 97, 97, 97, 97, 97, 97, 97, 118, 118, + 118, 118, 118, 118, 118, 118, 212, 212, 212, 374, + 162, 247, 152, 59, 153, 154, 231, 59, 59, 59, + 59, 59, 59, 59, 59, 95, 359, 153, 154, 215, + 215, 215, 370, 95, 120, 120, 120, 120, 120, 120, + 120, 120, 121, 121, 121, 121, 121, 121, 121, 121, + 216, 216, 216, 217, 217, 217, 154, 95, 374, 153, + 359, 95, 95, 95, 95, 95, 95, 95, 95, 114, + 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, + + 114, 114, 114, 114, 114, 664, 222, 235, 235, 235, + 114, 114, 114, 114, 124, 124, 124, 124, 124, 124, + 124, 124, 126, 126, 126, 126, 126, 126, 126, 126, + 222, 690, 135, 270, 270, 114, 114, 114, 127, 127, + 127, 127, 127, 127, 127, 127, 135, 135, 135, 135, + 135, 135, 312, 312, 222, 241, 241, 241, 663, 114, + 114, 116, 116, 116, 116, 116, 143, 116, 116, 116, + 116, 116, 116, 148, 143, 116, 116, 144, 157, 143, + 156, 160, 116, 116, 158, 116, 148, 144, 347, 144, + 165, 157, 164, 156, 160, 144, 395, 158, 181, 163, + + 690, 135, 274, 165, 662, 164, 348, 116, 116, 181, + 274, 160, 163, 161, 148, 148, 148, 148, 148, 148, + 148, 148, 161, 161, 161, 598, 161, 249, 249, 249, + 348, 116, 116, 119, 274, 157, 179, 119, 180, 156, + 163, 164, 158, 165, 170, 119, 347, 119, 598, 179, + 119, 180, 337, 170, 170, 170, 395, 170, 119, 223, + 337, 119, 360, 267, 119, 119, 465, 181, 267, 119, + 268, 223, 223, 119, 119, 119, 119, 119, 119, 119, + 119, 267, 119, 268, 337, 119, 242, 658, 119, 123, + 179, 178, 180, 242, 242, 242, 360, 123, 123, 123, + + 178, 178, 178, 123, 178, 394, 123, 262, 150, 252, + 252, 252, 262, 262, 123, 465, 168, 123, 280, 325, + 123, 123, 166, 166, 166, 166, 166, 166, 166, 166, + 123, 280, 479, 123, 313, 313, 178, 655, 123, 188, + 188, 123, 582, 582, 123, 125, 188, 188, 188, 188, + 188, 188, 394, 125, 150, 150, 150, 150, 150, 150, + 150, 150, 168, 168, 168, 168, 168, 168, 168, 168, + 232, 232, 232, 232, 255, 255, 255, 125, 280, 288, + 325, 125, 125, 125, 125, 125, 125, 125, 125, 128, + 479, 654, 288, 128, 128, 128, 174, 128, 169, 169, + + 169, 169, 169, 169, 169, 169, 172, 172, 172, 172, + 172, 172, 172, 172, 258, 253, 232, 258, 258, 258, + 649, 128, 253, 253, 253, 128, 128, 128, 128, 128, + 128, 128, 128, 149, 272, 361, 648, 288, 299, 299, + 299, 149, 174, 174, 174, 174, 174, 174, 174, 174, + 175, 175, 175, 175, 175, 175, 175, 175, 304, 304, + 304, 269, 349, 258, 369, 149, 269, 373, 647, 149, + 149, 149, 149, 149, 149, 149, 149, 167, 361, 269, + 266, 167, 443, 283, 278, 266, 349, 272, 392, 167, + 392, 167, 257, 266, 167, 272, 283, 278, 284, 257, + + 257, 257, 167, 284, 623, 167, 443, 369, 167, 167, + 373, 284, 286, 167, 338, 338, 338, 167, 167, 167, + 167, 167, 167, 167, 167, 286, 167, 278, 283, 167, + 189, 189, 167, 171, 171, 257, 279, 189, 189, 189, + 189, 189, 171, 171, 171, 273, 171, 298, 171, 279, + 293, 171, 293, 298, 273, 273, 273, 480, 273, 171, + 298, 286, 171, 293, 623, 171, 171, 214, 214, 214, + 214, 214, 214, 214, 214, 171, 281, 236, 171, 279, + 297, 281, 297, 171, 434, 236, 171, 497, 236, 171, + 173, 236, 236, 297, 281, 497, 434, 243, 173, 329, + + 281, 236, 298, 396, 622, 243, 243, 243, 276, 236, + 636, 243, 236, 446, 646, 236, 396, 276, 276, 276, + 480, 276, 173, 282, 281, 297, 173, 173, 173, 173, + 173, 173, 173, 173, 176, 455, 282, 446, 176, 176, + 176, 243, 176, 237, 237, 237, 237, 237, 237, 237, + 237, 238, 238, 238, 238, 238, 238, 238, 238, 622, + 329, 344, 344, 344, 643, 368, 176, 636, 282, 455, + 176, 176, 176, 176, 176, 176, 176, 176, 218, 368, + 282, 282, 365, 365, 365, 642, 218, 250, 250, 250, + 250, 250, 250, 250, 250, 251, 251, 251, 251, 251, + + 251, 251, 251, 378, 378, 378, 439, 439, 439, 368, + 218, 362, 362, 362, 218, 218, 218, 218, 218, 218, + 218, 218, 230, 230, 239, 230, 230, 230, 230, 230, + 516, 230, 230, 230, 230, 308, 230, 230, 464, 245, + 308, 239, 516, 230, 230, 230, 230, 245, 308, 239, + 245, 294, 239, 245, 245, 239, 239, 362, 246, 393, + 294, 294, 294, 245, 294, 239, 460, 393, 230, 230, + 230, 245, 393, 239, 245, 246, 239, 245, 397, 239, + 460, 464, 640, 246, 639, 275, 246, 230, 635, 246, + 246, 397, 230, 230, 234, 234, 234, 234, 234, 246, + + 234, 234, 234, 234, 234, 234, 309, 246, 234, 234, + 246, 254, 261, 246, 634, 234, 234, 309, 234, 254, + 254, 254, 478, 478, 478, 254, 261, 261, 261, 261, + 261, 275, 275, 275, 275, 275, 275, 275, 275, 287, + 234, 234, 300, 300, 300, 300, 300, 300, 300, 300, + 330, 593, 287, 471, 330, 254, 633, 545, 291, 295, + 632, 295, 330, 401, 234, 234, 244, 471, 295, 295, + 295, 291, 295, 380, 387, 309, 401, 530, 651, 651, + 244, 261, 406, 244, 387, 292, 387, 380, 630, 530, + 287, 244, 387, 301, 244, 406, 407, 244, 244, 291, + + 291, 291, 291, 291, 291, 291, 291, 244, 545, 407, + 244, 330, 593, 401, 302, 244, 417, 380, 244, 605, + 665, 244, 256, 302, 302, 302, 407, 302, 629, 417, + 256, 292, 292, 292, 292, 292, 292, 292, 292, 301, + 301, 301, 301, 301, 301, 301, 301, 383, 426, 426, + 383, 383, 383, 426, 256, 409, 621, 495, 256, 256, + 256, 256, 256, 256, 256, 256, 277, 303, 409, 303, + 495, 605, 665, 402, 277, 388, 303, 303, 303, 482, + 303, 306, 410, 306, 482, 388, 402, 388, 620, 614, + 306, 306, 306, 388, 306, 410, 383, 482, 277, 494, + + 409, 494, 277, 277, 277, 277, 277, 277, 277, 277, + 289, 289, 494, 289, 289, 289, 289, 289, 289, 289, + 289, 289, 289, 402, 289, 289, 306, 410, 650, 307, + 423, 289, 289, 289, 289, 307, 316, 316, 307, 307, + 307, 423, 307, 316, 316, 316, 316, 316, 342, 342, + 342, 342, 342, 342, 342, 342, 289, 289, 289, 343, + 343, 343, 343, 343, 343, 343, 343, 398, 398, 398, + 398, 398, 398, 398, 398, 289, 472, 612, 371, 650, + 289, 289, 290, 290, 307, 403, 371, 518, 472, 371, + 403, 484, 371, 371, 550, 290, 484, 290, 611, 423, + + 290, 518, 371, 403, 404, 372, 685, 550, 290, 484, + 371, 290, 382, 371, 290, 290, 371, 404, 496, 382, + 382, 382, 372, 610, 290, 604, 603, 290, 404, 496, + 372, 400, 290, 372, 408, 290, 372, 372, 290, 296, + 400, 400, 400, 403, 400, 472, 372, 408, 415, 491, + 415, 550, 404, 296, 372, 382, 296, 372, 399, 385, + 372, 415, 491, 685, 296, 422, 416, 296, 602, 486, + 296, 296, 416, 385, 385, 385, 385, 385, 422, 416, + 296, 408, 486, 296, 456, 456, 456, 496, 296, 483, + 474, 296, 474, 415, 296, 305, 600, 637, 474, 485, + + 599, 491, 483, 305, 399, 399, 399, 399, 399, 399, + 399, 399, 485, 420, 486, 420, 547, 483, 547, 422, + 485, 416, 420, 420, 420, 444, 420, 305, 385, 547, + 456, 305, 305, 305, 305, 305, 305, 305, 305, 350, + 350, 483, 350, 350, 350, 350, 350, 492, 350, 350, + 350, 350, 492, 350, 350, 615, 637, 444, 420, 549, + 350, 350, 350, 350, 421, 492, 444, 459, 459, 459, + 421, 490, 549, 421, 421, 421, 597, 421, 588, 615, + 444, 533, 533, 533, 490, 350, 350, 350, 499, 499, + 548, 588, 350, 549, 596, 499, 499, 499, 499, 499, + + 544, 544, 544, 548, 350, 350, 596, 595, 691, 350, + 350, 357, 357, 459, 357, 357, 357, 357, 357, 421, + 357, 357, 357, 357, 490, 357, 357, 533, 461, 689, + 519, 548, 357, 357, 357, 357, 461, 553, 519, 461, + 584, 519, 461, 461, 519, 519, 594, 592, 627, 591, + 553, 552, 461, 584, 519, 539, 555, 357, 357, 357, + 461, 627, 519, 461, 552, 519, 461, 555, 519, 539, + 539, 539, 539, 539, 584, 586, 616, 691, 553, 618, + 689, 357, 357, 358, 358, 462, 358, 358, 358, 358, + 358, 626, 358, 358, 358, 358, 552, 358, 358, 585, + + 616, 587, 462, 618, 358, 358, 358, 358, 552, 657, + 462, 520, 585, 462, 587, 626, 462, 462, 679, 692, + 581, 657, 590, 580, 539, 555, 462, 578, 520, 358, + 358, 358, 579, 590, 462, 631, 520, 462, 576, 520, + 462, 631, 520, 520, 589, 587, 579, 579, 579, 579, + 579, 609, 520, 358, 358, 367, 585, 589, 608, 631, + 520, 625, 609, 520, 638, 631, 520, 558, 558, 367, + 575, 608, 367, 679, 558, 558, 558, 558, 558, 628, + 367, 641, 659, 367, 659, 645, 367, 367, 692, 625, + 628, 590, 641, 638, 644, 656, 367, 660, 652, 644, + + 653, 579, 589, 608, 367, 680, 656, 367, 659, 645, + 367, 381, 666, 625, 645, 669, 574, 638, 644, 660, + 609, 660, 573, 653, 572, 381, 669, 652, 381, 653, + 673, 571, 680, 682, 680, 707, 381, 570, 569, 381, + 667, 666, 381, 381, 682, 568, 666, 653, 628, 566, + 641, 652, 381, 653, 673, 381, 681, 686, 680, 565, + 381, 563, 562, 381, 656, 666, 381, 405, 405, 667, + 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, + 561, 405, 405, 687, 669, 681, 686, 560, 405, 405, + 405, 405, 559, 667, 687, 693, 557, 694, 667, 554, + + 695, 696, 682, 551, 707, 697, 693, 681, 694, 681, + 686, 695, 696, 405, 405, 405, 697, 543, 542, 698, + 405, 541, 540, 699, 700, 701, 538, 535, 531, 529, + 698, 528, 405, 405, 699, 700, 701, 405, 405, 411, + 411, 527, 411, 411, 411, 411, 411, 411, 411, 411, + 411, 411, 687, 411, 411, 526, 525, 524, 523, 522, + 411, 411, 411, 411, 693, 521, 694, 702, 703, 695, + 696, 704, 705, 706, 697, 517, 515, 514, 702, 703, + 513, 512, 704, 705, 706, 411, 411, 411, 698, 511, + 510, 509, 699, 700, 701, 508, 507, 506, 505, 504, + + 503, 502, 501, 500, 493, 488, 477, 476, 475, 411, + 411, 413, 413, 473, 413, 413, 413, 413, 413, 413, + 413, 413, 413, 413, 470, 413, 413, 468, 467, 463, + 458, 454, 413, 413, 413, 413, 702, 703, 453, 452, + 704, 705, 706, 448, 447, 445, 442, 438, 437, 436, + 435, 433, 432, 431, 430, 429, 428, 413, 413, 413, + 427, 425, 424, 412, 391, 390, 389, 386, 384, 376, + 375, 364, 363, 355, 354, 353, 352, 346, 345, 335, + 334, 413, 413, 414, 414, 333, 332, 328, 326, 324, + 323, 322, 321, 320, 319, 318, 414, 317, 414, 314, + + 310, 414, 271, 265, 263, 259, 240, 229, 228, 414, + 227, 225, 414, 224, 221, 414, 414, 220, 219, 210, + 209, 208, 207, 205, 204, 414, 203, 202, 201, 198, + 197, 196, 195, 414, 194, 193, 414, 191, 190, 414, + 419, 186, 182, 139, 137, 136, 134, 132, 131, 113, + 112, 111, 110, 107, 419, 106, 105, 419, 104, 103, + 102, 101, 100, 99, 90, 419, 88, 84, 419, 81, + 80, 419, 419, 79, 76, 71, 68, 39, 26, 21, + 20, 419, 17, 16, 419, 14, 9, 3, 0, 419, + 0, 0, 419, 0, 0, 419, 441, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 441, 0, 0, 441, 0, 0, 0, 0, 0, 0, + 0, 441, 0, 0, 441, 0, 0, 441, 441, 0, + 0, 0, 0, 0, 0, 0, 0, 441, 0, 0, + 0, 0, 0, 0, 0, 441, 0, 0, 441, 0, + 0, 441, 450, 450, 0, 450, 450, 450, 450, 450, + 0, 450, 450, 450, 450, 0, 450, 450, 0, 0, + 0, 0, 0, 450, 450, 450, 450, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 450, 450, + + 450, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 450, 450, 451, 451, 0, 451, 451, 451, + 451, 451, 0, 451, 451, 451, 451, 0, 451, 451, + 0, 0, 0, 0, 0, 451, 451, 451, 451, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 451, 451, 451, 0, 0, 0, 0, 451, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 451, + 451, 0, 0, 0, 451, 451, 481, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 481, 0, 0, 481, 0, 0, 0, 0, 0, 0, + 0, 481, 0, 0, 481, 0, 0, 481, 481, 0, + 0, 0, 0, 0, 0, 0, 0, 481, 0, 0, + 0, 0, 0, 0, 0, 481, 0, 0, 481, 0, + 0, 481, 487, 487, 0, 487, 487, 487, 487, 487, + 487, 487, 487, 487, 487, 0, 487, 487, 0, 0, + 0, 0, 0, 487, 487, 487, 487, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 487, 487, + + 487, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 487, 487, 489, 489, 0, 489, 489, 489, + 489, 489, 489, 489, 489, 489, 489, 0, 489, 489, + 0, 0, 0, 0, 0, 489, 489, 489, 489, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 489, 489, 489, 0, 0, 0, 0, 489, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 489, + 489, 0, 0, 0, 489, 489, 601, 601, 0, 601, + + 601, 601, 601, 601, 0, 601, 601, 601, 601, 0, + 601, 601, 0, 0, 0, 0, 0, 601, 601, 601, + 601, 0, 0, 0, 0, 0, 0, 601, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 601, 601, 601, 0, 0, 0, 0, 0, + 0, 601, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 601, 601, 607, 607, + 0, 607, 607, 607, 607, 607, 607, 607, 607, 607, + 607, 0, 607, 607, 0, 0, 0, 0, 0, 607, + 607, 607, 607, 0, 0, 0, 0, 0, 0, 607, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 607, 607, 607, 0, 0, 0, + 0, 0, 0, 607, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 607, 607, + 617, 617, 0, 617, 617, 617, 617, 617, 0, 617, + 617, 617, 617, 0, 617, 617, 0, 0, 0, 0, + 0, 617, 617, 617, 617, 0, 0, 0, 0, 0, + 0, 617, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 617, 617, 617, 0, + 0, 0, 0, 0, 0, 617, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 617, 617, 624, 624, 0, 624, 624, 624, 624, 624, + 624, 624, 624, 624, 624, 0, 624, 624, 0, 0, + 0, 0, 0, 624, 624, 624, 624, 0, 0, 0, + 0, 0, 0, 624, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 624, 624, + 624, 0, 0, 0, 0, 0, 0, 624, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 624, 624, 711, 0, 0, 711, 711, 0, + 0, 711, 711, 711, 711, 711, 712, 712, 712, 712, + + 712, 0, 712, 712, 712, 712, 712, 712, 712, 712, + 712, 713, 713, 713, 713, 713, 713, 713, 713, 713, + 713, 713, 713, 713, 713, 713, 714, 714, 714, 714, + 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, + 714, 715, 715, 715, 715, 715, 715, 715, 715, 715, + 715, 715, 715, 715, 715, 715, 716, 0, 0, 716, + 716, 716, 0, 716, 716, 716, 716, 716, 717, 717, + 717, 717, 717, 0, 717, 717, 717, 717, 717, 717, + 717, 717, 717, 718, 718, 718, 718, 718, 718, 718, + 718, 718, 718, 718, 718, 718, 718, 718, 719, 719, + + 0, 0, 0, 0, 0, 0, 0, 719, 719, 719, + 719, 719, 720, 720, 720, 720, 720, 720, 720, 720, + 720, 720, 720, 720, 720, 720, 720, 721, 721, 721, + 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, + 721, 721, 722, 722, 722, 722, 722, 722, 722, 722, + 722, 722, 722, 722, 722, 722, 722, 723, 723, 723, + 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, + 723, 723, 724, 724, 724, 724, 724, 724, 724, 724, + 724, 724, 724, 724, 724, 724, 724, 725, 725, 725, + 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, + + 725, 725, 726, 726, 726, 726, 726, 726, 726, 726, + 726, 726, 726, 726, 726, 726, 726, 727, 727, 727, + 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, + 727, 727, 728, 728, 0, 728, 728, 728, 728, 728, + 728, 728, 728, 728, 728, 728, 728, 729, 729, 0, + 729, 729, 729, 729, 729, 729, 729, 729, 729, 729, + 729, 729, 730, 730, 0, 730, 730, 730, 730, 730, + 730, 730, 730, 730, 730, 730, 730, 731, 731, 731, + 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, + 731, 731, 732, 732, 732, 732, 732, 732, 732, 732, + + 732, 732, 732, 732, 732, 732, 732, 733, 733, 733, + 733, 733, 733, 733, 733, 733, 733, 733, 733, 733, + 733, 733, 734, 734, 734, 734, 734, 734, 734, 734, + 734, 734, 734, 734, 734, 734, 734, 735, 0, 0, + 735, 0, 735, 735, 0, 0, 735, 735, 736, 736, + 736, 736, 736, 736, 736, 736, 736, 736, 736, 736, + 736, 736, 736, 737, 737, 737, 737, 737, 737, 737, + 737, 737, 737, 737, 737, 737, 737, 737, 738, 738, + 738, 738, 738, 738, 738, 738, 738, 738, 738, 738, + 738, 738, 738, 739, 739, 739, 739, 739, 739, 739, + + 739, 739, 739, 739, 739, 739, 739, 739, 740, 740, + 0, 740, 740, 740, 740, 740, 740, 740, 740, 740, + 740, 740, 740, 741, 741, 741, 741, 741, 741, 741, + 741, 741, 741, 741, 741, 741, 741, 741, 742, 742, + 742, 742, 0, 742, 742, 742, 742, 742, 742, 742, + 742, 742, 742, 743, 743, 743, 743, 743, 743, 743, + 743, 743, 743, 743, 743, 743, 743, 743, 744, 744, + 0, 744, 744, 744, 744, 744, 744, 744, 744, 744, + 744, 744, 744, 745, 745, 0, 745, 745, 745, 745, + 745, 745, 745, 745, 745, 745, 745, 745, 746, 0, + + 746, 0, 0, 0, 746, 746, 746, 747, 747, 0, + 747, 747, 747, 747, 747, 747, 747, 747, 747, 747, + 747, 747, 748, 748, 0, 748, 748, 748, 748, 748, + 748, 748, 748, 748, 748, 748, 748, 749, 749, 0, + 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, + 749, 749, 750, 750, 750, 750, 750, 750, 750, 750, + 750, 750, 750, 750, 750, 750, 750, 751, 751, 751, + 751, 751, 751, 751, 751, 751, 751, 751, 751, 751, + 751, 751, 752, 752, 752, 752, 752, 752, 752, 752, + 752, 752, 752, 752, 752, 752, 752, 753, 753, 753, + + 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, + 753, 753, 754, 0, 0, 0, 0, 754, 754, 0, + 0, 754, 754, 755, 755, 755, 755, 755, 755, 755, + 755, 755, 755, 755, 755, 755, 755, 755, 756, 756, + 756, 756, 756, 756, 756, 756, 756, 756, 756, 756, + 756, 756, 756, 757, 757, 0, 757, 757, 757, 757, + 757, 757, 757, 757, 757, 757, 757, 757, 758, 758, + 0, 758, 758, 758, 758, 758, 758, 758, 758, 758, + 758, 758, 758, 759, 759, 759, 759, 0, 759, 759, + 759, 759, 759, 759, 759, 759, 759, 759, 760, 760, + + 760, 760, 760, 760, 760, 760, 760, 760, 760, 760, + 760, 760, 760, 761, 761, 0, 761, 761, 761, 761, + 761, 761, 761, 761, 761, 761, 761, 761, 762, 762, + 0, 762, 762, 762, 762, 762, 762, 762, 762, 762, + 762, 762, 762, 763, 763, 0, 763, 763, 763, 763, + 763, 763, 763, 763, 763, 763, 763, 763, 764, 764, + 0, 764, 764, 764, 764, 764, 764, 764, 764, 764, + 764, 764, 764, 765, 765, 0, 765, 765, 765, 765, + 765, 765, 765, 765, 765, 765, 765, 765, 766, 766, + 0, 766, 766, 766, 766, 766, 766, 766, 766, 766, + + 766, 766, 766, 767, 767, 0, 767, 767, 767, 767, + 767, 767, 767, 767, 767, 767, 767, 767, 768, 768, + 0, 768, 768, 768, 768, 768, 768, 768, 768, 768, + 768, 768, 768, 769, 769, 769, 769, 769, 769, 769, + 769, 769, 769, 769, 769, 769, 769, 769, 770, 770, + 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, + 770, 770, 770, 771, 771, 771, 771, 771, 771, 771, + 771, 771, 771, 771, 771, 771, 771, 771, 772, 0, + 0, 0, 0, 772, 772, 0, 0, 772, 773, 773, + 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, + + 773, 773, 773, 774, 774, 774, 774, 774, 774, 774, + 774, 774, 774, 774, 774, 774, 774, 774, 775, 775, + 0, 775, 775, 775, 775, 775, 775, 775, 775, 775, + 775, 775, 775, 776, 776, 776, 776, 776, 776, 776, + 776, 776, 776, 776, 776, 776, 776, 776, 777, 0, + 0, 0, 0, 777, 777, 0, 0, 777, 778, 778, + 0, 778, 778, 778, 778, 778, 778, 778, 778, 778, + 778, 778, 778, 779, 779, 779, 779, 779, 779, 779, + 779, 779, 779, 779, 779, 779, 779, 779, 780, 780, + 0, 780, 780, 780, 780, 780, 780, 780, 780, 780, + + 780, 780, 780, 781, 781, 0, 781, 781, 781, 781, + 781, 781, 781, 781, 781, 781, 781, 781, 782, 782, + 0, 782, 782, 782, 782, 782, 782, 782, 782, 782, + 782, 782, 782, 783, 783, 783, 783, 783, 783, 783, + 783, 783, 783, 783, 783, 783, 783, 783, 784, 784, + 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, + 784, 784, 784, 785, 785, 785, 785, 785, 785, 785, + 785, 785, 785, 785, 785, 785, 785, 785, 786, 786, + 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, + 786, 786, 786, 710, 710, 710, 710, 710, 710, 710, + + 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, + 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, + 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, + 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, + 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, + 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, + 710, 710, 710, 710, 710, 710 + } ; + +static yy_state_type yy_state_buf[YY_BUF_SIZE + 2], *yy_state_ptr; +static char *yy_full_match; +static int yy_lp; +static int yy_looking_for_trail_begin = 0; +static int yy_full_lp; +static int *yy_full_state; +#define YY_TRAILING_MASK 0x2000 +#define YY_TRAILING_HEAD_MASK 0x4000 +#define REJECT \ +{ \ +*yy_cp = yy_hold_char; /* undo effects of setting up yytext */ \ +yy_cp = yy_full_match; /* restore poss. backed-over text */ \ +yy_lp = yy_full_lp; /* restore orig. accepting pos. */ \ +yy_state_ptr = yy_full_state; /* restore orig. state */ \ +yy_current_state = *yy_state_ptr; /* restore curr. state */ \ +++yy_lp; \ +goto find_rule; \ +} +#define yymore() yymore_used_but_not_detected +#define YY_MORE_ADJ 0 +#define YY_RESTORE_YY_MORE_OFFSET +char *yytext; +#define INITIAL 0 +/* + * parser.l -- lex parser of algebraic chess moves for XBoard + * $Id$ + * + * Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts. + * Enhancements Copyright 1992-95 Free Software Foundation, Inc. + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * ------------------------------------------------------------------------ + */ + +/* This parser handles all forms of promotion. + * The parser resolves ambiguous moves by searching and check-testing. + * It also parses comments of the form [anything] or (anything). + */ + +#include "config.h" + +#define NO_CONSTRAINT -1 +#undef YYLMAX +#define YYLMAX 4096 +#define UNPUT_BUF_SIZE YYLMAX + +#ifdef FLEX_SCANNER +/* yytext is probably a char*, but could be a char[]. yy_text is set + in YY_DECL below, because if yytext is a char*, its value is not + constant. */ +char *yy_text; +#else /*!FLEX_SCANNER*/ +/* yytext is definitely a char[], so yy_text can be set here, statically. */ +char *yy_text = (char *) yytext; +#endif + +#ifdef FLEX_SCANNER +/* This is flex */ +#undef YY_INPUT +#define YY_INPUT(buf, result, max_size) my_yy_input(buf, &result, max_size) +#undef YY_DECL +#define YY_DECL \ + int _yylex YY_PROTO((void)); \ + int yylex YY_PROTO((void)) \ + { \ + int result = _yylex(); \ + yy_text = (char *) yytext; \ + return(result); \ + } \ + int _yylex YY_PROTO((void)) +#else +/* This is lex */ +#undef input +#undef output +#undef unput +#endif + +/* The includes must be here, below the #undef input */ + +#include + +#if STDC_HEADERS +# include +# include +#else /* not STDC_HEADERS */ +# if HAVE_STRING_H +# include +# else /* not HAVE_STRING_H */ +# include +# endif /* not HAVE_STRING_H */ +#endif /* not STDC_HEADERS */ + +#if HAVE_UNISTD_H +# include +#endif + +#if defined(_amigados) +# include +# if HAVE_FCNTL_H +# include /* isatty() prototype */ +# endif /* HAVE_FCNTL_H */ +#endif /* defined(_amigados) */ + +#include "common.h" +#include "backend.h" +#include "frontend.h" +#include "parser.h" +#include "moves.h" + +extern int PosFlags P((int)); + +extern Board boards[MAX_MOVES]; +int yyboardindex; +int yyskipmoves = FALSE; +char currentMoveString[YYLMAX]; +#ifndef FLEX_SCANNER +char unputBuffer[UNPUT_BUF_SIZE]; +int unputCount = 0; +#endif + +#ifdef FLEX_SCANNER +void my_yy_input P((char *buf, int *result, int max_size)); +#else /*!FLEX_SCANNER*/ +static int input P((void)); +static void output P((int ch)); +static void unput P((int ch)); +int yylook P((void)); +int yyback P((int *, int)); +#endif +#undef yywrap +int yywrap P((void)); +extern void CopyBoard P((Board to, Board from)); + + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int yywrap YY_PROTO(( void )); +#else +extern int yywrap YY_PROTO(( void )); +#endif +#endif + +#ifndef YY_NO_UNPUT +static void yyunput YY_PROTO(( int c, char *buf_ptr )); +#endif + +#ifndef yytext_ptr +static void yy_flex_strncpy YY_PROTO(( char *, yyconst char *, int )); +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen YY_PROTO(( yyconst char * )); +#endif + +#ifndef YY_NO_INPUT +#ifdef __cplusplus +static int yyinput YY_PROTO(( void )); +#else +static int input YY_PROTO(( void )); +#endif +#endif + +#if YY_STACK_USED +static int yy_start_stack_ptr = 0; +static int yy_start_stack_depth = 0; +static int *yy_start_stack = 0; +#ifndef YY_NO_PUSH_STATE +static void yy_push_state YY_PROTO(( int new_state )); +#endif +#ifndef YY_NO_POP_STATE +static void yy_pop_state YY_PROTO(( void )); +#endif +#ifndef YY_NO_TOP_STATE +static int yy_top_state YY_PROTO(( void )); +#endif + +#else +#define YY_NO_PUSH_STATE 1 +#define YY_NO_POP_STATE 1 +#define YY_NO_TOP_STATE 1 +#endif + +#ifdef YY_MALLOC_DECL +YY_MALLOC_DECL +#else +#if __STDC__ +#ifndef __cplusplus +#include +#endif +#else +/* Just try to get by without declaring the routines. This will fail + * miserably on non-ANSI systems for which sizeof(size_t) != sizeof(int) + * or sizeof(void*) != sizeof(int). + */ +#endif +#endif + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#define YY_READ_BUF_SIZE 8192 +#endif + +/* Copy whatever the last rule matched to the standard output. */ + +#ifndef ECHO +/* This used to be an fputs(), but since the string might contain NUL's, + * we now use fwrite(). + */ +#define ECHO (void) fwrite( yytext, yyleng, 1, yyout ) +#endif + +/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, + * is returned in "result". + */ +#ifndef YY_INPUT +#define YY_INPUT(buf,result,max_size) \ + if ( yy_current_buffer->yy_is_interactive ) \ + { \ + int c = '*', n; \ + for ( n = 0; n < max_size && \ + (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ + buf[n] = (char) c; \ + if ( c == '\n' ) \ + buf[n++] = (char) c; \ + if ( c == EOF && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + result = n; \ + } \ + else if ( ((result = fread( buf, 1, max_size, yyin )) == 0) \ + && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); +#endif + +/* No semi-colon after return; correct usage is to write "yyterminate();" - + * we don't want an extra ';' after the "return" because that will cause + * some compilers to complain about unreachable statements. + */ +#ifndef yyterminate +#define yyterminate() return YY_NULL +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Report a fatal error. */ +#ifndef YY_FATAL_ERROR +#define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) +#endif + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL int yylex YY_PROTO(( void )) +#endif + +/* Code executed at the beginning of each rule, after yytext and yyleng + * have been set up. + */ +#ifndef YY_USER_ACTION +#define YY_USER_ACTION +#endif + +/* Code executed at the end of each rule. */ +#ifndef YY_BREAK +#define YY_BREAK break; +#endif + +#define YY_RULE_SETUP \ + if ( yyleng > 0 ) \ + yy_current_buffer->yy_at_bol = \ + (yytext[yyleng - 1] == '\n'); \ + YY_USER_ACTION + +YY_DECL + { + register yy_state_type yy_current_state; + register char *yy_cp, *yy_bp; + register int yy_act; + + + + + if ( yy_init ) + { + yy_init = 0; + +#ifdef YY_USER_INIT + YY_USER_INIT; +#endif + + if ( ! yy_start ) + yy_start = 1; /* first start state */ + + if ( ! yyin ) + yyin = stdin; + + if ( ! yyout ) + yyout = stdout; + + if ( ! yy_current_buffer ) + yy_current_buffer = + yy_create_buffer( yyin, YY_BUF_SIZE ); + + yy_load_buffer_state(); + } + + while ( 1 ) /* loops until end-of-file is reached */ + { + yy_cp = yy_c_buf_p; + + /* Support of yytext. */ + *yy_cp = yy_hold_char; + + /* yy_bp points to the position in yy_ch_buf of the start of + * the current run. + */ + yy_bp = yy_cp; + + yy_current_state = yy_start; + yy_current_state += YY_AT_BOL(); + yy_state_ptr = yy_state_buf; + *yy_state_ptr++ = yy_current_state; +yy_match: + do + { + register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 711 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + *yy_state_ptr++ = yy_current_state; + ++yy_cp; + } + while ( yy_base[yy_current_state] != 4394 ); + +yy_find_action: + yy_current_state = *--yy_state_ptr; + yy_lp = yy_accept[yy_current_state]; +find_rule: /* we branch to this label when backing up */ + for ( ; ; ) /* until we find what rule we matched */ + { + if ( yy_lp && yy_lp < yy_accept[yy_current_state + 1] ) + { + yy_act = yy_acclist[yy_lp]; + if ( yy_act & YY_TRAILING_HEAD_MASK || + yy_looking_for_trail_begin ) + { + if ( yy_act == yy_looking_for_trail_begin ) + { + yy_looking_for_trail_begin = 0; + yy_act &= ~YY_TRAILING_HEAD_MASK; + break; + } + } + else if ( yy_act & YY_TRAILING_MASK ) + { + yy_looking_for_trail_begin = yy_act & ~YY_TRAILING_MASK; + yy_looking_for_trail_begin |= YY_TRAILING_HEAD_MASK; + } + else + { + yy_full_match = yy_cp; + yy_full_state = yy_state_ptr; + yy_full_lp = yy_lp; + break; + } + ++yy_lp; + goto find_rule; + } + --yy_cp; + yy_current_state = *--yy_state_ptr; + yy_lp = yy_accept[yy_current_state]; + } + + YY_DO_BEFORE_ACTION; + + +do_action: /* This label is used only to access EOF actions. */ + + + switch ( yy_act ) + { /* beginning of action switch */ +case 1: +YY_RULE_SETUP +{ + /* + * Fully-qualified algebraic move, possibly with promotion + */ + int skip1 = 0, skip2 = 0; + ChessSquare piece; + ChessMove result; + + if (yyskipmoves) return (int) AmbiguousMove; /* not disambiguated */ + + /* remove the / */ + if (yytext[1] == '/') skip1 = 1; + + /* remove the [xX:-] */ + if ((yytext[3+skip1] == 'x') || (yytext[3+skip1] == 'X') || + (yytext[3+skip1] == '-') || (yytext[3+skip1] == ':')) skip2 = 1; + + currentMoveString[0] = yytext[1+skip1]; + currentMoveString[1] = yytext[2+skip1]; + currentMoveString[2] = yytext[3+skip1+skip2]; + currentMoveString[3] = yytext[4+skip1+skip2]; + currentMoveString[4] = NULLCHAR; + + if (yyleng-skip1-skip2 > 5) { + if (yytext[yyleng-1] == ')') { + currentMoveString[4] = ToLower(yytext[yyleng-2]); + } else { + currentMoveString[4] = ToLower(yytext[yyleng-1]); + } + currentMoveString[5] = NULLCHAR; + } + + piece = boards[yyboardindex] + [currentMoveString[1] - '1'][currentMoveString[0] - 'a']; + if (ToLower(yytext[0]) != ToLower(PieceToChar(piece))) + return (int) IllegalMove; + + result = LegalityTest(boards[yyboardindex], + PosFlags(yyboardindex), EP_UNKNOWN, + currentMoveString[1] - '1', + currentMoveString[0] - 'a', + currentMoveString[3] - '1', + currentMoveString[2] - 'a', + currentMoveString[4]); + + if (currentMoveString[4] == NULLCHAR && + (result == WhitePromotionQueen || result == BlackPromotionQueen)) { + currentMoveString[4] = 'q'; + currentMoveString[5] = NULLCHAR; + } + + return (int) result; +} + YY_BREAK +case 2: +YY_RULE_SETUP +{ + /* + * Simple algebraic move, possibly with promotion + */ + int skip = 0; + ChessMove result; + + if (yyskipmoves) return (int) AmbiguousMove; /* not disambiguated */ + + /* remove the [xX:-] */ + if ((yytext[2] == 'x') || (yytext[2] == 'X') || + (yytext[2] == '-') || (yytext[2] == ':')) skip = 1; + + currentMoveString[0] = yytext[0]; + currentMoveString[1] = yytext[1]; + currentMoveString[2] = yytext[2+skip]; + currentMoveString[3] = yytext[3+skip]; + currentMoveString[4] = NULLCHAR; + + if (yyleng-skip > 4) { + if (yytext[yyleng-1] == ')') { + currentMoveString[4] = ToLower(yytext[yyleng-2]); + } else { + currentMoveString[4] = ToLower(yytext[yyleng-1]); + } + currentMoveString[5] = NULLCHAR; + } + + result = LegalityTest(boards[yyboardindex], + PosFlags(yyboardindex), EP_UNKNOWN, + currentMoveString[1] - '1', + currentMoveString[0] - 'a', + currentMoveString[3] - '1', + currentMoveString[2] - 'a', + currentMoveString[4]); + + if (currentMoveString[4] == NULLCHAR && + (result == WhitePromotionQueen || result == BlackPromotionQueen)) { + currentMoveString[4] = 'q'; + currentMoveString[5] = NULLCHAR; + } + + return (int) result; +} + YY_BREAK +case 3: +YY_RULE_SETUP +{ + /* + * Pawn move, possibly with promotion + */ + DisambiguateClosure cl; + int skip = 0; + + if (yyskipmoves) return (int) AmbiguousMove; /* not disambiguated */ + + /* remove the =() */ + if (yytext[2] == '=') skip++; + if (yytext[2+skip] == '(') skip++; + + cl.pieceIn = WhiteOnMove(yyboardindex) ? WhitePawn : BlackPawn; + cl.rfIn = -1; + cl.ffIn = yytext[0] - 'a'; + cl.rtIn = yytext[1] - '1'; + cl.ftIn = yytext[0] - 'a'; + cl.promoCharIn = yytext[2+skip]; + Disambiguate(boards[yyboardindex], + PosFlags(yyboardindex), EP_UNKNOWN, &cl); + + currentMoveString[0] = cl.ff + 'a'; + currentMoveString[1] = cl.rf + '1'; + currentMoveString[2] = cl.ft + 'a'; + currentMoveString[3] = cl.rt + '1'; + currentMoveString[4] = cl.promoChar; + currentMoveString[5] = NULLCHAR; + + return (int) cl.kind; +} + YY_BREAK +case 4: +YY_RULE_SETUP +{ + /* + * Pawn capture, possibly with promotion, possibly ambiguous + */ + DisambiguateClosure cl; + int skip1 = 0, skip2 = 0; + + if (yyskipmoves) return (int) AmbiguousMove; /* not disambiguated */ + + /* remove trailing ep or e.p. (nonstandard PGN) */ + if (yytext[yyleng-1] == 'p') { + yyleng -= 2; + yytext[yyleng] = NULLCHAR; + } else if (yytext[yyleng-1] == '.') { + yyleng -= 4; + yytext[yyleng] = NULLCHAR; + } + + /* remove the [xX:-] and =() */ + if ((yytext[1] == 'x') || (yytext[1] == 'X') + || (yytext[1] == ':') || (yytext[1] == '-')) skip1 = 1; + if (yytext[2+skip1] == '=') skip2++; + if (yytext[2+skip1+skip2] == '(') skip2++; + + cl.pieceIn = WhiteOnMove(yyboardindex) ? WhitePawn : BlackPawn; + cl.rfIn = -1; + cl.ffIn = yytext[0] - 'a'; + cl.rtIn = -1; + cl.ftIn = yytext[1+skip1] - 'a'; + cl.promoCharIn = yytext[2+skip1+skip2]; + Disambiguate(boards[yyboardindex], + PosFlags(yyboardindex), EP_UNKNOWN, &cl); + + currentMoveString[0] = cl.ff + 'a'; + currentMoveString[1] = cl.rf + '1'; + currentMoveString[2] = cl.ft + 'a'; + currentMoveString[3] = cl.rt + '1'; + currentMoveString[4] = cl.promoChar; + currentMoveString[5] = NULLCHAR; + + return (int) cl.kind; +} + YY_BREAK +case 5: +YY_RULE_SETUP +{ + /* + * unambiguously abbreviated Pawn capture, possibly with promotion + */ + int skip = 0; + ChessMove result; + + if (yyskipmoves) return (int) AmbiguousMove; /* not disambiguated */ + + /* remove trailing ep or e.p. (nonstandard PGN) */ + if (yytext[yyleng-1] == 'p') { + yyleng -= 2; + yytext[yyleng] = NULLCHAR; + } else if (yytext[yyleng-1] == '.') { + yyleng -= 4; + yytext[yyleng] = NULLCHAR; + } + + /* remove the [xX:-] */ + if ((yytext[1] == 'x') || (yytext[1] == 'X') + || (yytext[1] == ':') || (yytext[1] == '-')) skip = 1; + + currentMoveString[0] = yytext[0]; + currentMoveString[2] = yytext[1+skip]; + currentMoveString[3] = yytext[2+skip]; + if (WhiteOnMove(yyboardindex)) { + if (yytext[2+skip] == '1') return (int) ImpossibleMove; + currentMoveString[1] = yytext[2+skip] - 1; + } else { + if (yytext[2+skip] == '8') return (int) ImpossibleMove; + currentMoveString[1] = yytext[2+skip] + 1; + } + if (yyleng-skip > 3) { + if (yytext[yyleng-1] == ')') + currentMoveString[4] = ToLower(yytext[yyleng-2]); + else + currentMoveString[4] = ToLower(yytext[yyleng-1]); + currentMoveString[5] = NULLCHAR; + } else { + currentMoveString[4] = NULLCHAR; + } + + result = LegalityTest(boards[yyboardindex], + PosFlags(yyboardindex), EP_UNKNOWN, + currentMoveString[1] - '1', + currentMoveString[0] - 'a', + currentMoveString[3] - '1', + currentMoveString[2] - 'a', + currentMoveString[4]); + + if (currentMoveString[4] == NULLCHAR && + (result == WhitePromotionQueen || result == BlackPromotionQueen)) { + currentMoveString[4] = 'q'; + currentMoveString[5] = NULLCHAR; + } + + if (result != IllegalMove) return (int) result; + + /* Special case: improperly written en passant capture */ + if (WhiteOnMove(yyboardindex)) { + if (currentMoveString[3] == '5') { + currentMoveString[1] = '5'; + currentMoveString[3] = '6'; + } else { + return (int) IllegalMove; + } + } else { + if (currentMoveString[3] == '4') { + currentMoveString[1] = '4'; + currentMoveString[3] = '3'; + } else { + return (int) IllegalMove; + } + } + + result = LegalityTest(boards[yyboardindex], + PosFlags(yyboardindex), EP_UNKNOWN, + currentMoveString[1] - '1', + currentMoveString[0] - 'a', + currentMoveString[3] - '1', + currentMoveString[2] - 'a', + currentMoveString[4]); + + if (result == WhiteCapturesEnPassant || result == BlackCapturesEnPassant) + return (int) result; + else + return (int) IllegalMove; +} + YY_BREAK +case 6: +YY_RULE_SETUP +{ + /* + * piece move, possibly ambiguous + */ + DisambiguateClosure cl; + int skip = 0; + + if (yyskipmoves) return (int) AmbiguousMove; /* not disambiguated */ + + /* remove the [xX:-] */ + if ((yytext[1] == 'x') || (yytext[1] == 'X') + || (yytext[1] == ':') || (yytext[1] == '-')) skip = 1; + + if (WhiteOnMove(yyboardindex)) { + cl.pieceIn = CharToPiece(ToUpper(yytext[0])); + } else { + cl.pieceIn = CharToPiece(ToLower(yytext[0])); + } + cl.rfIn = -1; + cl.ffIn = -1; + cl.rtIn = yytext[2+skip] - '1'; + cl.ftIn = yytext[1+skip] - 'a'; + cl.promoCharIn = NULLCHAR; + Disambiguate(boards[yyboardindex], + PosFlags(yyboardindex), EP_UNKNOWN, &cl); + + currentMoveString[0] = cl.ff + 'a'; + currentMoveString[1] = cl.rf + '1'; + currentMoveString[2] = cl.ft + 'a'; + currentMoveString[3] = cl.rt + '1'; + currentMoveString[4] = cl.promoChar; + currentMoveString[5] = NULLCHAR; + + return (int) cl.kind; +} + YY_BREAK +case 7: +YY_RULE_SETUP +{ + /* + * piece move with rank or file disambiguator + */ + DisambiguateClosure cl; + int skip = 0; + + if (yyskipmoves) return (int) AmbiguousMove; /* not disambiguated */ + + /* remove the [xX:-] */ + if ((yytext[2] == 'x') || (yytext[2] == 'X') + || (yytext[2] == ':') || (yytext[2] == '-')) skip = 1; + + if (WhiteOnMove(yyboardindex)) { + cl.pieceIn = CharToPiece(ToUpper(yytext[0])); + } else { + cl.pieceIn = CharToPiece(ToLower(yytext[0])); + } + if (isalpha(yytext[1])) { + cl.rfIn = -1; + cl.ffIn = yytext[1] - 'a'; + } else { + cl.rfIn = yytext[1] - '1'; + cl.ffIn = -1; + } + cl.rtIn = yytext[3+skip] - '1'; + cl.ftIn = yytext[2+skip] - 'a'; + cl.promoCharIn = NULLCHAR; + Disambiguate(boards[yyboardindex], + PosFlags(yyboardindex), EP_UNKNOWN, &cl); + + currentMoveString[0] = cl.ff + 'a'; + currentMoveString[1] = cl.rf + '1'; + currentMoveString[2] = cl.ft + 'a'; + currentMoveString[3] = cl.rt + '1'; + currentMoveString[4] = cl.promoChar; + currentMoveString[5] = NULLCHAR; + + return (int) cl.kind; +} + YY_BREAK +case 8: +YY_RULE_SETUP +{ + int rf, ff, rt, ft; + + if (yyskipmoves) return (int) AmbiguousMove; /* not disambiguated */ + + if (WhiteOnMove(yyboardindex)) { + if (boards[yyboardindex][0][3] == WhiteKing) { + /* ICS wild castling */ + strcpy(currentMoveString, "d1f1"); + rf = 0; + ff = 3; + rt = 0; + ft = 5; + } else { + strcpy(currentMoveString, "e1c1"); + rf = 0; + ff = 4; + rt = 0; + ft = 2; + } + } else{ + if (boards[yyboardindex][7][3] == BlackKing) { + /* ICS wild castling */ + strcpy(currentMoveString, "d8f8"); + rf = 7; + ff = 3; + rt = 7; + ft = 5; + } else { + strcpy(currentMoveString, "e8c8"); + rf = 7; + ff = 4; + rt = 7; + ft = 2; + } + } + return (int) LegalityTest(boards[yyboardindex], + PosFlags(yyboardindex), EP_UNKNOWN, + rf, ff, rt, ft, NULLCHAR); +} + YY_BREAK +case 9: +YY_RULE_SETUP +{ + int rf, ff, rt, ft; + + if (yyskipmoves) return (int) AmbiguousMove; /* not disambiguated */ + + if (WhiteOnMove(yyboardindex)) { + if (boards[yyboardindex][0][3] == WhiteKing) { + /* ICS wild castling */ + strcpy(currentMoveString, "d1b1"); + rf = 0; + ff = 3; + rt = 0; + ft = 1; + } else { + strcpy(currentMoveString, "e1g1"); + rf = 0; + ff = 4; + rt = 0; + ft = 6; + } + } else { + if (boards[yyboardindex][7][3] == BlackKing) { + /* ICS wild castling */ + strcpy(currentMoveString, "d8b8"); + rf = 7; + ff = 3; + rt = 7; + ft = 1; + } else { + strcpy(currentMoveString, "e8g8"); + rf = 7; + ff = 4; + rt = 7; + ft = 6; + } + } + return (int) LegalityTest(boards[yyboardindex], + PosFlags(yyboardindex), EP_UNKNOWN, + rf, ff, rt, ft, NULLCHAR); +} + YY_BREAK +case 10: +YY_RULE_SETUP +{ + /* Bughouse piece drop. No legality checking for now. */ + currentMoveString[1] = '@'; + currentMoveString[2] = yytext[2]; + currentMoveString[3] = yytext[3]; + currentMoveString[4] = NULLCHAR; + if (WhiteOnMove(yyboardindex)) { + currentMoveString[0] = ToUpper(yytext[0]); + return (int) WhiteDrop; + } else { + currentMoveString[0] = ToLower(yytext[0]); + return (int) BlackDrop; + } +} + YY_BREAK +case 11: +YY_RULE_SETUP +{ + if (WhiteOnMove(yyboardindex)) + return (int) BlackWins; + else + return (int) WhiteWins; +} + YY_BREAK +case 12: +YY_RULE_SETUP +{ + return (int) (ToUpper(yytext[0]) == 'W' ? BlackWins : WhiteWins); +} + YY_BREAK +case 13: +YY_RULE_SETUP +{ + return (int) GameUnfinished; +} + YY_BREAK +case 14: +YY_RULE_SETUP +{ + return (int) GameIsDrawn; +} + YY_BREAK +case 15: +YY_RULE_SETUP +{ + return (int) GameIsDrawn; +} + YY_BREAK +case 16: +YY_RULE_SETUP +{ + if (WhiteOnMove(yyboardindex)) + return (int) BlackWins; + else + return (int) WhiteWins; +} + YY_BREAK +case 17: +YY_RULE_SETUP +{ + if (WhiteOnMove(yyboardindex)) + return (int) BlackWins; + else + return (int) WhiteWins; +} + YY_BREAK +case 18: +YY_RULE_SETUP +{ + return (int) GameIsDrawn; +} + YY_BREAK +case 19: +YY_RULE_SETUP +{ + return (int) GameIsDrawn; +} + YY_BREAK +case 20: +YY_RULE_SETUP +{ + return (int) (ToUpper(yytext[0]) == 'W' ? WhiteWins : BlackWins); +} + YY_BREAK +case 21: +YY_RULE_SETUP +{ + return (int) (ToUpper(yytext[0]) == 'W' ? BlackWins : WhiteWins); +} + YY_BREAK +case 22: +YY_RULE_SETUP +{ + return (int) WhiteWins; +} + YY_BREAK +case 23: +YY_RULE_SETUP +{ + return (int) BlackWins; +} + YY_BREAK +case 24: +YY_RULE_SETUP +{ + return (int) GameIsDrawn; +} + YY_BREAK +case 25: +YY_RULE_SETUP +{ + return (int) GameUnfinished; +} + YY_BREAK +case 26: +YY_RULE_SETUP +{ + /* move numbers */ + if ((yyleng == 1) && (yytext[0] == '1')) + return (int) MoveNumberOne; +} + YY_BREAK +case 27: +YY_RULE_SETUP +{ + /* elapsed time indication, e.g. (0:12) or {10:21.071} */ + return (int) ElapsedTime; +} + YY_BREAK +case 28: +YY_RULE_SETUP +{ + /* position diagram enclosed in [-- --] */ + return (int) PositionDiagram; +} + YY_BREAK +case 29: +*yy_cp = yy_hold_char; /* undo effects of setting up yytext */ +yy_c_buf_p = yy_cp -= 1; +YY_DO_BEFORE_ACTION; /* set up yytext again */ +YY_RULE_SETUP +{ + /* position diagram enclosed in {-- --} */ + return (int) PositionDiagram; +} + YY_BREAK +case 30: +YY_RULE_SETUP +{ + return (int) PGNTag; +} + YY_BREAK +case 31: +YY_RULE_SETUP +{ + return (int) GNUChessGame; +} + YY_BREAK +case 32: +*yy_cp = yy_hold_char; /* undo effects of setting up yytext */ +yy_c_buf_p = yy_cp -= 1; +YY_DO_BEFORE_ACTION; /* set up yytext again */ +YY_RULE_SETUP +{ + return (int) XBoardGame; +} + YY_BREAK +case 33: +YY_RULE_SETUP +{ /* numeric annotation glyph */ + return (int) NAG; +} + YY_BREAK +case 34: +YY_RULE_SETUP +{ /* anything in {} */ + return (int) Comment; +} + YY_BREAK +case 35: +*yy_cp = yy_hold_char; /* undo effects of setting up yytext */ +yy_c_buf_p = yy_cp -= 1; +YY_DO_BEFORE_ACTION; /* set up yytext again */ +YY_RULE_SETUP +{ /* ; to end of line */ + return (int) Comment; +} + YY_BREAK +case 36: +YY_RULE_SETUP +{ /* anything in [] */ + return (int) Comment; +} + YY_BREAK +case 37: +YY_RULE_SETUP +{ /* nested () */ + return (int) Comment; +} + YY_BREAK +case 38: +YY_RULE_SETUP +{ /* >=2 chars in () */ + return (int) Comment; +} + YY_BREAK +case 39: +YY_RULE_SETUP +{ + /* Skip mail headers */ +} + YY_BREAK +case 40: +YY_RULE_SETUP +{ + /* Skip random words */ +} + YY_BREAK +case 41: +YY_RULE_SETUP +{ + /* Skip everything else */ +} + YY_BREAK +case 42: +YY_RULE_SETUP +ECHO; + YY_BREAK + case YY_STATE_EOF(INITIAL): + yyterminate(); + + case YY_END_OF_BUFFER: + { + /* Amount of text matched not including the EOB char. */ + int yy_amount_of_matched_text = (int) (yy_cp - yytext_ptr) - 1; + + /* Undo the effects of YY_DO_BEFORE_ACTION. */ + *yy_cp = yy_hold_char; + YY_RESTORE_YY_MORE_OFFSET + + if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_NEW ) + { + /* We're scanning a new file or input source. It's + * possible that this happened because the user + * just pointed yyin at a new source and called + * yylex(). If so, then we have to assure + * consistency between yy_current_buffer and our + * globals. Here is the right place to do so, because + * this is the first action (other than possibly a + * back-up) that will match for the new input source. + */ + yy_n_chars = yy_current_buffer->yy_n_chars; + yy_current_buffer->yy_input_file = yyin; + yy_current_buffer->yy_buffer_status = YY_BUFFER_NORMAL; + } + + /* Note that here we test for yy_c_buf_p "<=" to the position + * of the first EOB in the buffer, since yy_c_buf_p will + * already have been incremented past the NUL character + * (since all states make transitions on EOB to the + * end-of-buffer state). Contrast this with the test + * in input(). + */ + if ( yy_c_buf_p <= &yy_current_buffer->yy_ch_buf[yy_n_chars] ) + { /* This was really a NUL. */ + yy_state_type yy_next_state; + + yy_c_buf_p = yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state(); + + /* Okay, we're now positioned to make the NUL + * transition. We couldn't have + * yy_get_previous_state() go ahead and do it + * for us because it doesn't know how to deal + * with the possibility of jamming (and we don't + * want to build jamming into it because then it + * will run more slowly). + */ + + yy_next_state = yy_try_NUL_trans( yy_current_state ); + + yy_bp = yytext_ptr + YY_MORE_ADJ; + + if ( yy_next_state ) + { + /* Consume the NUL. */ + yy_cp = ++yy_c_buf_p; + yy_current_state = yy_next_state; + goto yy_match; + } + + else + { + yy_cp = yy_c_buf_p; + goto yy_find_action; + } + } + + else switch ( yy_get_next_buffer() ) + { + case EOB_ACT_END_OF_FILE: + { + yy_did_buffer_switch_on_eof = 0; + + if ( yywrap() ) + { + /* Note: because we've taken care in + * yy_get_next_buffer() to have set up + * yytext, we can now set up + * yy_c_buf_p so that if some total + * hoser (like flex itself) wants to + * call the scanner after we return the + * YY_NULL, it'll still work - another + * YY_NULL will get returned. + */ + yy_c_buf_p = yytext_ptr + YY_MORE_ADJ; + + yy_act = YY_STATE_EOF(YY_START); + goto do_action; + } + + else + { + if ( ! yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; + } + break; + } + + case EOB_ACT_CONTINUE_SCAN: + yy_c_buf_p = + yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state(); + + yy_cp = yy_c_buf_p; + yy_bp = yytext_ptr + YY_MORE_ADJ; + goto yy_match; + + case EOB_ACT_LAST_MATCH: + yy_c_buf_p = + &yy_current_buffer->yy_ch_buf[yy_n_chars]; + + yy_current_state = yy_get_previous_state(); + + yy_cp = yy_c_buf_p; + yy_bp = yytext_ptr + YY_MORE_ADJ; + goto yy_find_action; + } + break; + } + + default: + YY_FATAL_ERROR( + "fatal flex scanner internal error--no action found" ); + } /* end of action switch */ + } /* end of scanning one token */ + } /* end of yylex */ + + +/* yy_get_next_buffer - try to read in a new buffer + * + * Returns a code representing an action: + * EOB_ACT_LAST_MATCH - + * EOB_ACT_CONTINUE_SCAN - continue scanning from current position + * EOB_ACT_END_OF_FILE - end of file + */ + +static int yy_get_next_buffer() + { + register char *dest = yy_current_buffer->yy_ch_buf; + register char *source = yytext_ptr; + register int number_to_move, i; + int ret_val; + + if ( yy_c_buf_p > &yy_current_buffer->yy_ch_buf[yy_n_chars + 1] ) + YY_FATAL_ERROR( + "fatal flex scanner internal error--end of buffer missed" ); + + if ( yy_current_buffer->yy_fill_buffer == 0 ) + { /* Don't try to fill the buffer, so this is an EOF. */ + if ( yy_c_buf_p - yytext_ptr - YY_MORE_ADJ == 1 ) + { + /* We matched a single character, the EOB, so + * treat this as a final EOF. + */ + return EOB_ACT_END_OF_FILE; + } + + else + { + /* We matched some text prior to the EOB, first + * process it. + */ + return EOB_ACT_LAST_MATCH; + } + } + + /* Try to read more data. */ + + /* First move last chars to start of buffer. */ + number_to_move = (int) (yy_c_buf_p - yytext_ptr) - 1; + + for ( i = 0; i < number_to_move; ++i ) + *(dest++) = *(source++); + + if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_EOF_PENDING ) + /* don't do the read, it's not guaranteed to return an EOF, + * just force an EOF + */ + yy_current_buffer->yy_n_chars = yy_n_chars = 0; + + else + { + int num_to_read = + yy_current_buffer->yy_buf_size - number_to_move - 1; + + while ( num_to_read <= 0 ) + { /* Not enough room in the buffer - grow it. */ +#ifdef YY_USES_REJECT + YY_FATAL_ERROR( +"input buffer overflow, can't enlarge buffer because scanner uses REJECT" ); +#else + + /* just a shorter name for the current buffer */ + YY_BUFFER_STATE b = yy_current_buffer; + + int yy_c_buf_p_offset = + (int) (yy_c_buf_p - b->yy_ch_buf); + + if ( b->yy_is_our_buffer ) + { + int new_size = b->yy_buf_size * 2; + + if ( new_size <= 0 ) + b->yy_buf_size += b->yy_buf_size / 8; + else + b->yy_buf_size *= 2; + + b->yy_ch_buf = (char *) + /* Include room in for 2 EOB chars. */ + yy_flex_realloc( (void *) b->yy_ch_buf, + b->yy_buf_size + 2 ); + } + else + /* Can't grow it, we don't own it. */ + b->yy_ch_buf = 0; + + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( + "fatal error - scanner input buffer overflow" ); + + yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset]; + + num_to_read = yy_current_buffer->yy_buf_size - + number_to_move - 1; +#endif + } + + if ( num_to_read > YY_READ_BUF_SIZE ) + num_to_read = YY_READ_BUF_SIZE; + + /* Read in more data. */ + YY_INPUT( (&yy_current_buffer->yy_ch_buf[number_to_move]), + yy_n_chars, num_to_read ); + + yy_current_buffer->yy_n_chars = yy_n_chars; + } + + if ( yy_n_chars == 0 ) + { + if ( number_to_move == YY_MORE_ADJ ) + { + ret_val = EOB_ACT_END_OF_FILE; + yyrestart( yyin ); + } + + else + { + ret_val = EOB_ACT_LAST_MATCH; + yy_current_buffer->yy_buffer_status = + YY_BUFFER_EOF_PENDING; + } + } + + else + ret_val = EOB_ACT_CONTINUE_SCAN; + + yy_n_chars += number_to_move; + yy_current_buffer->yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR; + yy_current_buffer->yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR; + + yytext_ptr = &yy_current_buffer->yy_ch_buf[0]; + + return ret_val; + } + + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + +static yy_state_type yy_get_previous_state() + { + register yy_state_type yy_current_state; + register char *yy_cp; + + yy_current_state = yy_start; + yy_current_state += YY_AT_BOL(); + yy_state_ptr = yy_state_buf; + *yy_state_ptr++ = yy_current_state; + + for ( yy_cp = yytext_ptr + YY_MORE_ADJ; yy_cp < yy_c_buf_p; ++yy_cp ) + { + register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 711 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + *yy_state_ptr++ = yy_current_state; + } + + return yy_current_state; + } + + +/* yy_try_NUL_trans - try to make a transition on the NUL character + * + * synopsis + * next_state = yy_try_NUL_trans( current_state ); + */ + +#ifdef YY_USE_PROTOS +static yy_state_type yy_try_NUL_trans( yy_state_type yy_current_state ) +#else +static yy_state_type yy_try_NUL_trans( yy_current_state ) +yy_state_type yy_current_state; +#endif + { + register int yy_is_jam; + + register YY_CHAR yy_c = 1; + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 711 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + yy_is_jam = (yy_current_state == 710); + if ( ! yy_is_jam ) + *yy_state_ptr++ = yy_current_state; + + return yy_is_jam ? 0 : yy_current_state; + } + + +#ifndef YY_NO_UNPUT +#ifdef YY_USE_PROTOS +static void yyunput( int c, register char *yy_bp ) +#else +static void yyunput( c, yy_bp ) +int c; +register char *yy_bp; +#endif + { + register char *yy_cp = yy_c_buf_p; + + /* undo effects of setting up yytext */ + *yy_cp = yy_hold_char; + + if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) + { /* need to shift things up to make room */ + /* +2 for EOB chars. */ + register int number_to_move = yy_n_chars + 2; + register char *dest = &yy_current_buffer->yy_ch_buf[ + yy_current_buffer->yy_buf_size + 2]; + register char *source = + &yy_current_buffer->yy_ch_buf[number_to_move]; + + while ( source > yy_current_buffer->yy_ch_buf ) + *--dest = *--source; + + yy_cp += (int) (dest - source); + yy_bp += (int) (dest - source); + yy_current_buffer->yy_n_chars = + yy_n_chars = yy_current_buffer->yy_buf_size; + + if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) + YY_FATAL_ERROR( "flex scanner push-back overflow" ); + } + + *--yy_cp = (char) c; + + + yytext_ptr = yy_bp; + yy_hold_char = *yy_cp; + yy_c_buf_p = yy_cp; + } +#endif /* ifndef YY_NO_UNPUT */ + + +#ifdef __cplusplus +static int yyinput() +#else +static int input() +#endif + { + int c; + + *yy_c_buf_p = yy_hold_char; + + if ( *yy_c_buf_p == YY_END_OF_BUFFER_CHAR ) + { + /* yy_c_buf_p now points to the character we want to return. + * If this occurs *before* the EOB characters, then it's a + * valid NUL; if not, then we've hit the end of the buffer. + */ + if ( yy_c_buf_p < &yy_current_buffer->yy_ch_buf[yy_n_chars] ) + /* This was really a NUL. */ + *yy_c_buf_p = '\0'; + + else + { /* need more input */ + int offset = yy_c_buf_p - yytext_ptr; + ++yy_c_buf_p; + + switch ( yy_get_next_buffer() ) + { + case EOB_ACT_LAST_MATCH: + /* This happens because yy_g_n_b() + * sees that we've accumulated a + * token and flags that we need to + * try matching the token before + * proceeding. But for input(), + * there's no matching to consider. + * So convert the EOB_ACT_LAST_MATCH + * to EOB_ACT_END_OF_FILE. + */ + + /* Reset buffer status. */ + yyrestart( yyin ); + + /* fall through */ + + case EOB_ACT_END_OF_FILE: + { + if ( yywrap() ) + return EOF; + + if ( ! yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; +#ifdef __cplusplus + return yyinput(); +#else + return input(); +#endif + } + + case EOB_ACT_CONTINUE_SCAN: + yy_c_buf_p = yytext_ptr + offset; + break; + } + } + } + + c = *(unsigned char *) yy_c_buf_p; /* cast for 8-bit char's */ + *yy_c_buf_p = '\0'; /* preserve yytext */ + yy_hold_char = *++yy_c_buf_p; + + yy_current_buffer->yy_at_bol = (c == '\n'); + + return c; + } + + +#ifdef YY_USE_PROTOS +void yyrestart( FILE *input_file ) +#else +void yyrestart( input_file ) +FILE *input_file; +#endif + { + if ( ! yy_current_buffer ) + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); + + yy_init_buffer( yy_current_buffer, input_file ); + yy_load_buffer_state(); + } + + +#ifdef YY_USE_PROTOS +void yy_switch_to_buffer( YY_BUFFER_STATE new_buffer ) +#else +void yy_switch_to_buffer( new_buffer ) +YY_BUFFER_STATE new_buffer; +#endif + { + if ( yy_current_buffer == new_buffer ) + return; + + if ( yy_current_buffer ) + { + /* Flush out information for old buffer. */ + *yy_c_buf_p = yy_hold_char; + yy_current_buffer->yy_buf_pos = yy_c_buf_p; + yy_current_buffer->yy_n_chars = yy_n_chars; + } + + yy_current_buffer = new_buffer; + yy_load_buffer_state(); + + /* We don't actually know whether we did this switch during + * EOF (yywrap()) processing, but the only time this flag + * is looked at is after yywrap() is called, so it's safe + * to go ahead and always set it. + */ + yy_did_buffer_switch_on_eof = 1; + } + + +#ifdef YY_USE_PROTOS +void yy_load_buffer_state( void ) +#else +void yy_load_buffer_state() +#endif + { + yy_n_chars = yy_current_buffer->yy_n_chars; + yytext_ptr = yy_c_buf_p = yy_current_buffer->yy_buf_pos; + yyin = yy_current_buffer->yy_input_file; + yy_hold_char = *yy_c_buf_p; + } + + +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_create_buffer( FILE *file, int size ) +#else +YY_BUFFER_STATE yy_create_buffer( file, size ) +FILE *file; +int size; +#endif + { + YY_BUFFER_STATE b; + + b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_buf_size = size; + + /* yy_ch_buf has to be 2 characters longer than the size given because + * we need to put in 2 end-of-buffer characters. + */ + b->yy_ch_buf = (char *) yy_flex_alloc( b->yy_buf_size + 2 ); + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_is_our_buffer = 1; + + yy_init_buffer( b, file ); + + return b; + } + + +#ifdef YY_USE_PROTOS +void yy_delete_buffer( YY_BUFFER_STATE b ) +#else +void yy_delete_buffer( b ) +YY_BUFFER_STATE b; +#endif + { + if ( ! b ) + return; + + if ( b == yy_current_buffer ) + yy_current_buffer = (YY_BUFFER_STATE) 0; + + if ( b->yy_is_our_buffer ) + yy_flex_free( (void *) b->yy_ch_buf ); + + yy_flex_free( (void *) b ); + } + + +#ifndef YY_ALWAYS_INTERACTIVE +#ifndef YY_NEVER_INTERACTIVE +extern int isatty YY_PROTO(( int )); +#endif +#endif + +#ifdef YY_USE_PROTOS +void yy_init_buffer( YY_BUFFER_STATE b, FILE *file ) +#else +void yy_init_buffer( b, file ) +YY_BUFFER_STATE b; +FILE *file; +#endif + + + { + yy_flush_buffer( b ); + + b->yy_input_file = file; + b->yy_fill_buffer = 1; + +#if YY_ALWAYS_INTERACTIVE + b->yy_is_interactive = 1; +#else +#if YY_NEVER_INTERACTIVE + b->yy_is_interactive = 0; +#else + b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; +#endif +#endif + } + + +#ifdef YY_USE_PROTOS +void yy_flush_buffer( YY_BUFFER_STATE b ) +#else +void yy_flush_buffer( b ) +YY_BUFFER_STATE b; +#endif + + { + if ( ! b ) + return; + + b->yy_n_chars = 0; + + /* We always need two end-of-buffer characters. The first causes + * a transition to the end-of-buffer state. The second causes + * a jam in that state. + */ + b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; + b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; + + b->yy_buf_pos = &b->yy_ch_buf[0]; + + b->yy_at_bol = 1; + b->yy_buffer_status = YY_BUFFER_NEW; + + if ( b == yy_current_buffer ) + yy_load_buffer_state(); + } + + +#ifndef YY_NO_SCAN_BUFFER +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_buffer( char *base, yy_size_t size ) +#else +YY_BUFFER_STATE yy_scan_buffer( base, size ) +char *base; +yy_size_t size; +#endif + { + YY_BUFFER_STATE b; + + if ( size < 2 || + base[size-2] != YY_END_OF_BUFFER_CHAR || + base[size-1] != YY_END_OF_BUFFER_CHAR ) + /* They forgot to leave room for the EOB's. */ + return 0; + + b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); + + b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ + b->yy_buf_pos = b->yy_ch_buf = base; + b->yy_is_our_buffer = 0; + b->yy_input_file = 0; + b->yy_n_chars = b->yy_buf_size; + b->yy_is_interactive = 0; + b->yy_at_bol = 1; + b->yy_fill_buffer = 0; + b->yy_buffer_status = YY_BUFFER_NEW; + + yy_switch_to_buffer( b ); + + return b; + } +#endif + + +#ifndef YY_NO_SCAN_STRING +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_string( yyconst char *yy_str ) +#else +YY_BUFFER_STATE yy_scan_string( yy_str ) +yyconst char *yy_str; +#endif + { + int len; + for ( len = 0; yy_str[len]; ++len ) + ; + + return yy_scan_bytes( yy_str, len ); + } +#endif + + +#ifndef YY_NO_SCAN_BYTES +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_bytes( yyconst char *bytes, int len ) +#else +YY_BUFFER_STATE yy_scan_bytes( bytes, len ) +yyconst char *bytes; +int len; +#endif + { + YY_BUFFER_STATE b; + char *buf; + yy_size_t n; + int i; + + /* Get memory for full buffer, including space for trailing EOB's. */ + n = len + 2; + buf = (char *) yy_flex_alloc( n ); + if ( ! buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); + + for ( i = 0; i < len; ++i ) + buf[i] = bytes[i]; + + buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR; + + b = yy_scan_buffer( buf, n ); + if ( ! b ) + YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); + + /* It's okay to grow etc. this buffer, and we should throw it + * away when we're done. + */ + b->yy_is_our_buffer = 1; + + return b; + } +#endif + + +#ifndef YY_NO_PUSH_STATE +#ifdef YY_USE_PROTOS +static void yy_push_state( int new_state ) +#else +static void yy_push_state( new_state ) +int new_state; +#endif + { + if ( yy_start_stack_ptr >= yy_start_stack_depth ) + { + yy_size_t new_size; + + yy_start_stack_depth += YY_START_STACK_INCR; + new_size = yy_start_stack_depth * sizeof( int ); + + if ( ! yy_start_stack ) + yy_start_stack = (int *) yy_flex_alloc( new_size ); + + else + yy_start_stack = (int *) yy_flex_realloc( + (void *) yy_start_stack, new_size ); + + if ( ! yy_start_stack ) + YY_FATAL_ERROR( + "out of memory expanding start-condition stack" ); + } + + yy_start_stack[yy_start_stack_ptr++] = YY_START; + + BEGIN(new_state); + } +#endif + + +#ifndef YY_NO_POP_STATE +static void yy_pop_state() + { + if ( --yy_start_stack_ptr < 0 ) + YY_FATAL_ERROR( "start-condition stack underflow" ); + + BEGIN(yy_start_stack[yy_start_stack_ptr]); + } +#endif + + +#ifndef YY_NO_TOP_STATE +static int yy_top_state() + { + return yy_start_stack[yy_start_stack_ptr - 1]; + } +#endif + +#ifndef YY_EXIT_FAILURE +#define YY_EXIT_FAILURE 2 +#endif + +#ifdef YY_USE_PROTOS +static void yy_fatal_error( yyconst char msg[] ) +#else +static void yy_fatal_error( msg ) +char msg[]; +#endif + { + (void) fprintf( stderr, "%s\n", msg ); + exit( YY_EXIT_FAILURE ); + } + + + +/* Redefine yyless() so it works in section 3 code. */ + +#undef yyless +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + yytext[yyleng] = yy_hold_char; \ + yy_c_buf_p = yytext + n; \ + yy_hold_char = *yy_c_buf_p; \ + *yy_c_buf_p = '\0'; \ + yyleng = n; \ + } \ + while ( 0 ) + + +/* Internal utility routines. */ + +#ifndef yytext_ptr +#ifdef YY_USE_PROTOS +static void yy_flex_strncpy( char *s1, yyconst char *s2, int n ) +#else +static void yy_flex_strncpy( s1, s2, n ) +char *s1; +yyconst char *s2; +int n; +#endif + { + register int i; + for ( i = 0; i < n; ++i ) + s1[i] = s2[i]; + } +#endif + +#ifdef YY_NEED_STRLEN +#ifdef YY_USE_PROTOS +static int yy_flex_strlen( yyconst char *s ) +#else +static int yy_flex_strlen( s ) +yyconst char *s; +#endif + { + register int n; + for ( n = 0; s[n]; ++n ) + ; + + return n; + } +#endif + + +#ifdef YY_USE_PROTOS +static void *yy_flex_alloc( yy_size_t size ) +#else +static void *yy_flex_alloc( size ) +yy_size_t size; +#endif + { + return (void *) malloc( size ); + } + +#ifdef YY_USE_PROTOS +static void *yy_flex_realloc( void *ptr, yy_size_t size ) +#else +static void *yy_flex_realloc( ptr, size ) +void *ptr; +yy_size_t size; +#endif + { + /* The cast to (char *) in the following accommodates both + * implementations that use char* generic pointers, and those + * that use void* generic pointers. It works with the latter + * because both ANSI C and C++ allow castless assignment from + * any pointer type to void*, and deal with argument conversions + * as though doing an assignment. + */ + return (void *) realloc( (char *) ptr, size ); + } + +#ifdef YY_USE_PROTOS +static void yy_flex_free( void *ptr ) +#else +static void yy_flex_free( ptr ) +void *ptr; +#endif + { + free( ptr ); + } + +#if YY_MAIN +int main() + { + yylex(); + return 0; + } +#endif + + + +static char *StringToLex; + +#ifndef FLEX_SCANNER +static FILE *lexFP; + +static int input() +{ + int ret; + + if (StringToLex != NULL) { + ret = *StringToLex; + if (ret == NULLCHAR) + ret = EOF; + else + StringToLex++; + } else if (unputCount > 0) { + ret = unputBuffer[--unputCount]; + } else { + ret = fgetc(lexFP); + } + + if (ret == EOF) + return 0; + else + return ret; +} + +/* + * Return offset of next pattern within current file + */ +int yyoffset() +{ + int offset = ftell(lexFP) - unputCount; + + if (offset < 0) { + offset = 0; + } + return(offset); +} + +static void output(ch) + int ch; +{ + fprintf(stderr, "PARSER BUG: unmatched character '%c' (0%o)\n", + ch, ch); +} + +static void unput(ch) + int ch; +{ + if (ch == 0) return; + if (StringToLex != NULL) { + StringToLex--; + } else { + if (unputCount >= UNPUT_BUF_SIZE) + fprintf(stderr, "PARSER BUG: unput buffer overflow '%c' (0%o)\n", + ch, ch); + unputBuffer[unputCount++] = ch; + } +} + +/* Get ready to lex from a new file. Kludge below sticks + an artificial newline at the front of the file, which the + above grammar ignores, but which makes ^ at start of pattern + match at the real start of the file. +*/ +void yynewfile(f) + FILE *f; +{ + lexFP = f; + StringToLex = NULL; + unputCount = 0; + unput('\n'); /* kludge */ +} + +/* Get ready to lex from a string. ^ at start of pattern WON'T + match at the start of the string! +*/ +void yynewstr(s) + char *s; +{ + lexFP = NULL; + StringToLex = s; + unputCount = 0; +} +#endif /*!FLEX_SCANNER*/ + +#ifdef FLEX_SCANNER +void my_yy_input(buf, result, max_size) + char *buf; + int *result; + int max_size; +{ + int count; + + if (StringToLex != NULL) { + count = 0; + while (*StringToLex != NULLCHAR) { + *buf++ = *StringToLex++; + count++; + } + *result = count; + return; + } else { + count = fread(buf, 1, max_size, yyin); + if (count == 0) { + *result = YY_NULL; + } else { + *result = count; + } + return; + } +} + +static YY_BUFFER_STATE my_file_buffer = NULL; + +/* + Return offset of next pattern in the current file. +*/ +int yyoffset() +{ + int pos = yy_c_buf_p - yy_current_buffer->yy_ch_buf; + + return(ftell(yy_current_buffer->yy_input_file) - + yy_n_chars + pos); +} + + +void yynewstr(s) + char *s; +{ + if (my_file_buffer != NULL) + yy_delete_buffer(my_file_buffer); + StringToLex = s; + my_file_buffer = yy_create_buffer(stdin, YY_BUF_SIZE); + yy_switch_to_buffer(my_file_buffer); +} + +void yynewfile(f) + FILE *f; +{ + if (my_file_buffer != NULL) + yy_delete_buffer(my_file_buffer); + StringToLex = NULL; + my_file_buffer = yy_create_buffer(f, YY_BUF_SIZE); + yy_switch_to_buffer(my_file_buffer); +} +#endif /*FLEX_SCANNER*/ + +int yywrap() +{ + return TRUE; +} + +/* Parse a move from the given string s */ +/* ^ at start of pattern WON'T work here unless using flex */ +ChessMove yylexstr(boardIndex, s) + int boardIndex; + char *s; +{ + ChessMove ret; + char *oldStringToLex; +#ifdef FLEX_SCANNER + YY_BUFFER_STATE buffer, oldBuffer; +#endif + + yyboardindex = boardIndex; + oldStringToLex = StringToLex; + StringToLex = s; +#ifdef FLEX_SCANNER + buffer = yy_create_buffer(stdin, YY_BUF_SIZE); + oldBuffer = YY_CURRENT_BUFFER; + yy_switch_to_buffer(buffer); +#endif /*FLEX_SCANNER*/ + + ret = (ChessMove) yylex(); + +#ifdef FLEX_SCANNER + if (oldBuffer != NULL) + yy_switch_to_buffer(oldBuffer); + yy_delete_buffer(buffer); +#endif /*FLEX_SCANNER*/ + StringToLex = oldStringToLex; + + return ret; +} diff --git a/winboard-dm-beta4/parser.h b/winboard-dm-beta4/parser.h new file mode 100755 index 0000000..dfc257a --- /dev/null +++ b/winboard-dm-beta4/parser.h @@ -0,0 +1,59 @@ +/* + * parser.h -- Interface to XBoard move parser + * $Id$ + * + * Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts. + * Enhancements Copyright 1992-95 Free Software Foundation, Inc. + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * ------------------------------------------------------------------------ + */ + +extern void yynewfile P((FILE *f)); +extern void yynewstr P((char *s)); +extern int yylex P((void)); +extern ChessMove yylexstr P((int boardIndex, char *s)); +extern char currentMoveString[]; +extern int yyboardindex; +extern int yyskipmoves; /* If TRUE, all moves are reported as AmbiguousMove + instead of being disambiguated. */ +extern char *yy_text; /* Needed because yytext can be either a char[] + or a (non-constant) char* */ +extern int yyoffset P((void)); diff --git a/winboard-dm-beta4/pgntags.c b/winboard-dm-beta4/pgntags.c new file mode 100755 index 0000000..8a1f6b5 --- /dev/null +++ b/winboard-dm-beta4/pgntags.c @@ -0,0 +1,262 @@ +/* + * pgntags.c -- Functions to manage PGN tags + * XBoard $Id$ + * + * Copyright 1995 Free Software Foundation, Inc. + * + * ------------------------------------------------------------------------ + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA. + * ------------------------------------------------------------------------ + * + * This file could well be a part of backend.c, but I prefer it this + * way. + */ + +#include "config.h" + +#include +#include +#include +#if STDC_HEADERS +# include +# include +#else /* not STDC_HEADERS */ +# if HAVE_STRING_H +# include +# else /* not HAVE_STRING_H */ +# include +# endif /* not HAVE_STRING_H */ +#endif /* not STDC_HEADERS */ + +#include "common.h" +#include "frontend.h" +#include "backend.h" +#include "parser.h" + +static char *PGNTagsStatic P((GameInfo *)); + + + +/* Parse PGN tags; returns 0 for success or error number + */ +int ParsePGNTag(tag, gameInfo) + char *tag; + GameInfo *gameInfo; +{ + char *name, *value, *p, *oldTags; + int len; + int success; + + name = tag; + while (!isalpha(*name) && !isdigit(*name)) { + name++; + } + p = name; + while (*p != ' ' && *p != '\t' && *p != '\n') { + p++; + } + *p = NULLCHAR; + value = strchr(p + 1, '"') + 1; + p = strrchr(value, '"'); + *p = NULLCHAR; + + if (StrCaseCmp(name, "Event") == 0) { + success = StrSavePtr(value, &gameInfo->event) != NULL; + } else if (StrCaseCmp(name, "Site") == 0) { + success = StrSavePtr(value, &gameInfo->site) != NULL; + } else if (StrCaseCmp(name, "Date") == 0) { + success = StrSavePtr(value, &gameInfo->date) != NULL; + } else if (StrCaseCmp(name, "Round") == 0) { + success = StrSavePtr(value, &gameInfo->round) != NULL; + } else if (StrCaseCmp(name, "White") == 0) { + success = StrSavePtr(value, &gameInfo->white) != NULL; + } else if (StrCaseCmp(name, "Black") == 0) { + success = StrSavePtr(value, &gameInfo->black) != NULL; + } + /* Fold together the various ways of denoting White/Black rating */ + else if ((StrCaseCmp(name, "WhiteElo")==0) || + (StrCaseCmp(name, "WhiteUSCF")==0) ) { + success = TRUE; + gameInfo->whiteRating = atoi( value ); + } else if ((StrCaseCmp(name, "BlackElo")==0) || + (StrCaseCmp(name, "BlackUSCF")==0)) { + success = TRUE; + gameInfo->blackRating = atoi( value ); + } + else if (StrCaseCmp(name, "Result") == 0) { + if (strcmp(value, "1-0") == 0) + gameInfo->result = WhiteWins; + else if (strcmp(value, "0-1") == 0) + gameInfo->result = BlackWins; + else if (strcmp(value, "1/2-1/2") == 0) + gameInfo->result = GameIsDrawn; + else + gameInfo->result = GameUnfinished; + success = TRUE; + } else if (StrCaseCmp(name, "FEN") == 0) { + success = StrSavePtr(value, &gameInfo->fen) != NULL; + } else if (StrCaseCmp(name, "SetUp") == 0) { + /* ignore on input; presence of FEN governs */ + success = TRUE; + } else if (StrCaseCmp(name, "Variant") == 0) { + /* xboard-defined extension */ + gameInfo->variant = StringToVariant(value); + success = TRUE; + } else { + if (gameInfo->extraTags == NULL) { + oldTags = ""; + } else { + oldTags = gameInfo->extraTags; + } + /* Buffer size includes 7 bytes of space for [ ""]\n\0 */ + len = strlen(oldTags) + strlen(value) + strlen(name) + 7; + if ((p = (char *) malloc(len)) != NULL) { + sprintf(p, "%s[%s \"%s\"]\n", oldTags, name, value); + if (gameInfo->extraTags != NULL) free(gameInfo->extraTags); + gameInfo->extraTags = p; + success = TRUE; + } else { + success = FALSE; + } + } + return(success ? 0 : ENOMEM); +} + + + +/* Return a static buffer with a game's data. + */ +static char *PGNTagsStatic(gameInfo) + GameInfo *gameInfo; +{ + static char buf[8192]; + char buf1[MSG_SIZ]; + + buf[0] = NULLCHAR; + + sprintf(buf1, "[Event \"%s\"]\n", + gameInfo->event ? gameInfo->event : "?"); + strcat(buf, buf1); + sprintf(buf1, "[Site \"%s\"]\n", + gameInfo->site ? gameInfo->site : "?"); + strcat(buf, buf1); + sprintf(buf1, "[Date \"%s\"]\n", + gameInfo->date ? gameInfo->date : "?"); + strcat(buf, buf1); + sprintf(buf1, "[Round \"%s\"]\n", + gameInfo->round ? gameInfo->round : "-"); + strcat(buf, buf1); + sprintf(buf1, "[White \"%s\"]\n", + gameInfo->white ? gameInfo->white : "?"); + strcat(buf, buf1); + sprintf(buf1, "[Black \"%s\"]\n", + gameInfo->black ? gameInfo->black : "?"); + strcat(buf, buf1); + sprintf(buf1, "[Result \"%s\"]\n", PGNResult(gameInfo->result)); + strcat(buf, buf1); + + if (gameInfo->whiteRating >= 0 ) { + sprintf(buf1, "[WhiteElo \"%d\"]\n", gameInfo->whiteRating ); + strcat(buf, buf1); + } + if ( gameInfo->blackRating >= 0 ) { + sprintf(buf1, "[BlackElo \"%d\"]\n", gameInfo->blackRating ); + strcat(buf, buf1); + } + if (gameInfo->timeControl != NULL) { + sprintf(buf1, "[TimeControl \"%s\"]\n", gameInfo->timeControl); + strcat(buf, buf1); + } + if (gameInfo->variant != VariantNormal) { + sprintf(buf1, "[Variant \"%s\"]\n", VariantName(gameInfo->variant)); + strcat(buf, buf1); + } + if (gameInfo->extraTags != NULL) { + strcat(buf, gameInfo->extraTags); + } + return buf; +} + + + +/* Print game info + */ +void PrintPGNTags(fp, gameInfo) + FILE *fp; + GameInfo *gameInfo; +{ + fprintf(fp, "%s", PGNTagsStatic(gameInfo)); +} + + +/* Return a non-static buffer with a games info. + */ +char *PGNTags(gameInfo) + GameInfo *gameInfo; +{ + return StrSave(PGNTagsStatic(gameInfo)); +} + + +/* Returns pointer to a static string with a result. + */ +char *PGNResult(result) + ChessMove result; +{ + switch (result) { + case GameUnfinished: + default: + return "*"; + case WhiteWins: + return "1-0"; + case BlackWins: + return "0-1"; + case GameIsDrawn: + return "1/2-1/2"; + } +} + +/* Returns 0 for success, nonzero for error */ +int +ReplaceTags(tags, gameInfo) + char *tags; + GameInfo *gameInfo; +{ + ChessMove moveType; + int err; + + ClearGameInfo(gameInfo); + yynewstr(tags); + for (;;) { + yyboardindex = 0; + moveType = (ChessMove) yylex(); + if (moveType == (ChessMove) 0) { + break; + } else if (moveType == PGNTag) { + err = ParsePGNTag(yy_text, gameInfo); + if (err != 0) return err; + } + } + /* just one problem...if there is a result in the new tags, + * DisplayMove() won't ever show it because ClearGameInfo() set + * gameInfo->resultDetails to NULL. So we must plug something in if there + * is a result. + */ + if (gameInfo->result != GameUnfinished) { + if (gameInfo->resultDetails) free(gameInfo->resultDetails); + gameInfo->resultDetails = strdup(""); + } + return 0; +} diff --git a/winboard-dm-beta4/wclipbrd.c b/winboard-dm-beta4/wclipbrd.c new file mode 100755 index 0000000..85e91f9 --- /dev/null +++ b/winboard-dm-beta4/wclipbrd.c @@ -0,0 +1,320 @@ +/* + * wclipbrd.c -- Clipboard routines for WinBoard + * $Id$ + * + * Copyright 2000 Free Software Foundation, Inc. + * + * ------------------------------------------------------------------------ + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * ------------------------------------------------------------------------ + */ + +#include "config.h" + +#include /* required for all Windows applications */ +#include +#include +#include +#include +#include + +#include "common.h" +#include "winboard.h" +#include "frontend.h" +#include "backend.h" +#include "wclipbrd.h" + +/* Imports from winboard.c */ +extern HWND hwndMain; + +/* File globals */ +static char *copyTemp; +static char *pasteTemp; + +VOID +CopyFENToClipboard() +{ + char *fen = NULL; + + fen = PositionToFEN(currentMove); + if (!fen) { + DisplayError("Unable to convert position to FEN.", 0); + return; + } + if (!CopyTextToClipboard(fen)) + DisplayError("Unable to copy FEN to clipboard.", 0); + free(fen); +} + + +VOID +CopyGameToClipboard() +{ + /* A rather cheesy hack here. Write the game to a file, then read from the + * file into the clipboard. + */ + char *buf = NULL; + FILE *f; + unsigned long size; + size_t len; + struct stat st; + + if (!copyTemp) { + copyTemp = tmpnam(NULL); + } + if (!copyTemp) { + DisplayError("Cannot create temporary file name.",0); + return; + } + f = fopen(copyTemp, "w"); + if (!f) { + DisplayError("Cannot open temporary file.", 0); + return; + } + if (!SaveGame(f,0,"")) { /* call into backend */ + DisplayError("Cannot write to temporary file.", 0); + goto copy_game_to_clipboard_cleanup; + } + f = fopen(copyTemp, "rb"); + if (!f) { + DisplayError("Cannot reopen temporary file.", 0); + goto copy_game_to_clipboard_cleanup; + } + if (fstat(fileno(f), &st) < 0) { + DisplayError("Cannot determine size of file.", 0); + goto copy_game_to_clipboard_cleanup; + } + size = st.st_size; + if (size == -1) { + DisplayError("Cannot determine size of file.", 0); + goto copy_game_to_clipboard_cleanup; + } + rewind(f); + buf = (char*)malloc(size+1); + if (!buf) { + DisplayError("Cannot allocate clipboard buffer.", 0); + goto copy_game_to_clipboard_cleanup; + } + len = fread(buf, sizeof(char), size, f); + if (len == -1) { + DisplayError("Cannot read from temporary file.", 0); + goto copy_game_to_clipboard_cleanup; + } + if ((unsigned long)size != (unsigned long)len) { /* sigh */ + DisplayError("Error reading from temporary file.", 0); + goto copy_game_to_clipboard_cleanup; + } + buf[size] = 0; + if (!CopyTextToClipboard(buf)) { + DisplayError("Cannot copy text to clipboard", 0); + } + +copy_game_to_clipboard_cleanup: + if (buf) free(buf); + if (f) fclose(f); +} + + +int +CopyTextToClipboard(char *text) +{ + /* some (most?) of the error checking may be overkill, + * but hey, this is Windows + */ + HGLOBAL hGlobalMem; + LPVOID lpGlobalMem; + BOOL locked; + UINT lockCount; + DWORD err; + + hGlobalMem = GlobalAlloc(GHND, (DWORD)lstrlen(text)+1); + if (hGlobalMem == NULL) { + DisplayError("Unable to allocate memory for clipboard.", 0); + return FALSE; + } + lpGlobalMem = GlobalLock(hGlobalMem); + if (lpGlobalMem == NULL) { + DisplayError("Unable to lock clipboard memory.", 0); + GlobalFree(hGlobalMem); + return FALSE; + } + lstrcpy(lpGlobalMem, text); + if (appData.debugMode) { + lockCount = GlobalFlags(hGlobalMem) & GMEM_LOCKCOUNT; + fprintf(debugFP, "CopyTextToClipboard(): lock count %d\n", lockCount); + } + SetLastError(NO_ERROR); + locked = GlobalUnlock(hGlobalMem); + err = GetLastError(); + if (appData.debugMode) { + lockCount = GlobalFlags(hGlobalMem) & GMEM_LOCKCOUNT; + fprintf(debugFP, "CopyTextToClipboard(): lock count %d\n", lockCount); + } + if (!locked) { + locked = !((err == NO_ERROR) || (err == ERROR_NOT_LOCKED)); + if (appData.debugMode) { + fprintf(debugFP, + "CopyTextToClipboard(): err %d locked %d\n", err, locked); + } + } + if (locked) { + DisplayError("Cannot unlock clipboard memory.", 0); + GlobalFree(hGlobalMem); + return FALSE; + } + if (!OpenClipboard(hwndMain)) { + DisplayError("Cannot open clipboard.", 0); + GlobalFree(hGlobalMem); + return FALSE; + } + if (!EmptyClipboard()) { + DisplayError("Cannot empty clipboard.", 0); + return FALSE; + } + if (hGlobalMem != SetClipboardData(CF_TEXT, hGlobalMem)) { + DisplayError("Cannot copy text to clipboard.", 0); + CloseClipboard(); + GlobalFree(hGlobalMem); + return FALSE; + } + if (!CloseClipboard()) + DisplayError("Cannot close clipboard.", 0); + + return TRUE; +} + + + +VOID +PasteFENFromClipboard() +{ + char *fen = NULL; + if (!PasteTextFromClipboard(&fen)) { + DisplayError("Unable to paste FEN from clipboard.", 0); + return; + } + if (appData.debugMode) { + fprintf(debugFP, "PasteFenFromClipboard(): fen '%s'\n", fen); + } + EditPositionPasteFEN(fen); /* call into backend */ + free(fen); +} + + +VOID +PasteGameFromClipboard() +{ + /* Write the clipboard to a temp file, then let LoadGameFromFile() + * do all the work. */ + char *buf; + FILE *f; + size_t len; + if (!PasteTextFromClipboard(&buf)) { + return; + } + if (!pasteTemp) { + pasteTemp = tmpnam(NULL); + } + f = fopen(pasteTemp, "wb+"); + if (!f) { + DisplayError("Unable to create temporary file.", 0); + return; + } + len = fwrite(buf, sizeof(char), strlen(buf), f); + fclose(f); + if (len != strlen(buf)) { + DisplayError("Error writing to temporary file.", 0); + return; + } + LoadGameFromFile(pasteTemp, 0, "Clipboard", TRUE); +} + + +int +PasteTextFromClipboard(char **text) +{ + /* some (most?) of the error checking may be overkill, + * but hey, this is Windows + */ + HANDLE hClipMem; + LPVOID lpClipMem; + BOOL locked = FALSE; + DWORD err; + UINT lockCount; + + if (!OpenClipboard(hwndMain)) { + DisplayError("Unable to open clipboard.", 0); + return FALSE; + } + hClipMem = GetClipboardData(CF_TEXT); + if (hClipMem == NULL) { + CloseClipboard(); + DisplayError("No text in clipboard.", 0); + return FALSE; + } + lpClipMem = GlobalLock(hClipMem); + if (lpClipMem == NULL) { + CloseClipboard(); + DisplayError("Unable to lock clipboard memory.", 0); + return FALSE; + } + *text = (char *) malloc(GlobalSize(hClipMem)+1); + if (!*text) { + DisplayError("Unable to allocate memory for text string.", 0); + CloseClipboard(); + return FALSE; + } + lstrcpy(*text, lpClipMem); + if (appData.debugMode) { + lockCount = GlobalFlags(hClipMem) & GMEM_LOCKCOUNT; + fprintf(debugFP, "PasteTextFromClipboard(): lock count %d\n", lockCount); + } + SetLastError(NO_ERROR); +#if 1 + /*suggested by Wilkin Ng*/ + lockCount = GlobalFlags(hClipMem) & GMEM_LOCKCOUNT; + if (lockCount) { + locked = GlobalUnlock(hClipMem); + } +#else + locked = GlobalUnlock(hClipMem); +#endif + err = GetLastError(); + if (appData.debugMode) { + lockCount = GlobalFlags(hClipMem) & GMEM_LOCKCOUNT; + fprintf(debugFP, "PasteTextFromClipboard(): lock count %d\n", lockCount); + } + if (!locked) { + locked = !((err == NO_ERROR) || (err == ERROR_NOT_LOCKED)); + if (appData.debugMode) { + fprintf(debugFP, + "PasteTextFromClipboard(): err %d locked %d\n", err, locked); + } + } + if (locked) + DisplayError("Unable to unlock clipboard memory.", 0); + + if (!CloseClipboard()) + DisplayError("Unable to close clipboard.", 0); + + return TRUE; +} + +VOID +DeleteClipboardTempFiles() +{ + if (copyTemp) remove(copyTemp); + if (pasteTemp) remove(pasteTemp); +} diff --git a/winboard-dm-beta4/wclipbrd.h b/winboard-dm-beta4/wclipbrd.h new file mode 100755 index 0000000..010166e --- /dev/null +++ b/winboard-dm-beta4/wclipbrd.h @@ -0,0 +1,32 @@ +/* + * wclipbrd.c -- Clipboard routines for WinBoard + * $Id$ + * + * Copyright 2000 Free Software Foundation, Inc. + * + * ------------------------------------------------------------------------ + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * ------------------------------------------------------------------------ + */ + +VOID CopyFENToClipboard(); +VOID CopyGameToClipboard(); +int CopyTextToClipboard(char *text); + +VOID PasteFENFromClipboard(); +VOID PasteGameFromClipboard(); +int PasteTextFromClipboard(char **text); + +VOID DeleteClipboardTempFiles(); diff --git a/winboard-dm-beta4/wedittags.c b/winboard-dm-beta4/wedittags.c new file mode 100755 index 0000000..5730f6b --- /dev/null +++ b/winboard-dm-beta4/wedittags.c @@ -0,0 +1,234 @@ +/* + * wedittags.c -- EditTags window for WinBoard + * $Id$ + * + * Copyright 1995 Free Software Foundation, Inc. + * + * ------------------------------------------------------------------------ + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * ------------------------------------------------------------------------ + */ + +#include "config.h" + +#include /* required for all Windows applications */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common.h" +#include "winboard.h" +#include "frontend.h" +#include "backend.h" + +/* Module globals */ +static char *editTagsText; +HWND editTagsDialog = NULL; +BOOL editTagsUp = FALSE; +BOOL canEditTags = FALSE; +int editTagsX, editTagsY, editTagsW, editTagsH; + +/* Imports from winboard.c */ +extern HINSTANCE hInst; +extern HWND hwndMain; +extern BoardSize boardSize; + +LRESULT CALLBACK +EditTagsDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + static HANDLE hwndText; + static int sizeX, sizeY; + int len, newSizeX, newSizeY, flags; + char *str; + RECT rect; + MINMAXINFO *mmi; + int err; + + switch (message) { + case WM_INITDIALOG: /* message: initialize dialog box */ + /* Initialize the dialog items */ + hwndText = GetDlgItem(hDlg, OPT_TagsText); + SendMessage(hwndText, WM_SETFONT, + (WPARAM)font[boardSize][EDITTAGS_FONT]->hf, MAKELPARAM(FALSE, 0)); + SetDlgItemText(hDlg, OPT_TagsText, editTagsText); + EnableWindow(GetDlgItem(hDlg, OPT_TagsCancel), canEditTags); + EnableWindow(GetDlgItem(hDlg, OPT_EditTags), !canEditTags); + SendMessage(hwndText, EM_SETREADONLY, !canEditTags, 0); + if (canEditTags) { + SetWindowText(hDlg, "Edit Tags"); + SetFocus(hwndText); + } else { + SetWindowText(hDlg, "Tags"); + SetFocus(GetDlgItem(hDlg, IDOK)); + } + if (!editTagsDialog) { + editTagsDialog = hDlg; + flags = SWP_NOZORDER; + GetClientRect(hDlg, &rect); + sizeX = rect.right; + sizeY = rect.bottom; + if (editTagsX != CW_USEDEFAULT && editTagsY != CW_USEDEFAULT && + editTagsW != CW_USEDEFAULT && editTagsH != CW_USEDEFAULT) { + WINDOWPLACEMENT wp; + EnsureOnScreen(&editTagsX, &editTagsY); + wp.length = sizeof(WINDOWPLACEMENT); + wp.flags = 0; + wp.showCmd = SW_SHOW; + wp.ptMaxPosition.x = wp.ptMaxPosition.y = 0; + wp.rcNormalPosition.left = editTagsX; + wp.rcNormalPosition.right = editTagsX + editTagsW; + wp.rcNormalPosition.top = editTagsY; + wp.rcNormalPosition.bottom = editTagsY + editTagsH; + SetWindowPlacement(hDlg, &wp); + + GetClientRect(hDlg, &rect); + newSizeX = rect.right; + newSizeY = rect.bottom; + ResizeEditPlusButtons(hDlg, hwndText, sizeX, sizeY, + newSizeX, newSizeY); + sizeX = newSizeX; + sizeY = newSizeY; + } + } + return FALSE; + + case WM_COMMAND: + switch (LOWORD(wParam)) { + case IDOK: + if (canEditTags) { + char *p, *q; + /* Read changed options from the dialog box */ + len = GetWindowTextLength(hwndText); + str = (char *) malloc(len + 1); + GetWindowText(hwndText, str, len + 1); + p = q = str; + while (*q) { + if (*q == '\r'|| *q == '\n') + q++; + else + *p++ = *q++; + } + *p = NULLCHAR; + err = ReplaceTags(str, &gameInfo); + if (err) DisplayError("Error replacing tags.", err); + + free(str); + } + TagsPopDown(); + return TRUE; + + case IDCANCEL: + case OPT_TagsCancel: + TagsPopDown(); + return TRUE; + + case OPT_EditTags: + EditTagsEvent(); + return TRUE; + + default: + break; + } + break; + + case WM_SIZE: + newSizeX = LOWORD(lParam); + newSizeY = HIWORD(lParam); + ResizeEditPlusButtons(hDlg, hwndText, sizeX, sizeY, newSizeX, newSizeY); + sizeX = newSizeX; + sizeY = newSizeY; + break; + + case WM_GETMINMAXINFO: + /* Prevent resizing window too small */ + mmi = (MINMAXINFO *) lParam; + mmi->ptMinTrackSize.x = 100; + mmi->ptMinTrackSize.y = 100; + break; + } + return FALSE; +} + +VOID TagsPopDown(void) +{ + if (editTagsDialog) ShowWindow(editTagsDialog, SW_HIDE); + CheckMenuItem(GetMenu(hwndMain), IDM_EditTags, MF_UNCHECKED); + editTagsUp = FALSE; +} + + +VOID EitherTagsPopUp(char *tags, char *msg, BOOLEAN edit) +{ + FARPROC lpProc; + char *p, *q; + + if (msg == NULL) msg = ""; + p = (char *) malloc(2 * (strlen(tags) + strlen(msg)) + 2); + q = p; + while (*tags) { + if (*tags == '\n') *q++ = '\r'; + *q++ = *tags++; + } + if (*msg != NULLCHAR) { + *q++ = '\r'; + *q++ = '\n'; + while (*msg) { + if (*msg == '\n') *q++ = '\r'; + *q++ = *msg++; + } + } + *q = NULLCHAR; + if (editTagsText != NULL) free(editTagsText); + editTagsText = p; + canEditTags = edit; + + CheckMenuItem(GetMenu(hwndMain), IDM_EditTags, MF_CHECKED); + if (editTagsDialog) { + SendMessage(editTagsDialog, WM_INITDIALOG, 0, 0); + ShowWindow(editTagsDialog, SW_SHOW); + } else { + lpProc = MakeProcInstance((FARPROC)EditTagsDialog, hInst); + CreateDialog(hInst, MAKEINTRESOURCE(DLG_EditTags), + hwndMain, (DLGPROC)lpProc); + FreeProcInstance(lpProc); + } + editTagsUp = TRUE; +} + +VOID TagsPopUp(char *tags, char *msg) +{ + HWND hwnd = GetActiveWindow(); + EitherTagsPopUp(tags, msg, FALSE); + SetActiveWindow(hwnd); +} + +VOID EditTagsPopUp(char *tags) +{ + EitherTagsPopUp(tags, "", TRUE); +} + +VOID EditTagsProc() +{ + if (editTagsUp) { + TagsPopDown(); + } else { + EditTagsEvent(); + } +} diff --git a/winboard-dm-beta4/wedittags.h b/winboard-dm-beta4/wedittags.h new file mode 100755 index 0000000..45e3359 --- /dev/null +++ b/winboard-dm-beta4/wedittags.h @@ -0,0 +1,27 @@ +/* + * wedittags.h -- EditTags window for WinBoard + * $Id$ + * + * Copyright 1995 Free Software Foundation, Inc. + * + * ------------------------------------------------------------------------ + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * ------------------------------------------------------------------------ + */ + +VOID EditTagsProc(void); +extern HWND editTagsDialog; +extern int editTagsX, editTagsY, editTagsW, editTagsH; + diff --git a/winboard-dm-beta4/wgamelist.c b/winboard-dm-beta4/wgamelist.c new file mode 100755 index 0000000..4abca99 --- /dev/null +++ b/winboard-dm-beta4/wgamelist.c @@ -0,0 +1,250 @@ +/* + * wgamelist.c -- Game list window for WinBoard + * $Id$ + * + * Copyright 1995 Free Software Foundation, Inc. + * + * ------------------------------------------------------------------------ + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * ------------------------------------------------------------------------ + */ + +#include "config.h" + +#include /* required for all Windows applications */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common.h" +#include "winboard.h" +#include "frontend.h" +#include "backend.h" + +/* Module globals */ +HWND gameListDialog = NULL; +BOOLEAN gameListUp = FALSE; +FILE* gameFile; +char* gameFileName = NULL; +int gameListX, gameListY, gameListW, gameListH; + +/* Imports from winboard.c */ +extern HINSTANCE hInst; +extern HWND hwndMain; + + +LRESULT CALLBACK +GameListDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + static HANDLE hwndText; + int nItem; + ListGame *lg; + RECT rect; + static int sizeX, sizeY; + int newSizeX, newSizeY, flags; + MINMAXINFO *mmi; + + switch (message) { + case WM_INITDIALOG: + if (gameListDialog) { + SendDlgItemMessage(hDlg, OPT_GameListText, LB_RESETCONTENT, 0, 0); + } + /* Initialize the dialog items */ + hwndText = GetDlgItem(hDlg, OPT_TagsText); + lg = (ListGame *) gameList.head; + for (nItem = 0; nItem < ((ListGame *) gameList.tailPred)->number; nItem++){ + char *st = GameListLine(lg->number, &lg->gameInfo); + SendDlgItemMessage(hDlg, OPT_GameListText, LB_ADDSTRING, 0, (LPARAM) st); + free(st); + lg = (ListGame *) lg->node.succ; + } + SendDlgItemMessage(hDlg, OPT_GameListText, LB_SETCURSEL, 0, 0); + /* Size and position the dialog */ + if (!gameListDialog) { + gameListDialog = hDlg; + flags = SWP_NOZORDER; + GetClientRect(hDlg, &rect); + sizeX = rect.right; + sizeY = rect.bottom; + if (gameListX != CW_USEDEFAULT && gameListY != CW_USEDEFAULT && + gameListW != CW_USEDEFAULT && gameListH != CW_USEDEFAULT) { + WINDOWPLACEMENT wp; + EnsureOnScreen(&gameListX, &gameListY); + wp.length = sizeof(WINDOWPLACEMENT); + wp.flags = 0; + wp.showCmd = SW_SHOW; + wp.ptMaxPosition.x = wp.ptMaxPosition.y = 0; + wp.rcNormalPosition.left = gameListX; + wp.rcNormalPosition.right = gameListX + gameListW; + wp.rcNormalPosition.top = gameListY; + wp.rcNormalPosition.bottom = gameListY + gameListH; + SetWindowPlacement(hDlg, &wp); + + GetClientRect(hDlg, &rect); + newSizeX = rect.right; + newSizeY = rect.bottom; + ResizeEditPlusButtons(hDlg, hwndText, sizeX, sizeY, + newSizeX, newSizeY); + sizeX = newSizeX; + sizeY = newSizeY; + } + } + return FALSE; + + case WM_SIZE: + newSizeX = LOWORD(lParam); + newSizeY = HIWORD(lParam); + ResizeEditPlusButtons(hDlg, GetDlgItem(hDlg, OPT_GameListText), + sizeX, sizeY, newSizeX, newSizeY); + sizeX = newSizeX; + sizeY = newSizeY; + break; + + case WM_GETMINMAXINFO: + /* Prevent resizing window too small */ + mmi = (MINMAXINFO *) lParam; + mmi->ptMinTrackSize.x = 100; + mmi->ptMinTrackSize.y = 100; + break; + + case WM_COMMAND: + switch (LOWORD(wParam)) { + case IDOK: + case OPT_GameListLoad: + nItem = SendDlgItemMessage(hDlg, OPT_GameListText, LB_GETCURSEL, 0, 0); + if (nItem < 0) { + /* is this possible? */ + DisplayError("No game selected", 0); + return TRUE; + } + break; /* load the game*/ + + case OPT_GameListNext: + nItem = SendDlgItemMessage(hDlg, OPT_GameListText, LB_GETCURSEL, 0, 0); + nItem++; + if (nItem >= ((ListGame *) gameList.tailPred)->number) { + DisplayError("Can't go forward any further", 0); + return TRUE; + } + SendDlgItemMessage(hDlg, OPT_GameListText, LB_SETCURSEL, nItem, 0); + break; /* load the game*/ + + case OPT_GameListPrev: + nItem = SendDlgItemMessage(hDlg, OPT_GameListText, LB_GETCURSEL, 0, 0); + nItem--; + if (nItem < 0) { + DisplayError("Can't back up any further", 0); + } + SendDlgItemMessage(hDlg, OPT_GameListText, LB_SETCURSEL, nItem, 0); + break; /* load the game*/ + + case IDCANCEL: + case OPT_GameListClose: + GameListPopDown(); + return TRUE; + + case OPT_GameListText: + switch (HIWORD(wParam)) { + case LBN_DBLCLK: + nItem = SendMessage((HWND) lParam, LB_GETCURSEL, 0, 0); + break; /* load the game*/ + + default: + return FALSE; + } + break; + + default: + return FALSE; + } + /* Load the game */ + if (cmailMsgLoaded) { + CmailLoadGame(gameFile, nItem + 1, gameFileName, TRUE); + } else { + LoadGame(gameFile, nItem + 1, gameFileName, TRUE); + } + return TRUE; + + default: + break; + } + return FALSE; +} + + +VOID GameListPopUp(FILE *fp, char *filename) +{ + FARPROC lpProc; + + gameFile = fp; + if (gameFileName != filename) { + if (gameFileName) free(gameFileName); + gameFileName = StrSave(filename); + } + CheckMenuItem(GetMenu(hwndMain), IDM_ShowGameList, MF_CHECKED); + if (gameListDialog) { + SendMessage(gameListDialog, WM_INITDIALOG, 0, 0); + if (!gameListUp) ShowWindow(gameListDialog, SW_SHOW); + } else { + lpProc = MakeProcInstance((FARPROC)GameListDialog, hInst); + CreateDialog(hInst, MAKEINTRESOURCE(DLG_GameList), + hwndMain, (DLGPROC)lpProc); + FreeProcInstance(lpProc); + } + gameListUp = TRUE; +} + +VOID GameListPopDown(void) +{ + CheckMenuItem(GetMenu(hwndMain), IDM_ShowGameList, MF_UNCHECKED); + if (gameListDialog) ShowWindow(gameListDialog, SW_HIDE); + gameListUp = FALSE; +} + + +VOID GameListHighlight(int index) +{ + if (gameListDialog == NULL) return; + SendDlgItemMessage(gameListDialog, OPT_GameListText, + LB_SETCURSEL, index - 1, 0); +} + + +VOID GameListDestroy() +{ + GameListPopDown(); + if (gameFileName) { + free(gameFileName); + gameFileName = NULL; + } +} + +VOID ShowGameListProc() +{ + if (gameListUp) { + GameListPopDown(); + } else { + if (gameFileName) { + GameListPopUp(gameFile, gameFileName); + } else { + DisplayError("No game list", 0); + } + } +} diff --git a/winboard-dm-beta4/winboard.c b/winboard-dm-beta4/winboard.c new file mode 100755 index 0000000..c0f7a0c --- /dev/null +++ b/winboard-dm-beta4/winboard.c @@ -0,0 +1,8401 @@ +/* + * 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 +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Need for Shell */ +#include + +#if __GNUC__ +#include +#include +#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" + + char *tit; + char *pvs; + char *dep; + char *np; + char *nod; + char *sco; + +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 DelayedEventCallback delayedTimerCallback; +static int delayedTimerEvent = 0; +static int buttonCount = 2; +char *icsTextMenuString; +char *icsNames; +char *firstChessProgramNames; +char *secondChessProgramNames; + +static int analysisTimerEvent = 0; + +#define ARG_MAX 20000 + +#define PALETTESIZE 256 + +/* GUI -> engine */ +extern void GuiCommand P((int command, int param)); + +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; + +#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; + +HWND analysisDialog = NULL; +BOOLEAN analysisDialogUp = FALSE; +static int analysisX, analysisY, analysisH, analysisW; + +char errorMessage[2*MSG_SIZ]; +HWND errorDialog = NULL; +BOOLEAN moveErrorMessageUp = FALSE; +BOOLEAN consoleEcho = TRUE; +CHARFORMAT consoleCF; +COLORREF consoleBackgroundColor; + +char *programVersion; + +#include + +#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); +LRESULT CALLBACK + AnalysisDialog(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 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 */ + { "EngineRoom", ArgBoolean, (LPVOID) &appData.AnalysisWindow, TRUE }, + { "eRoom", ArgTrue, (LPVOID) &appData.AnalysisWindow, FALSE }, + { "xeRoom", ArgFalse, (LPVOID) &appData.AnalysisWindow, FALSE }, + { "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 }, + { "icc", ArgTrue, (LPVOID) &appData.ICC_feature, 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 }, + { "zippyPassword2", ArgString, (LPVOID) &appData.zippyPassword2, FALSE }, + { "zippyPassword3", ArgString, (LPVOID) &appData.zippyPassword3, FALSE }, + { "zippyWrongPassword", ArgString, (LPVOID) &appData.zippyWrongPassword, + FALSE }, + { "zippyAcceptOnly", ArgString, (LPVOID) &appData.zippyAcceptOnly, FALSE }, + { "zippyUseI", ArgBoolean, (LPVOID) &appData.zippyUseI, FALSE }, + { "zui", ArgTrue, (LPVOID) &appData.zippyUseI, FALSE }, + { "xzui", ArgFalse, (LPVOID) &appData.zippyUseI, FALSE }, + { "-zui", ArgFalse, (LPVOID) &appData.zippyUseI, FALSE }, + { "zippyBughouse", ArgInt, (LPVOID) &appData.zippyBughouse, FALSE }, + { "zippyNoplayCrafty", ArgBoolean, (LPVOID) &appData.zippyNoplayCrafty, + FALSE }, + { "znc", ArgTrue, (LPVOID) &appData.zippyNoplayCrafty, FALSE }, + { "xznc", ArgFalse, (LPVOID) &appData.zippyNoplayCrafty, FALSE }, + { "-znc", ArgFalse, (LPVOID) &appData.zippyNoplayCrafty, FALSE }, + { "zippyGameEnd", ArgString, (LPVOID) &appData.zippyGameEnd, FALSE }, + { "zippyGameStart", ArgString, (LPVOID) &appData.zippyGameStart, FALSE }, + { "zippyAdjourn", ArgBoolean, (LPVOID) &appData.zippyAdjourn, FALSE }, + { "zadj", ArgTrue, (LPVOID) &appData.zippyAdjourn, FALSE }, + { "xzadj", ArgFalse, (LPVOID) &appData.zippyAdjourn, FALSE }, + { "-zadj", ArgFalse, (LPVOID) &appData.zippyAdjourn, FALSE }, + { "zippyAbort", ArgBoolean, (LPVOID) &appData.zippyAbort, FALSE }, + { "zab", ArgTrue, (LPVOID) &appData.zippyAbort, FALSE }, + { "xzab", ArgFalse, (LPVOID) &appData.zippyAbort, FALSE }, + { "-zab", ArgFalse, (LPVOID) &appData.zippyAbort, FALSE }, + { "zippyVariants", ArgString, (LPVOID) &appData.zippyVariants, FALSE }, + { "zippyMaxGames", ArgInt, (LPVOID)&appData.zippyMaxGames, FALSE }, + { "zippyReplayTimeout", ArgInt, (LPVOID)&appData.zippyReplayTimeout, FALSE }, + /* Kludge to allow winboard.ini files from buggy 4.0.4 to be read: */ + { "zippyReplyTimeout", ArgInt, (LPVOID)&junk, FALSE }, +#endif + { NULL, ArgNone, NULL, FALSE } +}; + + +/* Kludge for indirection files on command line */ +char* lastIndirectionFilename; +ArgDescriptor argDescriptorIndirection = +{ "", ArgSettingsFilename, (LPVOID) NULL, FALSE }; + + +VOID +ExitArgError(char *msg, char *badArg) +{ + char buf[MSG_SIZ]; + + sprintf(buf, "%s %s", msg, badArg); + DisplayFatalError(buf, 0, 2); + exit(2); +} + +/* Command line font name parser. NULL name means do nothing. + Syntax like "Courier New:10.0 bi" or "Arial:10" or "Arial:10b" + For backward compatibility, syntax without the colon is also + accepted, but font names with digits in them won't work in that case. +*/ +VOID +ParseFontName(char *name, MyFontParams *mfp) +{ + char *p, *q; + if (name == NULL) return; + p = name; + q = strchr(p, ':'); + if (q) { + if (q - p >= sizeof(mfp->faceName)) + ExitArgError("Font name too long:", name); + memcpy(mfp->faceName, p, q - p); + mfp->faceName[q - p] = NULLCHAR; + p = q + 1; + } else { + q = mfp->faceName; + while (*p && !isdigit(*p)) { + *q++ = *p++; + if (q - mfp->faceName >= sizeof(mfp->faceName)) + ExitArgError("Font name too long:", name); + } + while (q > mfp->faceName && q[-1] == ' ') q--; + *q = NULLCHAR; + } + if (!*p) ExitArgError("Font point size missing:", name); + mfp->pointSize = (float) atof(p); + mfp->bold = (strchr(p, 'b') != NULL); + mfp->italic = (strchr(p, 'i') != NULL); + mfp->underline = (strchr(p, 'u') != NULL); + mfp->strikeout = (strchr(p, 's') != NULL); +} + +/* Color name parser. + X version accepts X color names, but this one + handles only the #rrggbb form (hex) or rrr,ggg,bbb (decimal) */ +COLORREF +ParseColorName(char *name) +{ + int red, green, blue, count; + char buf[MSG_SIZ]; + + count = sscanf(name, "#%2x%2x%2x", &red, &green, &blue); + if (count != 3) { + count = sscanf(name, "%3d%*[^0-9]%3d%*[^0-9]%3d", + &red, &green, &blue); + } + if (count != 3) { + sprintf(buf, "Can't parse color name %s", name); + DisplayError(buf, 0); + return RGB(0, 0, 0); + } + return PALETTERGB(red, green, blue); +} + + +void ParseAttribs(COLORREF *color, int *effects, char* argValue) +{ + char *e = argValue; + int eff = 0; + + while (*e) { + if (*e == 'b') eff |= CFE_BOLD; + else if (*e == 'i') eff |= CFE_ITALIC; + else if (*e == 'u') eff |= CFE_UNDERLINE; + else if (*e == 's') eff |= CFE_STRIKEOUT; + else if (*e == '#' || isdigit(*e)) break; + e++; + } + *effects = eff; + *color = ParseColorName(e); +} + + +BoardSize +ParseBoardSize(char *name) +{ + BoardSize bs = SizeTiny; + while (sizeInfo[bs].name != NULL) { + if (StrCaseCmp(name, sizeInfo[bs].name) == 0) return bs; + bs++; + } + ExitArgError("Unrecognized board size value", name); + return bs; /* not reached */ +} + + +char +StringGet(void *getClosure) +{ + char **p = (char **) getClosure; + return *((*p)++); +} + +char +FileGet(void *getClosure) +{ + int c; + FILE* f = (FILE*) getClosure; + + c = getc(f); + if (c == EOF) + return NULLCHAR; + else + return (char) c; +} + +/* Parse settings file named "name". If file found, return the + full name in fullname and return TRUE; else return FALSE */ +BOOLEAN +ParseSettingsFile(char *name, char fullname[MSG_SIZ]) +{ + char *dummy; + FILE *f; + + if (SearchPath(installDir, name, NULL, MSG_SIZ, fullname, &dummy)) { + f = fopen(fullname, "r"); + if (f != NULL) { + ParseArgs(FileGet, f); + fclose(f); + return TRUE; + } + } + return FALSE; +} + +VOID +ParseArgs(GetFunc get, void *cl) +{ + char argName[ARG_MAX]; + char argValue[ARG_MAX]; + ArgDescriptor *ad; + char start; + char *q; + int i, octval; + char ch; + int posarg = 0; + + ch = get(cl); + for (;;) { + while (ch == ' ' || ch == '\n' || ch == '\t') ch = get(cl); + if (ch == NULLCHAR) break; + if (ch == ';') { + /* Comment to end of line */ + ch = get(cl); + while (ch != '\n' && ch != NULLCHAR) ch = get(cl); + continue; + } else if (ch == '/' || ch == '-') { + /* Switch */ + q = argName; + while (ch != ' ' && ch != '=' && ch != ':' && ch != NULLCHAR && + ch != '\n' && ch != '\t') { + *q++ = ch; + ch = get(cl); + } + *q = NULLCHAR; + + for (ad = argDescriptors; ad->argName != NULL; ad++) + if (strcmp(ad->argName, argName + 1) == 0) break; + + if (ad->argName == NULL) + ExitArgError("Unrecognized argument", argName); + + } else if (ch == '@') { + /* Indirection file */ + ad = &argDescriptorIndirection; + ch = get(cl); + } else { + /* Positional argument */ + ad = &argDescriptors[posarg++]; + strcpy(argName, ad->argName); + } + + if (ad->argType == ArgTrue) { + *(Boolean *) ad->argLoc = TRUE; + continue; + } + if (ad->argType == ArgFalse) { + *(Boolean *) ad->argLoc = FALSE; + continue; + } + + while (ch == ' ' || ch == '=' || ch == ':' || ch == '\t') ch = get(cl); + if (ch == NULLCHAR || ch == '\n') { + ExitArgError("No value provided for argument", argName); + } + q = argValue; + if (ch == '{') { + // Quoting with { }. No characters have to (or can) be escaped. + // Thus the string cannot contain a '}' character. + start = ch; + ch = get(cl); + while (start) { + switch (ch) { + case NULLCHAR: + start = NULLCHAR; + break; + + case '}': + ch = get(cl); + start = NULLCHAR; + break; + + default: + *q++ = ch; + ch = get(cl); + break; + } + } + } else if (ch == '\'' || ch == '"') { + // Quoting with ' ' or " ", with \ as escape character. + // Inconvenient for long strings that may contain Windows filenames. + start = ch; + ch = get(cl); + while (start) { + switch (ch) { + case NULLCHAR: + start = NULLCHAR; + break; + + default: + not_special: + *q++ = ch; + ch = get(cl); + break; + + case '\'': + case '\"': + if (ch == start) { + ch = get(cl); + start = NULLCHAR; + break; + } else { + goto not_special; + } + + case '\\': + if (ad->argType == ArgFilename + || ad->argType == ArgSettingsFilename) { + goto not_special; + } + ch = get(cl); + switch (ch) { + case NULLCHAR: + ExitArgError("Incomplete \\ escape in value for", argName); + break; + case 'n': + *q++ = '\n'; + ch = get(cl); + break; + case 'r': + *q++ = '\r'; + ch = get(cl); + break; + case 't': + *q++ = '\t'; + ch = get(cl); + break; + case 'b': + *q++ = '\b'; + ch = get(cl); + break; + case 'f': + *q++ = '\f'; + ch = get(cl); + break; + default: + octval = 0; + for (i = 0; i < 3; i++) { + if (ch >= '0' && ch <= '7') { + octval = octval*8 + (ch - '0'); + ch = get(cl); + } else { + break; + } + } + if (i > 0) { + *q++ = (char) octval; + } else { + *q++ = ch; + ch = get(cl); + } + break; + } + break; + } + } + } else { + while (ch != ' ' && ch != NULLCHAR && ch != '\t' && ch != '\n') { + *q++ = ch; + ch = get(cl); + } + } + *q = NULLCHAR; + + switch (ad->argType) { + case ArgInt: + *(int *) ad->argLoc = atoi(argValue); + break; + + case ArgFloat: + *(float *) ad->argLoc = (float) atof(argValue); + break; + + case ArgString: + case ArgFilename: + *(char **) ad->argLoc = strdup(argValue); + break; + + case ArgSettingsFilename: + { + char fullname[MSG_SIZ]; + if (ParseSettingsFile(argValue, fullname)) { + if (ad->argLoc != NULL) { + *(char **) ad->argLoc = strdup(fullname); + } + } else { + if (ad->argLoc != NULL) { + } else { + ExitArgError("Failed to open indirection file", argValue); + } + } + } + break; + + case ArgBoolean: + switch (argValue[0]) { + case 't': + case 'T': + *(Boolean *) ad->argLoc = TRUE; + break; + case 'f': + case 'F': + *(Boolean *) ad->argLoc = FALSE; + break; + default: + ExitArgError("Unrecognized boolean argument value", argValue); + break; + } + break; + + case ArgColor: + *(COLORREF *)ad->argLoc = ParseColorName(argValue); + break; + + case ArgAttribs: { + ColorClass cc = (ColorClass)ad->argLoc; + ParseAttribs(&textAttribs[cc].color, &textAttribs[cc].effects, argValue); + } + break; + + case ArgBoardSize: + *(BoardSize *)ad->argLoc = ParseBoardSize(argValue); + break; + + case ArgFont: + ParseFontName(argValue, &font[boardSize][(int)ad->argLoc]->mfp); + break; + + case ArgCommSettings: + ParseCommSettings(argValue, &dcb); + break; + + case ArgNone: + ExitArgError("Unrecognized argument", argValue); + break; + } + } +} + +VOID +LFfromMFP(LOGFONT* lf, MyFontParams *mfp) +{ + HDC hdc = CreateDC("DISPLAY", NULL, NULL, NULL); + lf->lfHeight = -(int)(mfp->pointSize * GetDeviceCaps(hdc, LOGPIXELSY) / 72.0 + 0.5); + DeleteDC(hdc); + lf->lfWidth = 0; + lf->lfEscapement = 0; + lf->lfOrientation = 0; + lf->lfWeight = mfp->bold ? FW_BOLD : FW_NORMAL; + lf->lfItalic = mfp->italic; + lf->lfUnderline = mfp->underline; + lf->lfStrikeOut = mfp->strikeout; + lf->lfCharSet = DEFAULT_CHARSET; + lf->lfOutPrecision = OUT_DEFAULT_PRECIS; + lf->lfClipPrecision = CLIP_DEFAULT_PRECIS; + lf->lfQuality = DEFAULT_QUALITY; + lf->lfPitchAndFamily = DEFAULT_PITCH|FF_DONTCARE; + strcpy(lf->lfFaceName, mfp->faceName); +} + +VOID +CreateFontInMF(MyFont *mf) +{ + LFfromMFP(&mf->lf, &mf->mfp); + if (mf->hf) DeleteObject(mf->hf); + mf->hf = CreateFontIndirect(&mf->lf); +} + +VOID +SetDefaultTextAttribs() +{ + ColorClass cc; + for (cc = (ColorClass)0; cc < NColorClasses; cc++) { + ParseAttribs(&textAttribs[cc].color, + &textAttribs[cc].effects, + defaultTextAttribs[cc]); + } +} + +VOID +SetDefaultSounds() +{ + ColorClass cc; + SoundClass sc; + for (cc = (ColorClass)0; cc < NColorClasses; cc++) { + textAttribs[cc].sound.name = strdup(""); + textAttribs[cc].sound.data = NULL; + } + for (sc = (SoundClass)0; sc < NSoundClasses; sc++) { + sounds[sc].name = strdup(""); + sounds[sc].data = NULL; + } + sounds[(int)SoundBell].name = strdup(SOUND_BELL); +} + +VOID +LoadAllSounds() +{ + ColorClass cc; + SoundClass sc; + for (cc = (ColorClass)0; cc < NColorClasses; cc++) { + MyLoadSound(&textAttribs[cc].sound); + } + for (sc = (SoundClass)0; sc < NSoundClasses; sc++) { + MyLoadSound(&sounds[sc]); + } +} + +VOID +InitAppData(LPSTR lpCmdLine) +{ + int i, j; + char buf[ARG_MAX], currDir[MSG_SIZ]; + char *dummy, *p; + + programName = szAppName; + + /* Initialize to defaults */ + lightSquareColor = ParseColorName(LIGHT_SQUARE_COLOR); + darkSquareColor = ParseColorName(DARK_SQUARE_COLOR); + whitePieceColor = ParseColorName(WHITE_PIECE_COLOR); + blackPieceColor = ParseColorName(BLACK_PIECE_COLOR); + highlightSquareColor = ParseColorName(HIGHLIGHT_SQUARE_COLOR); + premoveHighlightColor = ParseColorName(PREMOVE_HIGHLIGHT_COLOR); + consoleBackgroundColor = ParseColorName(COLOR_BKGD); + SetDefaultTextAttribs(); + SetDefaultSounds(); + appData.movesPerSession = MOVES_PER_SESSION; + appData.initString = INIT_STRING; + appData.secondInitString = INIT_STRING; + appData.firstComputerString = COMPUTER_STRING; + appData.secondComputerString = COMPUTER_STRING; + appData.firstChessProgram = FIRST_CHESS_PROGRAM; + appData.secondChessProgram = SECOND_CHESS_PROGRAM; + appData.firstPlaysBlack = FALSE; + appData.noChessProgram = FALSE; + chessProgram = FALSE; + appData.firstHost = FIRST_HOST; + appData.secondHost = SECOND_HOST; + appData.firstDirectory = FIRST_DIRECTORY; + appData.secondDirectory = SECOND_DIRECTORY; + appData.bitmapDirectory = ""; + appData.remoteShell = REMOTE_SHELL; + appData.remoteUser = ""; + appData.timeDelay = TIME_DELAY; + appData.timeControl = TIME_CONTROL; + appData.timeIncrement = TIME_INCREMENT; + appData.icsActive = FALSE; + appData.icsHost = ""; + appData.icsPort = ICS_PORT; + appData.icsCommPort = ICS_COMM_PORT; + appData.icsLogon = ICS_LOGON; + appData.icsHelper = ""; + appData.useTelnet = FALSE; + appData.telnetProgram = TELNET_PROGRAM; + appData.gateway = ""; + appData.loadGameFile = ""; + appData.loadGameIndex = 0; + appData.saveGameFile = ""; + appData.autoSaveGames = FALSE; + appData.loadPositionFile = ""; + appData.loadPositionIndex = 1; + appData.savePositionFile = ""; + appData.matchMode = FALSE; + appData.matchGames = 0; + appData.monoMode = FALSE; + appData.debugMode = FALSE; + appData.clockMode = TRUE; + boardSize = (BoardSize) -1; /* determine by screen size */ + appData.Iconic = FALSE; /*unused*/ + appData.searchTime = ""; + appData.searchDepth = 0; + appData.showCoords = FALSE; + appData.ringBellAfterMoves = TRUE; /*obsolete in WinBoard*/ + appData.autoCallFlag = FALSE; + appData.flipView = FALSE; + appData.autoFlipView = TRUE; + appData.cmailGameName = ""; + appData.alwaysPromoteToQueen = FALSE; + appData.oldSaveStyle = FALSE; + appData.quietPlay = FALSE; + appData.showThinking = FALSE; + appData.ButtonSendOutPutToICS = TRUE; + appData.SendOutPutToICS = 1; /* default whisper */ + appData.icsAnalyze = FALSE; + appData.icsEngineKillPV = FALSE; + appData.smartQueue = TRUE; /* smart queue with IcsAnalyzeOutPut */ + appData.icsEngineWhisper = FALSE; + appData.icsEngineKibitz = FALSE; + appData.icsEngineTell = FALSE; + appData.icsAnalyzeWindow = FALSE; + appData.icsEngineNone = TRUE; /* don't send */ + appData.icsAnalyzeOutPut = 4; /* don't send */ + appData.icsKillPVs = 9; /* a recommend value for most programs */ + appData.windowMove = TRUE; /* Drop display fail low/high moves at ICS */ + appData.icsSmartQueue = 0; /* 0 = standard 1 = blitz */ + appData.icsShowBook = FALSE; /* show engine book */ + appData.userVersion = FALSE; /* programmer version false */ + appData.icsWBprotoAgr = FALSE; + appData.icsWBprotoNorm = TRUE; + appData.icsSmartQueueStd = TRUE; + appData.icsSmartQueueBlitz = FALSE; + appData.engineStatLine = TRUE; /* default send "." with engine room */ + appData.engineTourneyMode = FALSE; /* default no tourney mode */ + appData.zippyDraw = TRUE; + appData.ponderNextMove = TRUE; + appData.periodicUpdates = TRUE; + appData.popupExitMessage = TRUE; + appData.popupMoveErrors = FALSE; + appData.autoObserve = FALSE; + appData.autoComment = FALSE; + appData.animate = TRUE; + appData.animSpeed = 10; + appData.animateDragging = TRUE; + appData.highlightLastMove = TRUE; + appData.getMoveList = TRUE; + appData.testLegality = TRUE; + appData.premove = TRUE; + appData.premoveWhite = FALSE; + appData.premoveWhiteText = ""; + appData.premoveBlack = FALSE; + appData.premoveBlackText = ""; + appData.icsAlarm = TRUE; + appData.icsAlarmTime = 5000; + appData.autoRaiseBoard = TRUE; + appData.localLineEditing = TRUE; + appData.colorize = TRUE; + appData.reuseFirst = TRUE; + appData.reuseSecond = TRUE; + appData.blindfold = FALSE; + dcb.DCBlength = sizeof(DCB); + dcb.BaudRate = 9600; + dcb.fBinary = TRUE; + dcb.fParity = FALSE; + dcb.fOutxCtsFlow = FALSE; + dcb.fOutxDsrFlow = FALSE; + dcb.fDtrControl = DTR_CONTROL_ENABLE; + dcb.fDsrSensitivity = FALSE; + dcb.fTXContinueOnXoff = TRUE; + dcb.fOutX = FALSE; + dcb.fInX = FALSE; + dcb.fNull = FALSE; + dcb.fRtsControl = RTS_CONTROL_ENABLE; + dcb.fAbortOnError = FALSE; + dcb.wReserved = 0; + dcb.ByteSize = 7; + dcb.Parity = SPACEPARITY; + dcb.StopBits = ONESTOPBIT; + settingsFileName = SETTINGS_FILE; + saveSettingsOnExit = TRUE; + boardX = CW_USEDEFAULT; + boardY = CW_USEDEFAULT; + consoleX = CW_USEDEFAULT; + consoleY = CW_USEDEFAULT; + consoleW = CW_USEDEFAULT; + consoleH = CW_USEDEFAULT; + analysisX = CW_USEDEFAULT; + analysisY = CW_USEDEFAULT; + analysisW = 589; + analysisH = 330; + commentX = CW_USEDEFAULT; + commentY = CW_USEDEFAULT; + commentW = CW_USEDEFAULT; + commentH = CW_USEDEFAULT; + editTagsX = CW_USEDEFAULT; + editTagsY = CW_USEDEFAULT; + editTagsW = CW_USEDEFAULT; + editTagsH = CW_USEDEFAULT; + gameListX = CW_USEDEFAULT; + gameListY = CW_USEDEFAULT; + gameListW = CW_USEDEFAULT; + gameListH = CW_USEDEFAULT; + icsTextMenuString = ICS_TEXT_MENU_DEFAULT; + icsNames = ICS_NAMES; + firstChessProgramNames = FCP_NAMES; + secondChessProgramNames = SCP_NAMES; + appData.initialMode = ""; + appData.variant = "normal"; + appData.firstProtocolVersion = PROTOVER; + appData.secondProtocolVersion = PROTOVER; + appData.showButtonBar = TRUE; +#ifdef ZIPPY + appData.zippyTalk = ZIPPY_TALK; + appData.zippyPlay = ZIPPY_PLAY; + appData.zippyLines = ZIPPY_LINES; + appData.zippyPinhead = ZIPPY_PINHEAD; + appData.zippyPassword = ZIPPY_PASSWORD; + appData.zippyPassword2 = ZIPPY_PASSWORD2; + appData.zippyPassword3 = ZIPPY_PASSWORD3; + appData.zippyWrongPassword = ZIPPY_WRONG_PASSWORD; + appData.zippyAcceptOnly = ZIPPY_ACCEPT_ONLY; + appData.zippyUseI = ZIPPY_USE_I; + appData.zippyBughouse = ZIPPY_BUGHOUSE; + appData.zippyNoplayCrafty = ZIPPY_NOPLAY_CRAFTY; + appData.zippyGameEnd = ZIPPY_GAME_END; + appData.zippyGameStart = ZIPPY_GAME_START; + appData.zippyAdjourn = ZIPPY_ADJOURN; + appData.zippyAbort = ZIPPY_ABORT; + appData.zippyVariants = ZIPPY_VARIANTS; + appData.zippyMaxGames = ZIPPY_MAX_GAMES; + appData.zippyReplayTimeout = ZIPPY_REPLAY_TIMEOUT; +#endif + + /* Point font array elements to structures and + parse default font names */ + for (i=0; idef, &font[j][i]->mfp); + } + } + + /* Parse default settings file if any */ + if (ParseSettingsFile(settingsFileName, buf)) { + settingsFileName = strdup(buf); + } + + /* Parse command line */ + ParseArgs(StringGet, &lpCmdLine); + + /* Propagate options that affect others */ + if (appData.matchMode || appData.matchGames) chessProgram = TRUE; + if (appData.icsActive || appData.noChessProgram) { + chessProgram = FALSE; /* not local chess program mode */ + } + + /* Open startup dialog if needed */ + if ((!appData.noChessProgram && !chessProgram && !appData.icsActive) || + (appData.icsActive && *appData.icsHost == NULLCHAR) || + (chessProgram && (*appData.firstChessProgram == NULLCHAR || + *appData.secondChessProgram == NULLCHAR))) { + FARPROC lpProc; + + lpProc = MakeProcInstance((FARPROC)StartupDialog, hInst); + DialogBox(hInst, MAKEINTRESOURCE(DLG_Startup), NULL, (DLGPROC)lpProc); + FreeProcInstance(lpProc); + } + + /* Make sure save files land in the right (?) directory */ + if (GetFullPathName(appData.saveGameFile, MSG_SIZ, buf, &dummy)) { + appData.saveGameFile = strdup(buf); + } + if (GetFullPathName(appData.savePositionFile, MSG_SIZ, buf, &dummy)) { + appData.savePositionFile = strdup(buf); + } + + /* Finish initialization for fonts and sounds */ + for (i=0; iargName != NULL; ad++) { + if (!ad->save) continue; + switch (ad->argType) { + case ArgString: + { + char *p = *(char **)ad->argLoc; + if ((strchr(p, '\\') || strchr(p, '\n')) && !strchr(p, '}')) { + /* Quote multiline values or \-containing values + with { } if possible */ + fprintf(f, "/%s={%s}\n", ad->argName, p); + } else { + /* Else quote with " " */ + fprintf(f, "/%s=\"", ad->argName); + while (*p) { + if (*p == '\n') fprintf(f, "\n"); + else if (*p == '\r') fprintf(f, "\\r"); + else if (*p == '\t') fprintf(f, "\\t"); + else if (*p == '\b') fprintf(f, "\\b"); + else if (*p == '\f') fprintf(f, "\\f"); + else if (*p < ' ') fprintf(f, "\\%03o", *p); + else if (*p == '\"') fprintf(f, "\\\""); + else if (*p == '\\') fprintf(f, "\\\\"); + else putc(*p, f); + p++; + } + fprintf(f, "\"\n"); + } + } + break; + case ArgInt: + fprintf(f, "/%s=%d\n", ad->argName, *(int *)ad->argLoc); + break; + case ArgFloat: + fprintf(f, "/%s=%g\n", ad->argName, *(float *)ad->argLoc); + break; + case ArgBoolean: + fprintf(f, "/%s=%s\n", ad->argName, + (*(Boolean *)ad->argLoc) ? "true" : "false"); + break; + case ArgTrue: + if (*(Boolean *)ad->argLoc) fprintf(f, "/%s\n", ad->argName); + break; + case ArgFalse: + if (!*(Boolean *)ad->argLoc) fprintf(f, "/%s\n", ad->argName); + break; + case ArgColor: + { + COLORREF color = *(COLORREF *)ad->argLoc; + fprintf(f, "/%s=#%02x%02x%02x\n", ad->argName, + color&0xff, (color>>8)&0xff, (color>>16)&0xff); + } + break; + case ArgAttribs: + { + MyTextAttribs* ta = &textAttribs[(ColorClass)ad->argLoc]; + fprintf(f, "/%s=\"%s%s%s%s%s#%02x%02x%02x\"\n", ad->argName, + (ta->effects & CFE_BOLD) ? "b" : "", + (ta->effects & CFE_ITALIC) ? "i" : "", + (ta->effects & CFE_UNDERLINE) ? "u" : "", + (ta->effects & CFE_STRIKEOUT) ? "s" : "", + (ta->effects) ? " " : "", + ta->color&0xff, (ta->color >> 8)&0xff, (ta->color >> 16)&0xff); + } + break; + case ArgFilename: + if (strchr(*(char **)ad->argLoc, '\"')) { + fprintf(f, "/%s='%s'\n", ad->argName, *(char **)ad->argLoc); + } else { + fprintf(f, "/%s=\"%s\"\n", ad->argName, *(char **)ad->argLoc); + } + break; + case ArgBoardSize: + fprintf(f, "/%s=%s\n", ad->argName, + sizeInfo[*(BoardSize *)ad->argLoc].name); + break; + case ArgFont: + { + int bs; + for (bs=0; bsargLoc]->mfp; + fprintf(f, "/size=%s ", sizeInfo[bs].name); + fprintf(f, "/%s=\"%s:%g%s%s%s%s%s\"\n", + ad->argName, mfp->faceName, mfp->pointSize, + mfp->bold || mfp->italic || mfp->underline || mfp->strikeout ? " " : "", + mfp->bold ? "b" : "", + mfp->italic ? "i" : "", + mfp->underline ? "u" : "", + mfp->strikeout ? "s" : ""); + } + } + break; + case ArgCommSettings: + PrintCommSettings(f, ad->argName, (DCB *)ad->argLoc); + } + } + fclose(f); +} + + + +/*---------------------------------------------------------------------------*\ + * + * GDI board drawing routines + * +\*---------------------------------------------------------------------------*/ + +HBITMAP +DoLoadBitmap(HINSTANCE hinst, char *piece, int squareSize, char *suffix) +{ + char name[128]; + + sprintf(name, "%s%d%s", piece, squareSize, suffix); + if (gameInfo.event && + strcmp(gameInfo.event, "Easter Egg Hunt") == 0 && + strcmp(name, "k80s") == 0) { + strcpy(name, "tim"); + } + return LoadBitmap(hinst, name); +} + + +/* Insert a color into the program's logical palette + structure. This code assumes the given color is + the result of the RGB or PALETTERGB macro, and it + knows how those macros work (which is documented). +*/ +VOID +InsertInPalette(COLORREF color) +{ + LPPALETTEENTRY pe = &(pLogPal->palPalEntry[pLogPal->palNumEntries]); + + if (pLogPal->palNumEntries++ >= PALETTESIZE) { + DisplayFatalError("Too many colors", 0, 1); + pLogPal->palNumEntries--; + return; + } + + pe->peFlags = (char) 0; + pe->peRed = (char) (0xFF & color); + pe->peGreen = (char) (0xFF & (color >> 8)); + pe->peBlue = (char) (0xFF & (color >> 16)); + return; +} + + +VOID +InitDrawingColors() +{ + if (pLogPal == NULL) { + /* Allocate enough memory for a logical palette with + * PALETTESIZE entries and set the size and version fields + * of the logical palette structure. + */ + pLogPal = (NPLOGPALETTE) + LocalAlloc(LMEM_FIXED, (sizeof(LOGPALETTE) + + (sizeof(PALETTEENTRY) * (PALETTESIZE)))); + pLogPal->palVersion = 0x300; + } + pLogPal->palNumEntries = 0; + + InsertInPalette(lightSquareColor); + InsertInPalette(darkSquareColor); + InsertInPalette(whitePieceColor); + InsertInPalette(blackPieceColor); + InsertInPalette(highlightSquareColor); + InsertInPalette(premoveHighlightColor); + + /* create a logical color palette according the information + * in the LOGPALETTE structure. + */ + hPal = CreatePalette((LPLOGPALETTE) pLogPal); + + lightSquareBrush = CreateSolidBrush(lightSquareColor); + darkSquareBrush = CreateSolidBrush(darkSquareColor); + whitePieceBrush = CreateSolidBrush(whitePieceColor); + blackPieceBrush = CreateSolidBrush(blackPieceColor); + iconBkgndBrush = CreateSolidBrush(GetSysColor(COLOR_BACKGROUND)); +} + + +int +BoardWidth(int boardSize) +{ + return (BOARD_SIZE + 1) * sizeInfo[boardSize].lineGap + + BOARD_SIZE * sizeInfo[boardSize].squareSize; +} + +/* Respond to board resize by dragging edge */ +VOID +ResizeBoard(int newSizeX, int newSizeY, int flags) +{ + BoardSize newSize = NUM_SIZES - 1; + static int recurse = 0; + if (IsIconic(hwndMain)) return; + if (recurse > 0) return; + recurse++; + while (newSize > 0 && + (newSizeX < sizeInfo[newSize].cliWidth || + newSizeY < sizeInfo[newSize].cliHeight)) { + newSize--; + } + boardSize = newSize; + InitDrawingSizes(boardSize, flags); + recurse--; +} + + + +VOID +InitDrawingSizes(BoardSize boardSize, int flags) +{ + int i, boardWidth; + ChessSquare piece; + static int oldBoardSize = -1, oldTinyLayout = 0; + HDC hdc; + SIZE clockSize, messageSize; + HFONT oldFont; + char buf[MSG_SIZ]; + char *str; + HMENU hmenu = GetMenu(hwndMain); + RECT crect, wrect; + int offby; + LOGBRUSH logbrush; + + tinyLayout = sizeInfo[boardSize].tinyLayout; + smallLayout = sizeInfo[boardSize].smallLayout; + squareSize = sizeInfo[boardSize].squareSize; + lineGap = sizeInfo[boardSize].lineGap; + + if (tinyLayout != oldTinyLayout) { + long style = GetWindowLong(hwndMain, GWL_STYLE); + if (tinyLayout) { + style &= ~WS_SYSMENU; + InsertMenu(hmenu, IDM_Exit, MF_BYCOMMAND, IDM_Minimize, + "&Minimize\tCtrl+F4"); + } else { + style |= WS_SYSMENU; + RemoveMenu(hmenu, IDM_Minimize, MF_BYCOMMAND); + } + SetWindowLong(hwndMain, GWL_STYLE, style); + + for (i=0; menuBarText[tinyLayout][i]; i++) { + ModifyMenu(hmenu, i, MF_STRING|MF_BYPOSITION|MF_POPUP, + (UINT)GetSubMenu(hmenu, i), menuBarText[tinyLayout][i]); + } + DrawMenuBar(hwndMain); + } + + boardWidth = BoardWidth(boardSize); + + /* Get text area sizes */ + hdc = GetDC(hwndMain); + if (appData.clockMode) { + sprintf(buf, "White: %s", TimeString(23*60*60*1000L)); + } else { + sprintf(buf, "White"); + } + oldFont = SelectObject(hdc, font[boardSize][CLOCK_FONT]->hf); + GetTextExtentPoint(hdc, buf, strlen(buf), &clockSize); + SelectObject(hdc, font[boardSize][MESSAGE_FONT]->hf); + str = "We only care about the height here"; + GetTextExtentPoint(hdc, str, strlen(str), &messageSize); + SelectObject(hdc, oldFont); + ReleaseDC(hwndMain, hdc); + + /* Compute where everything goes */ + whiteRect.left = OUTER_MARGIN; + whiteRect.right = whiteRect.left + boardWidth/2 - INNER_MARGIN/2; + whiteRect.top = OUTER_MARGIN; + whiteRect.bottom = whiteRect.top + clockSize.cy; + + blackRect.left = whiteRect.right + INNER_MARGIN; + blackRect.right = blackRect.left + boardWidth/2 - 1; + blackRect.top = whiteRect.top; + blackRect.bottom = whiteRect.bottom; + + messageRect.left = whiteRect.left + MESSAGE_LINE_LEFTMARGIN; + if (appData.showButtonBar) { + messageRect.right = blackRect.right + - N_BUTTONS*BUTTON_WIDTH - MESSAGE_LINE_LEFTMARGIN; + } else { + messageRect.right = blackRect.right; + } + messageRect.top = whiteRect.bottom + INNER_MARGIN; + messageRect.bottom = messageRect.top + messageSize.cy; + + boardRect.left = whiteRect.left; + boardRect.right = boardRect.left + boardWidth; + boardRect.top = messageRect.bottom + INNER_MARGIN; + boardRect.bottom = boardRect.top + boardWidth; + + sizeInfo[boardSize].cliWidth = boardRect.right + OUTER_MARGIN; + sizeInfo[boardSize].cliHeight = boardRect.bottom + OUTER_MARGIN; + winWidth = 2 * GetSystemMetrics(SM_CXFRAME) + boardRect.right + OUTER_MARGIN; + winHeight = 2 * GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYMENU) + + GetSystemMetrics(SM_CYCAPTION) + boardRect.bottom + OUTER_MARGIN; + GetWindowRect(hwndMain, &wrect); + SetWindowPos(hwndMain, NULL, 0, 0, winWidth, winHeight, + SWP_NOCOPYBITS|SWP_NOZORDER|SWP_NOMOVE); + /* compensate if menu bar wrapped */ + GetClientRect(hwndMain, &crect); + offby = boardRect.bottom + OUTER_MARGIN - crect.bottom; + winHeight += offby; + switch (flags) { + case WMSZ_TOPLEFT: + SetWindowPos(hwndMain, NULL, + wrect.right - winWidth, wrect.bottom - winHeight, + winWidth, winHeight, SWP_NOCOPYBITS|SWP_NOZORDER); + break; + + case WMSZ_TOPRIGHT: + case WMSZ_TOP: + SetWindowPos(hwndMain, NULL, + wrect.left, wrect.bottom - winHeight, + winWidth, winHeight, SWP_NOCOPYBITS|SWP_NOZORDER); + break; + + case WMSZ_BOTTOMLEFT: + case WMSZ_LEFT: + SetWindowPos(hwndMain, NULL, + wrect.right - winWidth, wrect.top, + winWidth, winHeight, SWP_NOCOPYBITS|SWP_NOZORDER); + break; + + case WMSZ_BOTTOMRIGHT: + case WMSZ_BOTTOM: + case WMSZ_RIGHT: + default: + SetWindowPos(hwndMain, NULL, 0, 0, winWidth, winHeight, + SWP_NOCOPYBITS|SWP_NOZORDER|SWP_NOMOVE); + break; + } + + hwndPause = NULL; + for (i = 0; i < N_BUTTONS; i++) { + if (buttonDesc[i].hwnd != NULL) { + DestroyWindow(buttonDesc[i].hwnd); + buttonDesc[i].hwnd = NULL; + } + if (appData.showButtonBar) { + buttonDesc[i].hwnd = + CreateWindow("BUTTON", buttonDesc[i].label, + WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON , + boardRect.right - BUTTON_WIDTH*(N_BUTTONS-i), + messageRect.top, BUTTON_WIDTH, messageSize.cy, hwndMain, + (HMENU) buttonDesc[i].id, + (HINSTANCE) GetWindowLong(hwndMain, GWL_HINSTANCE), NULL); + if (tinyLayout) { + SendMessage(buttonDesc[i].hwnd, WM_SETFONT, + (WPARAM)font[boardSize][MESSAGE_FONT]->hf, + MAKELPARAM(FALSE, 0)); + } + if (buttonDesc[i].id == IDM_Pause) + hwndPause = buttonDesc[i].hwnd; + buttonDesc[i].wndproc = (WNDPROC) + SetWindowLong(buttonDesc[i].hwnd, GWL_WNDPROC, (LONG) ButtonProc); + } + } + if (gridPen != NULL) DeleteObject(gridPen); + if (highlightPen != NULL) DeleteObject(highlightPen); + if (premovePen != NULL) DeleteObject(premovePen); + if (lineGap != 0) { + logbrush.lbStyle = BS_SOLID; + logbrush.lbColor = RGB(0, 0, 0); /* grid pen color = black */ + gridPen = + ExtCreatePen(PS_GEOMETRIC|PS_SOLID|PS_ENDCAP_FLAT|PS_JOIN_MITER, + lineGap, &logbrush, 0, NULL); + logbrush.lbColor = highlightSquareColor; + highlightPen = + ExtCreatePen(PS_GEOMETRIC|PS_SOLID|PS_ENDCAP_FLAT|PS_JOIN_MITER, + lineGap, &logbrush, 0, NULL); + + logbrush.lbColor = premoveHighlightColor; + premovePen = + ExtCreatePen(PS_GEOMETRIC|PS_SOLID|PS_ENDCAP_FLAT|PS_JOIN_MITER, + lineGap, &logbrush, 0, NULL); + + for (i = 0; i < BOARD_SIZE + 1; i++) { + gridEndpoints[i*2].x = boardRect.left + lineGap / 2; + gridEndpoints[i*2 + BOARD_SIZE*2 + 2].y = boardRect.top + lineGap / 2; + gridEndpoints[i*2].y = gridEndpoints[i*2 + 1].y = + boardRect.top + lineGap / 2 + (i * (squareSize + lineGap)); + gridEndpoints[i*2 + 1].x = boardRect.left + lineGap / 2 + + BOARD_SIZE * (squareSize + lineGap); + gridEndpoints[i*2 + BOARD_SIZE*2 + 2].x = + gridEndpoints[i*2 + 1 + BOARD_SIZE*2 + 2].x = boardRect.left + + lineGap / 2 + (i * (squareSize + lineGap)); + gridEndpoints[i*2 + 1 + BOARD_SIZE*2 + 2].y = + boardRect.top + BOARD_SIZE * (squareSize + lineGap); + gridVertexCounts[i*2] = gridVertexCounts[i*2 + 1] = 2; + } + } + + if (boardSize == oldBoardSize) return; + oldBoardSize = boardSize; + oldTinyLayout = tinyLayout; + + /* Load piece bitmaps for this board size */ + for (i=0; i<=2; i++) { + for (piece = WhitePawn; + (int) piece <= (int) WhiteKing; + piece = (ChessSquare) ((int) piece + 1)) { + if (pieceBitmap[i][piece] != NULL) + DeleteObject(pieceBitmap[i][piece]); + } + } + + pieceBitmap[0][WhitePawn] = DoLoadBitmap(hInst, "p", squareSize, "s"); + pieceBitmap[0][WhiteKnight] = DoLoadBitmap(hInst, "n", squareSize, "s"); + pieceBitmap[0][WhiteBishop] = DoLoadBitmap(hInst, "b", squareSize, "s"); + pieceBitmap[0][WhiteRook] = DoLoadBitmap(hInst, "r", squareSize, "s"); + pieceBitmap[0][WhiteQueen] = DoLoadBitmap(hInst, "q", squareSize, "s"); + pieceBitmap[0][WhiteKing] = DoLoadBitmap(hInst, "k", squareSize, "s"); + pieceBitmap[1][WhitePawn] = DoLoadBitmap(hInst, "p", squareSize, "o"); + pieceBitmap[1][WhiteKnight] = DoLoadBitmap(hInst, "n", squareSize, "o"); + pieceBitmap[1][WhiteBishop] = DoLoadBitmap(hInst, "b", squareSize, "o"); + pieceBitmap[1][WhiteRook] = DoLoadBitmap(hInst, "r", squareSize, "o"); + pieceBitmap[1][WhiteQueen] = DoLoadBitmap(hInst, "q", squareSize, "o"); + pieceBitmap[1][WhiteKing] = DoLoadBitmap(hInst, "k", squareSize, "o"); + pieceBitmap[2][WhitePawn] = DoLoadBitmap(hInst, "p", squareSize, "w"); + pieceBitmap[2][WhiteKnight] = DoLoadBitmap(hInst, "n", squareSize, "w"); + pieceBitmap[2][WhiteBishop] = DoLoadBitmap(hInst, "b", squareSize, "w"); + pieceBitmap[2][WhiteRook] = DoLoadBitmap(hInst, "r", squareSize, "w"); + pieceBitmap[2][WhiteQueen] = DoLoadBitmap(hInst, "q", squareSize, "w"); + pieceBitmap[2][WhiteKing] = DoLoadBitmap(hInst, "k", squareSize, "w"); + +} + +HBITMAP +PieceBitmap(ChessSquare p, int kind) +{ + if ((int) p >= (int) BlackPawn) + p = (ChessSquare) ((int) p - (int) BlackPawn + (int) WhitePawn); + + return pieceBitmap[kind][(int) p]; +} + +/***************************************************************/ + +#define MIN(a,b) (((a) < (b)) ? (a) : (b)) +#define MAX(a,b) (((a) > (b)) ? (a) : (b)) +/* +#define MIN3(a,b,c) (((a) < (b) && (a) < (c)) ? (a) : (((b) < (a) && (b) < (c)) ? (b) : (c))) +#define MAX3(a,b,c) (((a) > (b) && (a) > (c)) ? (a) : (((b) > (a) && (b) > (c)) ? (b) : (c))) +*/ + +VOID +SquareToPos(int row, int column, int * x, int * y) +{ + if (flipView) { + *x = boardRect.left + lineGap + ((BOARD_SIZE-1)-column) * (squareSize + lineGap); + *y = boardRect.top + lineGap + row * (squareSize + lineGap); + } else { + *x = boardRect.left + lineGap + column * (squareSize + lineGap); + *y = boardRect.top + lineGap + ((BOARD_SIZE-1)-row) * (squareSize + lineGap); + } +} + +VOID +DrawCoordsOnDC(HDC hdc) +{ + static char files[16] = {'1','2','3','4','5','6','7','8','8','7','6','5','4','3','2','1'}; + static char ranks[16] = {'h','g','f','e','d','c','b','a','a','b','c','d','e','f','g','h'}; + char str[2] = { NULLCHAR, NULLCHAR }; + int oldMode, oldAlign, x, y, start, i; + HFONT oldFont; + HBRUSH oldBrush; + + if (!appData.showCoords) + return; + + start = flipView ? 0 : 8; + + oldBrush = SelectObject(hdc, GetStockObject(BLACK_BRUSH)); + oldMode = SetBkMode(hdc, (appData.monoMode ? OPAQUE : TRANSPARENT)); + oldAlign = GetTextAlign(hdc); + oldFont = SelectObject(hdc, font[boardSize][COORD_FONT]->hf); + + y = boardRect.top + lineGap; + x = boardRect.left + lineGap; + + SetTextAlign(hdc, TA_LEFT|TA_TOP); + for (i = 0; i < 8; i++) { + str[0] = files[start + i]; + ExtTextOut(hdc, x + 2, y + 1, 0, NULL, str, 1, NULL); + y += squareSize + lineGap; + } + + SetTextAlign(hdc, TA_RIGHT|TA_BOTTOM); + for (i = 0; i < 8; i++) { + str[0] = ranks[start + i]; + ExtTextOut(hdc, x + squareSize - 2, y - 1, 0, NULL, str, 1, NULL); + x += squareSize + lineGap; + } + + SelectObject(hdc, oldBrush); + SetBkMode(hdc, oldMode); + SetTextAlign(hdc, oldAlign); + SelectObject(hdc, oldFont); +} + +VOID +DrawGridOnDC(HDC hdc) +{ + HPEN oldPen; + + if (lineGap != 0) { + oldPen = SelectObject(hdc, gridPen); + PolyPolyline(hdc, gridEndpoints, gridVertexCounts, BOARD_SIZE*2 + 2); + SelectObject(hdc, oldPen); + } +} + +#define HIGHLIGHT_PEN 0 +#define PREMOVE_PEN 1 + +VOID +DrawHighlightOnDC(HDC hdc, BOOLEAN on, int x, int y, int pen) +{ + int x1, y1; + HPEN oldPen, hPen; + if (lineGap == 0) return; + if (flipView) { + x1 = boardRect.left + + lineGap/2 + ((BOARD_SIZE-1)-x) * (squareSize + lineGap); + y1 = boardRect.top + + lineGap/2 + y * (squareSize + lineGap); + } else { + x1 = boardRect.left + + lineGap/2 + x * (squareSize + lineGap); + y1 = boardRect.top + + lineGap/2 + ((BOARD_SIZE-1)-y) * (squareSize + lineGap); + } + hPen = pen ? premovePen : highlightPen; + oldPen = SelectObject(hdc, on ? hPen : gridPen); + MoveToEx(hdc, x1, y1, NULL); + LineTo(hdc, x1 + squareSize + lineGap, y1); + LineTo(hdc, x1 + squareSize + lineGap, y1 + squareSize + lineGap); + LineTo(hdc, x1, y1 + squareSize + lineGap); + LineTo(hdc, x1, y1); + SelectObject(hdc, oldPen); +} + +VOID +DrawHighlightsOnDC(HDC hdc) +{ + int i; + for (i=0; i<2; i++) { + if (highlightInfo.sq[i].x >= 0 && highlightInfo.sq[i].y >= 0) + DrawHighlightOnDC(hdc, TRUE, + highlightInfo.sq[i].x, highlightInfo.sq[i].y, + HIGHLIGHT_PEN); + } + for (i=0; i<2; i++) { + if (premoveHighlightInfo.sq[i].x >= 0 && + premoveHighlightInfo.sq[i].y >= 0) { + DrawHighlightOnDC(hdc, TRUE, + premoveHighlightInfo.sq[i].x, + premoveHighlightInfo.sq[i].y, + PREMOVE_PEN); + } + } +} + +/* Note: sqcolor is used only in monoMode */ +/* Note that this code is largely duplicated in woptions.c, + function DrawSampleSquare, so that needs to be updated too */ +VOID +DrawPieceOnDC(HDC hdc, ChessSquare piece, int color, int sqcolor, int x, int y, HDC tmphdc) +{ + HBITMAP oldBitmap; + HBRUSH oldBrush; + + if (appData.blindfold) return; + + if (appData.monoMode) { + SelectObject(tmphdc, PieceBitmap(piece, + color == sqcolor ? OUTLINE_PIECE : SOLID_PIECE)); + BitBlt(hdc, x, y, squareSize, squareSize, tmphdc, 0, 0, + sqcolor ? SRCCOPY : NOTSRCCOPY); + } else { + if (color) { + oldBitmap = SelectObject(tmphdc, PieceBitmap(piece, WHITE_PIECE)); + oldBrush = SelectObject(hdc, whitePieceBrush); + BitBlt(hdc, x, y, squareSize, squareSize, tmphdc, 0, 0, 0x00B8074A); +#if 0 + /* Use black piece color for outline of white pieces */ + /* Not sure this looks really good (though xboard does it). + Maybe better to have another selectable color, default black */ + SelectObject(hdc, blackPieceBrush); /* could have own brush */ + SelectObject(tmphdc, PieceBitmap(piece, OUTLINE_PIECE)); + BitBlt(hdc, x, y, squareSize, squareSize, tmphdc, 0, 0, 0x00B8074A); +#else + /* Use black for outline of white pieces */ + SelectObject(tmphdc, PieceBitmap(piece, OUTLINE_PIECE)); + BitBlt(hdc, x, y, squareSize, squareSize, tmphdc, 0, 0, SRCAND); +#endif + } else { +#if 0 + /* Use white piece color for details of black pieces */ + /* Requires filled-in solid bitmaps (BLACK_PIECE class); the + WHITE_PIECE ones aren't always the right shape. */ + /* Not sure this looks really good (though xboard does it). + Maybe better to have another selectable color, default medium gray? */ + oldBitmap = SelectObject(tmphdc, PieceBitmap(piece, BLACK_PIECE)); + oldBrush = SelectObject(hdc, whitePieceBrush); /* could have own brush */ + BitBlt(hdc, x, y, squareSize, squareSize, tmphdc, 0, 0, 0x00B8074A); + SelectObject(tmphdc, PieceBitmap(piece, SOLID_PIECE)); + SelectObject(hdc, blackPieceBrush); + BitBlt(hdc, x, y, squareSize, squareSize, tmphdc, 0, 0, 0x00B8074A); +#else + /* Use square color for details of black pieces */ + oldBitmap = SelectObject(tmphdc, PieceBitmap(piece, SOLID_PIECE)); + oldBrush = SelectObject(hdc, blackPieceBrush); + BitBlt(hdc, x, y, squareSize, squareSize, tmphdc, 0, 0, 0x00B8074A); +#endif + } + SelectObject(hdc, oldBrush); + SelectObject(tmphdc, oldBitmap); + } +} + +VOID +DrawBoardOnDC(HDC hdc, Board board, HDC tmphdc) +{ + int row, column, x, y, square_color, piece_color; + ChessSquare piece; + HBRUSH oldBrush; + + for (row = 0; row < BOARD_SIZE; row++) { + for (column = 0; column < BOARD_SIZE; column++) { + + SquareToPos(row, column, &x, &y); + + piece = board[row][column]; + + square_color = ((column + row) % 2) == 1; + piece_color = (int) piece < (int) BlackPawn; + + if (appData.monoMode) { + if (piece == EmptySquare) { + BitBlt(hdc, x, y, squareSize, squareSize, 0, 0, 0, + square_color ? WHITENESS : BLACKNESS); + } else { + DrawPieceOnDC(hdc, piece, piece_color, square_color, x, y, tmphdc); + } + } else { + oldBrush = SelectObject(hdc, square_color ? + lightSquareBrush : darkSquareBrush); + BitBlt(hdc, x, y, squareSize, squareSize, 0, 0, 0, PATCOPY); + SelectObject(hdc, oldBrush); + if (piece != EmptySquare) + DrawPieceOnDC(hdc, piece, piece_color, -1, x, y, tmphdc); + } + } + } +} + +#define MAX_CLIPS 200 /* more than enough */ + +VOID +HDCDrawPosition(HDC hdc, BOOLEAN repaint, Board board) +{ + static Board lastReq, lastDrawn; + static HighlightInfo lastDrawnHighlight, lastDrawnPremove; + static int lastDrawnFlipView = 0; + static int lastReqValid = 0, lastDrawnValid = 0; + int releaseDC, x, y, x2, y2, row, column, num_clips = 0, i; + HDC tmphdc; + HDC hdcmem; + HBITMAP bufferBitmap; + HBITMAP oldBitmap; + RECT Rect; + HRGN clips[MAX_CLIPS]; + ChessSquare dragged_piece = EmptySquare; + + /* I'm undecided on this - this function figures out whether a full + * repaint is necessary on its own, so there's no real reason to have the + * caller tell it that. I think this can safely be set to FALSE - but + * if we trust the callers not to request full repaints unnessesarily, then + * we could skip some clipping work. In other words, only request a full + * redraw when the majority of pieces have changed positions (ie. flip, + * gamestart and similar) --Hawk + */ + Boolean fullrepaint = repaint; + + if (board == NULL) { + if (!lastReqValid) { + return; + } + board = lastReq; + } else { + CopyBoard(lastReq, board); + lastReqValid = 1; + } + + if (doingSizing) { + return; + } + + if (IsIconic(hwndMain)) { + return; + } + + if (hdc == NULL) { + hdc = GetDC(hwndMain); + if (!appData.monoMode) { + SelectPalette(hdc, hPal, FALSE); + RealizePalette(hdc); + } + releaseDC = TRUE; + } else { + releaseDC = FALSE; + } + +#if 0 + fprintf(debugFP, "*******************************\n" + "repaint = %s\n" + "dragInfo.from (%d,%d)\n" + "dragInfo.start (%d,%d)\n" + "dragInfo.pos (%d,%d)\n" + "dragInfo.lastpos (%d,%d)\n", + repaint ? "TRUE" : "FALSE", + dragInfo.from.x, dragInfo.from.y, + dragInfo.start.x, dragInfo.start.y, + dragInfo.pos.x, dragInfo.pos.y, + dragInfo.lastpos.x, dragInfo.lastpos.y); + fprintf(debugFP, "prev: "); + for (row = 0; row < 8; row++) { + for (column = 0; column < 8; column++) { + fprintf(debugFP, "%d ", lastDrawn[row][column]); + } + } + fprintf(debugFP, "\n"); + fprintf(debugFP, "board: "); + for (row = 0; row < 8; row++) { + for (column = 0; column < 8; column++) { + fprintf(debugFP, "%d ", board[row][column]); + } + } + fprintf(debugFP, "\n"); + fflush(debugFP); +#endif + + /* Create some work-DCs */ + hdcmem = CreateCompatibleDC(hdc); + tmphdc = CreateCompatibleDC(hdc); + + /* Figure out which squares need updating by comparing the + * newest board with the last drawn board and checking if + * flipping has changed. + */ + if (!fullrepaint && lastDrawnValid && lastDrawnFlipView == flipView) { + for (row = 0; row < 8; row++) { + for (column = 0; column < 8; column++) { + if (lastDrawn[row][column] != board[row][column]) { + SquareToPos(row, column, &x, &y); + clips[num_clips++] = + CreateRectRgn(x, y, x + squareSize, y + squareSize); + } + } + } + for (i=0; i<2; i++) { + if (lastDrawnHighlight.sq[i].x != highlightInfo.sq[i].x || + lastDrawnHighlight.sq[i].y != highlightInfo.sq[i].y) { + if (lastDrawnHighlight.sq[i].x >= 0 && + lastDrawnHighlight.sq[i].y >= 0) { + SquareToPos(lastDrawnHighlight.sq[i].y, + lastDrawnHighlight.sq[i].x, &x, &y); + clips[num_clips++] = + CreateRectRgn(x - lineGap, y - lineGap, + x + squareSize + lineGap, y + squareSize + lineGap); + } + if (highlightInfo.sq[i].x >= 0 && highlightInfo.sq[i].y >= 0) { + SquareToPos(highlightInfo.sq[i].y, highlightInfo.sq[i].x, &x, &y); + clips[num_clips++] = + CreateRectRgn(x - lineGap, y - lineGap, + x + squareSize + lineGap, y + squareSize + lineGap); + } + } + } + for (i=0; i<2; i++) { + if (lastDrawnPremove.sq[i].x != premoveHighlightInfo.sq[i].x || + lastDrawnPremove.sq[i].y != premoveHighlightInfo.sq[i].y) { + if (lastDrawnPremove.sq[i].x >= 0 && + lastDrawnPremove.sq[i].y >= 0) { + SquareToPos(lastDrawnPremove.sq[i].y, + lastDrawnPremove.sq[i].x, &x, &y); + clips[num_clips++] = + CreateRectRgn(x - lineGap, y - lineGap, + x + squareSize + lineGap, y + squareSize + lineGap); + } + if (premoveHighlightInfo.sq[i].x >= 0 && + premoveHighlightInfo.sq[i].y >= 0) { + SquareToPos(premoveHighlightInfo.sq[i].y, + premoveHighlightInfo.sq[i].x, &x, &y); + clips[num_clips++] = + CreateRectRgn(x - lineGap, y - lineGap, + x + squareSize + lineGap, y + squareSize + lineGap); + } + } + } + } else { + fullrepaint = TRUE; + } + + /* Create a buffer bitmap - this is the actual bitmap + * being written to. When all the work is done, we can + * copy it to the real DC (the screen). This avoids + * the problems with flickering. + */ + GetClientRect(hwndMain, &Rect); + bufferBitmap = CreateCompatibleBitmap(hdc, Rect.right-Rect.left+1, + Rect.bottom-Rect.top+1); + oldBitmap = SelectObject(hdcmem, bufferBitmap); + if (!appData.monoMode) { + SelectPalette(hdcmem, hPal, FALSE); + } + + /* Create clips for dragging */ + if (!fullrepaint) { + if (dragInfo.from.x >= 0) { + SquareToPos(dragInfo.from.y, dragInfo.from.x, &x, &y); + clips[num_clips++] = CreateRectRgn(x, y, x+squareSize, y+squareSize); + } + if (dragInfo.start.x >= 0) { + SquareToPos(dragInfo.start.y, dragInfo.start.x, &x, &y); + clips[num_clips++] = CreateRectRgn(x, y, x+squareSize, y+squareSize); + } + if (dragInfo.pos.x >= 0) { + x = dragInfo.pos.x - squareSize / 2; + y = dragInfo.pos.y - squareSize / 2; + clips[num_clips++] = CreateRectRgn(x, y, x+squareSize, y+squareSize); + } + if (dragInfo.lastpos.x >= 0) { + x = dragInfo.lastpos.x - squareSize / 2; + y = dragInfo.lastpos.y - squareSize / 2; + clips[num_clips++] = CreateRectRgn(x, y, x+squareSize, y+squareSize); + } + } + + /* If dragging is in progress, we temporarely remove the piece */ + if (dragInfo.from.x >= 0 && dragInfo.pos.x >= 0) { + dragged_piece = board[dragInfo.from.y][dragInfo.from.x]; + board[dragInfo.from.y][dragInfo.from.x] = EmptySquare; + } + + /* Are we animating a move? + * If so, + * - remove the piece from the board (temporarely) + * - calculate the clipping region + */ + if (!fullrepaint) { + if (animInfo.piece != EmptySquare) { + board[animInfo.from.y][animInfo.from.x] = EmptySquare; + x = boardRect.left + animInfo.lastpos.x; + y = boardRect.top + animInfo.lastpos.y; + x2 = boardRect.left + animInfo.pos.x; + y2 = boardRect.top + animInfo.pos.y; + clips[num_clips++] = CreateRectRgn(MIN(x,x2), MIN(y,y2), MAX(x,x2)+squareSize, MAX(y,y2)+squareSize); + /* Slight kludge. The real problem is that after AnimateMove is + done, the position on the screen does not match lastDrawn. + This currently causes trouble only on e.p. captures in + atomic, where the piece moves to an empty square and then + explodes. The old and new positions both had an empty square + at the destination, but animation has drawn a piece there and + we have to remember to erase it. */ + lastDrawn[animInfo.to.y][animInfo.to.x] = animInfo.piece; + } + } + + /* No clips? Make sure we have fullrepaint set to TRUE */ + if (num_clips == 0) + fullrepaint = TRUE; + + /* Set clipping on the memory DC */ + if (!fullrepaint) { + SelectClipRgn(hdcmem, clips[0]); + for (x = 1; x < num_clips; x++) { + if (ExtSelectClipRgn(hdcmem, clips[x], RGN_OR) == ERROR) + abort(); // this should never ever happen! + } + } + + /* Do all the drawing to the memory DC */ + DrawGridOnDC(hdcmem); + DrawHighlightsOnDC(hdcmem); + DrawBoardOnDC(hdcmem, board, tmphdc); + DrawCoordsOnDC(hdcmem); + + /* Put the dragged piece back into place and draw it */ + if (dragged_piece != EmptySquare) { + board[dragInfo.from.y][dragInfo.from.x] = dragged_piece; + x = dragInfo.pos.x - squareSize / 2; + y = dragInfo.pos.y - squareSize / 2; + DrawPieceOnDC(hdcmem, dragged_piece, + ((int) dragged_piece < (int) BlackPawn), + (dragInfo.from.y + dragInfo.from.x) % 2, x, y, tmphdc); + } + + /* Put the animated piece back into place and draw it */ + if (animInfo.piece != EmptySquare) { + board[animInfo.from.y][animInfo.from.x] = animInfo.piece; + x = boardRect.left + animInfo.pos.x; + y = boardRect.top + animInfo.pos.y; + DrawPieceOnDC(hdcmem, animInfo.piece, + ((int) animInfo.piece < (int) BlackPawn), + (animInfo.from.y + animInfo.from.x) % 2, x, y, tmphdc); + } + + /* Release the bufferBitmap by selecting in the old bitmap + * and delete the memory DC + */ + SelectObject(hdcmem, oldBitmap); + DeleteDC(hdcmem); + + /* Set clipping on the target DC */ + if (!fullrepaint) { + SelectClipRgn(hdc, clips[0]); + for (x = 1; x < num_clips; x++) { + if (ExtSelectClipRgn(hdc, clips[x], RGN_OR) == ERROR) + abort(); // this should never ever happen! + } + } + + /* Copy the new bitmap onto the screen in one go. + * This way we avoid any flickering + */ + oldBitmap = SelectObject(tmphdc, bufferBitmap); + BitBlt(hdc, boardRect.left, boardRect.top, + boardRect.right - boardRect.left, + boardRect.bottom - boardRect.top, + tmphdc, boardRect.left, boardRect.top, SRCCOPY); + SelectObject(tmphdc, oldBitmap); + + /* Massive cleanup */ + for (x = 0; x < num_clips; x++) + DeleteObject(clips[x]); + + DeleteDC(tmphdc); + DeleteObject(bufferBitmap); + + if (releaseDC) + ReleaseDC(hwndMain, hdc); + + if (lastDrawnFlipView != flipView) { + if (flipView) + CheckMenuItem(GetMenu(hwndMain),IDM_FlipView, MF_BYCOMMAND|MF_CHECKED); + else + CheckMenuItem(GetMenu(hwndMain),IDM_FlipView, MF_BYCOMMAND|MF_UNCHECKED); + } + + CopyBoard(lastDrawn, board); + lastDrawnHighlight = highlightInfo; + lastDrawnPremove = premoveHighlightInfo; + lastDrawnFlipView = flipView; + lastDrawnValid = 1; +} + + +/*---------------------------------------------------------------------------*\ +| CLIENT PAINT PROCEDURE +| This is the main event-handler for the WM_PAINT message. +| +\*---------------------------------------------------------------------------*/ +VOID +PaintProc(HWND hwnd) +{ + HDC hdc; + PAINTSTRUCT ps; + HFONT oldFont; + + if(hdc = BeginPaint(hwnd, &ps)) { + if (IsIconic(hwnd)) { + DrawIcon(hdc, 2, 2, iconCurrent); + } else { + if (!appData.monoMode) { + SelectPalette(hdc, hPal, FALSE); + RealizePalette(hdc); + } + HDCDrawPosition(hdc, 1, NULL); + oldFont = + SelectObject(hdc, font[boardSize][MESSAGE_FONT]->hf); + ExtTextOut(hdc, messageRect.left, messageRect.top, + ETO_CLIPPED|ETO_OPAQUE, + &messageRect, messageText, strlen(messageText), NULL); + SelectObject(hdc, oldFont); + DisplayBothClocks(); + } + EndPaint(hwnd,&ps); + } + + return; +} + + +/* + * If the user selects on a border boundary, return -1; if off the board, + * return -2. Otherwise map the event coordinate to the square. + * The offset boardRect.left or boardRect.top must already have been + * subtracted from x. + */ +int +EventToSquare(int x) +{ + if (x <= 0) + return -2; + if (x < lineGap) + return -1; + x -= lineGap; + if ((x % (squareSize + lineGap)) >= squareSize) + return -1; + x /= (squareSize + lineGap); + if (x >= BOARD_SIZE) + return -2; + return x; +} + +typedef struct { + char piece; + int command; + char* name; +} DropEnable; + +DropEnable dropEnables[] = { + { 'P', DP_Pawn, "Pawn" }, + { 'N', DP_Knight, "Knight" }, + { 'B', DP_Bishop, "Bishop" }, + { 'R', DP_Rook, "Rook" }, + { 'Q', DP_Queen, "Queen" }, +}; + +VOID +SetupDropMenu(HMENU hmenu) +{ + int i, count, enable; + char *p; + extern char white_holding[], black_holding[]; + char item[MSG_SIZ]; + + for (i=0; i 0 || !appData.testLegality + /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse + && !appData.icsActive); + ModifyMenu(hmenu, dropEnables[i].command, + MF_BYCOMMAND | (enable ? MF_ENABLED : MF_GRAYED) | MF_STRING, + dropEnables[i].command, item); + } +} + +static int fromX = -1, fromY = -1, toX, toY; + +/* Event handler for mouse messages */ +VOID +MouseEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + int x, y; + POINT pt; + static int recursive = 0; + HMENU hmenu; + BOOLEAN saveAnimate; + static BOOLEAN sameAgain = FALSE; + + if (recursive) { + if (message == WM_MBUTTONUP) { + /* Hideous kludge to fool TrackPopupMenu into paying attention + to the middle button: we simulate pressing the left button too! + */ + PostMessage(hwnd, WM_LBUTTONDOWN, wParam, lParam); + PostMessage(hwnd, WM_LBUTTONUP, wParam, lParam); + } + return; + } + recursive++; + + pt.x = LOWORD(lParam); + pt.y = HIWORD(lParam); + x = EventToSquare(pt.x - boardRect.left); + y = EventToSquare(pt.y - boardRect.top); + if (!flipView && y >= 0) { + y = BOARD_SIZE - 1 - y; + } + if (flipView && x >= 0) { + x = BOARD_SIZE - 1 - x; + } + + switch (message) { + case WM_LBUTTONDOWN: + ErrorPopDown(); + sameAgain = FALSE; + if (y == -2) { + /* Downclick vertically off board; check if on clock */ + if (PtInRect((LPRECT) &whiteRect, pt)) { + if (gameMode == EditPosition) { + SetWhiteToPlayEvent(); + } else if (gameMode == IcsPlayingBlack || + gameMode == MachinePlaysWhite) { + CallFlagEvent(); + } + } else if (PtInRect((LPRECT) &blackRect, pt)) { + if (gameMode == EditPosition) { + SetBlackToPlayEvent(); + } else if (gameMode == IcsPlayingWhite || + gameMode == MachinePlaysBlack) { + CallFlagEvent(); + } + } + if (!appData.highlightLastMove) { + ClearHighlights(); + DrawPosition(FALSE, NULL); + } + fromX = fromY = -1; + dragInfo.start.x = dragInfo.start.y = -1; + dragInfo.from = dragInfo.start; + break; + } else if (x < 0 || y < 0) { + break; + } else if (fromX == x && fromY == y) { + /* Downclick on same square again */ + ClearHighlights(); + DrawPosition(FALSE, NULL); + sameAgain = TRUE; + } else if (fromX != -1) { + /* Downclick on different square */ + ChessSquare pdown, pup; + pdown = boards[currentMove][fromY][fromX]; + pup = boards[currentMove][y][x]; + if (gameMode == EditPosition || + !((WhitePawn <= pdown && pdown <= WhiteKing && + WhitePawn <= pup && pup <= WhiteKing) || + (BlackPawn <= pdown && pdown <= BlackKing && + BlackPawn <= pup && pup <= BlackKing))) { + /* EditPosition, empty square, or different color piece; + click-click move is possible */ + toX = x; + toY = y; + if (IsPromotion(fromX, fromY, toX, toY)) { + if (appData.alwaysPromoteToQueen) { + UserMoveEvent(fromX, fromY, toX, toY, 'q'); + if (!appData.highlightLastMove) { + ClearHighlights(); + DrawPosition(FALSE, NULL); + } + } else { + SetHighlights(fromX, fromY, toX, toY); + DrawPosition(FALSE, NULL); + PromotionPopup(hwnd); + } + } else { /* not a promotion */ + if (appData.animate || appData.highlightLastMove) { + SetHighlights(fromX, fromY, toX, toY); + } else { + ClearHighlights(); + } + UserMoveEvent(fromX, fromY, toX, toY, NULLCHAR); + if (appData.animate && !appData.highlightLastMove) { + ClearHighlights(); + DrawPosition(FALSE, NULL); + } + } + if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY); + fromX = fromY = -1; + break; + } + ClearHighlights(); + DrawPosition(FALSE, NULL); + } + /* First downclick, or restart on a square with same color piece */ + if (!frozen && OKToStartUserMove(x, y)) { + fromX = x; + fromY = y; + dragInfo.lastpos = pt; + dragInfo.from.x = fromX; + dragInfo.from.y = fromY; + dragInfo.start = dragInfo.from; + SetCapture(hwndMain); + } else { + fromX = fromY = -1; + dragInfo.start.x = dragInfo.start.y = -1; + dragInfo.from = dragInfo.start; + } + break; + + case WM_LBUTTONUP: + ReleaseCapture(); + if (fromX == -1) break; + if (x == fromX && y == fromY) { + dragInfo.from.x = dragInfo.from.y = -1; + /* Upclick on same square */ + if (sameAgain) { + /* Clicked same square twice: abort click-click move */ + fromX = fromY = -1; + gotPremove = 0; + ClearPremoveHighlights(); + } else { + /* First square clicked: start click-click move */ + SetHighlights(fromX, fromY, -1, -1); + } + DrawPosition(FALSE, NULL); + } else if (dragInfo.from.x < 0 || dragInfo.from.y < 0) { + /* Errant click; ignore */ + break; + } else { + /* Finish drag move */ + dragInfo.from.x = dragInfo.from.y = -1; + toX = x; + toY = y; + saveAnimate = appData.animate; /* sorry, Hawk :) */ + appData.animate = appData.animate && !appData.animateDragging; + if (IsPromotion(fromX, fromY, toX, toY)) { + if (appData.alwaysPromoteToQueen) { + UserMoveEvent(fromX, fromY, toX, toY, 'q'); + } else { + DrawPosition(FALSE, NULL); + PromotionPopup(hwnd); + } + } else { + UserMoveEvent(fromX, fromY, toX, toY, NULLCHAR); + } + if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY); + appData.animate = saveAnimate; + fromX = fromY = -1; + if (appData.highlightDragging && !appData.highlightLastMove) { + ClearHighlights(); + } + if (appData.animate || appData.animateDragging || + appData.highlightDragging || gotPremove) { + DrawPosition(FALSE, NULL); + } + } + dragInfo.start.x = dragInfo.start.y = -1; + dragInfo.pos = dragInfo.lastpos = dragInfo.start; + break; + + case WM_MOUSEMOVE: + if ((appData.animateDragging || appData.highlightDragging) + && (wParam & MK_LBUTTON) + && dragInfo.from.x >= 0) { + if (appData.animateDragging) { + dragInfo.pos = pt; + } + if (appData.highlightDragging) { + SetHighlights(fromX, fromY, x, y); + } + DrawPosition(FALSE, NULL); + dragInfo.lastpos = dragInfo.pos; + } + break; + case WM_MOUSEWHEEL: + { + signed short u = HIWORD(wParam); + fprintf(debugFP, "mouse\n"); + + /* Example: if the mouse wheel is brought forward one click, u is 120. Two clicks, its 240. + if the mouse wheel is brought back one click, its -120, two clicks, -240, etc. */ + + if (u && !(u%WHEEL_DELTA)) { + while(u) { + if (u>0) { + u -= WHEEL_DELTA; + ForwardEvent(); + SetFocus(hwndMain); + } else { + u+= WHEEL_DELTA; + BackwardEvent(); + SetFocus(hwndMain); + } + } + } + } + break; + case WM_MBUTTONDOWN: + case WM_RBUTTONDOWN: + ErrorPopDown(); + ReleaseCapture(); + fromX = fromY = -1; + dragInfo.pos.x = dragInfo.pos.y = -1; + dragInfo.start.x = dragInfo.start.y = -1; + dragInfo.from = dragInfo.start; + dragInfo.lastpos = dragInfo.pos; + if (appData.highlightDragging) { + ClearHighlights(); + } + DrawPosition(TRUE, NULL); + + switch (gameMode) { + case EditPosition: + case IcsExamining: + if (x < 0 || y < 0) break; + fromX = x; + fromY = y; + if (message == WM_MBUTTONDOWN) { + buttonCount = 3; /* even if system didn't think so */ + if (wParam & MK_SHIFT) + MenuPopup(hwnd, pt, LoadMenu(hInst, "BlackPieceMenu"), -1); + else + MenuPopup(hwnd, pt, LoadMenu(hInst, "WhitePieceMenu"), -1); + } else { /* message == WM_RBUTTONDOWN */ +#if 0 + if (buttonCount == 3) { + if (wParam & MK_SHIFT) + MenuPopup(hwnd, pt, LoadMenu(hInst, "WhitePieceMenu"), -1); + else + MenuPopup(hwnd, pt, LoadMenu(hInst, "BlackPieceMenu"), -1); + } else { + MenuPopup(hwnd, pt, LoadMenu(hInst, "PieceMenu"), -1); + } +#else + /* Just have one menu, on the right button. Windows users don't + think to try the middle one, and sometimes other software steals + it, or it doesn't really exist. */ + MenuPopup(hwnd, pt, LoadMenu(hInst, "PieceMenu"), -1); +#endif + } + break; + case IcsPlayingWhite: + case IcsPlayingBlack: + case EditGame: + case MachinePlaysWhite: + case MachinePlaysBlack: + if (appData.testLegality && + gameInfo.variant != VariantBughouse && + gameInfo.variant != VariantCrazyhouse) break; + if (x < 0 || y < 0) break; + fromX = x; + fromY = y; + hmenu = LoadMenu(hInst, "DropPieceMenu"); + SetupDropMenu(hmenu); + MenuPopup(hwnd, pt, hmenu, -1); + break; + default: + break; + } + break; + } + + recursive--; +} + +/* Preprocess messages for buttons in main window */ +LRESULT CALLBACK +ButtonProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + int id = GetWindowLong(hwnd, GWL_ID); + int i, dir; + + for (i=0; inumber > 1) { + GameListPopUp(f, fileTitle); + return; + } + GameListDestroy(); + number = 1; + } + LoadGame(f, number, fileTitle, FALSE); + } +} + +VOID +ChangedConsoleFont() +{ + CHARFORMAT cfmt; + CHARRANGE tmpsel, sel; + MyFont *f = font[boardSize][CONSOLE_FONT]; + HWND hText = GetDlgItem(hwndConsole, OPT_ConsoleText); + HWND hInput = GetDlgItem(hwndConsole, OPT_ConsoleInput); + PARAFORMAT paraf; + + cfmt.cbSize = sizeof(CHARFORMAT); + cfmt.dwMask = CFM_FACE|CFM_SIZE|CFM_CHARSET; + strcpy(cfmt.szFaceName, font[boardSize][CONSOLE_FONT]->mfp.faceName); + /* yHeight is expressed in twips. A twip is 1/20 of a font's point + * size. This was undocumented in the version of MSVC++ that I had + * when I wrote the code, but is apparently documented now. + */ + cfmt.yHeight = (int)(f->mfp.pointSize * 20.0 + 0.5); + cfmt.bCharSet = f->lf.lfCharSet; + cfmt.bPitchAndFamily = f->lf.lfPitchAndFamily; + SendMessage(hText, EM_SETCHARFORMAT, SCF_ALL, (LPARAM) &cfmt); + SendMessage(hInput, EM_SETCHARFORMAT, SCF_ALL, (LPARAM) &cfmt); + /* Why are the following seemingly needed too? */ + SendMessage(hText, EM_SETCHARFORMAT, SCF_DEFAULT, (LPARAM) &cfmt); + SendMessage(hInput, EM_SETCHARFORMAT, SCF_DEFAULT, (LPARAM) &cfmt); + SendMessage(hText, EM_EXGETSEL, 0, (LPARAM)&sel); + tmpsel.cpMin = 0; + tmpsel.cpMax = -1; /*999999?*/ + SendMessage(hText, EM_EXSETSEL, 0, (LPARAM)&tmpsel); + SendMessage(hText, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM) &cfmt); + /* Trying putting this here too. It still seems to tickle a RichEdit + * bug: sometimes RichEdit indents the first line of a paragraph too. + */ + paraf.cbSize = sizeof(paraf); + paraf.dwMask = PFM_OFFSET | PFM_STARTINDENT; + paraf.dxStartIndent = 0; + paraf.dxOffset = WRAP_INDENT; + SendMessage(hText, EM_SETPARAFORMAT, 0, (LPARAM) ¶f); + SendMessage(hText, EM_EXSETSEL, 0, (LPARAM)&sel); +} + +/*---------------------------------------------------------------------------*\ + * + * Window Proc for main window + * +\*---------------------------------------------------------------------------*/ + +/* Process messages for main window, etc. */ +LRESULT CALLBACK +WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + FARPROC lpProc; + int wmId, wmEvent; + char *defName; + FILE *f; + UINT number; + char fileTitle[MSG_SIZ]; + + switch (message) { + + case WM_PAINT: /* message: repaint portion of window */ + PaintProc(hwnd); + break; + + case WM_ERASEBKGND: + if (IsIconic(hwnd)) { + /* Cheat; change the message */ + return (DefWindowProc(hwnd, WM_ICONERASEBKGND, wParam, lParam)); + } else { + return (DefWindowProc(hwnd, message, wParam, lParam)); + } + break; + + case WM_LBUTTONDOWN: + case WM_MBUTTONDOWN: + case WM_RBUTTONDOWN: + case WM_LBUTTONUP: + case WM_MBUTTONUP: + case WM_RBUTTONUP: + case WM_MOUSEMOVE: + case WM_MOUSEWHEEL: + MouseEvent(hwnd, message, wParam, lParam); + break; + + case WM_CHAR: + + if (appData.icsActive) { + if (wParam == '\t') { + if (GetKeyState(VK_SHIFT) < 0) { + /* shifted */ + HWND h = GetDlgItem(hwndConsole, OPT_ConsoleInput); + if (IsIconic(hwndConsole)) ShowWindow(hwndConsole, SW_RESTORE); + SetFocus(h); + } else { + /* unshifted */ + HWND h = GetDlgItem(hwndConsole, OPT_ConsoleText); + if (IsIconic(hwndConsole)) ShowWindow(hwndConsole, SW_RESTORE); + SetFocus(h); + } + } else { + HWND h = GetDlgItem(hwndConsole, OPT_ConsoleInput); + if (IsIconic(hwndConsole)) ShowWindow(hwndConsole, SW_RESTORE); + SetFocus(h); + SendMessage(h, message, wParam, lParam); + } + } else if (isalpha((char)wParam) || isdigit((char)wParam)) { + PopUpMoveDialog((char)wParam); + } + break; + + case WM_PALETTECHANGED: + if (hwnd != (HWND)wParam && !appData.monoMode) { + int nnew; + HDC hdc = GetDC(hwndMain); + SelectPalette(hdc, hPal, TRUE); + nnew = RealizePalette(hdc); + if (nnew > 0) { + paletteChanged = TRUE; +#if 0 + UpdateColors(hdc); +#else + InvalidateRect(hwnd, &boardRect, FALSE);/*faster!*/ +#endif + } + ReleaseDC(hwnd, hdc); + } + break; + + case WM_QUERYNEWPALETTE: + if (!appData.monoMode /*&& paletteChanged*/) { + int nnew; + HDC hdc = GetDC(hwndMain); + paletteChanged = FALSE; + SelectPalette(hdc, hPal, FALSE); + nnew = RealizePalette(hdc); + if (nnew > 0) { + InvalidateRect(hwnd, &boardRect, FALSE); + } + ReleaseDC(hwnd, hdc); + return TRUE; + } + return FALSE; + + case WM_COMMAND: /* message: command from application menu */ + wmId = LOWORD(wParam); + wmEvent = HIWORD(wParam); + + switch (wmId) { + case IDM_NewGame: + ResetGameEvent(); + /* try without */ + /*AnalysisPopDown(); */ + break; + + case IDM_LoadGame: + LoadGameDialog(hwnd, "Load Game from File"); + break; + + case IDM_LoadNextGame: + ReloadGame(1); + break; + + case IDM_LoadPrevGame: + ReloadGame(-1); + break; + + case IDM_ReloadGame: + ReloadGame(0); + break; + + case IDM_LoadPosition: + if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) { + Reset(FALSE, TRUE); + } + number = 1; + f = OpenFileDialog(hwnd, FALSE, "", + appData.oldSaveStyle ? "pos" : "fen", + POSITION_FILT, + "Load Position from File", &number, fileTitle, NULL); + if (f != NULL) { + LoadPosition(f, number, fileTitle); + } + break; + + case IDM_LoadNextPosition: + ReloadPosition(1); + break; + + case IDM_LoadPrevPosition: + ReloadPosition(-1); + break; + + case IDM_ReloadPosition: + ReloadPosition(0); + break; + + case IDM_SaveGame: + defName = DefaultFileName(appData.oldSaveStyle ? "gam" : "pgn"); + f = OpenFileDialog(hwnd, TRUE, defName, + appData.oldSaveStyle ? "gam" : "pgn", + GAME_FILT, + "Save Game to File", NULL, fileTitle, NULL); + if (f != NULL) { + SaveGame(f, 0, ""); + } + break; + + case IDM_SavePosition: + defName = DefaultFileName(appData.oldSaveStyle ? "pos" : "fen"); + f = OpenFileDialog(hwnd, TRUE, defName, + appData.oldSaveStyle ? "pos" : "fen", + POSITION_FILT, + "Save Position to File", NULL, fileTitle, NULL); + if (f != NULL) { + SavePosition(f, 0, ""); + } + break; + + case IDM_CopyGame: + CopyGameToClipboard(); + break; + + case IDM_PasteGame: + PasteGameFromClipboard(); + break; + + case IDM_CopyPosition: + CopyFENToClipboard(); + break; + + case IDM_PastePosition: + PasteFENFromClipboard(); + break; + + case IDM_MailMove: + MailMoveEvent(); + break; + + case IDM_ReloadCMailMsg: + Reset(TRUE, TRUE); + ReloadCmailMsgEvent(FALSE); + break; + + case IDM_Minimize: + ShowWindow(hwnd, SW_MINIMIZE); + break; + + case IDM_focus_EngineRoom: + SetFocus(analysisDialog); + break; + + case IDM_focus_wb: + SetFocus(hwndMain); + break; + + case IDM_Exit: + ExitEvent(0); + break; + + case IDM_MachineWhite: + MachineWhiteEvent(); + /* + * refresh the tags dialog only if it's visible + */ + if (gameMode == MachinePlaysWhite && IsWindowVisible(editTagsDialog)) { + char *tags; + tags = PGNTags(&gameInfo); + TagsPopUp(tags, CmailMsg()); + free(tags); + } + break; + + case IDM_MachineBlack: + MachineBlackEvent(); + /* + * refresh the tags dialog only if it's visible + */ + if (gameMode == MachinePlaysBlack && IsWindowVisible(editTagsDialog)) { + char *tags; + tags = PGNTags(&gameInfo); + TagsPopUp(tags, CmailMsg()); + free(tags); + } + break; + + case IDM_TwoMachines: + TwoMachinesEvent(); + /* + * refresh the tags dialog only if it's visible + */ + if (gameMode == TwoMachinesPlay && IsWindowVisible(editTagsDialog)) { + char *tags; + tags = PGNTags(&gameInfo); + TagsPopUp(tags, CmailMsg()); + free(tags); + } + break; + + case IDM_AnalysisMode: + if (!first.analysisSupport) { + char buf[MSG_SIZ]; + sprintf(buf, "%s does not support analysis", first.tidy); + DisplayError(buf, 0); + } else { + if (!appData.showThinking) ToggleShowThinking(); + AnalyzeModeEvent(); + } + break; + + case IDM_AnalyzeFile: + if (!first.analysisSupport) { + char buf[MSG_SIZ]; + sprintf(buf, "%s does not support analysis", first.tidy); + DisplayError(buf, 0); + } else { + if (!appData.showThinking) ToggleShowThinking(); + AnalyzeFileEvent(); + LoadGameDialog(hwnd, "Analyze Game from File"); + AnalysisPeriodicEvent(1); + } + break; + + case IDM_IcsClient: + IcsClientEvent(); + break; + + case IDM_EditGame: + EditGameEvent(); + break; + + case IDM_EditPosition: + EditPositionEvent(); + break; + + case IDM_Training: + TrainingEvent(); + break; + + case IDM_ShowGameList: + ShowGameListProc(); + break; + + case IDM_EditTags: + EditTagsProc(); + break; + + case IDM_EditComment: + if (commentDialogUp && editComment) { + CommentPopDown(); + } else { + EditCommentEvent(); + } + break; + + case IDM_Pause: + PauseEvent(); + break; + + case IDM_Accept: + AcceptEvent(); + break; + + case IDM_Decline: + DeclineEvent(); + break; + + case IDM_Rematch: + RematchEvent(); + break; + + case IDM_CallFlag: + CallFlagEvent(); + break; + + case IDM_Draw: + DrawEvent(); + break; + + case IDM_Adjourn: + AdjournEvent(); + break; + + case IDM_Abort: + AbortEvent(); + break; + + case IDM_Resign: + ResignEvent(); + break; + + case IDM_StopObserving: + StopObservingEvent(); + break; + + case IDM_StopExamining: + StopExaminingEvent(); + break; + + case IDM_TypeInMove: + PopUpMoveDialog('\000'); + break; + + case IDM_Backward: + BackwardEvent(); + SetFocus(hwndMain); + break; + + case IDM_Forward: + ForwardEvent(); + SetFocus(hwndMain); + break; + + case IDM_ToStart: + ToStartEvent(); + SetFocus(hwndMain); + break; + + case IDM_ToEnd: + ToEndEvent(); + SetFocus(hwndMain); + break; + + case IDM_Revert: + RevertEvent(); + break; + + case IDM_TruncateGame: + TruncateGameEvent(); + break; + + case IDM_MoveNow: + MoveNowEvent(); + break; + + case IDM_RetractMove: + RetractMoveEvent(); + break; + + case IDM_FlipView: + flipView = !flipView; + DrawPosition(FALSE, NULL); + break; + + case IDM_GeneralOptions: + GeneralOptionsPopup(hwnd); + break; + + case IDM_BoardOptions: + BoardOptionsPopup(hwnd); + break; + + case IDM_IcsOptions: + IcsOptionsPopup(hwnd); + break; + + case IDM_ZippyDraw: + icsZippyDrawPopUp(hwnd); + break; + + case IDM_Fonts: + FontsOptionsPopup(hwnd); + break; + + case IDM_Sounds: + SoundOptionsPopup(hwnd); + break; + + case IDM_CommPort: + CommPortOptionsPopup(hwnd); + break; + + case IDM_LoadOptions: + LoadOptionsPopup(hwnd); + break; + + case IDM_SaveOptions: + SaveOptionsPopup(hwnd); + break; + + case IDM_TimeControl: + TimeControlOptionsPopup(hwnd); + break; + + case IDM_SaveSettings: + SaveSettings(settingsFileName); + break; + + case IDM_SaveSettingsOnExit: + saveSettingsOnExit = !saveSettingsOnExit; + (void) CheckMenuItem(GetMenu(hwndMain), IDM_SaveSettingsOnExit, + MF_BYCOMMAND|(saveSettingsOnExit ? + MF_CHECKED : MF_UNCHECKED)); + break; + + case IDM_Hint: + HintEvent(); + break; + + case IDM_Book: + BookEvent(); + break; + + case IDM_AboutGame: + AboutGameEvent(); + break; + + case IDM_Debug: + appData.debugMode = !appData.debugMode; + if (appData.debugMode) { + char dir[MSG_SIZ]; + GetCurrentDirectory(MSG_SIZ, dir); + SetCurrentDirectory(installDir); + debugFP = fopen("WinBoard.debug", "w"); + SetCurrentDirectory(dir); + setbuf(debugFP, NULL); + } else { + fclose(debugFP); + debugFP = NULL; + } + break; + + case IDM_HELPCONTENTS: + if (!WinHelp (hwnd, "winboard.hlp", HELP_KEY,(DWORD)(LPSTR)"CONTENTS")) { + MessageBox (GetFocus(), + "Unable to activate help", + szAppName, MB_SYSTEMMODAL|MB_OK|MB_ICONHAND); + } + break; + + case IDM_HELPSEARCH: + if (!WinHelp(hwnd, "winboard.hlp", HELP_PARTIALKEY, (DWORD)(LPSTR)"")) { + MessageBox (GetFocus(), + "Unable to activate help", + szAppName, MB_SYSTEMMODAL|MB_OK|MB_ICONHAND); + } + break; + + case IDM_HELPHELP: + if(!WinHelp(hwnd, (LPSTR)NULL, HELP_HELPONHELP, 0)) { + MessageBox (GetFocus(), + "Unable to activate help", + szAppName, MB_SYSTEMMODAL|MB_OK|MB_ICONHAND); + } + break; + + case IDM_ABOUT: + lpProc = MakeProcInstance((FARPROC)About, hInst); + DialogBox(hInst, + (gameInfo.event && strcmp(gameInfo.event, "Easter Egg Hunt") == 0) ? + "AboutBox2" : "AboutBox", hwnd, (DLGPROC)lpProc); + FreeProcInstance(lpProc); + break; + + case IDM_DirectCommand1: + AskQuestionEvent("Direct Command", + "Send to chess program:", "", "1"); + break; + case IDM_DirectCommand2: + AskQuestionEvent("Direct Command", + "Send to second chess program:", "", "2"); + break; + + case EP_WhitePawn: + EditPositionMenuEvent(WhitePawn, fromX, fromY); + fromX = fromY = -1; + break; + + case EP_WhiteKnight: + EditPositionMenuEvent(WhiteKnight, fromX, fromY); + fromX = fromY = -1; + break; + + case EP_WhiteBishop: + EditPositionMenuEvent(WhiteBishop, fromX, fromY); + fromX = fromY = -1; + break; + + case EP_WhiteRook: + EditPositionMenuEvent(WhiteRook, fromX, fromY); + fromX = fromY = -1; + break; + + case EP_WhiteQueen: + EditPositionMenuEvent(WhiteQueen, fromX, fromY); + fromX = fromY = -1; + break; + + case EP_WhiteKing: + EditPositionMenuEvent(WhiteKing, fromX, fromY); + fromX = fromY = -1; + break; + + case EP_BlackPawn: + EditPositionMenuEvent(BlackPawn, fromX, fromY); + fromX = fromY = -1; + break; + + case EP_BlackKnight: + EditPositionMenuEvent(BlackKnight, fromX, fromY); + fromX = fromY = -1; + break; + + case EP_BlackBishop: + EditPositionMenuEvent(BlackBishop, fromX, fromY); + fromX = fromY = -1; + break; + + case EP_BlackRook: + EditPositionMenuEvent(BlackRook, fromX, fromY); + fromX = fromY = -1; + break; + + case EP_BlackQueen: + EditPositionMenuEvent(BlackQueen, fromX, fromY); + fromX = fromY = -1; + break; + + case EP_BlackKing: + EditPositionMenuEvent(BlackKing, fromX, fromY); + fromX = fromY = -1; + break; + + case EP_EmptySquare: + EditPositionMenuEvent(EmptySquare, fromX, fromY); + fromX = fromY = -1; + break; + + case EP_ClearBoard: + EditPositionMenuEvent(ClearBoard, fromX, fromY); + fromX = fromY = -1; + break; + + case EP_White: + EditPositionMenuEvent(WhitePlay, fromX, fromY); + fromX = fromY = -1; + break; + + case EP_Black: + EditPositionMenuEvent(BlackPlay, fromX, fromY); + fromX = fromY = -1; + break; + + case DP_Pawn: + DropMenuEvent(WhitePawn, fromX, fromY); + fromX = fromY = -1; + break; + + case DP_Knight: + DropMenuEvent(WhiteKnight, fromX, fromY); + fromX = fromY = -1; + break; + + case DP_Bishop: + DropMenuEvent(WhiteBishop, fromX, fromY); + fromX = fromY = -1; + break; + + case DP_Rook: + DropMenuEvent(WhiteRook, fromX, fromY); + fromX = fromY = -1; + break; + + case DP_Queen: + DropMenuEvent(WhiteQueen, fromX, fromY); + fromX = fromY = -1; + break; + + default: + return (DefWindowProc(hwnd, message, wParam, lParam)); + } + break; + + case WM_TIMER: + switch (wParam) { + case CLOCK_TIMER_ID: + KillTimer(hwnd, clockTimerEvent); /* Simulate one-shot timer as in X */ + clockTimerEvent = 0; + DecrementClocks(); /* call into back end */ + break; + case LOAD_GAME_TIMER_ID: + KillTimer(hwnd, loadGameTimerEvent); /* Simulate one-shot timer as in X*/ + loadGameTimerEvent = 0; + AutoPlayGameLoop(); /* call into back end */ + break; + case ANALYSIS_TIMER_ID: + /* dirty hack without stat line and support */ + if ((gameMode == AnalyzeMode || gameMode == AnalyzeFile || + appData.icsAnalyzeWindow || appData.AnalysisWindow) && + appData.periodicUpdates) { + AnalysisPeriodicEvent(0); + } else { + KillTimer(hwnd, analysisTimerEvent); + analysisTimerEvent = 0; + } + break; + case DELAYED_TIMER_ID: + KillTimer(hwnd, delayedTimerEvent); + delayedTimerEvent = 0; + delayedTimerCallback(); + break; + } + break; + + case WM_USER_Input: + InputEvent(hwnd, message, wParam, lParam); + break; + + case WM_ENTERSIZEMOVE: + if (hwnd == hwndMain) { + doingSizing = TRUE; + lastSizing = 0; + } + break; + + case WM_SIZING: + if (hwnd == hwndMain) { + lastSizing = wParam; + } + break; + + case WM_EXITSIZEMOVE: + if (hwnd == hwndMain) { + RECT client; + doingSizing = FALSE; + InvalidateRect(hwnd, &boardRect, FALSE); + GetClientRect(hwnd, &client); + ResizeBoard(client.right, client.bottom, lastSizing); + lastSizing = 0; + } + break; + + case WM_DESTROY: /* message: window being destroyed */ + PostQuitMessage(0); + break; + + case WM_CLOSE: + if (hwnd == hwndMain) { + ExitEvent(0); + } + break; + + default: /* Passes it on if unprocessed */ + return (DefWindowProc(hwnd, message, wParam, lParam)); + } + return 0; +} + +/*---------------------------------------------------------------------------*\ + * + * Misc utility routines + * +\*---------------------------------------------------------------------------*/ + +/* + * returns TRUE if user selects a different color, FALSE otherwise + */ + +BOOL +ChangeColor(HWND hwnd, COLORREF *which) +{ + static BOOL firstTime = TRUE; + static DWORD customColors[16]; + CHOOSECOLOR cc; + COLORREF newcolor; + int i; + ColorClass ccl; + + if (firstTime) { + /* Make initial colors in use available as custom colors */ + /* Should we put the compiled-in defaults here instead? */ + i = 0; + customColors[i++] = lightSquareColor & 0xffffff; + customColors[i++] = darkSquareColor & 0xffffff; + customColors[i++] = whitePieceColor & 0xffffff; + customColors[i++] = blackPieceColor & 0xffffff; + customColors[i++] = highlightSquareColor & 0xffffff; + customColors[i++] = premoveHighlightColor & 0xffffff; + + for (ccl = (ColorClass) 0; ccl < NColorClasses && i < 16; ccl++) { + customColors[i++] = textAttribs[ccl].color; + } + while (i < 16) customColors[i++] = RGB(255, 255, 255); + firstTime = FALSE; + } + + cc.lStructSize = sizeof(cc); + cc.hwndOwner = hwnd; + cc.hInstance = NULL; + cc.rgbResult = (DWORD) (*which & 0xffffff); + cc.lpCustColors = (LPDWORD) customColors; + cc.Flags = CC_RGBINIT|CC_FULLOPEN; + + if (!ChooseColor(&cc)) return FALSE; + + newcolor = (COLORREF) (0x2000000 | cc.rgbResult); + if (newcolor == *which) return FALSE; + *which = newcolor; + return TRUE; + + /* + InitDrawingColors(); + InvalidateRect(hwnd, &boardRect, FALSE); + */ +} + +BOOLEAN +MyLoadSound(MySound *ms) +{ + BOOL ok = FALSE; + struct stat st; + FILE *f; + + if (ms->data) free(ms->data); + ms->data = NULL; + + switch (ms->name[0]) { + case NULLCHAR: + /* Silence */ + ok = TRUE; + break; + case '$': + /* System sound from Control Panel. Don't preload here. */ + ok = TRUE; + break; + case '!': + if (ms->name[1] == NULLCHAR) { + /* "!" alone = silence */ + ok = TRUE; + } else { + /* Builtin wave resource. Error if not found. */ + HANDLE h = FindResource(hInst, ms->name + 1, "WAVE"); + if (h == NULL) break; + ms->data = (void *)LoadResource(hInst, h); + if (h == NULL) break; + ok = TRUE; + } + break; + default: + /* .wav file. Error if not found. */ + f = fopen(ms->name, "rb"); + if (f == NULL) break; + if (fstat(fileno(f), &st) < 0) break; + ms->data = malloc(st.st_size); + if (fread(ms->data, st.st_size, 1, f) < 1) break; + fclose(f); + ok = TRUE; + break; + } + if (!ok) { + char buf[MSG_SIZ]; + sprintf(buf, "Error loading sound %s", ms->name); + DisplayError(buf, GetLastError()); + } + return ok; +} + +BOOLEAN +MyPlaySound(MySound *ms) +{ + BOOLEAN ok = FALSE; + switch (ms->name[0]) { + case NULLCHAR: + /* Silence */ + ok = TRUE; + break; + case '$': + /* System sound from Control Panel (deprecated feature). + "$" alone or an unset sound name gets default beep (still in use). */ + if (ms->name[1]) { + ok = PlaySound(ms->name + 1, NULL, SND_ALIAS|SND_ASYNC); + } + if (!ok) ok = MessageBeep(MB_OK); + break; + case '!': + /* Builtin wave resource, or "!" alone for silence */ + if (ms->name[1]) { + if (ms->data == NULL) return FALSE; + ok = PlaySound(ms->data, NULL, SND_MEMORY|SND_ASYNC); + } else { + ok = TRUE; + } + break; + default: + /* .wav file. Error if not found. */ + if (ms->data == NULL) return FALSE; + ok = PlaySound(ms->data, NULL, SND_MEMORY|SND_ASYNC); + break; + } + /* Don't print an error: this can happen innocently if the sound driver + is busy; for instance, if another instance of WinBoard is playing + a sound at about the same time. */ +#if 0 + if (!ok) { + char buf[MSG_SIZ]; + sprintf(buf, "Error playing sound %s", ms->name); + DisplayError(buf, GetLastError()); + } +#endif + return ok; +} + + +LRESULT CALLBACK +OldOpenFileHook(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + BOOL ok; + OPENFILENAME *ofn; + static UINT *number; /* gross that this is static */ + + switch (message) { + case WM_INITDIALOG: /* message: initialize dialog box */ + /* Center the dialog over the application window */ + ofn = (OPENFILENAME *) lParam; + if (ofn->Flags & OFN_ENABLETEMPLATE) { + number = (UINT *) ofn->lCustData; + SendMessage(GetDlgItem(hDlg, edt2), WM_SETTEXT, 0, (LPARAM) ""); + } else { + number = NULL; + } + CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER)); + return FALSE; /* Allow for further processing */ + + case WM_COMMAND: + if ((LOWORD(wParam) == IDOK) && (number != NULL)) { + *number = GetDlgItemInt(hDlg, OPT_IndexNumberOld, &ok, FALSE); + } + return FALSE; /* Allow for further processing */ + } + return FALSE; +} + +UINT APIENTRY +OpenFileHook(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam) +{ + static UINT *number; + OPENFILENAME *ofname; + OFNOTIFY *ofnot; + switch (uiMsg) { + case WM_INITDIALOG: + ofname = (OPENFILENAME *)lParam; + number = (UINT *)(ofname->lCustData); + break; + case WM_NOTIFY: + ofnot = (OFNOTIFY *)lParam; + if (ofnot->hdr.code == CDN_FILEOK) { + *number = GetDlgItemInt(hdlg, OPT_IndexNumber, NULL, FALSE); + } + break; + } + return 0; +} + + +FILE * +OpenFileDialog(HWND hwnd, BOOL write, char *defName, char *defExt, + char *nameFilt, char *dlgTitle, UINT *number, + char fileTitle[MSG_SIZ], char fileName[MSG_SIZ]) +{ + OPENFILENAME openFileName; + char buf1[MSG_SIZ]; + FILE *f; + + if (fileName == NULL) fileName = buf1; + if (defName == NULL) { + strcpy(fileName, "*."); + strcat(fileName, defExt); + } else { + strcpy(fileName, defName); + } + if (fileTitle) strcpy(fileTitle, ""); + if (number) *number = 0; + + openFileName.lStructSize = sizeof(OPENFILENAME); + openFileName.hwndOwner = hwnd; + openFileName.hInstance = (HANDLE) hInst; + openFileName.lpstrFilter = nameFilt; + openFileName.lpstrCustomFilter = (LPSTR) NULL; + openFileName.nMaxCustFilter = 0L; + openFileName.nFilterIndex = 1L; + openFileName.lpstrFile = fileName; + openFileName.nMaxFile = MSG_SIZ; + openFileName.lpstrFileTitle = fileTitle; + openFileName.nMaxFileTitle = fileTitle ? MSG_SIZ : 0; + openFileName.lpstrInitialDir = NULL; + openFileName.lpstrTitle = dlgTitle; + openFileName.Flags = OFN_PATHMUSTEXIST | OFN_HIDEREADONLY + | (write ? 0 : OFN_FILEMUSTEXIST) + | (number ? OFN_ENABLETEMPLATE | OFN_ENABLEHOOK: 0) + | (oldDialog ? 0 : OFN_EXPLORER); + openFileName.nFileOffset = 0; + openFileName.nFileExtension = 0; + openFileName.lpstrDefExt = defExt; + openFileName.lCustData = (LONG) number; + openFileName.lpfnHook = oldDialog ? + (LPOFNHOOKPROC) OldOpenFileHook : (LPOFNHOOKPROC) OpenFileHook; + openFileName.lpTemplateName = (LPSTR)(oldDialog ? 1536 : DLG_IndexNumber); + + if (write ? GetSaveFileName(&openFileName) : + GetOpenFileName(&openFileName)) { + /* open the file */ + f = fopen(openFileName.lpstrFile, write ? "a" : "r"); + if (f == NULL) { + MessageBox(hwnd, "File open failed", NULL, + MB_OK|MB_ICONEXCLAMATION); + return NULL; + } + } else { + int err = CommDlgExtendedError(); + if (err != 0) DisplayError("Internal error in file dialog box", err); + return FALSE; + } + return f; +} + + + +VOID APIENTRY +MenuPopup(HWND hwnd, POINT pt, HMENU hmenu, UINT def) +{ + HMENU hmenuTrackPopup; /* floating pop-up menu */ + + /* + * Get the first pop-up menu in the menu template. This is the + * menu that TrackPopupMenu displays. + */ + hmenuTrackPopup = GetSubMenu(hmenu, 0); + + SetMenuDefaultItem(hmenuTrackPopup, def, FALSE); + + /* + * TrackPopup uses screen coordinates, so convert the + * coordinates of the mouse click to screen coordinates. + */ + ClientToScreen(hwnd, (LPPOINT) &pt); + + /* Draw and track the floating pop-up menu. */ + TrackPopupMenu(hmenuTrackPopup, TPM_CENTERALIGN | TPM_RIGHTBUTTON, + pt.x, pt.y, 0, hwnd, NULL); + + /* Destroy the menu.*/ + DestroyMenu(hmenu); +} + +typedef struct { + HWND hDlg, hText; + int sizeX, sizeY, newSizeX, newSizeY; + HDWP hdwp; +} ResizeEditPlusButtonsClosure; + +BOOL CALLBACK +ResizeEditPlusButtonsCallback(HWND hChild, LPARAM lparam) +{ + ResizeEditPlusButtonsClosure *cl = (ResizeEditPlusButtonsClosure *)lparam; + RECT rect; + POINT pt; + + if (hChild == cl->hText) return TRUE; + GetWindowRect(hChild, &rect); /* gives screen coords */ + pt.x = rect.left + (cl->newSizeX - cl->sizeX)/2; + pt.y = rect.top + cl->newSizeY - cl->sizeY; + ScreenToClient(cl->hDlg, &pt); + cl->hdwp = DeferWindowPos(cl->hdwp, hChild, NULL, + pt.x, pt.y, rect.right - rect.left, rect.bottom - rect.top, SWP_NOZORDER); + return TRUE; +} + +/* Resize a dialog that has a (rich) edit field filling most of + the top, with a row of buttons below */ +VOID +ResizeEditPlusButtons(HWND hDlg, HWND hText, int sizeX, int sizeY, int newSizeX, int newSizeY) +{ + RECT rectText; + int newTextHeight, newTextWidth; + ResizeEditPlusButtonsClosure cl; + + /*if (IsIconic(hDlg)) return;*/ + if (newSizeX == sizeX && newSizeY == sizeY) return; + + cl.hdwp = BeginDeferWindowPos(8); + + GetWindowRect(hText, &rectText); /* gives screen coords */ + newTextWidth = rectText.right - rectText.left + newSizeX - sizeX; + newTextHeight = rectText.bottom - rectText.top + newSizeY - sizeY; + if (newTextHeight < 0) { + newSizeY += -newTextHeight; + newTextHeight = 0; + } + cl.hdwp = DeferWindowPos(cl.hdwp, hText, NULL, 0, 0, + newTextWidth, newTextHeight, SWP_NOZORDER|SWP_NOMOVE); + + cl.hDlg = hDlg; + cl.hText = hText; + cl.sizeX = sizeX; + cl.sizeY = sizeY; + cl.newSizeX = newSizeX; + cl.newSizeY = newSizeY; + EnumChildWindows(hDlg, ResizeEditPlusButtonsCallback, (LPARAM)&cl); + + EndDeferWindowPos(cl.hdwp); +} + +/* Center one window over another */ +BOOL CenterWindow (HWND hwndChild, HWND hwndParent) +{ + RECT rChild, rParent; + int wChild, hChild, wParent, hParent; + int wScreen, hScreen, xNew, yNew; + HDC hdc; + + /* Get the Height and Width of the child window */ + GetWindowRect (hwndChild, &rChild); + wChild = rChild.right - rChild.left; + hChild = rChild.bottom - rChild.top; + + /* Get the Height and Width of the parent window */ + GetWindowRect (hwndParent, &rParent); + wParent = rParent.right - rParent.left; + hParent = rParent.bottom - rParent.top; + + /* Get the display limits */ + hdc = GetDC (hwndChild); + wScreen = GetDeviceCaps (hdc, HORZRES); + hScreen = GetDeviceCaps (hdc, VERTRES); + ReleaseDC(hwndChild, hdc); + + /* Calculate new X position, then adjust for screen */ + xNew = rParent.left + ((wParent - wChild) /2); + if (xNew < 0) { + xNew = 0; + } else if ((xNew+wChild) > wScreen) { + xNew = wScreen - wChild; + } + + /* Calculate new Y position, then adjust for screen */ + yNew = rParent.top + ((hParent - hChild) /2); + if (yNew < 0) { + yNew = 0; + } else if ((yNew+hChild) > hScreen) { + yNew = hScreen - hChild; + } + + /* Set it, and return */ + return SetWindowPos (hwndChild, NULL, + xNew, yNew, 0, 0, SWP_NOSIZE | SWP_NOZORDER); +} + +/*---------------------------------------------------------------------------*\ + * + * Startup Dialog functions + * +\*---------------------------------------------------------------------------*/ +void +InitComboStrings(HANDLE hwndCombo, char **cd) +{ + SendMessage(hwndCombo, CB_RESETCONTENT, 0, 0); + + while (*cd != NULL) { + SendMessage(hwndCombo, CB_ADDSTRING, 0, (LPARAM) *cd); + cd++; + } +} + +void +InitComboStringsFromOption(HANDLE hwndCombo, char *str) +{ + char buf1[ARG_MAX]; + int len; + + if (str[0] == '@') { + FILE* f = fopen(str + 1, "r"); + if (f == NULL) { + DisplayFatalError(str + 1, errno, 2); + return; + } + len = fread(buf1, 1, sizeof(buf1)-1, f); + fclose(f); + buf1[len] = NULLCHAR; + str = buf1; + } + + SendMessage(hwndCombo, CB_RESETCONTENT, 0, 0); + + for (;;) { + char buf[MSG_SIZ]; + char *end = strchr(str, '\n'); + if (end == NULL) return; + memcpy(buf, str, end - str); + buf[end - str] = NULLCHAR; + SendMessage(hwndCombo, CB_ADDSTRING, 0, (LPARAM) buf); + str = end + 1; + } +} + +void +SetStartupDialogEnables(HWND hDlg) +{ + EnableWindow(GetDlgItem(hDlg, OPT_ChessEngineName), + IsDlgButtonChecked(hDlg, OPT_ChessEngine) || + appData.zippyPlay && IsDlgButtonChecked(hDlg, OPT_ChessServer)); + EnableWindow(GetDlgItem(hDlg, OPT_SecondChessEngineName), + IsDlgButtonChecked(hDlg, OPT_ChessEngine)); + EnableWindow(GetDlgItem(hDlg, OPT_ChessServerName), + IsDlgButtonChecked(hDlg, OPT_ChessServer)); + EnableWindow(GetDlgItem(hDlg, OPT_AdditionalOptions), + IsDlgButtonChecked(hDlg, OPT_AnyAdditional)); + EnableWindow(GetDlgItem(hDlg, IDOK), + IsDlgButtonChecked(hDlg, OPT_ChessEngine) || + IsDlgButtonChecked(hDlg, OPT_ChessServer) || + IsDlgButtonChecked(hDlg, OPT_View)); +} + +char * +QuoteForFilename(char *filename) +{ + int dquote, space; + dquote = strchr(filename, '"') != NULL; + space = strchr(filename, ' ') != NULL; + if (dquote || space) { + if (dquote) { + return "'"; + } else { + return "\""; + } + } else { + return ""; + } +} + +VOID +InitEngineBox(HWND hDlg, HWND hwndCombo, char* nthcp, char* nthd, char* nthdir, char *nthnames) +{ + char buf[MSG_SIZ]; + char *q; + + InitComboStringsFromOption(hwndCombo, nthnames); + q = QuoteForFilename(nthcp); + sprintf(buf, "%s%s%s", q, nthcp, q); + if (*nthdir != NULLCHAR) { + q = QuoteForFilename(nthdir); + sprintf(buf + strlen(buf), " /%s=%s%s%s", nthd, q, nthdir, q); + } + if (*nthcp == NULLCHAR) { + SendMessage(hwndCombo, CB_SETCURSEL, (WPARAM) 0, (LPARAM) 0); + } else if (SendMessage(hwndCombo, CB_SELECTSTRING, (WPARAM) -1, (LPARAM) buf) == CB_ERR) { + SendMessage(hwndCombo, CB_SETCURSEL, (WPARAM) -1, (LPARAM) 0); + SendMessage(hwndCombo, WM_SETTEXT, (WPARAM) 0, (LPARAM) buf); + } +} + +LRESULT CALLBACK +StartupDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + char buf[MSG_SIZ]; + HANDLE hwndCombo; + char *p; + + switch (message) { + case WM_INITDIALOG: + /* Center the dialog */ + CenterWindow (hDlg, GetDesktopWindow()); + /* Initialize the dialog items */ + InitEngineBox(hDlg, GetDlgItem(hDlg, OPT_ChessEngineName), + appData.firstChessProgram, "fd", appData.firstDirectory, + firstChessProgramNames); + InitEngineBox(hDlg, GetDlgItem(hDlg, OPT_SecondChessEngineName), + appData.secondChessProgram, "sd", appData.secondDirectory, + secondChessProgramNames); + hwndCombo = GetDlgItem(hDlg, OPT_ChessServerName); + InitComboStringsFromOption(hwndCombo, icsNames); + sprintf(buf, "%s /icsport=%s", appData.icsHost, appData.icsPort); + if (*appData.icsHelper != NULLCHAR) { + char *q = QuoteForFilename(appData.icsHelper); + sprintf(buf + strlen(buf), " /icshelper=%s%s%s", q, appData.icsHelper, q); + } + if (*appData.icsHost == NULLCHAR) { + SendMessage(hwndCombo, CB_SETCURSEL, (WPARAM) 0, (LPARAM) 0); + /*SendMessage(hwndCombo, CB_SHOWDROPDOWN, (WPARAM) TRUE, (LPARAM) 0); !!too soon */ + } else if (SendMessage(hwndCombo, CB_SELECTSTRING, (WPARAM) -1, (LPARAM) buf) == CB_ERR) { + SendMessage(hwndCombo, CB_SETCURSEL, (WPARAM) -1, (LPARAM) 0); + SendMessage(hwndCombo, WM_SETTEXT, (WPARAM) 0, (LPARAM) buf); + } + if (chessProgram) { + CheckDlgButton(hDlg, OPT_ChessEngine, BST_CHECKED); + } else if (appData.icsActive) { + CheckDlgButton(hDlg, OPT_ChessServer, BST_CHECKED); + } else if (appData.noChessProgram) { + CheckDlgButton(hDlg, OPT_View, BST_CHECKED); + } + SetStartupDialogEnables(hDlg); + return TRUE; + + case WM_COMMAND: + switch (LOWORD(wParam)) { + case IDOK: + if (IsDlgButtonChecked(hDlg, OPT_ChessEngine)) { + strcpy(buf, "/fcp="); + GetDlgItemText(hDlg, OPT_ChessEngineName, buf + strlen(buf), sizeof(buf) - strlen(buf)); + p = buf; + ParseArgs(StringGet, &p); + strcpy(buf, "/scp="); + GetDlgItemText(hDlg, OPT_SecondChessEngineName, buf + strlen(buf), sizeof(buf) - strlen(buf)); + p = buf; + ParseArgs(StringGet, &p); + appData.noChessProgram = FALSE; + appData.icsActive = FALSE; + } else if (IsDlgButtonChecked(hDlg, OPT_ChessServer)) { + strcpy(buf, "/ics /icshost="); + GetDlgItemText(hDlg, OPT_ChessServerName, buf + strlen(buf), sizeof(buf) - strlen(buf)); + p = buf; + ParseArgs(StringGet, &p); + if (appData.zippyPlay) { + strcpy(buf, "/fcp="); + GetDlgItemText(hDlg, OPT_ChessEngineName, buf + strlen(buf), sizeof(buf) - strlen(buf)); + p = buf; + ParseArgs(StringGet, &p); + } + } else if (IsDlgButtonChecked(hDlg, OPT_View)) { + appData.noChessProgram = TRUE; + appData.icsActive = FALSE; + } else { + MessageBox(hDlg, "Choose an option, or cancel to exit", + "Option Error", MB_OK|MB_ICONEXCLAMATION); + return TRUE; + } + if (IsDlgButtonChecked(hDlg, OPT_AnyAdditional)) { + GetDlgItemText(hDlg, OPT_AdditionalOptions, buf, sizeof(buf)); + p = buf; + ParseArgs(StringGet, &p); + } + EndDialog(hDlg, TRUE); + return TRUE; + + case IDCANCEL: + ExitEvent(0); + return TRUE; + + case IDM_HELPCONTENTS: + if (!WinHelp (hDlg, "winboard.hlp", HELP_KEY,(DWORD)(LPSTR)"CONTENTS")) { + MessageBox (GetFocus(), + "Unable to activate help", + szAppName, MB_SYSTEMMODAL|MB_OK|MB_ICONHAND); + } + break; + + default: + SetStartupDialogEnables(hDlg); + break; + } + break; + } + return FALSE; +} + +/*---------------------------------------------------------------------------*\ + * + * About box dialog functions + * +\*---------------------------------------------------------------------------*/ + +/* Process messages for "About" dialog box */ +LRESULT CALLBACK +About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch (message) { + case WM_INITDIALOG: /* message: initialize dialog box */ + /* Center the dialog over the application window */ + CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER)); + SetDlgItemText(hDlg, ABOUTBOX_Version, programVersion); + return (TRUE); + + case WM_COMMAND: /* message: received a command */ + if (LOWORD(wParam) == IDOK /* "OK" box selected? */ + || LOWORD(wParam) == IDCANCEL) { /* System menu close command? */ + EndDialog(hDlg, TRUE); /* Exit the dialog */ + return (TRUE); + } + break; + } + return (FALSE); +} + +/*---------------------------------------------------------------------------*\ + * + * Comment Dialog functions + * +\*---------------------------------------------------------------------------*/ + +LRESULT CALLBACK +CommentDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + static HANDLE hwndText = NULL; + int len, newSizeX, newSizeY, flags; + static int sizeX, sizeY; + char *str; + RECT rect; + MINMAXINFO *mmi; + + switch (message) { + case WM_INITDIALOG: /* message: initialize dialog box */ + /* Initialize the dialog items */ + hwndText = GetDlgItem(hDlg, OPT_CommentText); + SetDlgItemText(hDlg, OPT_CommentText, commentText); + EnableWindow(GetDlgItem(hDlg, OPT_CancelComment), editComment); + EnableWindow(GetDlgItem(hDlg, OPT_ClearComment), editComment); + EnableWindow(GetDlgItem(hDlg, OPT_EditComment), !editComment); + SendMessage(hwndText, EM_SETREADONLY, !editComment, 0); + SetWindowText(hDlg, commentTitle); + if (editComment) { + SetFocus(hwndText); + } else { + SetFocus(GetDlgItem(hDlg, IDOK)); + } + SendMessage(GetDlgItem(hDlg, OPT_CommentText), + WM_SETFONT, (WPARAM)font[boardSize][COMMENT_FONT]->hf, + MAKELPARAM(FALSE, 0)); + /* Size and position the dialog */ + if (!commentDialog) { + commentDialog = hDlg; + flags = SWP_NOZORDER; + GetClientRect(hDlg, &rect); + sizeX = rect.right; + sizeY = rect.bottom; + if (commentX != CW_USEDEFAULT && commentY != CW_USEDEFAULT && + commentW != CW_USEDEFAULT && commentH != CW_USEDEFAULT) { + WINDOWPLACEMENT wp; + EnsureOnScreen(&commentX, &commentY); + wp.length = sizeof(WINDOWPLACEMENT); + wp.flags = 0; + wp.showCmd = SW_SHOW; + wp.ptMaxPosition.x = wp.ptMaxPosition.y = 0; + wp.rcNormalPosition.left = commentX; + wp.rcNormalPosition.right = commentX + commentW; + wp.rcNormalPosition.top = commentY; + wp.rcNormalPosition.bottom = commentY + commentH; + SetWindowPlacement(hDlg, &wp); + + GetClientRect(hDlg, &rect); + newSizeX = rect.right; + newSizeY = rect.bottom; + ResizeEditPlusButtons(hDlg, hwndText, sizeX, sizeY, + newSizeX, newSizeY); + sizeX = newSizeX; + sizeY = newSizeY; + } + } + return FALSE; + + case WM_COMMAND: /* message: received a command */ + switch (LOWORD(wParam)) { + case IDOK: + if (editComment) { + char *p, *q; + /* Read changed options from the dialog box */ + hwndText = GetDlgItem(hDlg, OPT_CommentText); + len = GetWindowTextLength(hwndText); + str = (char *) malloc(len + 1); + GetWindowText(hwndText, str, len + 1); + p = q = str; + while (*q) { + if (*q == '\r') + q++; + else + *p++ = *q++; + } + *p = NULLCHAR; + ReplaceComment(commentIndex, str); + free(str); + } + CommentPopDown(); + return TRUE; + + case IDCANCEL: + case OPT_CancelComment: + CommentPopDown(); + return TRUE; + + case OPT_ClearComment: + SetDlgItemText(hDlg, OPT_CommentText, ""); + break; + + case OPT_EditComment: + EditCommentEvent(); + return TRUE; + + default: + break; + } + break; + + case WM_SIZE: + newSizeX = LOWORD(lParam); + newSizeY = HIWORD(lParam); + ResizeEditPlusButtons(hDlg, hwndText, sizeX, sizeY, newSizeX, newSizeY); + sizeX = newSizeX; + sizeY = newSizeY; + break; + + case WM_GETMINMAXINFO: + /* Prevent resizing window too small */ + mmi = (MINMAXINFO *) lParam; + mmi->ptMinTrackSize.x = 100; + mmi->ptMinTrackSize.y = 100; + break; + } + return FALSE; +} + +VOID +EitherCommentPopUp(int index, char *title, char *str, BOOLEAN edit) +{ + FARPROC lpProc; + char *p, *q; + + CheckMenuItem(GetMenu(hwndMain), IDM_EditComment, edit ? MF_CHECKED : MF_UNCHECKED); + + if (str == NULL) str = ""; + p = (char *) malloc(2 * strlen(str) + 2); + q = p; + while (*str) { + if (*str == '\n') *q++ = '\r'; + *q++ = *str++; + } + *q = NULLCHAR; + if (commentText != NULL) free(commentText); + + commentIndex = index; + commentTitle = title; + commentText = p; + editComment = edit; + + if (commentDialog) { + SendMessage(commentDialog, WM_INITDIALOG, 0, 0); + if (!commentDialogUp) ShowWindow(commentDialog, SW_SHOW); + } else { + lpProc = MakeProcInstance((FARPROC)CommentDialog, hInst); + CreateDialog(hInst, MAKEINTRESOURCE(DLG_EditComment), + hwndMain, (DLGPROC)lpProc); + FreeProcInstance(lpProc); + } + commentDialogUp = TRUE; +} + + +/*---------------------------------------------------------------------------*\ + * + * Type-in move dialog functions + * +\*---------------------------------------------------------------------------*/ + +LRESULT CALLBACK +TypeInMoveDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + char move[MSG_SIZ]; + HWND hInput; + ChessMove moveType; + int fromX, fromY, toX, toY; + char promoChar; + + switch (message) { + case WM_INITDIALOG: + move[0] = (char) lParam; + move[1] = NULLCHAR; + CenterWindow(hDlg, GetWindow(hDlg, GW_OWNER)); + hInput = GetDlgItem(hDlg, OPT_Move); + SetWindowText(hInput, move); + SetFocus(hInput); + SendMessage(hInput, EM_SETSEL, (WPARAM)9999, (LPARAM)9999); + return FALSE; + + case WM_COMMAND: + switch (LOWORD(wParam)) { + case IDOK: + if (gameMode != EditGame && currentMove != forwardMostMove && + gameMode != Training) { + DisplayMoveError("Displayed move is not current"); + } else { + GetDlgItemText(hDlg, OPT_Move, move, sizeof(move)); + if (ParseOneMove(move, gameMode == EditPosition ? blackPlaysFirst : currentMove, + &moveType, &fromX, &fromY, &toX, &toY, &promoChar)) { + if (gameMode != Training) + forwardMostMove = currentMove; + UserMoveEvent(fromX, fromY, toX, toY, promoChar); + } else { + DisplayMoveError("Could not parse move"); + } + } + EndDialog(hDlg, TRUE); + return TRUE; + case IDCANCEL: + EndDialog(hDlg, FALSE); + return TRUE; + default: + break; + } + break; + } + return FALSE; +} + +VOID +PopUpMoveDialog(char firstchar) +{ + FARPROC lpProc; + + if ((gameMode == BeginningOfGame && !appData.icsActive) || + gameMode == MachinePlaysWhite || gameMode == MachinePlaysBlack || + gameMode == AnalyzeMode || gameMode == EditGame || + gameMode == EditPosition || gameMode == IcsExamining || + gameMode == IcsPlayingWhite || gameMode == IcsPlayingBlack || + gameMode == Training) { + lpProc = MakeProcInstance((FARPROC)TypeInMoveDialog, hInst); + DialogBoxParam(hInst, MAKEINTRESOURCE(DLG_TypeInMove), + hwndMain, (DLGPROC)lpProc, (LPARAM)firstchar); + FreeProcInstance(lpProc); + } +} + +/*---------------------------------------------------------------------------*\ + * + * Error dialogs + * +\*---------------------------------------------------------------------------*/ + +/* Nonmodal error box */ +VOID +ErrorPopDown() +{ + if (!appData.popupMoveErrors && moveErrorMessageUp) DisplayMessage("", ""); + if (errorDialog == NULL) return; + DestroyWindow(errorDialog); + errorDialog = NULL; +} + +LRESULT CALLBACK +ErrorDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + HANDLE hwndText; + RECT rChild; + + switch (message) { + case WM_INITDIALOG: + GetWindowRect(hDlg, &rChild); + SetWindowPos(hDlg, NULL, rChild.left, + rChild.top + boardRect.top - (rChild.bottom - rChild.top), + 0, 0, SWP_NOZORDER|SWP_NOSIZE); + errorDialog = hDlg; + hwndText = GetDlgItem(hDlg, OPT_ErrorText); + SetDlgItemText(hDlg, OPT_ErrorText, errorMessage); + return FALSE; + + case WM_COMMAND: + switch (LOWORD(wParam)) { + case IDOK: + case IDCANCEL: + if (errorDialog = hDlg) errorDialog = NULL; + DestroyWindow(hDlg); + return TRUE; + + default: + break; + } + break; + } + return FALSE; +} + +/*---------------------------------------------------------------------------*\ + * + * Ics Interaction console functions + * +\*---------------------------------------------------------------------------*/ + +#define HISTORY_SIZE 64 +static char *history[HISTORY_SIZE]; +int histIn = 0, histP = 0; + +VOID +SaveInHistory(char *cmd) +{ + if (history[histIn] != NULL) { + free(history[histIn]); + history[histIn] = NULL; + } + if (*cmd == NULLCHAR) return; + history[histIn] = StrSave(cmd); + histIn = (histIn + 1) % HISTORY_SIZE; + if (history[histIn] != NULL) { + free(history[histIn]); + history[histIn] = NULL; + } + histP = histIn; +} + +char * +PrevInHistory(char *cmd) +{ + int newhp; + if (histP == histIn) { + if (history[histIn] != NULL) free(history[histIn]); + history[histIn] = StrSave(cmd); + } + newhp = (histP - 1 + HISTORY_SIZE) % HISTORY_SIZE; + if (newhp == histIn || history[newhp] == NULL) return NULL; + histP = newhp; + return history[histP]; +} + +char * +NextInHistory() +{ + if (histP == histIn) return NULL; + histP = (histP + 1) % HISTORY_SIZE; + return history[histP]; +} + +typedef struct { + char *item; + char *command; + BOOLEAN getname; + BOOLEAN immediate; +} IcsTextMenuEntry; +#define ICS_TEXT_MENU_SIZE (IDM_CommandXLast - IDM_CommandX + 1) +IcsTextMenuEntry icsTextMenuEntry[ICS_TEXT_MENU_SIZE]; + +void +ParseIcsTextMenu(char *icsTextMenuString) +{ + int flags = 0; + IcsTextMenuEntry *e = icsTextMenuEntry; + char *p = icsTextMenuString; + while (e->item != NULL && e < icsTextMenuEntry + ICS_TEXT_MENU_SIZE) { + free(e->item); + e->item = NULL; + if (e->command != NULL) { + free(e->command); + e->command = NULL; + } + e++; + } + e = icsTextMenuEntry; + while (*p && e < icsTextMenuEntry + ICS_TEXT_MENU_SIZE) { + if (*p == ';' || *p == '\n') { + e->item = strdup("-"); + e->command = NULL; + p++; + } else if (*p == '-') { + e->item = strdup("-"); + e->command = NULL; + p++; + if (*p) p++; + } else { + char *q, *r, *s, *t; + char c; + q = strchr(p, ','); + if (q == NULL) break; + *q = NULLCHAR; + r = strchr(q + 1, ','); + if (r == NULL) break; + *r = NULLCHAR; + s = strchr(r + 1, ','); + if (s == NULL) break; + *s = NULLCHAR; + c = ';'; + t = strchr(s + 1, c); + if (t == NULL) { + c = '\n'; + t = strchr(s + 1, c); + } + if (t != NULL) *t = NULLCHAR; + e->item = strdup(p); + e->command = strdup(q + 1); + e->getname = *(r + 1) != '0'; + e->immediate = *(s + 1) != '0'; + *q = ','; + *r = ','; + *s = ','; + if (t == NULL) break; + *t = c; + p = t + 1; + } + e++; + } +} + +HMENU +LoadIcsTextMenu(IcsTextMenuEntry *e) +{ + HMENU hmenu, h; + int i = 0; + hmenu = LoadMenu(hInst, "TextMenu"); + h = GetSubMenu(hmenu, 0); + while (e->item) { + if (strcmp(e->item, "-") == 0) { + AppendMenu(h, MF_SEPARATOR, 0, 0); + } else { + if (e->item[0] == '|') { + AppendMenu(h, MF_STRING|MF_MENUBARBREAK, + IDM_CommandX + i, &e->item[1]); + } else { + AppendMenu(h, MF_STRING, IDM_CommandX + i, e->item); + } + } + e++; + i++; + } + return hmenu; +} + +WNDPROC consoleTextWindowProc; +WNDPROC PvWindowProc; +WNDPROC NameWindowProc; + +void +CommandX(HWND hwnd, char *command, BOOLEAN getname, BOOLEAN immediate) +{ + char buf[MSG_SIZ], name[MSG_SIZ]; + HWND hInput = GetDlgItem(hwndConsole, OPT_ConsoleInput); + CHARRANGE sel; + + if (!getname) { + SetWindowText(hInput, command); + if (immediate) { + SendMessage(hInput, WM_CHAR, '\r', 0); + } else { + sel.cpMin = 999999; + sel.cpMax = 999999; + SendMessage(hInput, EM_EXSETSEL, 0, (LPARAM)&sel); + SetFocus(hInput); + } + return; + } + SendMessage(hwnd, EM_EXGETSEL, 0, (LPARAM)&sel); + if (sel.cpMin == sel.cpMax) { + /* Expand to surrounding word */ + TEXTRANGE tr; + do { + tr.chrg.cpMax = sel.cpMin; + tr.chrg.cpMin = --sel.cpMin; + if (sel.cpMin < 0) break; + tr.lpstrText = name; + SendMessage(hwnd, EM_GETTEXTRANGE, 0, (LPARAM) &tr); + } while (isalpha(name[0]) || isdigit(name[0]) || name[0] == '-'); + sel.cpMin++; + + do { + tr.chrg.cpMin = sel.cpMax; + tr.chrg.cpMax = ++sel.cpMax; + tr.lpstrText = name; + if (SendMessage(hwnd, EM_GETTEXTRANGE, 0, (LPARAM) &tr) < 1) break; + } while (isalpha(name[0]) || isdigit(name[0]) || name[0] == '-'); + sel.cpMax--; + + if (sel.cpMax == sel.cpMin || sel.cpMax - sel.cpMin > MSG_SIZ/2) { + MessageBeep(MB_ICONEXCLAMATION); + return; + } + tr.chrg = sel; + tr.lpstrText = name; + SendMessage(hwnd, EM_GETTEXTRANGE, 0, (LPARAM) &tr); + } else { + if (sel.cpMax - sel.cpMin > MSG_SIZ/2) { + MessageBeep(MB_ICONEXCLAMATION); + return; + } + SendMessage(hwnd, EM_GETSELTEXT, 0, (LPARAM) name); + } + if (immediate) { + sprintf(buf, "%s %s", command, name); + SetWindowText(hInput, buf); + SendMessage(hInput, WM_CHAR, '\r', 0); + } else { + sprintf(buf, "%s %s ", command, name); /* trailing space */ + SetWindowText(hInput, buf); + sel.cpMin = 999999; + sel.cpMax = 999999; + SendMessage(hInput, EM_EXSETSEL, 0, (LPARAM)&sel); + SetFocus(hInput); + } +} + +LRESULT CALLBACK +ConsoleTextSubclass(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + HWND hInput; + CHARRANGE sel; + + switch (message) { + case WM_KEYDOWN: + if (!(GetKeyState(VK_CONTROL) & ~1)) break; + switch (wParam) { + case VK_PRIOR: + SendMessage(hwnd, EM_LINESCROLL, 0, -999999); + return 0; + case VK_NEXT: + sel.cpMin = 999999; + sel.cpMax = 999999; + SendMessage(hwnd, EM_EXSETSEL, 0, (LPARAM)&sel); + SendMessage(hwnd, EM_SCROLLCARET, 0, 0); + return 0; + } + break; + case WM_CHAR: + if (wParam == '\t') { + if (GetKeyState(VK_SHIFT) < 0) { + /* shifted */ + if (IsIconic(hwndMain)) ShowWindow(hwndMain, SW_RESTORE); + if (buttonDesc[0].hwnd) { + SetFocus(buttonDesc[0].hwnd); + } else { + SetFocus(hwndMain); + } + } else { + /* unshifted */ + SetFocus(GetDlgItem(hwndConsole, OPT_ConsoleInput)); + } + } else { + hInput = GetDlgItem(hwndConsole, OPT_ConsoleInput); + SetFocus(hInput); + SendMessage(hInput, message, wParam, lParam); + } + return 0; + case WM_PASTE: + hInput = GetDlgItem(hwndConsole, OPT_ConsoleInput); + SetFocus(hInput); + return SendMessage(hInput, message, wParam, lParam); + case WM_MBUTTONDOWN: + return SendMessage(hwnd, WM_COMMAND, MAKEWPARAM(IDM_QuickPaste, 0), 0); + case WM_RBUTTONDOWN: + if (!(GetKeyState(VK_SHIFT) & ~1)) { + /* Move selection here if it was empty */ + POINT pt; + pt.x = LOWORD(lParam); + pt.y = HIWORD(lParam); + SendMessage(hwnd, EM_EXGETSEL, 0, (LPARAM)&sel); + if (sel.cpMin == sel.cpMax) { + sel.cpMin = SendMessage(hwnd, EM_CHARFROMPOS, 0, (LPARAM)&pt); /*doc is wrong*/ + sel.cpMax = sel.cpMin; + SendMessage(hwnd, EM_EXSETSEL, 0, (LPARAM)&sel); + } + SendMessage(hwnd, EM_HIDESELECTION, FALSE, FALSE); + } + return 0; + case WM_RBUTTONUP: + if (GetKeyState(VK_SHIFT) & ~1) { + SendDlgItemMessage(hwndConsole, OPT_ConsoleText, + WM_COMMAND, MAKEWPARAM(IDM_QuickPaste, 0), 0); + } else { + POINT pt; + HMENU hmenu = LoadIcsTextMenu(icsTextMenuEntry); + SendMessage(hwnd, EM_EXGETSEL, 0, (LPARAM)&sel); + if (!IsClipboardFormatAvailable(CF_TEXT)) { + EnableMenuItem(hmenu, IDM_Paste, MF_BYCOMMAND|MF_GRAYED); + } + pt.x = LOWORD(lParam); + pt.y = HIWORD(lParam); + MenuPopup(hwnd, pt, hmenu, -1); + } + return 0; + case WM_COMMAND: + switch (LOWORD(wParam)) { + case IDM_QuickPaste: + { + SendMessage(hwnd, EM_EXGETSEL, 0, (LPARAM)&sel); + if (sel.cpMin == sel.cpMax) { + MessageBeep(MB_ICONEXCLAMATION); + return 0; + } + SendMessage(hwnd, WM_COPY, 0, 0); + hInput = GetDlgItem(hwndConsole, OPT_ConsoleInput); + SendMessage(hInput, WM_PASTE, 0, 0); + SetFocus(hInput); + return 0; + } + case IDM_Cut: + SendMessage(hwnd, WM_CUT, 0, 0); + return 0; + case IDM_Paste: + SendMessage(hwnd, WM_PASTE, 0, 0); + return 0; + case IDM_Copy: + SendMessage(hwnd, WM_COPY, 0, 0); + return 0; + default: + { + int i = LOWORD(wParam) - IDM_CommandX; + if (i >= 0 && i < ICS_TEXT_MENU_SIZE && + icsTextMenuEntry[i].command != NULL) { + CommandX(hwnd, icsTextMenuEntry[i].command, + icsTextMenuEntry[i].getname, + icsTextMenuEntry[i].immediate); + return 0; + } + } + break; + } + break; + } + return (*consoleTextWindowProc)(hwnd, message, wParam, lParam); +} + +WNDPROC consoleInputWindowProc; + +LRESULT CALLBACK +ConsoleInputSubclass(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + char buf[MSG_SIZ]; + char *p; + static BOOL sendNextChar = FALSE; + static BOOL quoteNextChar = FALSE; + InputSource *is = consoleInputSource; + CHARFORMAT cf; + CHARRANGE sel; + + switch (message) { + case WM_CHAR: + if (!appData.localLineEditing || sendNextChar) { + is->buf[0] = (CHAR) wParam; + is->count = 1; + SendMessage(hwndMain, WM_USER_Input, 0, (LPARAM) is); + sendNextChar = FALSE; + return 0; + } + if (quoteNextChar) { + buf[0] = (char) wParam; + buf[1] = NULLCHAR; + SendMessage(hwnd, EM_REPLACESEL, TRUE, (LPARAM) buf); + quoteNextChar = FALSE; + return 0; + } + switch (wParam) { + case '\r': /* Enter key */ + is->count = GetWindowText(hwnd, is->buf, INPUT_SOURCE_BUF_SIZE-1); + if (consoleEcho) SaveInHistory(is->buf); + is->buf[is->count++] = '\n'; + is->buf[is->count] = NULLCHAR; + SendMessage(hwndMain, WM_USER_Input, 0, (LPARAM) is); + if (consoleEcho) { + ConsoleOutput(is->buf, is->count, TRUE); + } else if (appData.localLineEditing) { + ConsoleOutput("\n", 1, TRUE); + } + /* fall thru */ + case '\033': /* Escape key */ + SetWindowText(hwnd, ""); + cf.cbSize = sizeof(CHARFORMAT); + cf.dwMask = CFM_COLOR|CFM_BOLD|CFM_ITALIC|CFM_UNDERLINE|CFM_STRIKEOUT; + if (consoleEcho) { + cf.crTextColor = textAttribs[ColorNormal].color; + } else { + cf.crTextColor = COLOR_ECHOOFF; + } + cf.dwEffects = textAttribs[ColorNormal].effects; + SendMessage(hwnd, EM_SETCHARFORMAT, SCF_ALL, (LPARAM)&cf); + return 0; + case '\t': /* Tab key */ + if (GetKeyState(VK_SHIFT) < 0) { + /* shifted */ + SetFocus(GetDlgItem(hwndConsole, OPT_ConsoleText)); + } else { + /* unshifted */ + if (IsIconic(hwndMain)) ShowWindow(hwndMain, SW_RESTORE); + if (buttonDesc[0].hwnd) { + SetFocus(buttonDesc[0].hwnd); + } else { + SetFocus(hwndMain); + } + } + return 0; + case '\023': /* Ctrl+S */ + sendNextChar = TRUE; + return 0; + case '\021': /* Ctrl+Q */ + quoteNextChar = TRUE; + return 0; + default: + break; + } + break; + case WM_KEYDOWN: + switch (wParam) { + case VK_UP: + GetWindowText(hwnd, buf, MSG_SIZ); + p = PrevInHistory(buf); + if (p != NULL) { + SetWindowText(hwnd, p); + sel.cpMin = 999999; + sel.cpMax = 999999; + SendMessage(hwnd, EM_EXSETSEL, 0, (LPARAM)&sel); + return 0; + } + break; + case VK_DOWN: + p = NextInHistory(); + if (p != NULL) { + SetWindowText(hwnd, p); + sel.cpMin = 999999; + sel.cpMax = 999999; + SendMessage(hwnd, EM_EXSETSEL, 0, (LPARAM)&sel); + return 0; + } + break; + case VK_HOME: + case VK_END: + if (!(GetKeyState(VK_CONTROL) & ~1)) break; + /* fall thru */ + case VK_PRIOR: + case VK_NEXT: + SendDlgItemMessage(hwndConsole, OPT_ConsoleText, message, wParam, lParam); + return 0; + } + break; + case WM_MBUTTONDOWN: + SendDlgItemMessage(hwndConsole, OPT_ConsoleText, + WM_COMMAND, MAKEWPARAM(IDM_QuickPaste, 0), 0); + break; + case WM_RBUTTONUP: + if (GetKeyState(VK_SHIFT) & ~1) { + SendDlgItemMessage(hwndConsole, OPT_ConsoleText, + WM_COMMAND, MAKEWPARAM(IDM_QuickPaste, 0), 0); + } else { + POINT pt; + HMENU hmenu; + hmenu = LoadMenu(hInst, "InputMenu"); + SendMessage(hwnd, EM_EXGETSEL, 0, (LPARAM)&sel); + if (sel.cpMin == sel.cpMax) { + EnableMenuItem(hmenu, IDM_Copy, MF_BYCOMMAND|MF_GRAYED); + EnableMenuItem(hmenu, IDM_Cut, MF_BYCOMMAND|MF_GRAYED); + } + if (!IsClipboardFormatAvailable(CF_TEXT)) { + EnableMenuItem(hmenu, IDM_Paste, MF_BYCOMMAND|MF_GRAYED); + } + pt.x = LOWORD(lParam); + pt.y = HIWORD(lParam); + MenuPopup(hwnd, pt, hmenu, -1); + } + return 0; + case WM_COMMAND: + switch (LOWORD(wParam)) { + case IDM_Undo: + SendMessage(hwnd, EM_UNDO, 0, 0); + return 0; + case IDM_SelectAll: + sel.cpMin = 0; + sel.cpMax = -1; /*999999?*/ + SendMessage(hwnd, EM_EXSETSEL, 0, (LPARAM)&sel); + return 0; + case IDM_Cut: + SendMessage(hwnd, WM_CUT, 0, 0); + return 0; + case IDM_Paste: + SendMessage(hwnd, WM_PASTE, 0, 0); + return 0; + case IDM_Copy: + SendMessage(hwnd, WM_COPY, 0, 0); + return 0; + } + break; + } + return (*consoleInputWindowProc)(hwnd, message, wParam, lParam); +} + +#define CO_MAX 100000 +#define CO_TRIM 1000 + +LRESULT CALLBACK +ConsoleWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + static HWND hText, hInput, hFocus; + InputSource *is = consoleInputSource; + RECT rect; + static int sizeX, sizeY; + int newSizeX, newSizeY; + MINMAXINFO *mmi; + + switch (message) { + case WM_INITDIALOG: /* message: initialize dialog box */ + hwndConsole = hDlg; + hText = GetDlgItem(hDlg, OPT_ConsoleText); + hInput = GetDlgItem(hDlg, OPT_ConsoleInput); + SetFocus(hInput); + consoleTextWindowProc = (WNDPROC) + SetWindowLong(hText, GWL_WNDPROC, (LONG) ConsoleTextSubclass); + SendMessage(hText, EM_SETBKGNDCOLOR, FALSE, consoleBackgroundColor); + consoleInputWindowProc = (WNDPROC) + SetWindowLong(hInput, GWL_WNDPROC, (LONG) ConsoleInputSubclass); + SendMessage(hInput, EM_SETBKGNDCOLOR, FALSE, consoleBackgroundColor); + Colorize(ColorNormal, TRUE); + SendMessage(hInput, EM_SETCHARFORMAT, SCF_ALL, (LPARAM) &consoleCF); + ChangedConsoleFont(); + GetClientRect(hDlg, &rect); + sizeX = rect.right; + sizeY = rect.bottom; + if (consoleX != CW_USEDEFAULT && consoleY != CW_USEDEFAULT && + consoleW != CW_USEDEFAULT && consoleH != CW_USEDEFAULT) { + WINDOWPLACEMENT wp; + EnsureOnScreen(&consoleX, &consoleY); + wp.length = sizeof(WINDOWPLACEMENT); + wp.flags = 0; + wp.showCmd = SW_SHOW; + wp.ptMaxPosition.x = wp.ptMaxPosition.y = 0; + wp.rcNormalPosition.left = consoleX; + wp.rcNormalPosition.right = consoleX + consoleW; + wp.rcNormalPosition.top = consoleY; + wp.rcNormalPosition.bottom = consoleY + consoleH; + SetWindowPlacement(hDlg, &wp); + } + return FALSE; + + case WM_SETFOCUS: + SetFocus(hInput); + return 0; + + case WM_CLOSE: + ExitEvent(0); + /* not reached */ + break; + + case WM_SIZE: + if (IsIconic(hDlg)) break; + newSizeX = LOWORD(lParam); + newSizeY = HIWORD(lParam); + if (sizeX != newSizeX || sizeY != newSizeY) { + RECT rectText, rectInput; + POINT pt; + int newTextHeight, newTextWidth; + GetWindowRect(hText, &rectText); + newTextWidth = rectText.right - rectText.left + newSizeX - sizeX; + newTextHeight = rectText.bottom - rectText.top + newSizeY - sizeY; + if (newTextHeight < 0) { + newSizeY += -newTextHeight; + newTextHeight = 0; + } + SetWindowPos(hText, NULL, 0, 0, + newTextWidth, newTextHeight, SWP_NOZORDER|SWP_NOMOVE); + GetWindowRect(hInput, &rectInput); /* gives screen coords */ + pt.x = rectInput.left; + pt.y = rectInput.top + newSizeY - sizeY; + ScreenToClient(hDlg, &pt); + SetWindowPos(hInput, NULL, + pt.x, pt.y, /* needs client coords */ + rectInput.right - rectInput.left + newSizeX - sizeX, + rectInput.bottom - rectInput.top, SWP_NOZORDER); + } + sizeX = newSizeX; + sizeY = newSizeY; + break; + + case WM_GETMINMAXINFO: + /* Prevent resizing window too small */ + mmi = (MINMAXINFO *) lParam; + mmi->ptMinTrackSize.x = 100; + mmi->ptMinTrackSize.y = 100; + break; + } + return DefWindowProc(hDlg, message, wParam, lParam); +} + + +VOID +ConsoleCreate() +{ + HWND hCons; + if (hwndConsole) return; + hCons = CreateDialog(hInst, szConsoleName, 0, NULL); + SendMessage(hCons, WM_INITDIALOG, 0, 0); +} + +BOOL httpseglight_continued = FALSE; +char *spitlight(HWND hText, char *p, ColorClass cc, CHARRANGE *sel) { + int effects; + char *urlstart = p; + char backup; + httpseglight_continued = TRUE; + backup = 0; + while (*p) { + switch(*p) { + case '\n': case '\r': case ' ': case '\t': + backup = *p; *p = 0; httpseglight_continued = FALSE; break; + default: p++; + } + } + effects = consoleCF.dwEffects; + consoleCF.crTextColor = textAttribs[ColorKibitz].color; + consoleCF.dwEffects |= CFM_UNDERLINE; + SendMessage(hText, EM_EXSETSEL, 0, (LPARAM)sel); + SendMessage(hText, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&consoleCF); + SendMessage(hText, EM_REPLACESEL, 0, (LPARAM) urlstart); + sel->cpMax = sel->cpMin += p - urlstart; + consoleCF.crTextColor = textAttribs[currentColorClass].color; + consoleCF.dwEffects = effects; + SendMessage(hText, EM_EXSETSEL, 0, (LPARAM)sel); + SendMessage(hText, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&consoleCF); + *p = backup; + return p; +} + +char *strnpstr(char *p, char *needle, char *end) { + char *loc; + char *o = needle; + while (p < end) { + if (*p == *o) { + if (o==needle) loc = p; + o++; + } else o = needle; + if (*o == 0) return loc; + p++; + } + return p=NULL; + } +int seglight(HWND hText, char *p, char *end, char *seg, int seglen, ColorClass cc, CHARRANGE *sel) { + char *op, *urlstart; + if (p==NULL || seg == NULL || sel == NULL) return -1; + if (httpseglight_continued) { + p = spitlight(hText, p, cc, sel); + } + while (end-p >= seglen && (urlstart = strnpstr(p, seg, end)) != NULL) { + op = urlstart; + *op = 0; + SendMessage(hText, EM_REPLACESEL, 0, (LPARAM) p); + sel->cpMax = sel->cpMin += op - p; + *op = seg[0]; + p = spitlight(hText, op, cc, sel); + } + if (end-p>0) { + SendMessage(hText, EM_REPLACESEL, 0, (LPARAM) p); + sel->cpMax = sel->cpMin += end-p; + } + return 0; +} + +VOID +ConsoleOutput(char* data, int length, int forceVisible) +{ + HWND hText; + int trim, exlen; + char *p, *q; + char buf[CO_MAX+1]; + POINT pEnd; + RECT rect; + static int delayLF = 0; + CHARRANGE savesel, sel; + + if (hwndConsole == NULL || length > CO_MAX-100 || length == 0) return; + p = data; + q = buf; + if (delayLF) { + *q++ = '\r'; + *q++ = '\n'; + delayLF = 0; + } + while (length--) { + if (*p == '\n') { + if (*++p) { + *q++ = '\r'; + *q++ = '\n'; + } else { + delayLF = 1; + } + } else if (*p == '\007') { + MyPlaySound(&sounds[(int)SoundBell]); + p++; + } else { + *q++ = *p++; + } + } + *q = NULLCHAR; + hText = GetDlgItem(hwndConsole, OPT_ConsoleText); + SendMessage(hText, EM_HIDESELECTION, TRUE, FALSE); + /* Save current selection */ + SendMessage(hText, EM_EXGETSEL, 0, (LPARAM)&savesel); + exlen = GetWindowTextLength(hText); + /* Find out whether current end of text is visible */ + SendMessage(hText, EM_GETRECT, 0, (LPARAM) &rect); + SendMessage(hText, EM_POSFROMCHAR, (WPARAM) &pEnd, exlen); + /* Trim existing text if it's too long */ + if (exlen + (q - buf) > CO_MAX) { + trim = (CO_TRIM > (q - buf)) ? CO_TRIM : (q - buf); + sel.cpMin = 0; + sel.cpMax = trim; + SendMessage(hText, EM_EXSETSEL, 0, (LPARAM)&sel); + SendMessage(hText, EM_REPLACESEL, 0, (LPARAM)""); + exlen -= trim; + savesel.cpMin -= trim; + savesel.cpMax -= trim; + if (exlen < 0) exlen = 0; + if (savesel.cpMin < 0) savesel.cpMin = 0; + if (savesel.cpMax < savesel.cpMin) savesel.cpMax = savesel.cpMin; + } + /* Append the new text */ + sel.cpMin = exlen; + sel.cpMax = exlen; + SendMessage(hText, EM_EXSETSEL, 0, (LPARAM)&sel); + SendMessage(hText, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&consoleCF); + + /* append text while checking for and highlight links */ + seglight(hText, buf, q, "http://", 7, ColorKibitz, &sel); + + if (forceVisible || exlen == 0 || + (rect.left <= pEnd.x && pEnd.x < rect.right && + rect.top <= pEnd.y && pEnd.y < rect.bottom)) { + /* Scroll to make new end of text visible if old end of text + was visible or new text is an echo of user typein */ + sel.cpMin = 9999999; + sel.cpMax = 9999999; + SendMessage(hText, EM_EXSETSEL, 0, (LPARAM)&sel); + SendMessage(hText, EM_HIDESELECTION, FALSE, FALSE); + SendMessage(hText, EM_SCROLLCARET, 0, 0); + SendMessage(hText, EM_HIDESELECTION, TRUE, FALSE); + } + if (savesel.cpMax == exlen || forceVisible) { + /* Move insert point to new end of text if it was at the old + end of text or if the new text is an echo of user typein */ + sel.cpMin = 9999999; + sel.cpMax = 9999999; + SendMessage(hText, EM_EXSETSEL, 0, (LPARAM)&sel); + } else { + /* Restore previous selection */ + SendMessage(hText, EM_EXSETSEL, 0, (LPARAM)&savesel); + } + SendMessage(hText, EM_HIDESELECTION, FALSE, FALSE); +} + +/*---------*/ + + +void +DisplayAClock(HDC hdc, int timeRemaining, int highlight, + RECT *rect, char *color) +{ + char buf[100]; + char *str; + COLORREF oldFg, oldBg; + HFONT oldFont; + + if (appData.clockMode) { + if (tinyLayout) + sprintf(buf, "%c %s", color[0], TimeString(timeRemaining)); + else + sprintf(buf, "%s: %s", color, TimeString(timeRemaining)); + str = buf; + } else { + str = color; + } + + if (highlight) { + oldFg = SetTextColor(hdc, RGB(255, 255, 255)); /* white */ + oldBg = SetBkColor(hdc, RGB(0, 0, 0)); /* black */ + } else { + oldFg = SetTextColor(hdc, RGB(0, 0, 0)); /* black */ + oldBg = SetBkColor(hdc, RGB(255, 255, 255)); /* white */ + } + oldFont = SelectObject(hdc, font[boardSize][CLOCK_FONT]->hf); + + ExtTextOut(hdc, rect->left + MESSAGE_LINE_LEFTMARGIN, + rect->top, ETO_CLIPPED|ETO_OPAQUE, + rect, str, strlen(str), NULL); + + (void) SetTextColor(hdc, oldFg); + (void) SetBkColor(hdc, oldBg); + (void) SelectObject(hdc, oldFont); +} + + +int +DoReadFile(HANDLE hFile, char *buf, int count, DWORD *outCount, + OVERLAPPED *ovl) +{ + int ok, err; + + ResetEvent(ovl->hEvent); + ovl->Offset = ovl->OffsetHigh = 0; + ok = ReadFile(hFile, buf, count, outCount, ovl); + if (ok) { + err = NO_ERROR; + } else { + err = GetLastError(); + if (err == ERROR_IO_PENDING) { + ok = GetOverlappedResult(hFile, ovl, outCount, TRUE); + if (ok) + err = NO_ERROR; + else + err = GetLastError(); + } + } + return err; +} + +int +DoWriteFile(HANDLE hFile, char *buf, int count, DWORD *outCount, + OVERLAPPED *ovl) +{ + int ok, err; + + ResetEvent(ovl->hEvent); + ovl->Offset = ovl->OffsetHigh = 0; + ok = WriteFile(hFile, buf, count, outCount, ovl); + if (ok) { + err = NO_ERROR; + } else { + err = GetLastError(); + if (err == ERROR_IO_PENDING) { + ok = GetOverlappedResult(hFile, ovl, outCount, TRUE); + if (ok) + err = NO_ERROR; + else + err = GetLastError(); + } + } + return err; +} + + +DWORD +InputThread(LPVOID arg) +{ + InputSource *is; + OVERLAPPED ovl; + + is = (InputSource *) arg; + ovl.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + ovl.Internal = ovl.InternalHigh = ovl.Offset = ovl.OffsetHigh = 0; + while (is->hThread != NULL) { + is->error = DoReadFile(is->hFile, is->next, + INPUT_SOURCE_BUF_SIZE - (is->next - is->buf), + &is->count, &ovl); + if (is->error == NO_ERROR) { + is->next += is->count; + } else { + if (is->error == ERROR_BROKEN_PIPE) { + /* Correct for MS brain damage. EOF reading a pipe is not an error. */ + is->count = 0; + } else { + is->count = (DWORD) -1; + } + } + SendMessage(hwndMain, WM_USER_Input, 0, (LPARAM) is); + if (is->count <= 0) break; /* Quit on EOF or error */ + } + CloseHandle(ovl.hEvent); + CloseHandle(is->hFile); + return 0; +} + + +/* Windows 95 beta 2 won't let you do overlapped i/o on a console or pipe */ +DWORD +NonOvlInputThread(LPVOID arg) +{ + InputSource *is; + char *p, *q; + int i; + char prev; + + is = (InputSource *) arg; + while (is->hThread != NULL) { + is->error = ReadFile(is->hFile, is->next, + INPUT_SOURCE_BUF_SIZE - (is->next - is->buf), + &is->count, NULL) ? NO_ERROR : GetLastError(); + if (is->error == NO_ERROR) { + /* Change CRLF to LF */ + if (is->next > is->buf) { + p = is->next - 1; + i = is->count + 1; + } else { + p = is->next; + i = is->count; + } + q = p; + prev = NULLCHAR; + while (i > 0) { + if (prev == '\r' && *p == '\n') { + *(q-1) = '\n'; + is->count--; + } else { + *q++ = *p; + } + prev = *p++; + i--; + } + *q = NULLCHAR; + is->next = q; + } else { + if (is->error == ERROR_BROKEN_PIPE) { + /* Correct for MS brain damage. EOF reading a pipe is not an error. */ + is->count = 0; + } else { + is->count = (DWORD) -1; + } + } + SendMessage(hwndMain, WM_USER_Input, 0, (LPARAM) is); + if (is->count < 0) break; /* Quit on error */ + } + CloseHandle(is->hFile); + return 0; +} + +DWORD +SocketInputThread(LPVOID arg) +{ + InputSource *is; + + is = (InputSource *) arg; + while (is->hThread != NULL) { + is->count = recv(is->sock, is->buf, INPUT_SOURCE_BUF_SIZE, 0); + if ((int)is->count == SOCKET_ERROR) { + is->count = (DWORD) -1; + is->error = WSAGetLastError(); + } else { + is->error = NO_ERROR; + is->next += is->count; + if (is->count == 0 && is->second == is) { + /* End of file on stderr; quit with no message */ + break; + } + } + SendMessage(hwndMain, WM_USER_Input, 0, (LPARAM) is); + if (is->count <= 0) break; /* Quit on EOF or error */ + } + return 0; +} + +VOID +InputEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + InputSource *is; + + is = (InputSource *) lParam; + if (is->lineByLine) { + /* Feed in lines one by one */ + char *p = is->buf; + char *q = p; + while (q < is->next) { + if (*q++ == '\n') { + (is->func)(is, is->closure, p, q - p, NO_ERROR); + p = q; + } + } + /* Move any partial line to the start of the buffer */ + q = is->buf; + while (p < is->next) { + *q++ = *p++; + } + is->next = q; + if (is->error != NO_ERROR || is->count == 0) { + /* Notify backend of the error. Note: If there was a partial + line at the end, it is not flushed through. */ + (is->func)(is, is->closure, is->buf, is->count, is->error); + } + } else { + /* Feed in the whole chunk of input at once */ + (is->func)(is, is->closure, is->buf, is->count, is->error); + is->next = is->buf; + } +} + +/*---------------------------------------------------------------------------*\ + * + * Menu enables. Used when setting various modes. + * +\*---------------------------------------------------------------------------*/ + +typedef struct { + int item; + int flags; +} Enables; + +VOID +SetMenuEnables(HMENU hmenu, Enables *enab) +{ + while (enab->item > 0) { + (void) EnableMenuItem(hmenu, enab->item, enab->flags); + enab++; + } +} + +Enables gnuEnables[] = { + { IDM_MailMove, MF_BYCOMMAND|MF_GRAYED }, + { IDM_ReloadCMailMsg, MF_BYCOMMAND|MF_GRAYED }, + { IDM_IcsClient, MF_BYCOMMAND|MF_GRAYED }, + { IDM_Accept, MF_BYCOMMAND|MF_GRAYED }, + { IDM_Decline, MF_BYCOMMAND|MF_GRAYED }, + { IDM_Rematch, MF_BYCOMMAND|MF_GRAYED }, + { IDM_Adjourn, MF_BYCOMMAND|MF_GRAYED }, + { IDM_StopExamining, MF_BYCOMMAND|MF_GRAYED }, + { IDM_StopObserving, MF_BYCOMMAND|MF_GRAYED }, + { IDM_Revert, MF_BYCOMMAND|MF_GRAYED }, + { -1, -1 } +}; + +Enables icsEnables[] = { + { IDM_MailMove, MF_BYCOMMAND|MF_GRAYED }, + { IDM_ReloadCMailMsg, MF_BYCOMMAND|MF_GRAYED }, + { IDM_MachineWhite, MF_BYCOMMAND|MF_GRAYED }, + { IDM_MachineBlack, MF_BYCOMMAND|MF_GRAYED }, + { IDM_TwoMachines, MF_BYCOMMAND|MF_GRAYED }, + { IDM_AnalysisMode, MF_BYCOMMAND|MF_GRAYED }, + { IDM_AnalyzeFile, MF_BYCOMMAND|MF_GRAYED }, + { IDM_TimeControl, MF_BYCOMMAND|MF_GRAYED }, + { IDM_MoveNow, MF_BYCOMMAND|MF_GRAYED }, + { IDM_Hint, MF_BYCOMMAND|MF_GRAYED }, + { IDM_Book, MF_BYCOMMAND|MF_GRAYED }, + { IDM_IcsOptions, MF_BYCOMMAND|MF_ENABLED }, + { -1, -1 } +}; + +#ifdef ZIPPY +Enables zippyEnables[] = { + { IDM_MoveNow, MF_BYCOMMAND|MF_ENABLED }, + { IDM_Hint, MF_BYCOMMAND|MF_ENABLED }, + { IDM_Book, MF_BYCOMMAND|MF_ENABLED }, + { -1, -1 } +}; +#endif + +Enables ncpEnables[] = { + { IDM_MailMove, MF_BYCOMMAND|MF_GRAYED }, + { IDM_ReloadCMailMsg, MF_BYCOMMAND|MF_GRAYED }, + { IDM_MachineWhite, MF_BYCOMMAND|MF_GRAYED }, + { IDM_MachineBlack, MF_BYCOMMAND|MF_GRAYED }, + { IDM_TwoMachines, MF_BYCOMMAND|MF_GRAYED }, + { IDM_AnalysisMode, MF_BYCOMMAND|MF_GRAYED }, + { IDM_AnalyzeFile, MF_BYCOMMAND|MF_GRAYED }, + { IDM_IcsClient, MF_BYCOMMAND|MF_GRAYED }, + { ACTION_POS, MF_BYPOSITION|MF_GRAYED }, + { IDM_Revert, MF_BYCOMMAND|MF_GRAYED }, + { IDM_MoveNow, MF_BYCOMMAND|MF_GRAYED }, + { IDM_RetractMove, MF_BYCOMMAND|MF_GRAYED }, + { IDM_TimeControl, MF_BYCOMMAND|MF_GRAYED }, + { IDM_Hint, MF_BYCOMMAND|MF_GRAYED }, + { IDM_Book, MF_BYCOMMAND|MF_GRAYED }, + { -1, -1 } +}; + +Enables trainingOnEnables[] = { + { IDM_EditComment, MF_BYCOMMAND|MF_GRAYED }, + { IDM_Pause, MF_BYCOMMAND|MF_GRAYED }, + { IDM_Forward, MF_BYCOMMAND|MF_GRAYED }, + { IDM_Backward, MF_BYCOMMAND|MF_GRAYED }, + { IDM_ToEnd, MF_BYCOMMAND|MF_GRAYED }, + { IDM_ToStart, MF_BYCOMMAND|MF_GRAYED }, + { IDM_MoveNow, MF_BYCOMMAND|MF_GRAYED }, + { IDM_TruncateGame, MF_BYCOMMAND|MF_GRAYED }, + { -1, -1 } +}; + +Enables trainingOffEnables[] = { + { IDM_EditComment, MF_BYCOMMAND|MF_ENABLED }, + { IDM_Pause, MF_BYCOMMAND|MF_ENABLED }, + { IDM_Forward, MF_BYCOMMAND|MF_ENABLED }, + { IDM_Backward, MF_BYCOMMAND|MF_ENABLED }, + { IDM_ToEnd, MF_BYCOMMAND|MF_ENABLED }, + { IDM_ToStart, MF_BYCOMMAND|MF_ENABLED }, + { IDM_MoveNow, MF_BYCOMMAND|MF_ENABLED }, + { IDM_TruncateGame, MF_BYCOMMAND|MF_ENABLED }, + { -1, -1 } +}; + +/* These modify either ncpEnables or gnuEnables */ +Enables cmailEnables[] = { + { IDM_MailMove, MF_BYCOMMAND|MF_ENABLED }, + { IDM_ReloadCMailMsg, MF_BYCOMMAND|MF_ENABLED }, + { ACTION_POS, MF_BYPOSITION|MF_ENABLED }, + { IDM_CallFlag, MF_BYCOMMAND|MF_GRAYED }, + { IDM_Draw, MF_BYCOMMAND|MF_ENABLED }, + { IDM_Adjourn, MF_BYCOMMAND|MF_GRAYED }, + { IDM_Abort, MF_BYCOMMAND|MF_GRAYED }, + { -1, -1 } +}; + +Enables machineThinkingEnables[] = { + { IDM_LoadGame, MF_BYCOMMAND|MF_GRAYED }, + { IDM_LoadNextGame, MF_BYCOMMAND|MF_GRAYED }, + { IDM_LoadPrevGame, MF_BYCOMMAND|MF_GRAYED }, + { IDM_ReloadGame, MF_BYCOMMAND|MF_GRAYED }, + { IDM_PasteGame, MF_BYCOMMAND|MF_GRAYED }, + { IDM_LoadPosition, MF_BYCOMMAND|MF_GRAYED }, + { IDM_LoadNextPosition, MF_BYCOMMAND|MF_GRAYED }, + { IDM_LoadPrevPosition, MF_BYCOMMAND|MF_GRAYED }, + { IDM_ReloadPosition, MF_BYCOMMAND|MF_GRAYED }, + { IDM_PastePosition, MF_BYCOMMAND|MF_GRAYED }, + { IDM_MachineWhite, MF_BYCOMMAND|MF_GRAYED }, + { IDM_MachineBlack, MF_BYCOMMAND|MF_GRAYED }, + { IDM_TwoMachines, MF_BYCOMMAND|MF_GRAYED }, + { IDM_TypeInMove, MF_BYCOMMAND|MF_GRAYED }, + { IDM_RetractMove, MF_BYCOMMAND|MF_GRAYED }, + { -1, -1 } +}; + +Enables userThinkingEnables[] = { + { IDM_LoadGame, MF_BYCOMMAND|MF_ENABLED }, + { IDM_LoadNextGame, MF_BYCOMMAND|MF_ENABLED }, + { IDM_LoadPrevGame, MF_BYCOMMAND|MF_ENABLED }, + { IDM_ReloadGame, MF_BYCOMMAND|MF_ENABLED }, + { IDM_PasteGame, MF_BYCOMMAND|MF_ENABLED }, + { IDM_LoadPosition, MF_BYCOMMAND|MF_ENABLED }, + { IDM_LoadNextPosition, MF_BYCOMMAND|MF_ENABLED }, + { IDM_LoadPrevPosition, MF_BYCOMMAND|MF_ENABLED }, + { IDM_ReloadPosition, MF_BYCOMMAND|MF_ENABLED }, + { IDM_PastePosition, MF_BYCOMMAND|MF_ENABLED }, + { IDM_MachineWhite, MF_BYCOMMAND|MF_ENABLED }, + { IDM_MachineBlack, MF_BYCOMMAND|MF_ENABLED }, + { IDM_TwoMachines, MF_BYCOMMAND|MF_ENABLED }, + { IDM_TypeInMove, MF_BYCOMMAND|MF_ENABLED }, + { IDM_RetractMove, MF_BYCOMMAND|MF_ENABLED }, + { -1, -1 } +}; + +/*---------------------------------------------------------------------------*\ + * + * Front-end interface functions exported by XBoard. + * Functions appear in same order as prototypes in frontend.h. + * +\*---------------------------------------------------------------------------*/ +VOID +ModeHighlight() +{ + static UINT prevChecked = 0; + static int prevPausing = 0; + UINT nowChecked; + + if (pausing != prevPausing) { + prevPausing = pausing; + (void) CheckMenuItem(GetMenu(hwndMain), IDM_Pause, + MF_BYCOMMAND|(pausing ? MF_CHECKED : MF_UNCHECKED)); + if (hwndPause) SetWindowText(hwndPause, pausing ? "C" : "P"); + } + + switch (gameMode) { + case BeginningOfGame: + if (appData.icsActive) + nowChecked = IDM_IcsClient; + else if (appData.noChessProgram) + nowChecked = IDM_EditGame; + else + nowChecked = IDM_MachineBlack; + break; + case MachinePlaysBlack: + nowChecked = IDM_MachineBlack; + break; + case MachinePlaysWhite: + nowChecked = IDM_MachineWhite; + break; + case TwoMachinesPlay: + nowChecked = IDM_TwoMachines; + break; + case AnalyzeMode: + nowChecked = IDM_AnalysisMode; + break; + case AnalyzeFile: + nowChecked = IDM_AnalyzeFile; + break; + case EditGame: + nowChecked = IDM_EditGame; + break; + case PlayFromGameFile: + nowChecked = IDM_LoadGame; + break; + case EditPosition: + nowChecked = IDM_EditPosition; + break; + case Training: + nowChecked = IDM_Training; + break; + case IcsPlayingWhite: + case IcsPlayingBlack: + case IcsObserving: + case IcsIdle: + nowChecked = IDM_IcsClient; + break; + default: + case EndOfGame: + nowChecked = 0; + break; + } + if (prevChecked != 0) + (void) CheckMenuItem(GetMenu(hwndMain), + prevChecked, MF_BYCOMMAND|MF_UNCHECKED); + if (nowChecked != 0) + (void) CheckMenuItem(GetMenu(hwndMain), + nowChecked, MF_BYCOMMAND|MF_CHECKED); + + if (nowChecked == IDM_LoadGame || nowChecked == IDM_Training) { + (void) EnableMenuItem(GetMenu(hwndMain), IDM_Training, + MF_BYCOMMAND|MF_ENABLED); + } else { + (void) EnableMenuItem(GetMenu(hwndMain), + IDM_Training, MF_BYCOMMAND|MF_GRAYED); + } + + prevChecked = nowChecked; +} + +VOID +SetICSMode() +{ + HMENU hmenu = GetMenu(hwndMain); + SetMenuEnables(hmenu, icsEnables); + EnableMenuItem(GetSubMenu(hmenu, OPTIONS_POS), ICS_POS, + MF_BYPOSITION|MF_ENABLED); +#ifdef ZIPPY + if (appData.zippyPlay) { + SetMenuEnables(hmenu, zippyEnables); + } +#endif +} + +VOID +SetGNUMode() +{ + SetMenuEnables(GetMenu(hwndMain), gnuEnables); +} + +VOID +SetNCPMode() +{ + HMENU hmenu = GetMenu(hwndMain); + SetMenuEnables(hmenu, ncpEnables); + EnableMenuItem(GetSubMenu(hmenu, OPTIONS_POS), SOUNDS_POS, + MF_BYPOSITION|MF_GRAYED); + DrawMenuBar(hwndMain); +} + +VOID +SetCmailMode() +{ + SetMenuEnables(GetMenu(hwndMain), cmailEnables); +} + +VOID +SetTrainingModeOn() +{ + int i; + SetMenuEnables(GetMenu(hwndMain), trainingOnEnables); + for (i = 0; i < N_BUTTONS; i++) { + if (buttonDesc[i].hwnd != NULL) + EnableWindow(buttonDesc[i].hwnd, FALSE); + } + CommentPopDown(); +} + +VOID SetTrainingModeOff() +{ + int i; + SetMenuEnables(GetMenu(hwndMain), trainingOffEnables); + for (i = 0; i < N_BUTTONS; i++) { + if (buttonDesc[i].hwnd != NULL) + EnableWindow(buttonDesc[i].hwnd, TRUE); + } +} + + +VOID +SetUserThinkingEnables() +{ + SetMenuEnables(GetMenu(hwndMain), userThinkingEnables); +} + +VOID +SetMachineThinkingEnables() +{ + HMENU hMenu = GetMenu(hwndMain); + int flags = MF_BYCOMMAND|MF_ENABLED; + + SetMenuEnables(hMenu, machineThinkingEnables); + + if (gameMode == MachinePlaysBlack) { + (void)EnableMenuItem(hMenu, IDM_MachineBlack, flags); + } else if (gameMode == MachinePlaysWhite) { + (void)EnableMenuItem(hMenu, IDM_MachineWhite, flags); + } else if (gameMode == TwoMachinesPlay) { + (void)EnableMenuItem(hMenu, IDM_TwoMachines, flags); + } +} + + +VOID +DisplayTitle(char *str) +{ + char title[MSG_SIZ], *host; + if (str[0] != NULLCHAR) { + strcpy(title, str); + } else if (appData.icsActive) { + if (appData.icsCommPort[0] != NULLCHAR) + host = "ICS"; + else + host = appData.icsHost; + sprintf(title, "%s: %s", szTitle, host); + } else if (appData.noChessProgram) { + strcpy(title, szTitle); + } else { + strcpy(title, szTitle); + strcat(title, ": "); + strcat(title, first.tidy); + } + SetWindowText(hwndMain, title); +} + + +VOID +DisplayMessage(char *str1, char *str2) +{ + HDC hdc; + HFONT oldFont; + int remain = MESSAGE_TEXT_MAX - 1; + int len; + + moveErrorMessageUp = FALSE; /* turned on later by caller if needed */ + messageText[0] = NULLCHAR; + if (*str1) { + len = strlen(str1); + if (len > remain) len = remain; + strncpy(messageText, str1, len); + messageText[len] = NULLCHAR; + remain -= len; + } + if (*str2 && remain >= 2) { + if (*str1) { + strcat(messageText, " "); + remain -= 2; + } + len = strlen(str2); + if (len > remain) len = remain; + strncat(messageText, str2, len); + } + messageText[MESSAGE_TEXT_MAX - 1] = NULLCHAR; + + if (IsIconic(hwndMain)) return; + hdc = GetDC(hwndMain); + oldFont = SelectObject(hdc, font[boardSize][MESSAGE_FONT]->hf); + ExtTextOut(hdc, messageRect.left, messageRect.top, ETO_CLIPPED|ETO_OPAQUE, + &messageRect, messageText, strlen(messageText), NULL); + (void) SelectObject(hdc, oldFont); + (void) ReleaseDC(hwndMain, hdc); +} + +VOID +DisplayError(char *str, int error) +{ + FARPROC lpProc; + char buf[MSG_SIZ*2], buf2[MSG_SIZ]; + int len; + char *p, *q; + + if (error == 0) { + strcpy(buf, str); + } else { + len = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, + NULL, error, LANG_NEUTRAL, + (LPSTR) buf2, MSG_SIZ, NULL); + if (len > 0) { + sprintf(buf, "%s:\n%s", str, buf2); + } else { + ErrorMap *em = errmap; + while (em->err != 0 && em->err != error) em++; + if (em->err != 0) { + sprintf(buf, "%s:\n%s", str, em->msg); + } else { + sprintf(buf, "%s:\nError code %d", str, error); + } + } + } + p = buf; + q = errorMessage; + while (*p) { + if (*p == '\n') { + if (hwndMain != NULL /*!!?*/) { + *q++ = '\r'; + *q++ = *p++; + } else { + *q++ = ' '; + p++; + } + } else { + *q++ = *p++; + } + } + *q = NULLCHAR; + + if (hwndMain == NULL) { + MessageBox(NULL, errorMessage, "Error", MB_OK|MB_ICONEXCLAMATION); + } else { + lpProc = MakeProcInstance((FARPROC)ErrorDialog, hInst); + CreateDialog(hInst, MAKEINTRESOURCE(DLG_Error), + hwndMain, (DLGPROC)lpProc); + FreeProcInstance(lpProc); + } +} + + +VOID +DisplayMoveError(char *str) +{ + fromX = fromY = -1; + ClearHighlights(); + DrawPosition(FALSE, NULL); + if (appData.popupMoveErrors) { + DisplayError(str, 0); + } else { + DisplayMessage(str, ""); + moveErrorMessageUp = TRUE; + } +} + +VOID +DisplayFatalError(char *str, int error, int exitStatus) +{ + char buf[2*MSG_SIZ], buf2[MSG_SIZ]; + int len; + char *label = exitStatus ? "Fatal Error" : "Exiting"; + + if (error != 0) { + len = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, + NULL, error, LANG_NEUTRAL, + (LPSTR) buf2, MSG_SIZ, NULL); + if (len > 0) { + sprintf(buf, "%s:\n%s", str, buf2); + } else { + ErrorMap *em = errmap; + while (em->err != 0 && em->err != error) em++; + if (em->err != 0) { + sprintf(buf, "%s:\n%s", str, em->msg); + } else { + sprintf(buf, "%s:\nError code %d", str, error); + } + } + str = buf; + } + if (appData.debugMode) { + fprintf(debugFP, "%s: %s\n", label, str); + } + if (appData.popupExitMessage) { + (void) MessageBox(hwndMain, str, label, MB_OK| + (exitStatus ? MB_ICONSTOP : MB_ICONINFORMATION)); + } + ExitEvent(exitStatus); +} + + +VOID +DisplayInformation(char *str) +{ + (void) MessageBox(hwndMain, str, "Information", MB_OK|MB_ICONINFORMATION); +} + + +typedef struct { + char *title, *question, *replyPrefix; + ProcRef pr; +} QuestionParams; + +LRESULT CALLBACK +QuestionDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + static QuestionParams *qp; + char reply[MSG_SIZ]; + int len, err; + + switch (message) { + case WM_INITDIALOG: + qp = (QuestionParams *) lParam; + CenterWindow(hDlg, GetWindow(hDlg, GW_OWNER)); + SetWindowText(hDlg, qp->title); + SetDlgItemText(hDlg, OPT_QuestionText, qp->question); + SetFocus(GetDlgItem(hDlg, OPT_QuestionInput)); + return FALSE; + + case WM_COMMAND: + switch (LOWORD(wParam)) { + case IDOK: + strcpy(reply, qp->replyPrefix); + if (*reply) strcat(reply, " "); + len = strlen(reply); + GetDlgItemText(hDlg, OPT_QuestionInput, reply + len, sizeof(reply) - len); + strcat(reply, "\n"); + OutputToProcess(qp->pr, reply, strlen(reply), &err); + EndDialog(hDlg, TRUE); + if (err) DisplayFatalError("Error writing to chess program", err, 1); + return TRUE; + case IDCANCEL: + EndDialog(hDlg, FALSE); + return TRUE; + default: + break; + } + break; + } + return FALSE; +} + +VOID +AskQuestion(char* title, char *question, char *replyPrefix, ProcRef pr) +{ + QuestionParams qp; + FARPROC lpProc; + + qp.title = title; + qp.question = question; + qp.replyPrefix = replyPrefix; + qp.pr = pr; + lpProc = MakeProcInstance((FARPROC)QuestionDialog, hInst); + DialogBoxParam(hInst, MAKEINTRESOURCE(DLG_Question), + hwndMain, (DLGPROC)lpProc, (LPARAM)&qp); + FreeProcInstance(lpProc); +} + + +VOID +DisplayIcsInteractionTitle(char *str) +{ + char consoleTitle[MSG_SIZ]; + + sprintf(consoleTitle, "%s: %s", szConsoleTitle, str); + SetWindowText(hwndConsole, consoleTitle); +} + +void +DrawPosition(int fullRedraw, Board board) +{ + HDCDrawPosition(NULL, (BOOLEAN) fullRedraw, board); +} + + +VOID +ResetFrontEnd() +{ + fromX = fromY = -1; + if (dragInfo.pos.x != -1 || dragInfo.pos.y != -1) { + dragInfo.pos.x = dragInfo.pos.y = -1; + dragInfo.pos.x = dragInfo.pos.y = -1; + dragInfo.lastpos = dragInfo.pos; + dragInfo.start.x = dragInfo.start.y = -1; + dragInfo.from = dragInfo.start; + ReleaseCapture(); + DrawPosition(TRUE, NULL); + } +} + + +VOID +CommentPopUp(char *title, char *str) +{ + HWND hwnd = GetActiveWindow(); + EitherCommentPopUp(0, title, str, FALSE); + SetActiveWindow(hwnd); +} + +VOID +CommentPopDown(void) +{ + CheckMenuItem(GetMenu(hwndMain), IDM_EditComment, MF_UNCHECKED); + if (commentDialog) { + ShowWindow(commentDialog, SW_HIDE); + } + commentDialogUp = FALSE; +} + +VOID +EditCommentPopUp(int index, char *title, char *str) +{ + EitherCommentPopUp(index, title, str, TRUE); +} + + +VOID +RingBell() +{ + MyPlaySound(&sounds[(int)SoundMove]); +} + +VOID PlayIcsWinSound() +{ + MyPlaySound(&sounds[(int)SoundIcsWin]); +} + +VOID PlayIcsLossSound() +{ + MyPlaySound(&sounds[(int)SoundIcsLoss]); +} + +VOID PlayIcsDrawSound() +{ + MyPlaySound(&sounds[(int)SoundIcsDraw]); +} + +VOID PlayIcsUnfinishedSound() +{ + MyPlaySound(&sounds[(int)SoundIcsUnfinished]); +} + +VOID +PlayAlarmSound() +{ + MyPlaySound(&sounds[(int)SoundAlarm]); +} + + +VOID +EchoOn() +{ + HWND hInput; + consoleEcho = TRUE; + hInput = GetDlgItem(hwndConsole, OPT_ConsoleInput); + SendMessage(hInput, EM_SETCHARFORMAT, SCF_ALL, (LPARAM)&consoleCF); + SendMessage(hInput, EM_SETBKGNDCOLOR, FALSE, consoleBackgroundColor); +} + + +VOID +EchoOff() +{ + CHARFORMAT cf; + HWND hInput; + consoleEcho = FALSE; + hInput = GetDlgItem(hwndConsole, OPT_ConsoleInput); + /* This works OK: set text and background both to the same color */ + cf = consoleCF; + cf.crTextColor = COLOR_ECHOOFF; + SendMessage(hInput, EM_SETCHARFORMAT, SCF_ALL, (LPARAM)&cf); + SendMessage(hInput, EM_SETBKGNDCOLOR, FALSE, cf.crTextColor); +} + +/* No Raw()...? */ + +void Colorize(ColorClass cc, int continuation) +{ + currentColorClass = cc; + consoleCF.dwMask = CFM_COLOR|CFM_BOLD|CFM_ITALIC|CFM_UNDERLINE|CFM_STRIKEOUT; + consoleCF.crTextColor = textAttribs[cc].color; + consoleCF.dwEffects = textAttribs[cc].effects|CFE_LINK; + if (!continuation) MyPlaySound(&textAttribs[cc].sound); +} + +char * +UserName() +{ + static char buf[MSG_SIZ]; + DWORD bufsiz = MSG_SIZ; + + if (!GetUserName(buf, &bufsiz)) { + /*DisplayError("Error getting user name", GetLastError());*/ + strcpy(buf, "User"); + } + return buf; +} + +char * +HostName() +{ + static char buf[MSG_SIZ]; + DWORD bufsiz = MSG_SIZ; + + if (!GetComputerName(buf, &bufsiz)) { + /*DisplayError("Error getting host name", GetLastError());*/ + strcpy(buf, "Unknown"); + } + return buf; +} + + +int +ClockTimerRunning() +{ + return clockTimerEvent != 0; +} + +int +StopClockTimer() +{ + if (clockTimerEvent == 0) return FALSE; + KillTimer(hwndMain, clockTimerEvent); + clockTimerEvent = 0; + return TRUE; +} + +void +StartClockTimer(long millisec) +{ + clockTimerEvent = SetTimer(hwndMain, (UINT) CLOCK_TIMER_ID, + (UINT) millisec, NULL); +} + +void +DisplayWhiteClock(long timeRemaining, int highlight) +{ + HDC hdc; + hdc = GetDC(hwndMain); + if (!IsIconic(hwndMain)) { + DisplayAClock(hdc, timeRemaining, highlight, &whiteRect, "White"); + } + if (highlight && iconCurrent == iconBlack) { + iconCurrent = iconWhite; + PostMessage(hwndMain, WM_SETICON, (WPARAM) TRUE, (LPARAM) iconCurrent); + if (IsIconic(hwndMain)) { + DrawIcon(hdc, 2, 2, iconCurrent); + } + } + (void) ReleaseDC(hwndMain, hdc); + if (hwndConsole) + PostMessage(hwndConsole, WM_SETICON, (WPARAM) TRUE, (LPARAM) iconCurrent); +} + +void +DisplayBlackClock(long timeRemaining, int highlight) +{ + HDC hdc; + hdc = GetDC(hwndMain); + if (!IsIconic(hwndMain)) { + DisplayAClock(hdc, timeRemaining, highlight, &blackRect, "Black"); + } + if (highlight && iconCurrent == iconWhite) { + iconCurrent = iconBlack; + PostMessage(hwndMain, WM_SETICON, (WPARAM) TRUE, (LPARAM) iconCurrent); + if (IsIconic(hwndMain)) { + DrawIcon(hdc, 2, 2, iconCurrent); + } + } + (void) ReleaseDC(hwndMain, hdc); + if (hwndConsole) + PostMessage(hwndConsole, WM_SETICON, (WPARAM) TRUE, (LPARAM) iconCurrent); +} + + +int +LoadGameTimerRunning() +{ + return loadGameTimerEvent != 0; +} + +int +StopLoadGameTimer() +{ + if (loadGameTimerEvent == 0) return FALSE; + KillTimer(hwndMain, loadGameTimerEvent); + loadGameTimerEvent = 0; + return TRUE; +} + +void +StartLoadGameTimer(long millisec) +{ + loadGameTimerEvent = SetTimer(hwndMain, (UINT) LOAD_GAME_TIMER_ID, + (UINT) millisec, NULL); +} + +void +AutoSaveGame() +{ + char *defName; + FILE *f; + char fileTitle[MSG_SIZ]; + + defName = DefaultFileName(appData.oldSaveStyle ? "gam" : "pgn"); + f = OpenFileDialog(hwndMain, TRUE, defName, + appData.oldSaveStyle ? "gam" : "pgn", + GAME_FILT, + "Save Game to File", NULL, fileTitle, NULL); + if (f != NULL) { + SaveGame(f, 0, ""); + fclose(f); + } +} + + +void +ScheduleDelayedEvent(DelayedEventCallback cb, long millisec) +{ + if (delayedTimerEvent != 0) { + if (appData.debugMode) { + fprintf(debugFP, "ScheduleDelayedEvent: event already scheduled\n"); + } + KillTimer(hwndMain, delayedTimerEvent); + delayedTimerEvent = 0; + delayedTimerCallback(); + } + delayedTimerCallback = cb; + delayedTimerEvent = SetTimer(hwndMain, (UINT) DELAYED_TIMER_ID, + (UINT) millisec, NULL); +} + +DelayedEventCallback +GetDelayedEvent() +{ + if (delayedTimerEvent) { + return delayedTimerCallback; + } else { + return NULL; + } +} + +void +CancelDelayedEvent() +{ + if (delayedTimerEvent) { + KillTimer(hwndMain, delayedTimerEvent); + delayedTimerEvent = 0; + } +} + +/* Start a child process running the given program. + The process's standard output can be read from "from", and its + standard input can be written to "to". + Exit with fatal error if anything goes wrong. + Returns an opaque pointer that can be used to destroy the process + later. +*/ +int +StartChildProcess(char *cmdLine, char *dir, ProcRef *pr) +{ +#define BUFSIZE 4096 + + HANDLE hChildStdinRd, hChildStdinWr, + hChildStdoutRd, hChildStdoutWr; + HANDLE hChildStdinWrDup, hChildStdoutRdDup; + SECURITY_ATTRIBUTES saAttr; + BOOL fSuccess; + PROCESS_INFORMATION piProcInfo; + STARTUPINFO siStartInfo; + ChildProc *cp; + char buf[MSG_SIZ]; + DWORD err; + + if (appData.debugMode) { + fprintf(debugFP, "StartChildProcess (dir=\"%s\") %s\n", dir, cmdLine); + } + + *pr = NoProc; + + /* Set the bInheritHandle flag so pipe handles are inherited. */ + saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); + saAttr.bInheritHandle = TRUE; + saAttr.lpSecurityDescriptor = NULL; + + /* + * The steps for redirecting child's STDOUT: + * 1. Create anonymous pipe to be STDOUT for child. + * 2. Create a noninheritable duplicate of read handle, + * and close the inheritable read handle. + */ + + /* Create a pipe for the child's STDOUT. */ + if (! CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &saAttr, 0)) { + return GetLastError(); + } + + /* Duplicate the read handle to the pipe, so it is not inherited. */ + fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdoutRd, + GetCurrentProcess(), &hChildStdoutRdDup, 0, + FALSE, /* not inherited */ + DUPLICATE_SAME_ACCESS); + if (! fSuccess) { + return GetLastError(); + } + CloseHandle(hChildStdoutRd); + + /* + * The steps for redirecting child's STDIN: + * 1. Create anonymous pipe to be STDIN for child. + * 2. Create a noninheritable duplicate of write handle, + * and close the inheritable write handle. + */ + + /* Create a pipe for the child's STDIN. */ + if (! CreatePipe(&hChildStdinRd, &hChildStdinWr, &saAttr, 0)) { + return GetLastError(); + } + + /* Duplicate the write handle to the pipe, so it is not inherited. */ + fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdinWr, + GetCurrentProcess(), &hChildStdinWrDup, 0, + FALSE, /* not inherited */ + DUPLICATE_SAME_ACCESS); + if (! fSuccess) { + return GetLastError(); + } + CloseHandle(hChildStdinWr); + + /* Arrange to (1) look in dir for the child .exe file, and + * (2) have dir be the child's working directory. Interpret + * dir relative to the directory WinBoard loaded from. */ + GetCurrentDirectory(MSG_SIZ, buf); + SetCurrentDirectory(installDir); + SetCurrentDirectory(dir); + + /* Now create the child process. */ + + siStartInfo.cb = sizeof(STARTUPINFO); + siStartInfo.lpReserved = NULL; + siStartInfo.lpDesktop = NULL; + siStartInfo.lpTitle = NULL; + siStartInfo.dwFlags = STARTF_USESTDHANDLES; + siStartInfo.cbReserved2 = 0; + siStartInfo.lpReserved2 = NULL; + siStartInfo.hStdInput = hChildStdinRd; + siStartInfo.hStdOutput = hChildStdoutWr; + siStartInfo.hStdError = hChildStdoutWr; + + fSuccess = CreateProcess(NULL, + cmdLine, /* command line */ + NULL, /* process security attributes */ + NULL, /* primary thread security attrs */ + TRUE, /* handles are inherited */ + DETACHED_PROCESS|CREATE_NEW_PROCESS_GROUP, + NULL, /* use parent's environment */ + NULL, + &siStartInfo, /* STARTUPINFO pointer */ + &piProcInfo); /* receives PROCESS_INFORMATION */ + + err = GetLastError(); + SetCurrentDirectory(buf); /* return to prev directory */ + if (! fSuccess) { + return err; + } + + /* Close the handles we don't need in the parent */ + CloseHandle(piProcInfo.hThread); + CloseHandle(hChildStdinRd); + CloseHandle(hChildStdoutWr); + + /* Prepare return value */ + cp = (ChildProc *) calloc(1, sizeof(ChildProc)); + cp->kind = CPReal; + cp->hProcess = piProcInfo.hProcess; + cp->pid = piProcInfo.dwProcessId; + cp->hFrom = hChildStdoutRdDup; + cp->hTo = hChildStdinWrDup; + + *pr = (void *) cp; + + /* Klaus Friedel says that this Sleep solves a problem under Windows + 2000 where engines sometimes don't see the initial command(s) + from WinBoard and hang. I don't understand how that can happen, + but the Sleep is harmless, so I've put it in. Others have also + reported what may be the same problem, so hopefully this will fix + it for them too. */ + Sleep(500); + + return NO_ERROR; +} + + +void +DestroyChildProcess(ProcRef pr, int/*boolean*/ signal) +{ + ChildProc *cp; + + cp = (ChildProc *) pr; + if (cp == NULL) return; + + switch (cp->kind) { + case CPReal: + /* TerminateProcess is considered harmful, so... */ + CloseHandle(cp->hTo); /* Closing this will give the child an EOF and hopefully kill it */ + if (cp->hFrom) CloseHandle(cp->hFrom); /* if NULL, InputThread will close it */ + /* The following doesn't work because the chess program + doesn't "have the same console" as WinBoard. Maybe + we could arrange for this even though neither WinBoard + nor the chess program uses a console for stdio? */ + /*!!if (signal) GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, cp->pid);*/ + CloseHandle(cp->hProcess); + break; + + case CPComm: + if (cp->hFrom) CloseHandle(cp->hFrom); + break; + + case CPSock: + closesocket(cp->sock); + WSACleanup(); + break; + + case CPRcmd: + if (signal) send(cp->sock2, "\017", 1, 0); /* 017 = 15 = SIGTERM */ + closesocket(cp->sock); + closesocket(cp->sock2); + WSACleanup(); + break; + } + free(cp); +} + +void +InterruptChildProcess(ProcRef pr) +{ + ChildProc *cp; + + cp = (ChildProc *) pr; + if (cp == NULL) return; + switch (cp->kind) { + case CPReal: + /* The following doesn't work because the chess program + doesn't "have the same console" as WinBoard. Maybe + we could arrange for this even though neither WinBoard + nor the chess program uses a console for stdio */ + /*!!GenerateConsoleCtrlEvent(CTRL_C_EVENT, cp->pid);*/ + break; + + case CPComm: + case CPSock: + /* Can't interrupt */ + break; + + case CPRcmd: + send(cp->sock2, "\002", 1, 0); /* 2 = SIGINT */ + break; + } +} + + +int +OpenTelnet(char *host, char *port, ProcRef *pr) +{ + char cmdLine[MSG_SIZ]; + + if (port[0] == NULLCHAR) { + sprintf(cmdLine, "%s %s", appData.telnetProgram, host); + } else { + sprintf(cmdLine, "%s %s %s", appData.telnetProgram, host, port); + } + return StartChildProcess(cmdLine, "", pr); +} + + +/* Code to open TCP sockets */ + +int +OpenTCP(char *host, char *port, ProcRef *pr) +{ + ChildProc *cp; + int err; + SOCKET s; + struct sockaddr_in sa, mysa; + struct hostent FAR *hp; + unsigned short uport; + WORD wVersionRequested; + WSADATA wsaData; + + /* Initialize socket DLL */ + wVersionRequested = MAKEWORD(1, 1); + err = WSAStartup(wVersionRequested, &wsaData); + if (err != 0) return err; + + /* Make socket */ + if ((s = socket(PF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) { + err = WSAGetLastError(); + WSACleanup(); + return err; + } + + /* Bind local address using (mostly) don't-care values. + */ + memset((char *) &mysa, 0, sizeof(struct sockaddr_in)); + mysa.sin_family = AF_INET; + mysa.sin_addr.s_addr = INADDR_ANY; + uport = (unsigned short) 0; + mysa.sin_port = htons(uport); + if (bind(s, (struct sockaddr *) &mysa, sizeof(struct sockaddr_in)) + == SOCKET_ERROR) { + err = WSAGetLastError(); + WSACleanup(); + return err; + } + + /* Resolve remote host name */ + memset((char *) &sa, 0, sizeof(struct sockaddr_in)); + if (!(hp = gethostbyname(host))) { + unsigned int b0, b1, b2, b3; + + err = WSAGetLastError(); + + if (sscanf(host, "%u.%u.%u.%u", &b0, &b1, &b2, &b3) == 4) { + hp = (struct hostent *) calloc(1, sizeof(struct hostent)); + hp->h_addrtype = AF_INET; + hp->h_length = 4; + hp->h_addr_list = (char **) calloc(2, sizeof(char *)); + hp->h_addr_list[0] = (char *) malloc(4); + hp->h_addr_list[0][0] = (char) b0; + hp->h_addr_list[0][1] = (char) b1; + hp->h_addr_list[0][2] = (char) b2; + hp->h_addr_list[0][3] = (char) b3; + } else { + WSACleanup(); + return err; + } + } + sa.sin_family = hp->h_addrtype; + uport = (unsigned short) atoi(port); + sa.sin_port = htons(uport); + memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length); + + /* Make connection */ + if (connect(s, (struct sockaddr *) &sa, + sizeof(struct sockaddr_in)) == SOCKET_ERROR) { + err = WSAGetLastError(); + WSACleanup(); + return err; + } + + /* Prepare return value */ + cp = (ChildProc *) calloc(1, sizeof(ChildProc)); + cp->kind = CPSock; + cp->sock = s; + *pr = (ProcRef *) cp; + + return NO_ERROR; +} + +int +OpenCommPort(char *name, ProcRef *pr) +{ + HANDLE h; + COMMTIMEOUTS ct; + ChildProc *cp; + char fullname[MSG_SIZ]; + + if (*name != '\\') + sprintf(fullname, "\\\\.\\%s", name); + else + strcpy(fullname, name); + + h = CreateFile(name, GENERIC_READ | GENERIC_WRITE, + 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); + if (h == (HANDLE) -1) { + return GetLastError(); + } + hCommPort = h; + + if (!SetCommState(h, (LPDCB) &dcb)) return GetLastError(); + + /* Accumulate characters until a 100ms pause, then parse */ + ct.ReadIntervalTimeout = 100; + ct.ReadTotalTimeoutMultiplier = 0; + ct.ReadTotalTimeoutConstant = 0; + ct.WriteTotalTimeoutMultiplier = 0; + ct.WriteTotalTimeoutConstant = 0; + if (!SetCommTimeouts(h, (LPCOMMTIMEOUTS) &ct)) return GetLastError(); + + /* Prepare return value */ + cp = (ChildProc *) calloc(1, sizeof(ChildProc)); + cp->kind = CPComm; + cp->hFrom = h; + cp->hTo = h; + *pr = (ProcRef *) cp; + + return NO_ERROR; +} + +int +OpenLoopback(ProcRef *pr) +{ + DisplayFatalError("Not implemented", 0, 1); + return NO_ERROR; +} + + +int +OpenRcmd(char* host, char* user, char* cmd, ProcRef* pr) +{ + ChildProc *cp; + int err; + SOCKET s, s2, s3; + struct sockaddr_in sa, mysa; + struct hostent FAR *hp; + unsigned short uport; + WORD wVersionRequested; + WSADATA wsaData; + int fromPort; + char stderrPortStr[MSG_SIZ]; + + /* Initialize socket DLL */ + wVersionRequested = MAKEWORD(1, 1); + err = WSAStartup(wVersionRequested, &wsaData); + if (err != 0) return err; + + /* Resolve remote host name */ + memset((char *) &sa, 0, sizeof(struct sockaddr_in)); + if (!(hp = gethostbyname(host))) { + unsigned int b0, b1, b2, b3; + + err = WSAGetLastError(); + + if (sscanf(host, "%u.%u.%u.%u", &b0, &b1, &b2, &b3) == 4) { + hp = (struct hostent *) calloc(1, sizeof(struct hostent)); + hp->h_addrtype = AF_INET; + hp->h_length = 4; + hp->h_addr_list = (char **) calloc(2, sizeof(char *)); + hp->h_addr_list[0] = (char *) malloc(4); + hp->h_addr_list[0][0] = (char) b0; + hp->h_addr_list[0][1] = (char) b1; + hp->h_addr_list[0][2] = (char) b2; + hp->h_addr_list[0][3] = (char) b3; + } else { + WSACleanup(); + return err; + } + } + sa.sin_family = hp->h_addrtype; + uport = (unsigned short) 514; + sa.sin_port = htons(uport); + memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length); + + /* Bind local socket to unused "privileged" port address + */ + s = INVALID_SOCKET; + memset((char *) &mysa, 0, sizeof(struct sockaddr_in)); + mysa.sin_family = AF_INET; + mysa.sin_addr.s_addr = INADDR_ANY; + for (fromPort = 1023;; fromPort--) { + if (fromPort < 0) { + WSACleanup(); + return WSAEADDRINUSE; + } + if (s == INVALID_SOCKET) { + if ((s = socket(PF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) { + err = WSAGetLastError(); + WSACleanup(); + return err; + } + } + uport = (unsigned short) fromPort; + mysa.sin_port = htons(uport); + if (bind(s, (struct sockaddr *) &mysa, sizeof(struct sockaddr_in)) + == SOCKET_ERROR) { + err = WSAGetLastError(); + if (err == WSAEADDRINUSE) continue; + WSACleanup(); + return err; + } + if (connect(s, (struct sockaddr *) &sa, + sizeof(struct sockaddr_in)) == SOCKET_ERROR) { + err = WSAGetLastError(); + if (err == WSAEADDRINUSE) { + closesocket(s); + s = -1; + continue; + } + WSACleanup(); + return err; + } + break; + } + + /* Bind stderr local socket to unused "privileged" port address + */ + s2 = INVALID_SOCKET; + memset((char *) &mysa, 0, sizeof(struct sockaddr_in)); + mysa.sin_family = AF_INET; + mysa.sin_addr.s_addr = INADDR_ANY; + for (fromPort = 1023;; fromPort--) { + if (fromPort < 0) { + (void) closesocket(s); + WSACleanup(); + return WSAEADDRINUSE; + } + if (s2 == INVALID_SOCKET) { + if ((s2 = socket(PF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) { + err = WSAGetLastError(); + closesocket(s); + WSACleanup(); + return err; + } + } + uport = (unsigned short) fromPort; + mysa.sin_port = htons(uport); + if (bind(s2, (struct sockaddr *) &mysa, sizeof(struct sockaddr_in)) + == SOCKET_ERROR) { + err = WSAGetLastError(); + if (err == WSAEADDRINUSE) continue; + (void) closesocket(s); + WSACleanup(); + return err; + } + if (listen(s2, 1) == SOCKET_ERROR) { + err = WSAGetLastError(); + if (err == WSAEADDRINUSE) { + closesocket(s2); + s2 = INVALID_SOCKET; + continue; + } + (void) closesocket(s); + (void) closesocket(s2); + WSACleanup(); + return err; + } + break; + } + sprintf(stderrPortStr, "%d", fromPort); + + if (send(s, stderrPortStr, strlen(stderrPortStr) + 1, 0) == SOCKET_ERROR) { + err = WSAGetLastError(); + (void) closesocket(s); + (void) closesocket(s2); + WSACleanup(); + return err; + } + + if (send(s, UserName(), strlen(UserName()) + 1, 0) == SOCKET_ERROR) { + err = WSAGetLastError(); + (void) closesocket(s); + (void) closesocket(s2); + WSACleanup(); + return err; + } + if (*user == NULLCHAR) user = UserName(); + if (send(s, user, strlen(user) + 1, 0) == SOCKET_ERROR) { + err = WSAGetLastError(); + (void) closesocket(s); + (void) closesocket(s2); + WSACleanup(); + return err; + } + if (send(s, cmd, strlen(cmd) + 1, 0) == SOCKET_ERROR) { + err = WSAGetLastError(); + (void) closesocket(s); + (void) closesocket(s2); + WSACleanup(); + return err; + } + + if ((s3 = accept(s2, NULL, NULL)) == INVALID_SOCKET) { + err = WSAGetLastError(); + (void) closesocket(s); + (void) closesocket(s2); + WSACleanup(); + return err; + } + (void) closesocket(s2); /* Stop listening */ + + /* Prepare return value */ + cp = (ChildProc *) calloc(1, sizeof(ChildProc)); + cp->kind = CPRcmd; + cp->sock = s; + cp->sock2 = s3; + *pr = (ProcRef *) cp; + + return NO_ERROR; +} + + +InputSourceRef +AddInputSource(ProcRef pr, int lineByLine, + InputCallback func, VOIDSTAR closure) +{ + InputSource *is, *is2; + ChildProc *cp = (ChildProc *) pr; + + is = (InputSource *) calloc(1, sizeof(InputSource)); + is->lineByLine = lineByLine; + is->func = func; + is->closure = closure; + is->second = NULL; + is->next = is->buf; + if (pr == NoProc) { + is->kind = CPReal; + consoleInputSource = is; + } else { + is->kind = cp->kind; + switch (cp->kind) { + case CPReal: + is->hFile = cp->hFrom; + cp->hFrom = NULL; /* now owned by InputThread */ + is->hThread = + CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) NonOvlInputThread, + (LPVOID) is, 0, &is->id); + break; + + case CPComm: + is->hFile = cp->hFrom; + cp->hFrom = NULL; /* now owned by InputThread */ + is->hThread = + CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) InputThread, + (LPVOID) is, 0, &is->id); + break; + + case CPSock: + is->sock = cp->sock; + is->hThread = + CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) SocketInputThread, + (LPVOID) is, 0, &is->id); + break; + + case CPRcmd: + is2 = (InputSource *) calloc(1, sizeof(InputSource)); + *is2 = *is; + is->sock = cp->sock; + is->second = is2; + is2->sock = cp->sock2; + is2->second = is2; + is->hThread = + CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) SocketInputThread, + (LPVOID) is, 0, &is->id); + is2->hThread = + CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) SocketInputThread, + (LPVOID) is2, 0, &is2->id); + break; + } + } + return (InputSourceRef) is; +} + +void +RemoveInputSource(InputSourceRef isr) +{ + InputSource *is; + + is = (InputSource *) isr; + is->hThread = NULL; /* tell thread to stop */ + CloseHandle(is->hThread); + if (is->second != NULL) { + is->second->hThread = NULL; + CloseHandle(is->second->hThread); + } +} + + +int +OutputToProcess(ProcRef pr, char *message, int count, int *outError) +{ + DWORD dOutCount; + int outCount = SOCKET_ERROR; + ChildProc *cp = (ChildProc *) pr; + static OVERLAPPED ovl; + + if (pr == NoProc) { + ConsoleOutput(message, count, FALSE); + return count; + } + + if (ovl.hEvent == NULL) { + ovl.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + } + ovl.Internal = ovl.InternalHigh = ovl.Offset = ovl.OffsetHigh = 0; + + switch (cp->kind) { + case CPSock: + case CPRcmd: + outCount = send(cp->sock, message, count, 0); + if (outCount == SOCKET_ERROR) { + *outError = WSAGetLastError(); + } else { + *outError = NO_ERROR; + } + break; + + case CPReal: + if (WriteFile(((ChildProc *)pr)->hTo, message, count, + &dOutCount, NULL)) { + *outError = NO_ERROR; + outCount = (int) dOutCount; + } else { + *outError = GetLastError(); + } + break; + + case CPComm: + *outError = DoWriteFile(((ChildProc *)pr)->hTo, message, count, + &dOutCount, &ovl); + if (*outError == NO_ERROR) { + outCount = (int) dOutCount; + } + break; + } + return outCount; +} + +int +OutputToProcessDelayed(ProcRef pr, char *message, int count, int *outError, + long msdelay) +{ + /* Ignore delay, not implemented for WinBoard */ + return OutputToProcess(pr, message, count, outError); +} + + +void +CmailSigHandlerCallBack(InputSourceRef isr, VOIDSTAR closure, + char *buf, int count, int error) +{ + DisplayFatalError("Not implemented", 0, 1); +} + +/* see wgamelist.c for Game List functions */ +/* see wedittags.c for Edit Tags functions */ + + +VOID +ICSInitScript() +{ + FILE *f; + char buf[MSG_SIZ]; + char *dummy; + + if (SearchPath(installDir, appData.icsLogon, NULL, MSG_SIZ, buf, &dummy)) { + f = fopen(buf, "r"); + if (f != NULL) { + ProcessICSInitScript(f); + fclose(f); + } + } +} + + +VOID +StartAnalysisClock() +{ + if (analysisTimerEvent) return; + analysisTimerEvent = SetTimer(hwndMain, (UINT) ANALYSIS_TIMER_ID, + (UINT) 1000, NULL); +} + +LRESULT CALLBACK +NameSubClass(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) +{ +/* + HWND Name; + CHARRANGE pos; +*/ + switch (message) { + switch (wParam) { + case VK_PRIOR: + return 0; + case VK_NEXT: + return 0; + } + break; + } + return (*NameWindowProc)(hwnd, message, wParam, lParam); +} + + +LRESULT CALLBACK +PvSubClass(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + HWND pvDisplay; + int GetSel; + char buf[MSG_SIZ]; + pvDisplay = GetDlgItem(analysisDialog, OPT_AnalysisText); + + switch (message) { + case WM_MBUTTONUP: + case WM_RBUTTONUP: + { + POINT pt; + pt.x = LOWORD(lParam); + pt.y = HIWORD(lParam); + if (appData.icsActive) { + MenuPopup(pvDisplay, pt, LoadMenu(hInst, "ICSENGINEROOM"), -1); + } else { + MenuPopup(pvDisplay, pt, LoadMenu(hInst, "ENGINEROOM"), -1); + } + } + break; + case WM_COMMAND: + switch (LOWORD(wParam)) { + case IDM_SelectAll: + GetSel = SendMessage(hwnd, LB_GETCOUNT, 0, 0); + SendMessage(hwnd, LB_SETSEL, GetSel, -1); + case IDM_Copy: + GetSel = SendMessage(hwnd, LB_GETCOUNT, 0, 0); + SendMessage(hwnd, LB_SETSEL, GetSel, -1); + SendMessage(hwnd, LB_GETTEXT, 0, (LPARAM)&buf); + + + SendMessage(hwnd, WM_COPY, 0, 0); + case IDM_SelPaste: + GetSel = SendMessage(hwnd, LB_GETCOUNT, 0, 0); + SendMessage(hwnd, LB_SETSEL, GetSel, -1); + SendMessage(hwnd, LB_GETTEXT, 0, (LPARAM)&buf); + + /* + SendMessage(hwnd, EM_EXSETSEL, 0, (LPARAM)&sel); + SendMessage(hwnd, WM_COPY, 0, 0); + */ + return 0; + case IDM_MachineWhite: + SendMessage(hwndMain, WM_COMMAND, IDM_MachineWhite, 0); + break; + case IDM_MachineBlack: + SendMessage(hwndMain, WM_COMMAND, IDM_MachineBlack, 0); + break; + case IDM_AnalysisMode: + SendMessage(hwndMain, WM_COMMAND, IDM_AnalysisMode, 0); + break; + case IDM_MoveNow: + GuiCommand(1,0); + break; + case IDM_EnginesButton: + if (first.analyzing == TRUE || first.maybeThinking == TRUE) { + SetDlgItemText(analysisDialog, OPT_engineStart, "Start Engine"); + } else if (first.analyzing == FALSE || first.maybeThinking == FALSE) { + SetDlgItemText(analysisDialog, OPT_engineStart, "Stop Engine"); + } + GuiCommand(2,0); + break; + case IDM_OperatorTime: + default: + break; + } + } + return (*PvWindowProc)(hwnd, message, wParam, lParam); +} + + +VOID +AnalysisDialogEnable(HWND hDlg) +{ + + #define IS_CHECKED(x) (Boolean)IsDlgButtonChecked(hDlg, (x)) + appData.engineStatLine = IS_CHECKED(OPT_engineStatLine); + if (!appData.engineTourneyMode) { + appData.engineTourneyMode = IS_CHECKED(OPT_engineTourneyMode); + } + #undef IS_CHECKED + + #define ENABLE_DLG_ITEM(x,y) EnableWindow(GetDlgItem(hDlg,(x)), (y)) + if (appData.engineTourneyMode) { + /* Freeze GUI */ + EnableWindow(GetDlgItem(hDlg, OPT_engineStart), FALSE); + EnableWindow(GetDlgItem(hDlg, OPT_engineMove), FALSE); + /* disable myself B-) */ + EnableWindow(GetDlgItem(hDlg, OPT_engineTourneyMode), FALSE); + EnableWindow(GetDlgItem(hDlg, OPT_engineStatLine), FALSE); + EnableWindow(GetDlgItem(hDlg, OPT_SendToICS), FALSE); + return; + } else { + if (appData.icsActive) { + EnableWindow(GetDlgItem(hDlg, OPT_engineTourneyMode), FALSE); + if (gameMode == IcsObserving) { + EnableWindow(GetDlgItem(hDlg, OPT_engineStart), FALSE); + EnableWindow(GetDlgItem(hDlg, OPT_engineMove), FALSE); + EnableWindow(GetDlgItem(hDlg, OPT_engineStatLine), FALSE); + EnableWindow(GetDlgItem(hDlg, OPT_SendToICS), FALSE); + } else { + EnableWindow(GetDlgItem(hDlg, OPT_engineStart), FALSE); + EnableWindow(GetDlgItem(hDlg, OPT_engineMove), FALSE); + EnableWindow(GetDlgItem(hDlg, OPT_engineStatLine), TRUE); + EnableWindow(GetDlgItem(hDlg, OPT_SendToICS), TRUE); + } + /* normal mode */ + } else { + /* mh, all should allow ;-) */ + switch (gameMode) { + case AnalyzeMode: + case AnalyzeFile: + EnableWindow(GetDlgItem(hDlg, OPT_engineTourneyMode), FALSE); + EnableWindow(GetDlgItem(hDlg, OPT_engineStatLine), FALSE); + EnableWindow(GetDlgItem(hDlg, OPT_engineStart), TRUE); + EnableWindow(GetDlgItem(hDlg, OPT_engineMove), FALSE); + break; + case MachinePlaysWhite: + if (WhiteOnMove(currentMove)) EnableWindow(GetDlgItem(hDlg, OPT_engineMove), TRUE); + if (!WhiteOnMove(currentMove)) EnableWindow(GetDlgItem(hDlg, OPT_engineMove), FALSE); + EnableWindow(GetDlgItem(hDlg, OPT_engineStart), TRUE); + EnableWindow(GetDlgItem(hDlg, OPT_engineTourneyMode), TRUE); + EnableWindow(GetDlgItem(hDlg, OPT_engineStatLine), TRUE); + break; + case MachinePlaysBlack: + if (!WhiteOnMove(currentMove)) EnableWindow(GetDlgItem(hDlg, OPT_engineMove), TRUE); + if (WhiteOnMove(currentMove)) EnableWindow(GetDlgItem(hDlg, OPT_engineMove), FALSE); + EnableWindow(GetDlgItem(hDlg, OPT_engineStart), TRUE); + EnableWindow(GetDlgItem(hDlg, OPT_engineTourneyMode), TRUE); + EnableWindow(GetDlgItem(hDlg, OPT_engineStatLine), TRUE); + break; + default: + EnableWindow(GetDlgItem(hDlg, OPT_engineStart), TRUE); + EnableWindow(GetDlgItem(hDlg, OPT_engineMove), FALSE); + EnableWindow(GetDlgItem(hDlg, OPT_engineTourneyMode), TRUE); + EnableWindow(GetDlgItem(hDlg, OPT_engineStatLine), TRUE); + } + /* Send OPT_SendToICS only for ICS */ + EnableWindow(GetDlgItem(hDlg, OPT_SendToICS), FALSE); + appData.ButtonSendOutPutToICS = FALSE; + appData.SendOutPutToICS = 0; + } + } + #undef ENABLE_DLG_ITEM +} + + +LRESULT CALLBACK +AnalysisDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + static HWND pvDisplay; + static HWND Name; + static HANDLE depth; + static HANDLE nps; + static HANDLE nodes; + static HANDLE score; + static HANDLE move_nr; + static HANDLE time; + static HANDLE statistic; + static HANDLE tourney; + static HANDLE OutPutSendToICS; + + RECT rect; + RECT rectPV; + RECT rectStatistic; + RECT rectTourney; + + RECT rc; + LPMEASUREITEMSTRUCT lpmis; + LPARAM lparam; + + static int sizeX, sizeY; + int newSizeX, newSizeY, flags; + static int newTextHeight, newTextWidth; + + MINMAXINFO *mmi; + + COLORREF PvBkColor = RGB(224,218,222); + COLORREF NameColor = RGB(171,216,173); + COLORREF FailLow = RGB(255, 255, 34); + COLORREF FailHigh = RGB(255, 0, 0); + /* + * COLORREF TourneyColor = RGB(235, 80, 71); + */ + switch (message) { + case WM_INITDIALOG: /* message: initialize dialog box */ + /* Initialize the dialog items */ + pvDisplay = GetDlgItem(hDlg, OPT_AnalysisText); + depth = GetDlgItem(hDlg, OPT_engineDepth); + nps = GetDlgItem(hDlg, OPT_engineNPS); + nodes = GetDlgItem(hDlg, OPT_engineNodes); + score = GetDlgItem(hDlg, OPT_engineScore); + Name = GetDlgItem(hDlg, OPT_engineName); + move_nr = GetDlgItem(hDlg, OPT_engineMoveNr); + time = GetDlgItem(hDlg, OPT_engineTime); + statistic = GetDlgItem(hDlg, OPT_engineStatLine); + tourney = GetDlgItem(hDlg, OPT_engineTourneyMode); + OutPutSendToICS = GetDlgItem(hDlg, OPT_SendToICS); + + #define CHECK_BOX(x,y) CheckDlgButton(hDlg, (x), (BOOL)(y)) + #define IS_CHECKED(x) (Boolean)IsDlgButtonChecked(hDlg, (x)) + AnalysisDialogEnable(hDlg); + SetWindowText(hDlg, "Winboard Engine Room"); + NameWindowProc = (WNDPROC) + SetWindowLong(Name, GWL_WNDPROC, (LONG) NameSubClass); + PvWindowProc = (WNDPROC) + SetWindowLong(pvDisplay, GWL_WNDPROC, (LONG) PvSubClass); + + if (!analysisDialog) { + analysisDialog = hDlg; + flags = SWP_NOZORDER; + GetClientRect(hDlg, &rect); + sizeX = rect.right; + sizeY = rect.bottom; + SendMessage(pvDisplay, EM_SETBKGNDCOLOR, FALSE, PvBkColor); + SendMessage(Name, EM_SETBKGNDCOLOR, FALSE, NameColor); + /* gameMode - we do a check */ + AnalysisDialogEnable(hDlg); + if (analysisH < 200 || analysisW < 300) { + /* center - safty position at startup after broken*/ + analysisH = 330; + analysisW = 518; + CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER)); + } + if (analysisW != CW_USEDEFAULT && analysisH != CW_USEDEFAULT) { + WINDOWPLACEMENT wp; + EnsureOnScreen(&analysisX, &analysisY); + wp.length = sizeof(WINDOWPLACEMENT); + wp.flags = WPF_RESTORETOMAXIMIZED; + wp.showCmd = SW_SHOW|SW_RESTORE; + wp.ptMaxPosition.x = wp.ptMaxPosition.y = 0; + wp.rcNormalPosition.left = analysisX; + wp.rcNormalPosition.right = analysisX + analysisW; + wp.rcNormalPosition.top = analysisY; + wp.rcNormalPosition.bottom = analysisY + analysisH; + SetWindowPlacement(hDlg, &wp); + GetClientRect(hDlg, &rect); + GetClientRect(pvDisplay, &rectPV); + GetClientRect(statistic, &rectStatistic); + GetClientRect(tourney, &rectTourney); + newSizeX = rect.right; + newSizeY = rect.bottom; + sizeX = newSizeX; + sizeY = newSizeY; + } + /* set focus to main window on start */ + SetFocus(hwndMain); + /* Check Send engine output to ICS */ + CHECK_BOX(OPT_SendToICS, appData.ButtonSendOutPutToICS); + } + return FALSE; + + case WM_MEASUREITEM: + // lpmis = (LPMEASUREITEMSTRUCT) lparam; + // GetWindowRect(GetDlgItem(pvDisplay, lpmis->CtlID), &rc); + break; + + case WM_DRAWITEM: + break; + + case WM_COMMAND: /* message: received a command */ + CHECK_BOX(OPT_engineStatLine, appData.engineStatLine); + CHECK_BOX(OPT_engineTourneyMode, appData.engineTourneyMode); + + switch (LOWORD(wParam)) { + case OPT_engineMove: + GuiCommand(1, 0); + break; + case OPT_engineStart: + if (first.analyzing == TRUE || first.maybeThinking == TRUE) { + SetDlgItemText(analysisDialog, OPT_engineStart, "Start Engine"); + } else if (first.analyzing == FALSE || first.maybeThinking == FALSE) { + SetDlgItemText(analysisDialog, OPT_engineStart, "Stop Engine"); + } + GuiCommand(2, 0); + break; + case OPT_engineStatLine: + /* over checkbox vars */ + break; + case OPT_SendToICS: + appData.ButtonSendOutPutToICS = IS_CHECKED(OPT_SendToICS); + + if (appData.ButtonSendOutPutToICS) { + appData.SendOutPutToICS = 1; + } else { + appData.SendOutPutToICS = 0; + } + break; + case OPT_engineTourneyMode: + /*appData.engineTourneyMode = TRUE;*/ + MessageBox(hDlg, "Tourney Mode: Disable a lot of WB function.\rYou can leave this mode by closing Engine Room Window !\r\ +This mode is for events suchs as World Champion Chips\rbut not ready at the moment.", + "ICCA/FIDE Tourney Mode", MB_OK); + SetWindowText(analysisDialog, "Winboard Engine Room - Tourney Mode"); + SetWindowText(hwndMain, "Winboard - Tourney Mode"); + break; + case IDCANCEL: + /* TourneyMode off */ + if (appData.engineTourneyMode) { + CheckDlgButton(hDlg, OPT_engineTourneyMode, BST_UNCHECKED); + appData.engineTourneyMode = FALSE; + AnalysisDialogEnable(hDlg); + SetWindowText(analysisDialog, "Winboard Engine Room"); + break; + } + if (gameMode == MachinePlaysWhite || gameMode == MachinePlaysBlack || + gameMode == IcsPlayingWhite || gameMode == IcsPlayingBlack) { + appData.AnalysisWindow = FALSE; + AnalysisPopDown(); + } else if (gameMode == IcsObserving) { + appData.icsAnalyzeWindow = FALSE; + AnalysisPopDown(); + } else { + AnalysisPopDown(); + appData.AnalysisWindow = FALSE; + EditGameEvent(); + } + return TRUE; + + default: + AnalysisDialogEnable(hDlg); + break; + } + break; + + case WM_SIZE: + newSizeX = LOWORD(lParam); + newSizeY = HIWORD(lParam); + if (sizeX != newSizeX || sizeY != newSizeY) { + GetWindowRect(pvDisplay, &rectPV); + newTextWidth = rectPV.right - + rectPV.left + newSizeX - sizeX; + newTextHeight = rectPV.bottom - + rectPV.top + newSizeY - sizeY; + if (newTextHeight < 0) { + newSizeY += -newTextHeight; + newTextHeight = 0; + } + SetWindowPos(pvDisplay, NULL, 0, 0, + newTextWidth, newTextHeight, SWP_NOZORDER|SWP_NOMOVE); + + } + sizeX = newSizeX; + sizeY = newSizeY; + break; + + case WM_GETMINMAXINFO: + mmi = (MINMAXINFO *) lParam; + mmi->ptMinTrackSize.x = 518; + mmi->ptMinTrackSize.y = 250; + break; + + case WM_QUERYOPEN: + MoveWindow(pvDisplay, sizeX, sizeY, newTextWidth, + newTextHeight, TRUE); + /* engineRoom no longer a parent Window */ + /* possible that hwndMain is hidden */ + /* if (IsIconic(hwndMain)) ShowWindow(hwndMain, SW_RESTORE); */ + break; + + default: + AnalysisDialogEnable(hDlg); + break; + } + return FALSE; +} + +/* Engine Room */ + +/* style from EngineRoom */ +void +SetEngineRoomFonts() +{ + CHARFORMAT2 pvdisplayf; + CHARFORMAT2 enginenamf; + HWND PvDisplay; + HWND Name; + PvDisplay = GetDlgItem(analysisDialog, OPT_AnalysisText); + Name = GetDlgItem(analysisDialog, OPT_engineName); + + /* PV screen */ + pvdisplayf.cbSize = sizeof(CHARFORMAT); + pvdisplayf.bCharSet = DEFAULT_CHARSET; + pvdisplayf.dwMask = CFM_COLOR|CFM_BOLD|CFM_SPACING| + CFM_ITALIC|CFM_CHARSET|CFM_WEIGHT; + pvdisplayf.dwEffects = CFE_ITALIC; + pvdisplayf.wWeight = 2; + pvdisplayf.sSpacing = 10; + pvdisplayf.crTextColor = RGB(0,0,0); + + /* + SendMessage(PvDisplay, EM_SETCHARFORMAT, (WPARAM) SCF_ALL, + (LPARAM) &pvdisplayf); + */ + + /* engine Name */ + enginenamf.cbSize = sizeof(CHARFORMAT); + enginenamf.bCharSet = "Arial Black"; + enginenamf.dwMask = CFM_BOLD; + enginenamf.crTextColor = RGB(0,0,0); + enginenamf.dwEffects = CFE_BOLD; + + SendMessage(Name, EM_SETCHARFORMAT, (WPARAM) SCF_ALL, + (LPARAM) &enginenamf); +} + +/* dirty dirty code: use buffer. I can use EM_*. If i have more time ... + * WriteText is allso better. If War Room comes (2 engine window) i will + * change to good code. At the moment we work with dirty buffers + */ +int i; + +VOID +AnalysisPopUp(pv, depth, nps, nodes, score, move_nr, time, state) +char* pv; +char* depth; +char* nps; +char* nodes; +char* score; +char* move_nr; +char* time; +int state; +{ + FARPROC lpProc; + HWND pvDisplay; + HWND Name; + HWND engineStart; + + COLORREF NamePonder = RGB(255, 132, 132); /* opponent/ponder on move */ + COLORREF NameColor = RGB(171,216,173); /* we are on move */ + COLORREF NameAnalyze = RGB(148, 148, 248); /* Analyze anf FileanalyzeMode */ + COLORREF NameObserve = RGB(241, 248, 116); /* ICS observe */ + + + static char last_pv[MSG_SIZ]; + char pv_output[16384]; + static int last_move; + static int counter, last_line; + pvDisplay = GetDlgItem(analysisDialog, OPT_AnalysisText); + Name = GetDlgItem(analysisDialog, OPT_engineName); + engineStart = GetDlgItem(analysisDialog, OPT_engineStart); + + if (!analysisDialog) { + lpProc = MakeProcInstance((FARPROC)AnalysisDialog, hInst); + CreateDialog(hInst, MAKEINTRESOURCE(DLG_Analysis), + 0, (DLGPROC)lpProc); + FreeProcInstance(lpProc); + SetEngineRoomFonts(); + /* engine button don't support icsMode */ + if (appData.icsActive) { + SetDlgItemText(analysisDialog, OPT_engineStart, "Disable"); + SetDlgItemText(analysisDialog, OPT_engineMove, "Disable"); + } else { + SetDlgItemText(analysisDialog, OPT_engineStart, "Start Engine"); + SetDlgItemText(analysisDialog, OPT_engineMove, "Move!"); + } + /* if state 5 we have a WB bootup init */ + if (state == 5) { + DisplayAnalysis(0,0); + SendDlgItemMessage(analysisDialog, OPT_AnalysisText, + LB_ADDSTRING, (WPARAM) 0, + (LPARAM) "ready for play"); + //SetDlgItemText(analysisDialog, OPT_AnalysisText, "ready for play"); + return; + } + } + + /* check if core part say no support for stat line */ + /* only if new game or so */ + if (appData.engineStatLine == TRUE) { + CheckDlgButton(analysisDialog, OPT_engineStatLine, BST_CHECKED); + SetDlgItemText(analysisDialog, OPT_engineMoveNr, "disable"); + } else if (appData.engineStatLine == FALSE) { + CheckDlgButton(analysisDialog, OPT_engineStatLine, BST_UNCHECKED); + } + + /* new move - begin from 0 */ + if (last_move != currentMove) { + SendDlgItemMessage(analysisDialog, OPT_AnalysisText, LB_RESETCONTENT, 0, 0); + last_move = currentMove; + counter = 0; + } + + /* Set engine button to engine state */ + if (pv[0] != NULLCHAR) { + if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) { + if (first.analyzing == TRUE) { + SetDlgItemText(analysisDialog, OPT_engineStart, "Stop Engine"); + + } + } else if (gameMode == MachinePlaysWhite || gameMode == MachinePlaysBlack) { + if (first.maybeThinking) { + SetDlgItemText(analysisDialog, OPT_engineStart, "Stop Engine"); + } + } + } + /* colorize EngineName - really check every action? */ + /* If we fast yes, think about build a own function + * and set it on GameModeEvent() + */ + switch (state) { + case 0: + SendMessage(Name, EM_SETBKGNDCOLOR, FALSE, NameColor); + break; + case 1: + SendMessage(Name, EM_SETBKGNDCOLOR, FALSE, NamePonder); + break; + case 2: + SendMessage(Name, EM_SETBKGNDCOLOR, FALSE, NameAnalyze); + break; + case 3: + SendMessage(Name, EM_SETBKGNDCOLOR, FALSE, NameObserve); + break; + } + + if (pv[0] != NULLCHAR) { + strcpy(pv_output, time); + strcat(pv_output, pv); + strcpy(engineRoom[counter].mainline, pv_output); + + counter++; + + /* + for (i = 0; i <= counter; i++) { + if (i == 0) { + strcpy(pv_output, engineRoom[i].mainline); + strcat(pv_output, "\r\n"); + } else if (i == counter) { + strcat(pv_output, engineRoom[i].mainline); + } else { + strcat(pv_output, engineRoom[i].mainline); + strcat(pv_output, "\r\n"); + } + } + //SetDlgItemText(analysisDialog, OPT_AnalysisText, pv_output); + */ + + + SendDlgItemMessage(analysisDialog, OPT_AnalysisText, LB_ADDSTRING, (WPARAM) 0, (LPARAM) pv_output); + + /* mark last pv */ + SendDlgItemMessage(analysisDialog, OPT_AnalysisText, LB_SETSEL, 0, -1); + SendDlgItemMessage(analysisDialog, OPT_AnalysisText, LB_SETSEL, counter, counter-1); + + SendMessage(pvDisplay, WM_VSCROLL, SB_BOTTOM, 0); + } + + SetDlgItemText(analysisDialog, OPT_engineDepth, depth); + SetDlgItemText(analysisDialog, OPT_engineNPS, nps); + SetDlgItemText(analysisDialog, OPT_engineNodes, nodes); + SetDlgItemText(analysisDialog, OPT_engineScore, score); + SetDlgItemText(analysisDialog, OPT_engineMoveNr, move_nr); + SetDlgItemText(analysisDialog, OPT_engineTime, time); + SetDlgItemText(analysisDialog, OPT_engineHash, "reserved"); + SetDlgItemText(analysisDialog, OPT_egtb, "reserved"); + if (state == 4) { + SetDlgItemText(analysisDialog, OPT_engineName, "no support"); + if (appData.AnalysisWindow) { + /* We need an other window and a *queue* for each engine to + * read data !! + */ + appData.AnalysisWindow = FALSE; + SetDlgItemText(analysisDialog, OPT_AnalysisText, + "Sorry, no Support. Please wait for a coming Engine War Room !"); + /* take TourneyMode to block user action ;-) */ + if (!appData.engineTourneyMode) appData.engineTourneyMode = TRUE; + } + } else { + /* We don't need this because we have only 1 engine + * and set on start should be enought, but for tests + * it's enable at the moment + */ + SetDlgItemText(analysisDialog, OPT_engineName, first.tidy); + } + + strcpy(last_pv, pv); + if (analysisDialogUp != TRUE) { + analysisDialogUp = TRUE; + ShowWindow(analysisDialog, SW_SHOW); + } +} + +VOID +AnalysisPopDown() +{ + if (analysisDialog) { + ShowWindow(analysisDialog, SW_HIDE); + } + analysisDialogUp = FALSE; +} + + +VOID +SetHighlights(int fromX, int fromY, int toX, int toY) +{ + highlightInfo.sq[0].x = fromX; + highlightInfo.sq[0].y = fromY; + highlightInfo.sq[1].x = toX; + highlightInfo.sq[1].y = toY; +} + +VOID +ClearHighlights() +{ + highlightInfo.sq[0].x = highlightInfo.sq[0].y = + highlightInfo.sq[1].x = highlightInfo.sq[1].y = -1; +} + +VOID +SetPremoveHighlights(int fromX, int fromY, int toX, int toY) +{ + premoveHighlightInfo.sq[0].x = fromX; + premoveHighlightInfo.sq[0].y = fromY; + premoveHighlightInfo.sq[1].x = toX; + premoveHighlightInfo.sq[1].y = toY; +} + +VOID +ClearPremoveHighlights() +{ + premoveHighlightInfo.sq[0].x = premoveHighlightInfo.sq[0].y = + premoveHighlightInfo.sq[1].x = premoveHighlightInfo.sq[1].y = -1; +} + +VOID +ShutDownFrontEnd() +{ + if (saveSettingsOnExit) SaveSettings(settingsFileName); + DeleteClipboardTempFiles(); +} + +void +BoardToTop() +{ + if (IsIconic(hwndMain)) + ShowWindow(hwndMain, SW_RESTORE); + + SetActiveWindow(hwndMain); +} + +/* + * Prototypes for animation support routines + */ +static void ScreenSquare(int column, int row, POINT * pt); +static void Tween( POINT * start, POINT * mid, POINT * finish, int factor, + POINT frames[], int * nFrames); + + +#define kFactor 4 + +void +AnimateMove(board, fromX, fromY, toX, toY) + Board board; + int fromX; + int fromY; + int toX; + int toY; +{ + ChessSquare piece; + POINT start, finish, mid; + POINT frames[kFactor * 2 + 1]; + int nFrames, n; + + if (!appData.animate) return; + if (doingSizing) return; + if (fromY < 0 || fromX < 0) return; + piece = board[fromY][fromX]; + if (piece >= EmptySquare) return; + + ScreenSquare(fromX, fromY, &start); + ScreenSquare(toX, toY, &finish); + + /* All pieces except knights move in straight line */ + if (piece != WhiteKnight && piece != BlackKnight) { + mid.x = start.x + (finish.x - start.x) / 2; + mid.y = start.y + (finish.y - start.y) / 2; + } else { + /* Knight: make diagonal movement then straight */ + if (abs(toY - fromY) < abs(toX - fromX)) { + mid.x = start.x + (finish.x - start.x) / 2; + mid.y = finish.y; + } else { + mid.x = finish.x; + mid.y = start.y + (finish.y - start.y) / 2; + } + } + + /* Don't use as many frames for very short moves */ + if (abs(toY - fromY) + abs(toX - fromX) <= 2) + Tween(&start, &mid, &finish, kFactor - 1, frames, &nFrames); + else + Tween(&start, &mid, &finish, kFactor, frames, &nFrames); + + animInfo.from.x = fromX; + animInfo.from.y = fromY; + animInfo.to.x = toX; + animInfo.to.y = toY; + animInfo.lastpos = start; + animInfo.piece = piece; + for (n = 0; n < nFrames; n++) { + animInfo.pos = frames[n]; + DrawPosition(FALSE, NULL); + animInfo.lastpos = animInfo.pos; + Sleep(appData.animSpeed); + } + animInfo.pos = finish; + DrawPosition(FALSE, NULL); + animInfo.piece = EmptySquare; +} + +/* Convert board position to corner of screen rect and color */ + +static void +ScreenSquare(column, row, pt) + int column; int row; POINT * pt; +{ + if (flipView) { + pt->x = lineGap + ((BOARD_SIZE-1)-column) * (squareSize + lineGap); + pt->y = lineGap + row * (squareSize + lineGap); + } else { + pt->x = lineGap + column * (squareSize + lineGap); + pt->y = lineGap + ((BOARD_SIZE-1)-row) * (squareSize + lineGap); + } +} + +/* Generate a series of frame coords from start->mid->finish. + The movement rate doubles until the half way point is + reached, then halves back down to the final destination, + which gives a nice slow in/out effect. The algorithmn + may seem to generate too many intermediates for short + moves, but remember that the purpose is to attract the + viewers attention to the piece about to be moved and + then to where it ends up. Too few frames would be less + noticeable. */ + +static void +Tween(start, mid, finish, factor, frames, nFrames) + POINT * start; POINT * mid; + POINT * finish; int factor; + POINT frames[]; int * nFrames; +{ + int n, fraction = 1, count = 0; + + /* Slow in, stepping 1/16th, then 1/8th, ... */ + for (n = 0; n < factor; n++) + fraction *= 2; + for (n = 0; n < factor; n++) { + frames[count].x = start->x + (mid->x - start->x) / fraction; + frames[count].y = start->y + (mid->y - start->y) / fraction; + count ++; + fraction = fraction / 2; + } + + /* Midpoint */ + frames[count] = *mid; + count ++; + + /* Slow out, stepping 1/2, then 1/4, ... */ + fraction = 2; + for (n = 0; n < factor; n++) { + frames[count].x = finish->x - (finish->x - mid->x) / fraction; + frames[count].y = finish->y - (finish->y - mid->y) / fraction; + count ++; + fraction = fraction * 2; + } + *nFrames = count; +} + +void +HistorySet(char movelist[][2*MOVE_LEN], int first, int last, int current) +{ + /* Currently not implemented in WinBoard */ +} + + diff --git a/winboard-dm-beta4/winboard.dsp b/winboard-dm-beta4/winboard.dsp new file mode 100755 index 0000000..9a25d50 --- /dev/null +++ b/winboard-dm-beta4/winboard.dsp @@ -0,0 +1,1776 @@ +# Microsoft Developer Studio Project File - Name="winboard" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** NICHT BEARBEITEN ** + +# TARGTYPE "Win32 (x86) External Target" 0x0106 + +CFG=winboard - Win32 Release +!MESSAGE Dies ist kein gültiges Makefile. Zum Erstellen dieses Projekts mit NMAKE +!MESSAGE verwenden Sie den Befehl "Makefile exportieren" und führen Sie den Befehl +!MESSAGE +!MESSAGE NMAKE /f "winboard.mak". +!MESSAGE +!MESSAGE Sie können beim Ausführen von NMAKE eine Konfiguration angeben +!MESSAGE durch Definieren des Makros CFG in der Befehlszeile. Zum Beispiel: +!MESSAGE +!MESSAGE NMAKE /f "winboard.mak" CFG="winboard - Win32 Release" +!MESSAGE +!MESSAGE Für die Konfiguration stehen zur Auswahl: +!MESSAGE +!MESSAGE "winboard - Win32 Release" (basierend auf "Win32 (x86) External Target") +!MESSAGE "winboard - Win32 Debug" (basierend auf "Win32 (x86) External Target") +!MESSAGE "winboard - Win32 Opt" (basierend auf "Win32 (x86) External Target") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" + +!IF "$(CFG)" == "winboard - Win32 Release" + +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir ".\Release" +# PROP BASE Intermediate_Dir ".\Release" +# PROP BASE Cmd_Line "NMAKE /f winboard.mak" +# PROP BASE Rebuild_Opt "/a" +# PROP BASE Target_File "winboard.exe" +# PROP BASE Bsc_Name "winboard.bsc" +# PROP BASE Target_Dir "" +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir ".\Release" +# PROP Intermediate_Dir ".\Release" +# PROP Cmd_Line "NMAKE" +# PROP Rebuild_Opt "/a" +# PROP Target_File "winboard.exe" +# PROP Bsc_Name "winboard.bsc" +# PROP Target_Dir "" + +!ELSEIF "$(CFG)" == "winboard - Win32 Debug" + +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir ".\Debug" +# PROP BASE Intermediate_Dir ".\Debug" +# PROP BASE Cmd_Line "NMAKE /f winboard.mak" +# PROP BASE Rebuild_Opt "/a" +# PROP BASE Target_File "winboard.exe" +# PROP BASE Bsc_Name "winboard.bsc" +# PROP BASE Target_Dir "" +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir ".\Debug" +# PROP Intermediate_Dir ".\Debug" +# PROP Cmd_Line "NMAKE" +# PROP Rebuild_Opt "" +# PROP Target_File "winboard.exe" +# PROP Bsc_Name "winboard.bsc" +# PROP Target_Dir "" + +!ELSEIF "$(CFG)" == "winboard - Win32 Opt" + +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "winboard___Win32_Opt" +# PROP BASE Intermediate_Dir "winboard___Win32_Opt" +# PROP BASE Cmd_Line "NMAKE" +# PROP BASE Rebuild_Opt "/a" +# PROP BASE Target_File "winboard.exe" +# PROP BASE Bsc_Name "winboard.bsc" +# PROP BASE Target_Dir "" +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "winboard___Win32_Opt" +# PROP Intermediate_Dir "winboard___Win32_Opt" +# PROP Cmd_Line "NMAKE" +# PROP Rebuild_Opt "/a" +# PROP Target_File "winboard.exe" +# PROP Bsc_Name "winboard.bsc" +# PROP Target_Dir "" + +!ENDIF + +# Begin Target + +# Name "winboard - Win32 Release" +# Name "winboard - Win32 Debug" +# Name "winboard - Win32 Opt" + +!IF "$(CFG)" == "winboard - Win32 Release" + +!ELSEIF "$(CFG)" == "winboard - Win32 Debug" + +!ELSEIF "$(CFG)" == "winboard - Win32 Opt" + +!ENDIF + +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90" +# Begin Source File + +SOURCE=.\backend.c +# End Source File +# Begin Source File + +SOURCE=.\gamelist.c +# End Source File +# Begin Source File + +SOURCE=.\lists.c +# End Source File +# Begin Source File + +SOURCE=.\moves.c +# End Source File +# Begin Source File + +SOURCE=.\parser.c +# End Source File +# Begin Source File + +SOURCE=.\parser.l +# End Source File +# Begin Source File + +SOURCE=.\pgntags.c +# End Source File +# Begin Source File + +SOURCE=.\wedittags.c +# End Source File +# Begin Source File + +SOURCE=.\wgamelist.c +# End Source File +# Begin Source File + +SOURCE=.\winboard.c +# End Source File +# Begin Source File + +SOURCE=.\woptions.c +# End Source File +# Begin Source File + +SOURCE=.\wsockerr.c +# End Source File +# Begin Source File + +SOURCE=.\zippy.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd" +# Begin Source File + +SOURCE=.\backend.h +# End Source File +# Begin Source File + +SOURCE=.\backendz.h +# End Source File +# Begin Source File + +SOURCE=.\common.h +# End Source File +# Begin Source File + +SOURCE=.\config.h +# End Source File +# Begin Source File + +SOURCE=.\defaults.h +# End Source File +# Begin Source File + +SOURCE=.\frontend.h +# End Source File +# Begin Source File + +SOURCE=.\lists.h +# End Source File +# Begin Source File + +SOURCE=.\moves.h +# End Source File +# Begin Source File + +SOURCE=.\parser.h +# End Source File +# Begin Source File + +SOURCE=.\resource.h +# End Source File +# Begin Source File + +SOURCE=.\wedittags.h +# End Source File +# Begin Source File + +SOURCE=.\wgamelist.h +# End Source File +# Begin Source File + +SOURCE=.\winboard.h +# End Source File +# Begin Source File + +SOURCE=.\woptions.h +# End Source File +# Begin Source File + +SOURCE=.\wsockerr.h +# End Source File +# Begin Source File + +SOURCE=.\zippy.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe" +# Begin Source File + +SOURCE=.\bitmaps\b108o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\b108s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\b108w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\b116o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\b116s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\b116w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\b129o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\b129s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\b129w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\B21o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\B21s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\b21w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\b25o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\b25s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\b25w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\b29o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\b29s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\b29w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\b33o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\b33s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\b33w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\b37o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\b37s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\b37w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\B40o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\B40s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\b40w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\b45o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\b45s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\b45w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\b49o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\b49s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\b49w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\b54o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\b54s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\b54w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\b58o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\b58s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\b58w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\b64o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\B64s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\b64w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\b72o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\b72s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\b72w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\B80o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\B80s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\b80w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\b87o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\b87s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\b87w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\b95o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\b95s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\b95w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\bepbeep.wav +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\board.ico +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\ching.wav +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\click.wav +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\cymbal.wav +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\Ding1.wav +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\doodloop.wav +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\drip.wav +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\galactic.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\gong.wav +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\honkhonk.wav +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\icon_b.ico +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\icon_ob.ico +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\icon_ow.ico +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\icon_whi.ico +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\k108o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\k108s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\k108w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\k116o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\k116s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\k116w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\k129o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\k129s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\k129w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\K21o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\K21s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\k21w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\k25o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\k25s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\k25w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\k29o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\k29s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\k29w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\k33o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\k33s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\k33w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\k37o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\k37s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\k37w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\k40o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\k40s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\k40w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\k45o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\k45s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\k45w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\k49o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\k49s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\k49w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\k54o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\k54s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\k54w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\k58o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\k58s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\k58w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\k64o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\k64s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\k64w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\k72o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\k72s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\k72w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\k80o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\k80s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\k80w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\k87o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\k87s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\k87w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\k95o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\k95s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\k95w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\laser.wav +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\move.wav +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\n108o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\n108s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\n108w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\n116o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\n116s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\n116w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\n129o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\n129s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\n129w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\N21o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\N21s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\n21w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\n25o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\n25s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\n25w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\n29o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\n29s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\n29w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\n33o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\n33s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\n33w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\n37o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\n37s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\n37w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\n40o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\n40s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\n40w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\n45o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\n45s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\n45w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\n49o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\n49s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\n49w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\n54o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\n54s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\n54w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\n58o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\n58s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\n58w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\n64o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\n64s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\n64w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\n72o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\n72s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\n72w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\n80o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\n80s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\n80w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\n87o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\n87s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\n87w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\n95o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\n95s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\n95w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\p108o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\p108s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\p108w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\p116o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\p116s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\p116w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\p129o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\p129s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\p129w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\P21o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\P21s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\p21w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\p25o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\p25s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\p25w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\p29o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\p29s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\p29w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\p33o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\p33s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\p33w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\p37o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\p37s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\p37w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\p40o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\p40s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\p40w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\p45o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\p45s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\p45w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\p49o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\p49s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\p49w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\p54o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\p54s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\p54w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\p58o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\p58s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\p58w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\p64o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\p64s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\p64w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\p72o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\p72s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\p72w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\p80o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\p80s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\p80w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\p87o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\p87s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\p87w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\p95o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\p95s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\p95w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\penalty.wav +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\phone.wav +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\pop.wav +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\pop2.wav +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\q108o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\q108s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\q108w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\q116o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\q116s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\q116w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\q129o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\q129s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\q129w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\Q21o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\Q21s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\q21w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\q25o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\q25s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\q25w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\q29o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\q29s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\q29w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\q33o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\q33s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\q33w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\q37o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\q37s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\q37w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\q40o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\q40s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\q40w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\q45o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\q45s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\q45w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\q49o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\q49s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\q49w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\q54o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\q54s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\q54w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\q58o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\q58s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\q58w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\q64o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\q64s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\q64w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\q72o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\q72s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\q72w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\q80o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\q80s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\q80w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\q87o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\q87s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\q87w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\q95o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\q95s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\q95w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\r108o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\r108s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\r108w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\r116o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\r116s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\r116w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\r129o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\r129s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\r129w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\R21o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\R21s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\r21w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\r25o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\r25s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\r25w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\r29o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\r29s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\r29w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\r33o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\r33s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\r33w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\r37o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\r37s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\r37w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\r40o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\r40s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\r40w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\r45o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\r45s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\r45w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\r49o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\r49s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\r49w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\r54o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\r54s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\r54w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\r58o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\r58s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\r58w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\r64o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\r64s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\r64w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\r72o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\r72s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\r72w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\R80o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\R80s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\r80w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\r87o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\r87s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\r87w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\r95o.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\r95s.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\r95w.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\slap.wav +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\squeak.wav +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\swish.wav +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\thud.wav +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\tim.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\whipcrak.wav +# End Source File +# Begin Source File + +SOURCE=.\winboard.rc +# End Source File +# Begin Source File + +SOURCE=.\WINBOARD.rtf +# End Source File +# Begin Source File + +SOURCE=.\bitmaps\zap.wav +# End Source File +# End Group +# Begin Source File + +SOURCE=.\sounds\alarm.wav +# End Source File +# Begin Source File + +SOURCE=.\sounds\challenge.wav +# End Source File +# Begin Source File + +SOURCE=.\sounds\channel.wav +# End Source File +# Begin Source File + +SOURCE=.\sounds\channel1.wav +# End Source File +# Begin Source File + +SOURCE=.\sounds\ching.wav +# End Source File +# Begin Source File + +SOURCE=.\sounds\click.wav +# End Source File +# Begin Source File + +SOURCE=.\sounds\cymbal.wav +# End Source File +# Begin Source File + +SOURCE=.\sounds\ding1.wav +# End Source File +# Begin Source File + +SOURCE=.\sounds\draw.wav +# End Source File +# Begin Source File + +SOURCE=.\sounds\drip.wav +# End Source File +# Begin Source File + +SOURCE=.\sounds\gong.wav +# End Source File +# Begin Source File + +SOURCE=.\sounds\honkhonk.wav +# End Source File +# Begin Source File + +SOURCE=.\sounds\kibitz.wav +# End Source File +# Begin Source File + +SOURCE=.\sounds\laser.wav +# End Source File +# Begin Source File + +SOURCE=.\sounds\lose.wav +# End Source File +# Begin Source File + +SOURCE=.\sounds\move.wav +# End Source File +# Begin Source File + +SOURCE=.\sounds\penalty.wav +# End Source File +# Begin Source File + +SOURCE=.\sounds\phone.wav +# End Source File +# Begin Source File + +SOURCE=.\sounds\pop.wav +# End Source File +# Begin Source File + +SOURCE=.\sounds\pop2.wav +# End Source File +# Begin Source File + +SOURCE=.\sounds\request.wav +# End Source File +# Begin Source File + +SOURCE=.\sounds\seek.wav +# End Source File +# Begin Source File + +SOURCE=.\sounds\shout.wav +# End Source File +# Begin Source File + +SOURCE=.\sounds\slap.wav +# End Source File +# Begin Source File + +SOURCE=.\sounds\squeak.wav +# End Source File +# Begin Source File + +SOURCE=.\sounds\sshout.wav +# End Source File +# Begin Source File + +SOURCE=.\sounds\swish.wav +# End Source File +# Begin Source File + +SOURCE=.\sounds\tell.wav +# End Source File +# Begin Source File + +SOURCE=.\sounds\thud.wav +# End Source File +# Begin Source File + +SOURCE=.\sounds\unfinished.wav +# End Source File +# Begin Source File + +SOURCE=.\sounds\whipcrak.wav +# End Source File +# Begin Source File + +SOURCE=.\sounds\win.wav +# End Source File +# End Target +# End Project diff --git a/winboard-dm-beta4/winboard.dsw b/winboard-dm-beta4/winboard.dsw new file mode 100755 index 0000000..0374221 --- /dev/null +++ b/winboard-dm-beta4/winboard.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNUNG: DIESE ARBEITSBEREICHSDATEI DARF NICHT BEARBEITET ODER GELÖSCHT WERDEN! + +############################################################################### + +Project: "winboard"=.\winboard.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/winboard-dm-beta4/winboard.h b/winboard-dm-beta4/winboard.h new file mode 100755 index 0000000..db7c2bd --- /dev/null +++ b/winboard-dm-beta4/winboard.h @@ -0,0 +1,165 @@ +/* + * WinBoard.h -- Definitions for Windows NT front end to XBoard + * + * Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts. + * Enhancements Copyright 1992-97 Free Software Foundation, Inc. + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * ------------------------------------------------------------------------ + */ +#include "resource.h" +#include + +/* Types */ +typedef struct { + char faceName[LF_FACESIZE]; + float pointSize; + BYTE bold, italic, underline, strikeout; +} MyFontParams; + +typedef struct { + char *def; + MyFontParams mfp; + LOGFONT lf; + HFONT hf; +} MyFont; + +typedef enum { + SizeTiny, SizeTeeny, SizeDinky, SizePetite, SizeSlim, SizeSmall, + SizeMediocre, SizeMiddling, SizeAverage, SizeModerate, SizeMedium, + SizeBulky, SizeLarge, SizeBig, SizeHuge, SizeGiant, SizeColossal, + SizeTitanic, NUM_SIZES +} BoardSize; + +typedef struct { + COLORREF color; + int effects; + char *name; +} MyColorizeAttribs; + +typedef struct { + char* name; + void* data; +} MySound; + +typedef struct { + COLORREF color; + int effects; + MySound sound; +} MyTextAttribs; + +/* Functions */ + +BOOL InitApplication(HINSTANCE); +BOOL InitInstance(HINSTANCE, int, LPSTR); +LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); +LRESULT CALLBACK About(HWND, UINT, WPARAM, LPARAM); +LRESULT CALLBACK BoardSizeDlg(HWND, UINT, WPARAM, LPARAM); +LRESULT CALLBACK ButtonProc(HWND, UINT, WPARAM, LPARAM); +VOID InitAppData(LPSTR); +VOID InitDrawingColors(VOID); +VOID InitDrawingSizes(BoardSize boardSize, int flags); +VOID InitMenuChecks(VOID); +VOID ICSInitScript(VOID); +BOOL CenterWindow(HWND hwndChild, HWND hwndParent); +VOID ResizeEditPlusButtons(HWND hDlg, HWND hText, int sizeX, int sizeY, int newSizeX, int newSizeY); +VOID PromotionPopup(HWND hwnd); +FILE *OpenFileDialog(HWND hWnd, BOOL write, char *defName, char *defExt, + char *nameFilt, char *dlgTitle, UINT *number, + char fileTitle[MSG_SIZ], char fileName[MSG_SIZ]); +VOID InputEvent(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); +DWORD InputThread(LPVOID arg); +DWORD NonOvlInputThread(LPVOID arg); +DWORD SocketInputThread(LPVOID arg); +BOOL ChangeColor(HWND hwnd, COLORREF *which); +VOID ChangeBoardSize(BoardSize newSize); +BOOL APIENTRY MyCreateFont(HWND hwnd, MyFont *font); +VOID ErrorPopDown(VOID); +VOID EnsureOnScreen(int *x, int *y); +typedef char GetFunc(void *getClosure); +VOID ParseArgs(GetFunc get, void *cl); +HBITMAP +DoLoadBitmap(HINSTANCE hinst, char *piece, int squareSize, char *suffix); +COLORREF ParseColorName(char *name); +void ParseAttribs(COLORREF *color, int *effects, char* argValue); +VOID CreateFontInMF(MyFont *mf); +VOID ChangedConsoleFont(); +VOID ParseFontName(char *name, MyFontParams *mfp); +void InitComboStrings(HANDLE hwndCombo, char **cd); +BOOLEAN MyLoadSound(MySound *ms); +BOOLEAN MyPlaySound(MySound *ms); +VOID ExitArgError(char *msg, char *badArg); + +/* Constants */ +#define CLOCK_FONT 0 +#define MESSAGE_FONT 1 +#define COORD_FONT 2 +#define CONSOLE_FONT 3 +#define COMMENT_FONT 4 +#define EDITTAGS_FONT 5 +#define NUM_FONTS 6 + +/* Positions of some menu items. Origin is zero and separator lines count. */ +/* It's gross that these are needed. */ +#define ACTION_POS 2 /* Posn of "Action" on menu bar */ +#define OPTIONS_POS 4 /* Posn of "Options" on menu bar */ +#define ICS_POS 4 /* Posn of "ICS " on Options menu */ +#define SOUNDS_POS 6 /* Posn of "Sounds" on Options menu */ +/* end grossness */ + +extern MyFont *font[NUM_SIZES][NUM_FONTS]; + +#define WM_USER_Input (WM_USER + 4242) +#define WM_USER_Mouseleave (WM_USER + 4243) +#define WM_USER_GetConsoleBackground (WM_USER + 4244) + +#define CLOCK_TIMER_ID 51 +#define LOAD_GAME_TIMER_ID 52 +#define ANALYSIS_TIMER_ID 53 +#define MOUSE_TIMER_ID 54 +#define DELAYED_TIMER_ID 55 + +#define SOLID_PIECE 0 +#define OUTLINE_PIECE 1 +#define WHITE_PIECE 2 + +#define COPY_TMP "wbcopy.tmp" +#define PASTE_TMP "wbpaste.tmp" + diff --git a/winboard-dm-beta4/winboard.hpj b/winboard-dm-beta4/winboard.hpj new file mode 100755 index 0000000..48e48ff --- /dev/null +++ b/winboard-dm-beta4/winboard.hpj @@ -0,0 +1,19 @@ +; This file is maintained by HCW. Do not modify this file directly. + +; This help project requires hc 3.1 +[OPTIONS] +ERRORLOG=winboard.err +LCID=0x409 0x0 0x0 ; English (United States) +REPORT=Yes +TITLE=WinBoard Help +BMROOT=bitmaps +HLP=.\winboard.hlp + +[FILES] +winboard.rtf + +[WINDOWS] +main="WinBoard Help",,60676,,(r12632256),f2 + +[CONFIG] +BrowseButtons() diff --git a/winboard-dm-beta4/winboard.rc b/winboard-dm-beta4/winboard.rc new file mode 100755 index 0000000..0e9dd4b --- /dev/null +++ b/winboard-dm-beta4/winboard.rc @@ -0,0 +1,1526 @@ +//Microsoft Developer Studio generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#define APSTUDIO_HIDDEN_SYMBOLS +#include "windows.h" +#undef APSTUDIO_HIDDEN_SYMBOLS +#include "dlgs.h" + + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// Englisch (USA) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +ABOUTBOX DIALOG DISCARDABLE 22, 17, 228, 73 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "About WinBoard" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,185,52,32,14,WS_GROUP + ICON "icon_white",-1,3,6,21,20 + LTEXT "Chessboard for Windows",400,25,15,121,8 + LTEXT "Copyright 1991-2002 Digital Equipment Corporation",201, + 6,34,149,8 + LTEXT "Enhancements Copyright 1992-2002 Free Software Foundation", + OPT_TCtext1,6,44,121,17 + CONTROL "",OPT_TCTime,"Static",SS_BLACKRECT,4,28,219,1 + LTEXT "WinBoard 0.0.0",ABOUTBOX_Version,25,4,142,8 +END + +DLG_TimeControl DIALOG DISCARDABLE 6, 18, 147, 113 +STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "Time Control" +FONT 8, "MS Sans Serif" +BEGIN + CONTROL "Conventional chess clock",OPT_TCUseMoves,"Button", + BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,6,6,113,10 + CONTROL "Incremental clock",OPT_TCUseInc,"Button", + BS_AUTORADIOBUTTON | WS_TABSTOP,6,42,107,10 + EDITTEXT OPT_TCMoves,14,20,22,12,ES_AUTOHSCROLL | WS_GROUP + LTEXT "moves in",OPT_TCtext1,40,22,30,8,NOT WS_GROUP + EDITTEXT OPT_TCTime,74,20,32,12,ES_AUTOHSCROLL + LTEXT "minutes",OPT_TCtext2,111,22,26,8,NOT WS_GROUP + EDITTEXT OPT_TCTime2,14,56,32,12,ES_AUTOHSCROLL | WS_GROUP + LTEXT "minutes initially,",405,51,57,73,8,NOT WS_GROUP + LTEXT "plus",406,19,74,15,8,NOT WS_GROUP + EDITTEXT OPT_TCInc,37,72,32,12,ES_AUTOHSCROLL + LTEXT "seconds per move",408,74,74,67,8,NOT WS_GROUP + PUSHBUTTON "OK",IDOK,32,95,40,14,WS_GROUP + PUSHBUTTON "Cancel",IDCANCEL,88,95,40,14 +END + +DLG_LoadOptions DIALOG DISCARDABLE 10, 18, 144, 55 +STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "Load Game Options" +FONT 8, "MS Sans Serif" +BEGIN + CONTROL "Load games with automatic stepping",OPT_Autostep,"Button", + BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,4,4,136,10 + EDITTEXT OPT_ASTimeDelay,23,18,28,12,ES_AUTOHSCROLL + LTEXT "seconds per move",OPT_AStext1,57,20,60,8,NOT WS_GROUP + PUSHBUTTON "OK",IDOK,24,37,40,14,WS_GROUP + PUSHBUTTON "Cancel",IDCANCEL,80,37,40,14 +END + +DLG_SaveOptions DIALOG DISCARDABLE 6, 17, 133, 119 +STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "Save Game Options" +FONT 8, "MS Sans Serif" +BEGIN + CONTROL "Save games automatically",OPT_Autosave,"Button", + BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,4,4,97,10 + CONTROL "Prompt for filename",OPT_AVPrompt,"Button", + BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,18,18,75,10 + CONTROL "To file:",OPT_AVToFile,"Button",BS_AUTORADIOBUTTON,18, + 31,36,10 + EDITTEXT OPT_AVFilename,18,44,97,12,ES_AUTOHSCROLL + GROUPBOX "Save Style",801,4,63,125,28,WS_GROUP + CONTROL "PGN",OPT_PGN,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP, + 18,75,39,10 + CONTROL "Old",OPT_Old,"Button",BS_AUTORADIOBUTTON,73,75,39,10 + PUSHBUTTON "OK",IDOK,18,98,40,14,WS_GROUP + PUSHBUTTON "Cancel",IDCANCEL,74,98,40,14 + PUSHBUTTON "Browse...",OPT_AVBrowse,76,31,39,14 +END + +1536 DIALOG DISCARDABLE 36, 24, 264, 134 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Open" +FONT 8, "Helv" +BEGIN + LTEXT "File &Name:",1090,6,6,76,9 + EDITTEXT 1152,6,16,90,12,ES_AUTOHSCROLL | ES_OEMCONVERT + LISTBOX 1120,6,32,90,68,LBS_SORT | LBS_OWNERDRAWFIXED | + LBS_HASSTRINGS | LBS_DISABLENOSCROLL | WS_VSCROLL | + WS_TABSTOP + LTEXT "&Directories:",-1,110,6,92,9 + LTEXT "",1088,110,18,92,9,SS_NOPREFIX | NOT WS_GROUP + LISTBOX 1121,110,32,92,68,LBS_SORT | LBS_OWNERDRAWFIXED | + LBS_HASSTRINGS | LBS_DISABLENOSCROLL | WS_VSCROLL | + WS_TABSTOP + LTEXT "List Files of &Type:",1089,6,104,90,9 + COMBOBOX 1136,6,114,90,36,CBS_DROPDOWNLIST | CBS_AUTOHSCROLL | + WS_BORDER | WS_VSCROLL | WS_TABSTOP + LTEXT "Dri&ves:",1091,110,104,92,9 + COMBOBOX 1137,110,114,92,68,CBS_DROPDOWNLIST | CBS_OWNERDRAWFIXED | + CBS_AUTOHSCROLL | CBS_SORT | CBS_HASSTRINGS | WS_BORDER | + WS_VSCROLL | WS_TABSTOP + DEFPUSHBUTTON "OK",IDOK,208,6,50,14,WS_GROUP + PUSHBUTTON "Cancel",IDCANCEL,208,24,50,14,WS_GROUP + PUSHBUTTON "&Help",1038,208,46,50,14,NOT WS_VISIBLE | WS_GROUP + LTEXT "&Index number:",-1,208,74,48,8 + EDITTEXT OPT_IndexNumberOld,208,84,50,12,ES_AUTOHSCROLL + PUSHBUTTON "Net&work...",1037,208,113,50,14,WS_GROUP +END + +DLG_CommPort DIALOG DISCARDABLE 25, 30, 159, 98 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Communication Port Settings" +FONT 8, "Helv" +BEGIN + RTEXT "&Port:",-1,4,6,40,10 + COMBOBOX OPT_Port,49,4,55,60,CBS_DROPDOWN | WS_VSCROLL | + WS_TABSTOP + RTEXT "Data &Rate:",-1,4,21,40,10,NOT WS_GROUP + COMBOBOX OPT_DataRate,49,19,55,100,CBS_DROPDOWN | WS_VSCROLL | + WS_TABSTOP + RTEXT "Data &Bits:",-1,4,36,40,10,NOT WS_GROUP + COMBOBOX OPT_Bits,49,34,55,60,CBS_DROPDOWNLIST | CBS_HASSTRINGS | + WS_VSCROLL | WS_TABSTOP + RTEXT "P&arity:",-1,4,51,40,10,NOT WS_GROUP + COMBOBOX OPT_Parity,49,49,55,60,CBS_DROPDOWNLIST | CBS_HASSTRINGS | + WS_VSCROLL | WS_TABSTOP + RTEXT "&Stop Bits:",-1,4,66,40,10,NOT WS_GROUP + COMBOBOX OPT_StopBits,49,64,55,60,CBS_DROPDOWNLIST | + CBS_HASSTRINGS | WS_VSCROLL | WS_TABSTOP + RTEXT "F&low:",-1,4,81,40,10,NOT WS_GROUP + DEFPUSHBUTTON "OK",IDOK,115,4,40,14 + PUSHBUTTON "Cancel",IDCANCEL,115,24,40,14 + COMBOBOX OPT_Flow,49,79,55,60,CBS_DROPDOWNLIST | CBS_HASSTRINGS | + WS_VSCROLL | WS_TABSTOP + PUSHBUTTON "&Help",OPT_SerialHelp,115,80,40,14,NOT WS_VISIBLE +END + +DLG_EditComment DIALOG DISCARDABLE 6, 18, 306, 104 +STYLE WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME +CAPTION "Edit Comment" +FONT 8, "MS Sans Serif" +BEGIN + PUSHBUTTON "OK",IDOK,61,86,40,14 + PUSHBUTTON "Cancel",OPT_CancelComment,109,86,40,14 + PUSHBUTTON "&Clear",OPT_ClearComment,157,86,40,14 + PUSHBUTTON "&Edit",OPT_EditComment,205,86,40,14 + CONTROL "",OPT_CommentText,"RICHEDIT",ES_MULTILINE | + ES_AUTOHSCROLL | ES_WANTRETURN | WS_BORDER | WS_VSCROLL | + WS_HSCROLL | WS_TABSTOP,4,4,298,78 +END + +DLG_PromotionKing DIALOG DISCARDABLE 98, 90, 183, 41 +STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "Promotion" +FONT 8, "MS Sans Serif" +BEGIN + PUSHBUTTON "&Queen",PB_Queen,4,23,40,14,WS_GROUP + PUSHBUTTON "&Rook",PB_Rook,49,23,40,14,NOT WS_TABSTOP + PUSHBUTTON "&Bishop",PB_Bishop,94,23,40,14,NOT WS_TABSTOP + PUSHBUTTON "K&night",PB_Knight,139,23,40,14,NOT WS_TABSTOP + PUSHBUTTON "&King",PB_King,94,4,40,14,NOT WS_TABSTOP + PUSHBUTTON "&Cancel",IDCANCEL,139,4,40,14,WS_GROUP + LTEXT "Promote pawn to:",501,6,8,58,8 +END + +ABOUTBOX2 DIALOG DISCARDABLE 22, 17, 281, 198 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "About WinBoard" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,244,180,32,14,WS_GROUP + RTEXT "Chessboard for Windows",DLG_TimeControl,196,154,80,8 + LTEXT "Copyright 1991 Digital Equipment Corporation",201,4,167, + 151,8 + LTEXT "Enhancements Copyright 1992-2002 Free Software Foundation", + OPT_TCtext1,4,177,126,17 + CONTROL "",OPT_TCTime,"Static",SS_BLACKRECT,4,164,272,1 + LTEXT "WinBoard 0.0.0",ABOUTBOX_Version,4,154,64,8 + CONTROL "galactic",IDC_STATIC,"Static",SS_BITMAP,4,4,15,13 +END + +DLG_GameList DIALOG DISCARDABLE 6, 18, 307, 159 +STYLE WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME +CAPTION "Game List" +FONT 8, "MS Sans Serif" +BEGIN + LISTBOX OPT_GameListText,4,4,299,130,LBS_NOINTEGRALHEIGHT | + WS_VSCROLL | WS_HSCROLL | WS_TABSTOP + PUSHBUTTON "&Load",OPT_GameListLoad,61,138,40,15 + PUSHBUTTON "&Prev",OPT_GameListPrev,109,138,40,15 + PUSHBUTTON "&Next",OPT_GameListNext,157,138,40,15 + PUSHBUTTON "&Close",OPT_GameListClose,205,138,40,15 +END + +DLG_EditTags DIALOG DISCARDABLE 6, 18, 160, 141 +STYLE WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME +CAPTION "Edit Tags" +FONT 8, "MS Sans Serif" +BEGIN + PUSHBUTTON "OK",IDOK,12,123,40,14 + PUSHBUTTON "Cancel",OPT_TagsCancel,60,123,40,14 + PUSHBUTTON "&Edit",OPT_EditTags,108,123,40,14 + CONTROL "",OPT_TagsText,"RICHEDIT",ES_MULTILINE | ES_AUTOVSCROLL | + ES_AUTOHSCROLL | ES_WANTRETURN | WS_BORDER | WS_VSCROLL | + WS_HSCROLL | WS_TABSTOP,4,4,152,115 +END + +WBCONSOLE DIALOG DISCARDABLE 0, 0, 335, 133 +STYLE WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_CAPTION | WS_SYSMENU | + WS_THICKFRAME +CAPTION "ICS Interaction" +CLASS "WBConsole" +FONT 8, "Courier New" +BEGIN + CONTROL "",OPT_ConsoleText,"RICHEDIT",ES_MULTILINE | + ES_AUTOVSCROLL | ES_NOHIDESEL | ES_READONLY | ES_NUMBER | + WS_BORDER | WS_VSCROLL | WS_TABSTOP,0,0,335,119 + CONTROL "",OPT_ConsoleInput,"RICHEDIT",ES_MULTILINE | + ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_NOHIDESEL | + ES_NUMBER | WS_BORDER | WS_TABSTOP,0,120,335,13, + WS_EX_TRANSPARENT +END + +DLG_Analysis DIALOGEX 330, 148, 338, 111 +STYLE DS_3DLOOK | DS_CENTERMOUSE | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | + WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME +FONT 8, "Arial", 0, 0, 0x1 +BEGIN + EDITTEXT OPT_engineDepth,55,32,44,12,ES_CENTER | ES_READONLY | + NOT WS_BORDER,WS_EX_DLGMODALFRAME + EDITTEXT OPT_engineScore,11,32,37,12,ES_CENTER | ES_READONLY | + NOT WS_BORDER,WS_EX_DLGMODALFRAME + EDITTEXT OPT_engineNPS,105,32,43,12,ES_CENTER | ES_READONLY | NOT + WS_BORDER,WS_EX_DLGMODALFRAME + EDITTEXT OPT_engineNodes,155,32,82,12,ES_CENTER | ES_READONLY | + NOT WS_BORDER,WS_EX_DLGMODALFRAME + GROUPBOX "Engine Information",IDC_STATIC,0,4,338,49,BS_LEFT + CONTROL "",OPT_engineName,"RICHEDIT",ES_CENTER | ES_MULTILINE | + ES_READONLY,10,15,104,12,WS_EX_DLGMODALFRAME + EDITTEXT OPT_engineMoveNr,121,15,50,12,ES_CENTER | ES_READONLY | + NOT WS_BORDER,WS_EX_DLGMODALFRAME + EDITTEXT OPT_engineTime,178,15,42,12,ES_CENTER | ES_READONLY | + NOT WS_BORDER,WS_EX_DLGMODALFRAME + DEFPUSHBUTTON "",OPT_engineStart,283,15,46,12,0,WS_EX_STATICEDGE + DEFPUSHBUTTON "",OPT_engineMove,289,32,35,12,NOT WS_TABSTOP, + WS_EX_STATICEDGE + CONTROL "Disable send statistic question",OPT_engineStatLine, + "Button",BS_AUTOCHECKBOX | BS_LEFT | BS_VCENTER | + BS_FLAT,0,55,118,8 + CONTROL "Enable Tourney Mode",OPT_engineTourneyMode,"Button", + BS_AUTOCHECKBOX | BS_LEFT | BS_VCENTER | BS_FLAT,242,55, + 84,8 + EDITTEXT OPT_engineHash,227,15,49,12,ES_CENTER | ES_READONLY | + NOT WS_BORDER,WS_EX_DLGMODALFRAME + EDITTEXT OPT_egtb,244,32,39,12,ES_CENTER | ES_READONLY | NOT + WS_BORDER,WS_EX_DLGMODALFRAME + CONTROL "Send engine output to ICS",OPT_SendToICS,"Button", + BS_AUTOCHECKBOX | BS_LEFT | BS_VCENTER | BS_FLAT,125,55, + 102,8 + LISTBOX OPT_AnalysisText,0,66,337,44,LBS_MULTIPLESEL | + LBS_USETABSTOPS | LBS_NOINTEGRALHEIGHT | + LBS_DISABLENOSCROLL | WS_VSCROLL | WS_HSCROLL | + WS_TABSTOP,WS_EX_TRANSPARENT +END + +DLG_Error DIALOG DISCARDABLE 0, 0, 183, 33 +STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION +CAPTION "Error" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,163,9,16,14 + ICON 32515,IDC_STATIC,4,6,20,20 + LTEXT "Sorry Charlie",OPT_ErrorText,27,4,130,25 +END + +DLG_Colorize DIALOGEX 0, 0, 183, 52 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "ICS Interaction Colors" +FONT 8, "MS Sans Serif", 0, 0, 0x1 +BEGIN + PUSHBUTTON "&Choose Color...",OPT_ChooseColor,15,29,51,14,WS_GROUP + CONTROL "&Bold",OPT_Bold,"Button",BS_AUTOCHECKBOX | WS_GROUP | + WS_TABSTOP,93,4,30,10 + CONTROL "&Italic",OPT_Italic,"Button",BS_AUTOCHECKBOX,93,14,30, + 10 + CONTROL "&Underline",OPT_Underline,"Button",BS_AUTOCHECKBOX,93, + 24,45,10 + CONTROL "&Strikeout",OPT_Strikeout,"Button",BS_AUTOCHECKBOX,93, + 34,42,10 + DEFPUSHBUTTON "OK",IDOK,145,7,31,14,WS_GROUP + PUSHBUTTON "Cancel",IDCANCEL,145,24,31,14 + CONTROL "",OPT_Sample,"RICHEDIT",ES_CENTER | ES_MULTILINE | + ES_READONLY | WS_GROUP,4,9,75,15,WS_EX_CLIENTEDGE +END + +DLG_Question DIALOG DISCARDABLE 0, 0, 187, 60 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Question" +FONT 8, "MS Sans Serif" +BEGIN + EDITTEXT OPT_QuestionInput,4,44,179,12,ES_AUTOHSCROLL + DEFPUSHBUTTON "Enter",IDOK,133,4,50,14,WS_GROUP + PUSHBUTTON "Cancel",IDCANCEL,133,24,50,14 + LTEXT "Enter a chess engine command or just type something stupid that will completely screw things up.", + OPT_QuestionText,27,4,101,33 + ICON 32514,IDC_STATIC,4,13,20,20 +END + +DLG_Startup DIALOG DISCARDABLE 0, 0, 276, 127 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "WinBoard Startup" +FONT 8, "MS Sans Serif" +BEGIN + CONTROL "Play against a chess engine or match two engines", + OPT_ChessEngine,"Button",BS_AUTORADIOBUTTON | WS_GROUP | + WS_TABSTOP,8,17,193,10 + COMBOBOX OPT_ChessEngineName,15,29,194,129,CBS_DROPDOWN | + CBS_AUTOHSCROLL | WS_VSCROLL | WS_TABSTOP + COMBOBOX OPT_SecondChessEngineName,15,45,194,129,CBS_DROPDOWN | + CBS_AUTOHSCROLL | WS_VSCROLL | WS_TABSTOP + CONTROL "Use an Internet Chess Server",OPT_ChessServer,"Button", + BS_AUTORADIOBUTTON | WS_TABSTOP,8,62,195,10 + COMBOBOX OPT_ChessServerName,16,73,194,129,CBS_DROPDOWN | + CBS_AUTOHSCROLL | WS_VSCROLL | WS_TABSTOP + CONTROL "Just view or edit game files",OPT_View,"Button", + BS_AUTORADIOBUTTON | WS_TABSTOP,8,91,193,10 + CONTROL "Additional options",OPT_AnyAdditional,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,8,111,71,10 + EDITTEXT OPT_AdditionalOptions,85,110,187,13,ES_AUTOHSCROLL + DEFPUSHBUTTON "OK",IDOK,222,4,50,14 + PUSHBUTTON "Cancel",IDCANCEL,222,21,50,14 + PUSHBUTTON "Help",IDM_HELPCONTENTS,222,38,50,14 + GROUPBOX "What would you like to do?",IDC_STATIC,4,4,211,101 +END + +DLG_IndexNumber DIALOG DISCARDABLE 0, 0, 236, 18 +STYLE DS_3DLOOK | DS_CONTROL | WS_CHILD | WS_CLIPSIBLINGS +FONT 8, "MS Sans Serif" +BEGIN + LTEXT "Inde&x number:",IDC_STATIC,5,2,46,8 + EDITTEXT OPT_IndexNumber,54,0,155,13,ES_AUTOHSCROLL +END + +DLG_TypeInMove DIALOG DISCARDABLE 0, 0, 186, 46 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Type in a move" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,129,7,50,14 + PUSHBUTTON "Cancel",IDCANCEL,129,24,50,14 + EDITTEXT OPT_Move,7,16,109,13,ES_AUTOHSCROLL +END + +DLG_Sound DIALOG DISCARDABLE 0, 0, 257, 95 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Sounds" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,199,6,47,14 + PUSHBUTTON "Cancel",IDCANCEL,199,23,47,14 + PUSHBUTTON "Defaults",OPT_DefaultSounds,199,40,47,14 + COMBOBOX CBO_Sounds,52,6,128,110,CBS_DROPDOWNLIST | WS_VSCROLL | + WS_TABSTOP + CONTROL "No sound",OPT_NoSound,"Button",BS_AUTORADIOBUTTON | + WS_GROUP | WS_TABSTOP,11,25,47,10 + CONTROL "Default beep",OPT_DefaultBeep,"Button", + BS_AUTORADIOBUTTON | WS_TABSTOP,11,42,57,10 + CONTROL "Built-in sound:",OPT_BuiltInSound,"Button", + BS_AUTORADIOBUTTON | WS_TABSTOP,11,59,60,10 + COMBOBOX OPT_BuiltInSoundName,78,58,103,109,CBS_DROPDOWNLIST | + CBS_SORT | WS_VSCROLL | WS_TABSTOP + PUSHBUTTON "Play",OPT_PlaySound,200,57,47,14 + CONTROL "WAV file:",OPT_WavFile,"Button",BS_AUTORADIOBUTTON | + WS_TABSTOP,11,76,45,10 + EDITTEXT OPT_WavFileName,78,75,103,12,ES_AUTOHSCROLL + PUSHBUTTON "Browse...",OPT_BrowseSound,200,74,47,14 + LTEXT "Event:",IDC_STATIC,19,9,26,9 +END + +DLG_GeneralOptions DIALOG DISCARDABLE 0, 0, 271, 154 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "General Options" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,207,7,50,14 + PUSHBUTTON "Cancel",IDCANCEL,208,25,50,14 + CONTROL "Always on &Top",OPT_AlwaysOnTop,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,16,6,79,10 + CONTROL "Always &Queen",OPT_AlwaysQueen,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,16,20,79,10 + CONTROL "Animate &Dragging",OPT_AnimateDragging,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,16,34,79,10 + CONTROL "&Animate Moving",OPT_AnimateMoving,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,16,48,79,10 + CONTROL "Auto &Flag",OPT_AutoFlag,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,16,62,79,10 + CONTROL "Auto Flip &View",OPT_AutoFlipView,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,16,76,79,10 + CONTROL "Auto &Raise Board",OPT_AutoRaiseBoard,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,16,90,71,10 + CONTROL "&Blindfold",OPT_Blindfold,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,16,104,79,10 + CONTROL "&Highlight Dragging",OPT_HighlightDragging,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,16,118,79,10 + CONTROL "Highlight Last &Move",OPT_HighlightLastMove,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,109,6,79,10 + CONTROL "Periodic &Updates",OPT_PeriodicUpdates,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,109,20,79,10 + CONTROL "Ponder &Next Move",OPT_PonderNextMove,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,109,34,79,10 + CONTROL "&Popup Exit Message",OPT_PopupExitMessage,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,109,48,79,10 + CONTROL "Popup Move &Errors",OPT_PopupMoveErrors,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,109,62,79,10 + CONTROL "Show Butt&on Bar",OPT_ShowButtonBar,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,109,76,79,10 + CONTROL "Show &Coordinates",OPT_ShowCoordinates,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,109,90,79,10 + CONTROL "&Show Thinking",OPT_ShowThinking,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,109,104,79,10 + CONTROL "Test &Legality",OPT_TestLegality,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,109,118,79,10 + CONTROL "Winboard Engine Room",OPT_AnalysisWindow,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,16,132,91,10 +END + +DLG_IcsOptions DIALOGEX 0, 0, 310, 338 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "ICS Options" +FONT 8, "MS Sans Serif", 0, 0, 0x1 +BEGIN + DEFPUSHBUTTON "OK",IDOK,101,316,48,15 + PUSHBUTTON "Cancel",IDCANCEL,165,316,48,15 + CONTROL "&Auto Comment",OPT_AutoComment,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,18,12,62,12 + CONTROL "Auto &Observe",OPT_AutoObserve,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,18,27,62,12 + CONTROL "&Get Move List",OPT_GetMoveList,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,18,42,62,12 + CONTROL "&Local Line Editing",OPT_LocalLineEditing,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,18,57,72,8 + CONTROL "&Quiet Play",OPT_QuietPlay,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,18,72,62,8 + CONTROL "&Premove",OPT_Premove,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,121,12,44,12 + CONTROL "&White first move",OPT_PremoveWhite,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,121,27,67,12 + EDITTEXT OPT_PremoveWhiteText,196,24,25,12,ES_AUTOHSCROLL + CONTROL "&Black first move",OPT_PremoveBlack,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,121,42,66,12 + EDITTEXT OPT_PremoveBlackText,196,40,25,12,ES_AUTOHSCROLL + CONTROL "&Sound alarm at",OPT_IcsAlarm,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,121,71,63,10 + EDITTEXT OPT_IcsAlarmTime,196,68,17,13 + LTEXT "seconds",IDC_STATIC,219,71,37,8 + PUSHBUTTON "Choose...",OPT_ChooseShoutColor,104,173,40,15 + PUSHBUTTON "Choose...",OPT_ChooseSShoutColor,104,195,40,15 + PUSHBUTTON "Choose...",OPT_ChooseChannel1Color,104,213,40,15 + PUSHBUTTON "Choose...",OPT_ChooseChannelColor,104,235,40,15 + PUSHBUTTON "Choose...",OPT_ChooseKibitzColor,104,253,40,15 + PUSHBUTTON "Choose...",OPT_ChooseTellColor,251,173,40,15 + PUSHBUTTON "Choose...",OPT_ChooseChallengeColor,251,195,40,15 + PUSHBUTTON "Choose...",OPT_ChooseRequestColor,251,213,40,15 + PUSHBUTTON "Choose...",OPT_ChooseSeekColor,251,235,40,15 + PUSHBUTTON "Choose...",OPT_ChooseNormalColor,251,253,40,15 + PUSHBUTTON "&Choose Background Color...",OPT_ChooseBackgroundColor, + 18,276,131,16 + PUSHBUTTON "&Default ICS Colors",OPT_DefaultColors,165,276,131,16 + CONTROL "Do ¬ colorize messages",OPT_DontColorize,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,110,299,97,10 + CONTROL "",OPT_SampleShout,"RICHEDIT",ES_CENTER | ES_MULTILINE | + ES_READONLY | WS_DISABLED | WS_GROUP,18,173,75,15, + WS_EX_CLIENTEDGE + CONTROL "",OPT_SampleSShout,"RICHEDIT",ES_CENTER | ES_MULTILINE | + ES_READONLY | WS_DISABLED | WS_GROUP,18,195,75,15, + WS_EX_CLIENTEDGE + CONTROL "",OPT_SampleChannel1,"RICHEDIT",ES_CENTER | + ES_MULTILINE | ES_READONLY | WS_DISABLED | WS_GROUP,18, + 213,75,15,WS_EX_CLIENTEDGE + CONTROL "",OPT_SampleChannel,"RICHEDIT",ES_CENTER | ES_MULTILINE | + ES_READONLY | WS_DISABLED | WS_GROUP,18,235,75,15, + WS_EX_CLIENTEDGE + CONTROL "",OPT_SampleKibitz,"RICHEDIT",ES_CENTER | ES_MULTILINE | + ES_READONLY | WS_GROUP,18,253,75,15,WS_EX_CLIENTEDGE + CONTROL "",OPT_SampleTell,"RICHEDIT",ES_CENTER | ES_MULTILINE | + ES_READONLY | WS_DISABLED | WS_GROUP,165,173,75,15, + WS_EX_CLIENTEDGE + CONTROL "",OPT_SampleChallenge,"RICHEDIT",ES_CENTER | + ES_MULTILINE | ES_READONLY | WS_DISABLED | WS_GROUP,165, + 195,75,15,WS_EX_CLIENTEDGE + CONTROL "",OPT_SampleRequest,"RICHEDIT",ES_CENTER | ES_MULTILINE | + ES_READONLY | WS_DISABLED | WS_GROUP,165,213,75,15, + WS_EX_CLIENTEDGE + CONTROL "",OPT_SampleSeek,"RICHEDIT",ES_CENTER | ES_MULTILINE | + ES_READONLY | WS_DISABLED | WS_GROUP,165,235,75,15, + WS_EX_CLIENTEDGE + CONTROL "",OPT_SampleNormal,"RICHEDIT",ES_CENTER | ES_MULTILINE | + ES_READONLY | WS_DISABLED | WS_GROUP,165,253,75,15, + WS_EX_CLIENTEDGE + GROUPBOX "Interaction Colors",IDC_STATIC,7,163,296,150 + GROUPBOX "Premove",IDC_STATIC,112,3,191,58 + GROUPBOX "Server",IDC_STATIC,7,3,101,83 + GROUPBOX "Alarm",IDC_STATIC,112,62,191,24 + GROUPBOX "Engine Analyse",IDC_STATIC,7,88,101,69 + CONTROL "Enable Engine",OPT_icsAnalyze,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,18,99,62,10 + CONTROL "Enable Window",OPT_icsAnalyzeWindow,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,18,117,89,10 + CONTROL "kill PV <",OPT_icsKillPV,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,196,140,40,10 + EDITTEXT OPT_icsKillPVs,238,139,13,12 + CONTROL "Whisper",OPT_icsWhisper,"Button",BS_AUTORADIOBUTTON | + WS_GROUP | WS_TABSTOP,121,97,42,10 + CONTROL "Kibitz",OPT_icsKibitz,"Button",BS_AUTORADIOBUTTON,121, + 113,33,10 + CONTROL "Tell",OPT_icsTell,"Button",BS_AUTORADIOBUTTON,121,129, + 27,10 + CONTROL "None",OPT_icsNone,"Button",BS_AUTORADIOBUTTON,121,145, + 33,10 + EDITTEXT OPT_icsTells,151,128,34,13,ES_AUTOHSCROLL + LTEXT "less then",IDC_STATIC,255,141,29,10 + CONTROL "Enable Smart Queue",OPT_smartQueue,"Button", + BS_AUTOCHECKBOX,196,100,81,10 + CONTROL "Skip fail low/high moves",OPT_dropMoves,"Button", + BS_AUTOCHECKBOX | BS_LEFT | BS_VCENTER,196,120,98,10 + GROUPBOX "Engine Analyse Broadcasting",IDC_STATIC,112,88,191,69 + PUSHBUTTON "Advanced / UCI...",OPT_ADV,18,136,70,15 +END + +DLG_BoardOptions DIALOG DISCARDABLE 0, 0, 262, 250 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Board Options" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,205,10,50,14 + PUSHBUTTON "Cancel",IDCANCEL,205,35,50,14 + CONTROL "&Tiny",OPT_SizeTiny,"Button",BS_AUTORADIOBUTTON | + WS_GROUP | WS_TABSTOP,15,15,50,10 + CONTROL "T&eeny",OPT_SizeTeeny,"Button",BS_AUTORADIOBUTTON,15,25, + 50,10 + CONTROL "&Dinky",OPT_SizeDinky,"Button",BS_AUTORADIOBUTTON,15,35, + 50,10 + CONTROL "&Petite",OPT_SizePetite,"Button",BS_AUTORADIOBUTTON,15, + 45,50,10 + CONTROL "Sl&im",OPT_SizeSlim,"Button",BS_AUTORADIOBUTTON,15,55, + 50,10 + CONTROL "&Small",OPT_SizeSmall,"Button",BS_AUTORADIOBUTTON,15,65, + 50,10 + CONTROL "Medi&ocre",OPT_SizeMediocre,"Button",BS_AUTORADIOBUTTON, + 76,15,50,10 + CONTROL "&Middling",OPT_SizeMiddling,"Button",BS_AUTORADIOBUTTON, + 76,25,50,10 + CONTROL "&Average",OPT_SizeAverage,"Button",BS_AUTORADIOBUTTON, + 76,35,50,10 + CONTROL "Mode&rate",OPT_SizeModerate,"Button",BS_AUTORADIOBUTTON, + 76,45,50,10 + CONTROL "Medi&um",OPT_SizeMedium,"Button",BS_AUTORADIOBUTTON,76, + 55,50,10 + CONTROL "Bul&ky",OPT_SizeBulky,"Button",BS_AUTORADIOBUTTON,76,65, + 50,10 + CONTROL "&Large",OPT_SizeLarge,"Button",BS_AUTORADIOBUTTON,140, + 15,50,10 + CONTROL "&Big",OPT_SizeBig,"Button",BS_AUTORADIOBUTTON,140,25,50, + 10 + CONTROL "&Huge",OPT_SizeHuge,"Button",BS_AUTORADIOBUTTON,140,35, + 50,10 + CONTROL "&Giant",OPT_SizeGiant,"Button",BS_AUTORADIOBUTTON,140, + 45,50,10 + CONTROL "&Colossal",OPT_SizeColossal,"Button",BS_AUTORADIOBUTTON, + 140,55,50,10 + CONTROL "Tita&nic",OPT_SizeTitanic,"Button",BS_AUTORADIOBUTTON, + 140,65,50,10 + PUSHBUTTON "Choose...",OPT_ChooseLightSquareColor,144,100,40,15 + PUSHBUTTON "Choose...",OPT_ChooseDarkSquareColor,144,120,40,15 + PUSHBUTTON "Choose...",OPT_ChooseWhitePieceColor,144,140,40,15 + PUSHBUTTON "Choose...",OPT_ChooseBlackPieceColor,144,160,40,15 + PUSHBUTTON "Choose...",OPT_ChooseHighlightSquareColor,144,180,40,15 + PUSHBUTTON "Choose...",OPT_ChoosePremoveHighlightColor,144,200,40, + 15 + PUSHBUTTON "Defaults",OPT_DefaultBoardColors,118,225,65,15 + EDITTEXT OPT_DarkSquareColor,104,120,25,15,ES_READONLY | + WS_DISABLED | NOT WS_BORDER | NOT WS_TABSTOP + EDITTEXT OPT_LightSquareColor,104,100,25,15,ES_READONLY | + WS_DISABLED | NOT WS_BORDER | NOT WS_TABSTOP + EDITTEXT OPT_WhitePieceColor,104,140,25,15,ES_READONLY | + WS_DISABLED | NOT WS_BORDER | NOT WS_TABSTOP + EDITTEXT OPT_BlackPieceColor,104,160,25,15,ES_READONLY | + WS_DISABLED | NOT WS_BORDER | NOT WS_TABSTOP + EDITTEXT OPT_HighlightSquareColor,104,180,25,15,ES_READONLY | + WS_DISABLED | NOT WS_BORDER | NOT WS_TABSTOP + GROUPBOX "Colors",IDC_STATIC,10,90,185,155 + EDITTEXT OPT_PremoveHighlightColor,104,200,25,15,ES_READONLY | + WS_DISABLED | NOT WS_BORDER | NOT WS_TABSTOP + LTEXT "Light Squares",IDC_STATIC,25,105,60,10 + LTEXT "Dark Squares",IDC_STATIC,25,124,60,10 + LTEXT "White Pieces",IDC_STATIC,25,145,60,10 + LTEXT "Black Pieces",IDC_STATIC,25,165,60,10 + LTEXT "Square Highlights",IDC_STATIC,25,185,60,10 + LTEXT "Premove Highlights",IDC_STATIC,25,205,70,10 + GROUPBOX "Size",IDC_STATIC,10,5,185,75 + CONTROL "Monochrome",OPT_Monochrome,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,25,225,75,10 + EDITTEXT OPT_SampleLightSquare,205,110,39,36,ES_READONLY | + WS_DISABLED | NOT WS_BORDER | NOT WS_TABSTOP + EDITTEXT OPT_SampleDarkSquare,205,165,39,36,ES_READONLY | + WS_DISABLED | NOT WS_BORDER | NOT WS_TABSTOP +END + +DLG_Fonts DIALOG DISCARDABLE 0, 0, 280, 231 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Fonts" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,155,210,50,14 + PUSHBUTTON "Cancel",IDCANCEL,215,210,50,14 + PUSHBUTTON "Choose...",OPT_ChooseClockFont,221,17,45,15 + PUSHBUTTON "Choose...",OPT_ChooseMessageFont,221,47,45,15 + PUSHBUTTON "Choose...",OPT_ChooseCoordFont,221,77,45,15 + PUSHBUTTON "Choose...",OPT_ChooseTagFont,221,120,45,15 + PUSHBUTTON "Choose...",OPT_ChooseCommentsFont,221,150,45,15 + PUSHBUTTON "Choose...",OPT_ChooseConsoleFont,221,180,45,15 + PUSHBUTTON "&Revert to Defaults",OPT_DefaultFonts,15,210,80,15 + CONTROL "",OPT_SampleCoordFont,"RICHEDIT",ES_READONLY | + WS_DISABLED | WS_BORDER,70,72,140,20 + CONTROL "",OPT_SampleTagFont,"RICHEDIT",ES_READONLY | + WS_DISABLED | WS_BORDER,70,115,140,20 + CONTROL "",OPT_SampleCommentsFont,"RICHEDIT",ES_READONLY | + WS_DISABLED | WS_BORDER,70,145,140,20 + CONTROL "",OPT_SampleConsoleFont,"RICHEDIT",ES_READONLY | + WS_DISABLED | WS_BORDER,70,175,140,20 + LTEXT "Clocks",OPT_ClockFont,16,17,45,10,NOT WS_GROUP + LTEXT "Messages",OPT_MessageFont,16,47,45,10,NOT WS_GROUP + LTEXT "Coordinates",OPT_CoordFont,16,77,45,10,NOT WS_GROUP + LTEXT "Tags",OPT_EditTagsFont,16,120,45,10,NOT WS_GROUP + LTEXT "Comments",OPT_CommentsFont,16,150,45,10,NOT WS_GROUP + LTEXT "ICS Interaction",OPT_MessageFont5,16,180,50,10,NOT + WS_GROUP + CONTROL "",OPT_SampleClockFont,"RICHEDIT",ES_READONLY | + WS_DISABLED | WS_BORDER,70,12,140,20 + CONTROL "",OPT_SampleMessageFont,"RICHEDIT",ES_READONLY | + WS_DISABLED | WS_BORDER,70,42,140,20 + GROUPBOX "Current Board Size",IDC_STATIC,5,2,270,100 + GROUPBOX "All Board Sizes",IDC_STATIC,5,105,270,100 +END + +DLG_icsAnalyze DIALOG DISCARDABLE 0, 0, 233, 117 +STYLE DS_MODALFRAME | DS_NOIDLEMSG | DS_3DLOOK | DS_NOFAILCREATE | WS_POPUP | + WS_CAPTION +CAPTION "ICS Engine Analysis Options" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,75,99,35,14 + PUSHBUTTON "Cancel",IDCANCEL,115,99,35,14 + GROUPBOX "Options",IDC_STATIC,7,50,103,44 + GROUPBOX "UCI Settings",IDC_STATIC,115,50,111,44 + CONTROL "normal commands",OPT_icsWBprotoNorm,"Button", + BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,13,16,86,10 + CONTROL "agressive commands",OPT_icsWBprotoAgr,"Button", + BS_AUTORADIOBUTTON | WS_TABSTOP,13,32,86,10 + CONTROL "Write Analysis Logfile",OPT_icsWriteLog,"Button", + BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,13,79,86,10 + CONTROL "Show Book",OPT_icsShowBook,"Button",BS_AUTOCHECKBOX | + WS_DISABLED | WS_TABSTOP,13,62,86,10 + GROUPBOX "Engine Handling",IDC_STATIC,7,3,103,44 + GROUPBOX "Smart Queue",IDC_STATIC,115,3,111,44 + CONTROL "Tuning for Blitz games",OPT_icsSmartQueueBlitz,"Button", + BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,121,16,99,10 + CONTROL "Tuning for Standard games",OPT_icsSmartQueueStd,"Button", + BS_AUTORADIOBUTTON,121,32,98,10 +END + +DLG_ZippyDraw DIALOG DISCARDABLE 0, 0, 219, 209 +STYLE DS_MODALFRAME | WS_CHILD | WS_CAPTION | WS_SYSMENU +CAPTION "ICS Zippy Draw" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,107,187,48,15 + CONTROL "&Enable Zippy Draw",OPT_EnableZippyDraw,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,15,26,75,12 + LTEXT "(Only avaible if engine don't support WB2 draw feature)", + IDC_STATIC,15,15,175,10 + GROUPBOX "General Options",IDC_STATIC,10,4,202,38 + PUSHBUTTON "Cancel",IDCANCEL,53,187,48,15 + CONTROL "&Offer Draw",OPT_OfferDraw,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,15,58,50,10 + CONTROL "&Accept Draw",OPT_AcceptDraw,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,68,57,57,10 + CONTROL "&Draw Factor add",OPT_DrawFactor,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,20,111,68,12 + CONTROL "Title players bonus",OPT_TitlePlayers,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,20,82,75,12 + GROUPBOX "Settings",IDC_STATIC,10,47,202,136 + GROUPBOX "Refer with",IDC_STATIC,16,71,190,107 + CONTROL "Opponent rating diff less then",OPT_DrawFactor2,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,20,96,109,12 + EDITTEXT OPT_RatingPoints,131,94,25,12,ES_AUTOHSCROLL + EDITTEXT OPT_RatingPoints2,39,124,21,12,ES_AUTOHSCROLL + LTEXT "points to score (1 pawn=100)",IDC_STATIC,65,128,92,8 + LTEXT "ELO",IDC_STATIC,161,98,19,8 + CONTROL "&Dynamic Draw: Take score as draw from ",OPT_smartQueue, + "Button",BS_AUTOCHECKBOX,41,142,143,10 + EDITTEXT OPT_RatingPoints3,53,153,21,12,ES_AUTOHSCROLL + LTEXT "points to",IDC_STATIC,79,156,28,8 + EDITTEXT OPT_RatingPoints4,110,154,21,12,ES_AUTOHSCROLL + LTEXT "points (1 Pawn=100)",IDC_STATIC,136,156,65,8 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO DISCARDABLE +BEGIN + DLG_GeneralOptions, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 264 + TOPMARGIN, 7 + BOTTOMMARGIN, 147 + END + + DLG_IcsOptions, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 303 + TOPMARGIN, 3 + BOTTOMMARGIN, 335 + END + + DLG_BoardOptions, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 255 + TOPMARGIN, 7 + BOTTOMMARGIN, 243 + END + + DLG_Fonts, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 273 + TOPMARGIN, 7 + BOTTOMMARGIN, 224 + END + + DLG_icsAnalyze, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 226 + TOPMARGIN, 3 + BOTTOMMARGIN, 113 + END + + DLG_ZippyDraw, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 212 + TOPMARGIN, 7 + BOTTOMMARGIN, 202 + END +END +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +ICON_BLACK ICON DISCARDABLE "bitmaps\\icon_ob.ico" +ICON_BOARD ICON DISCARDABLE "bitmaps\\board.ico" +ICON_WHITE ICON DISCARDABLE "bitmaps\\icon_whi.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// Menu +// + +WINBOARD MENU DISCARDABLE +BEGIN + POPUP "&File" + BEGIN + MENUITEM "Reset &Game", IDM_NewGame + MENUITEM SEPARATOR + MENUITEM "&Load Game...", IDM_LoadGame + MENUITEM "Load &Next Game\tAlt+PgDn", IDM_LoadNextGame + MENUITEM "Load &Previous Game\tAlt+PgUp", IDM_LoadPrevGame + MENUITEM "&Reload Same Game", IDM_ReloadGame + MENUITEM "&Save Game...", IDM_SaveGame + MENUITEM SEPARATOR + MENUITEM "&Copy Game To Clipboard\tAlt+C", IDM_CopyGame + MENUITEM "Paste Game &From Clipboard\tAlt+V", IDM_PasteGame + MENUITEM SEPARATOR + MENUITEM "L&oad Position...", IDM_LoadPosition + MENUITEM "Load N&ext Position\tAlt+Shift+PgDn", IDM_LoadNextPosition + MENUITEM "Load Pre&vious Position\tAlt+Shift+PgUp", + IDM_LoadPrevPosition + MENUITEM "Reload Sa&me Position", IDM_ReloadPosition + MENUITEM "S&ave Position...", IDM_SavePosition + MENUITEM SEPARATOR + MENUITEM "Cop&y Position To Clipboard\tAlt+Shift+C", + IDM_CopyPosition + MENUITEM "Pas&te Position From Clipboard\tAlt+Shift+V", + IDM_PastePosition + MENUITEM SEPARATOR + MENUITEM "E&xit", IDM_Exit + END + POPUP "&Mode" + BEGIN + MENUITEM "Machine &White", IDM_MachineWhite + MENUITEM "Machine &Black", IDM_MachineBlack + MENUITEM "Two &Machines", IDM_TwoMachines + MENUITEM "&Analysis Mode", IDM_AnalysisMode + MENUITEM "Analyze &File", IDM_AnalyzeFile + MENUITEM "&ICS Client", IDM_IcsClient + MENUITEM "Edit &Game", IDM_EditGame + MENUITEM "&Edit Position", IDM_EditPosition + MENUITEM "Trai&ning", IDM_Training, GRAYED + MENUITEM SEPARATOR + MENUITEM "Show Game &List...", IDM_ShowGameList + MENUITEM "Edit &Tags...", IDM_EditTags + MENUITEM "Edit &Comment...", IDM_EditComment + MENUITEM "&Pause\tPause", IDM_Pause + END + POPUP "&Action" + BEGIN + MENUITEM "&Accept\tF3", IDM_Accept + MENUITEM "D&ecline\tF4", IDM_Decline + MENUITEM "Re&match\tF12", IDM_Rematch + MENUITEM SEPARATOR + MENUITEM "Call &Flag\tF5", IDM_CallFlag + MENUITEM "&Draw\tF6", IDM_Draw + MENUITEM "Ad&journ\tF7", IDM_Adjourn + MENUITEM "A&bort\tF8", IDM_Abort + MENUITEM "&Resign\tF9", IDM_Resign + MENUITEM SEPARATOR + MENUITEM "Stop &Observing\tF10", IDM_StopObserving + MENUITEM "Stop E&xamining\tF11", IDM_StopExamining + END + POPUP "&Step" + BEGIN + MENUITEM "T&ype In Move...", IDM_TypeInMove + MENUITEM SEPARATOR + MENUITEM "&Backward\tAlt+Left", IDM_Backward + MENUITEM "&Forward\tAlt+Right", IDM_Forward + MENUITEM "Back to &Start\tAlt+Up", IDM_ToStart + MENUITEM "Forward to &End\tAlt+Down", IDM_ToEnd + MENUITEM "Re&vert\tAlt+Home", IDM_Revert + MENUITEM "&Truncate Game\tAlt+End", IDM_TruncateGame + MENUITEM SEPARATOR + MENUITEM "&Move Now\tAlt+Ins", IDM_MoveNow + MENUITEM "&Retract Move\tAlt+Del", IDM_RetractMove + END + POPUP "&Options" + BEGIN + MENUITEM "Flip &View\tF2", IDM_FlipView + MENUITEM SEPARATOR + MENUITEM "&General...", IDM_GeneralOptions + MENUITEM "&Board...", IDM_BoardOptions + POPUP "&ICS...", GRAYED + BEGIN + MENUITEM "ICS Options Gerneral", IDM_IcsOptions + MENUITEM "ICS Zippy Draw", IDM_ZippyDraw, GRAYED + END + MENUITEM "&Fonts...", IDM_Fonts + MENUITEM "Soun&ds...", IDM_Sounds + MENUITEM SEPARATOR + MENUITEM "Comm&unications...", IDM_CommPort + MENUITEM "&Load Game...", IDM_LoadOptions + MENUITEM "&Save Game...", IDM_SaveOptions + MENUITEM "&Time Control...", IDM_TimeControl + MENUITEM SEPARATOR + MENUITEM "Save Settings &Now", IDM_SaveSettings + MENUITEM "Save Settings on E&xit", IDM_SaveSettingsOnExit + END + POPUP "&Help" + BEGIN + MENUITEM "Help &Contents\tF1", IDM_HELPCONTENTS + MENUITEM "Help &Index", IDM_HELPSEARCH + MENUITEM "How to &Use Help", IDM_HELPHELP + MENUITEM SEPARATOR + MENUITEM "&Hint...", IDM_Hint + MENUITEM "&Book...", IDM_Book + MENUITEM SEPARATOR + MENUITEM "&About WinBoard", IDM_ABOUT + END +END + +PIECEMENU MENU DISCARDABLE +BEGIN + POPUP "" + BEGIN + MENUITEM "White", EP_White + MENUITEM SEPARATOR + MENUITEM "Pawn", EP_WhitePawn + MENUITEM "Knight", EP_WhiteKnight + MENUITEM "Bishop", EP_WhiteBishop + MENUITEM "Rook", EP_WhiteRook + MENUITEM "Queen", EP_WhiteQueen + MENUITEM "King", EP_WhiteKing + MENUITEM SEPARATOR + MENUITEM "Empty Square", EP_EmptySquare + MENUITEM "Black", EP_Black, MENUBARBREAK + MENUITEM SEPARATOR + MENUITEM "Pawn", EP_BlackPawn + MENUITEM "Knight", EP_BlackKnight + MENUITEM "Bishop", EP_BlackBishop + MENUITEM "Rook", EP_BlackRook + MENUITEM "Queen", EP_BlackQueen + MENUITEM "King", EP_BlackKing + MENUITEM SEPARATOR + MENUITEM "Clear Board ", EP_ClearBoard + END +END + +WHITEPIECEMENU MENU DISCARDABLE +BEGIN + POPUP "" + BEGIN + MENUITEM "White", EP_White + MENUITEM SEPARATOR + MENUITEM "Pawn", EP_WhitePawn + MENUITEM "Knight", EP_WhiteKnight + MENUITEM "Bishop", EP_WhiteBishop + MENUITEM "Rook", EP_WhiteRook + MENUITEM "Queen", EP_WhiteQueen + MENUITEM "King", EP_WhiteKing + MENUITEM SEPARATOR + MENUITEM "Empty Square", EP_EmptySquare + MENUITEM "Clear Board", EP_ClearBoard + END +END + +BLACKPIECEMENU MENU DISCARDABLE +BEGIN + POPUP "" + BEGIN + MENUITEM "Black", EP_Black + MENUITEM SEPARATOR + MENUITEM "Pawn", EP_BlackPawn + MENUITEM "Knight", EP_BlackKnight + MENUITEM "Bishop", EP_BlackBishop + MENUITEM "Rook", EP_BlackRook + MENUITEM "Queen", EP_BlackQueen + MENUITEM "King", EP_BlackKing + MENUITEM SEPARATOR + MENUITEM "Empty Square", EP_EmptySquare + MENUITEM "Clear Board", EP_ClearBoard + END +END + +DROPPIECEMENU MENU DISCARDABLE +BEGIN + POPUP "" + BEGIN + MENUITEM "Drop", 0, INACTIVE + MENUITEM SEPARATOR + MENUITEM "Pawn", DP_Pawn + MENUITEM "Knight", DP_Knight + MENUITEM "Bishop", DP_Bishop + MENUITEM "Rook", DP_Rook + MENUITEM "Queen", DP_Queen + END +END + +TEXTMENU MENU DISCARDABLE +BEGIN + POPUP "" + BEGIN + MENUITEM "Cop&y and Paste", IDM_QuickPaste + MENUITEM "&Copy", IDM_Copy + MENUITEM "&Paste", IDM_Paste + END +END + +INPUTMENU MENU DISCARDABLE +BEGIN + POPUP "" + BEGIN + MENUITEM "&Undo", IDM_Undo + MENUITEM SEPARATOR + MENUITEM "Cu&t", IDM_Cut + MENUITEM "&Copy", IDM_Copy + MENUITEM "&Paste", IDM_Paste + MENUITEM SEPARATOR + MENUITEM "Select &All", IDM_SelectAll + END +END + +ENGINEROOM MENU DISCARDABLE +BEGIN + POPUP "Engine Room" + BEGIN + MENUITEM "Select all and ©", IDM_SelPaste + MENUITEM "Select &all", IDM_SelectAll + MENUITEM "&Copy", IDM_Copy + MENUITEM SEPARATOR + MENUITEM "Move!", IDM_MoveNow + MENUITEM "Start/Stop Engine", IDM_EnginesButton + MENUITEM SEPARATOR + MENUITEM "Switch &Analysis Mode", IDM_AnalysisMode + MENUITEM "Switch &Machine White", IDM_MachineWhite + MENUITEM "Switch &Machine Black", IDM_MachineBlack + MENUITEM "Set/Change &Operator Time", IDM_OperatorTime + END +END + +ICSENGINEROOM MENU DISCARDABLE +BEGIN + POPUP "ICS Engine Room" + BEGIN + MENUITEM "Select all and ©", IDM_SelPaste + MENUITEM SEPARATOR + MENUITEM "Select &All", IDM_SelectAll + MENUITEM "&Copy", IDM_Copy + END +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Accelerator +// + +WINBOARD ACCELERATORS MOVEABLE PURE +BEGIN + "1", IDM_DirectCommand1, VIRTKEY, ALT, NOINVERT + "2", IDM_DirectCommand2, VIRTKEY, ALT, NOINVERT + "C", IDM_CopyGame, VIRTKEY, ALT, NOINVERT + "C", IDM_CopyPosition, VIRTKEY, SHIFT, ALT, NOINVERT + "E", IDM_focus_EngineRoom, VIRTKEY, ALT, NOINVERT + "R", IDM_focus_wb, VIRTKEY, ALT, NOINVERT + "V", IDM_PasteGame, VIRTKEY, ALT, NOINVERT + "V", IDM_PastePosition, VIRTKEY, SHIFT, ALT, NOINVERT + VK_DELETE, IDM_RetractMove, VIRTKEY, ALT, NOINVERT + VK_DOWN, IDM_ToEnd, VIRTKEY, ALT, NOINVERT + VK_END, IDM_TruncateGame, VIRTKEY, ALT, NOINVERT + VK_F1, IDM_HELPCONTENTS, VIRTKEY, NOINVERT + VK_F10, IDM_StopObserving, VIRTKEY, NOINVERT + VK_F11, IDM_StopExamining, VIRTKEY, NOINVERT + VK_F12, IDM_Rematch, VIRTKEY, NOINVERT + VK_F12, IDM_Debug, VIRTKEY, CONTROL, ALT, NOINVERT + VK_F2, IDM_FlipView, VIRTKEY, NOINVERT + VK_F3, IDM_Accept, VIRTKEY, NOINVERT + VK_F4, IDM_Decline, VIRTKEY, NOINVERT + VK_F4, IDM_Minimize, VIRTKEY, CONTROL, NOINVERT + VK_F5, IDM_CallFlag, VIRTKEY, NOINVERT + VK_F6, IDM_Draw, VIRTKEY, NOINVERT + VK_F7, IDM_Adjourn, VIRTKEY, NOINVERT + VK_F8, IDM_Abort, VIRTKEY, NOINVERT + VK_F9, IDM_Resign, VIRTKEY, NOINVERT + VK_HOME, IDM_Revert, VIRTKEY, ALT, NOINVERT + VK_INSERT, IDM_MoveNow, VIRTKEY, ALT, NOINVERT + VK_LBUTTON, IDM_focus_EngineRoom, VIRTKEY, CONTROL, NOINVERT + VK_LEFT, IDM_Backward, VIRTKEY, ALT, NOINVERT + VK_NEXT, IDM_LoadNextGame, VIRTKEY, ALT, NOINVERT + VK_NEXT, IDM_LoadNextPosition, VIRTKEY, SHIFT, ALT, NOINVERT + VK_PAUSE, IDM_Pause, VIRTKEY, NOINVERT + VK_PAUSE, IDM_Pause, VIRTKEY, ALT, NOINVERT + VK_PRIOR, IDM_LoadPrevGame, VIRTKEY, ALT, NOINVERT + VK_PRIOR, IDM_LoadPrevPosition, VIRTKEY, SHIFT, ALT, NOINVERT + VK_RIGHT, IDM_Forward, VIRTKEY, ALT, NOINVERT + VK_UP, IDM_ToStart, VIRTKEY, ALT, NOINVERT +END + +NO_ALT ACCELERATORS MOVEABLE PURE +BEGIN + VK_DELETE, IDM_RetractMove, VIRTKEY, NOINVERT + VK_DOWN, IDM_ToEnd, VIRTKEY, NOINVERT + VK_END, IDM_TruncateGame, VIRTKEY, NOINVERT + VK_HOME, IDM_Revert, VIRTKEY, NOINVERT + VK_INSERT, IDM_MoveNow, VIRTKEY, NOINVERT + VK_LEFT, IDM_Backward, VIRTKEY, NOINVERT + VK_NEXT, IDM_LoadNextGame, VIRTKEY, NOINVERT + VK_NEXT, IDM_LoadNextPosition, VIRTKEY, SHIFT, NOINVERT + VK_PRIOR, IDM_LoadPrevGame, VIRTKEY, NOINVERT + VK_PRIOR, IDM_LoadPrevPosition, VIRTKEY, SHIFT, NOINVERT + VK_RIGHT, IDM_Forward, VIRTKEY, NOINVERT + VK_UP, IDM_ToStart, VIRTKEY, NOINVERT +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Bitmap +// + +P21O BITMAP MOVEABLE PURE "bitmaps\\P21o.bmp" +N21O BITMAP MOVEABLE PURE "bitmaps\\N21o.bmp" +B21O BITMAP MOVEABLE PURE "bitmaps\\B21o.bmp" +R21O BITMAP MOVEABLE PURE "bitmaps\\R21o.bmp" +K21O BITMAP MOVEABLE PURE "bitmaps\\K21o.bmp" +Q21O BITMAP MOVEABLE PURE "bitmaps\\Q21o.bmp" +P21S BITMAP MOVEABLE PURE "bitmaps\\P21s.bmp" +N21S BITMAP MOVEABLE PURE "bitmaps\\N21s.bmp" +B21S BITMAP MOVEABLE PURE "bitmaps\\B21s.bmp" +R21S BITMAP MOVEABLE PURE "bitmaps\\R21s.bmp" +Q21S BITMAP MOVEABLE PURE "bitmaps\\Q21s.bmp" +K21S BITMAP MOVEABLE PURE "bitmaps\\K21s.bmp" +P21W BITMAP MOVEABLE PURE "bitmaps\\P21w.bmp" +N21W BITMAP MOVEABLE PURE "bitmaps\\N21w.bmp" +B21W BITMAP MOVEABLE PURE "bitmaps\\B21w.bmp" +R21W BITMAP MOVEABLE PURE "bitmaps\\R21w.bmp" +Q21W BITMAP MOVEABLE PURE "bitmaps\\Q21w.bmp" +K21W BITMAP MOVEABLE PURE "bitmaps\\K21w.bmp" +P25O BITMAP MOVEABLE PURE "bitmaps\\P25o.bmp" +N25O BITMAP MOVEABLE PURE "bitmaps\\N25o.bmp" +B25O BITMAP MOVEABLE PURE "bitmaps\\B25o.bmp" +R25O BITMAP MOVEABLE PURE "bitmaps\\R25o.bmp" +Q25O BITMAP MOVEABLE PURE "bitmaps\\Q25o.bmp" +K25O BITMAP MOVEABLE PURE "bitmaps\\K25o.bmp" +P25S BITMAP MOVEABLE PURE "bitmaps\\P25s.bmp" +N25S BITMAP MOVEABLE PURE "bitmaps\\N25s.bmp" +B25S BITMAP MOVEABLE PURE "bitmaps\\B25s.bmp" +R25S BITMAP MOVEABLE PURE "bitmaps\\R25s.bmp" +Q25S BITMAP MOVEABLE PURE "bitmaps\\Q25s.bmp" +K25S BITMAP MOVEABLE PURE "bitmaps\\K25s.bmp" +P25W BITMAP MOVEABLE PURE "bitmaps\\P25w.bmp" +N25W BITMAP MOVEABLE PURE "bitmaps\\N25w.bmp" +B25W BITMAP MOVEABLE PURE "bitmaps\\B25w.bmp" +R25W BITMAP MOVEABLE PURE "bitmaps\\R25w.bmp" +Q25W BITMAP MOVEABLE PURE "bitmaps\\Q25w.bmp" +K25W BITMAP MOVEABLE PURE "bitmaps\\K25w.bmp" +P29O BITMAP MOVEABLE PURE "bitmaps\\P29o.bmp" +N29O BITMAP MOVEABLE PURE "bitmaps\\N29o.bmp" +B29O BITMAP MOVEABLE PURE "bitmaps\\B29o.bmp" +R29O BITMAP MOVEABLE PURE "bitmaps\\R29o.bmp" +Q29O BITMAP MOVEABLE PURE "bitmaps\\Q29o.bmp" +K29O BITMAP MOVEABLE PURE "bitmaps\\K29o.bmp" +P29S BITMAP MOVEABLE PURE "bitmaps\\P29s.bmp" +N29S BITMAP MOVEABLE PURE "bitmaps\\N29s.bmp" +B29S BITMAP MOVEABLE PURE "bitmaps\\B29s.bmp" +R29S BITMAP MOVEABLE PURE "bitmaps\\R29s.bmp" +Q29S BITMAP MOVEABLE PURE "bitmaps\\Q29s.bmp" +K29S BITMAP MOVEABLE PURE "bitmaps\\K29s.bmp" +P29W BITMAP MOVEABLE PURE "bitmaps\\P29w.bmp" +N29W BITMAP MOVEABLE PURE "bitmaps\\N29w.bmp" +B29W BITMAP MOVEABLE PURE "bitmaps\\B29w.bmp" +R29W BITMAP MOVEABLE PURE "bitmaps\\R29w.bmp" +Q29W BITMAP MOVEABLE PURE "bitmaps\\Q29w.bmp" +K29W BITMAP MOVEABLE PURE "bitmaps\\K29w.bmp" +P33O BITMAP MOVEABLE PURE "bitmaps\\P33o.bmp" +N33O BITMAP MOVEABLE PURE "bitmaps\\N33o.bmp" +B33O BITMAP MOVEABLE PURE "bitmaps\\B33o.bmp" +R33O BITMAP MOVEABLE PURE "bitmaps\\R33o.bmp" +Q33O BITMAP MOVEABLE PURE "bitmaps\\Q33o.bmp" +K33O BITMAP MOVEABLE PURE "bitmaps\\K33o.bmp" +P33S BITMAP MOVEABLE PURE "bitmaps\\P33s.bmp" +N33S BITMAP MOVEABLE PURE "bitmaps\\N33s.bmp" +B33S BITMAP MOVEABLE PURE "bitmaps\\B33s.bmp" +R33S BITMAP MOVEABLE PURE "bitmaps\\R33s.bmp" +Q33S BITMAP MOVEABLE PURE "bitmaps\\Q33s.bmp" +K33S BITMAP MOVEABLE PURE "bitmaps\\K33s.bmp" +P33W BITMAP MOVEABLE PURE "bitmaps\\P33w.bmp" +N33W BITMAP MOVEABLE PURE "bitmaps\\N33w.bmp" +B33W BITMAP MOVEABLE PURE "bitmaps\\B33w.bmp" +R33W BITMAP MOVEABLE PURE "bitmaps\\R33w.bmp" +Q33W BITMAP MOVEABLE PURE "bitmaps\\Q33w.bmp" +K33W BITMAP MOVEABLE PURE "bitmaps\\K33w.bmp" +P37O BITMAP MOVEABLE PURE "bitmaps\\P37o.bmp" +N37O BITMAP MOVEABLE PURE "bitmaps\\N37o.bmp" +B37O BITMAP MOVEABLE PURE "bitmaps\\B37o.bmp" +R37O BITMAP MOVEABLE PURE "bitmaps\\R37o.bmp" +Q37O BITMAP MOVEABLE PURE "bitmaps\\Q37o.bmp" +K37O BITMAP MOVEABLE PURE "bitmaps\\K37o.bmp" +P37S BITMAP MOVEABLE PURE "bitmaps\\P37s.bmp" +N37S BITMAP MOVEABLE PURE "bitmaps\\N37s.bmp" +B37S BITMAP MOVEABLE PURE "bitmaps\\B37s.bmp" +R37S BITMAP MOVEABLE PURE "bitmaps\\R37s.bmp" +Q37S BITMAP MOVEABLE PURE "bitmaps\\Q37s.bmp" +K37S BITMAP MOVEABLE PURE "bitmaps\\K37s.bmp" +P37W BITMAP MOVEABLE PURE "bitmaps\\P37w.bmp" +N37W BITMAP MOVEABLE PURE "bitmaps\\N37w.bmp" +B37W BITMAP MOVEABLE PURE "bitmaps\\B37w.bmp" +R37W BITMAP MOVEABLE PURE "bitmaps\\R37w.bmp" +Q37W BITMAP MOVEABLE PURE "bitmaps\\Q37w.bmp" +K37W BITMAP MOVEABLE PURE "bitmaps\\K37w.bmp" +P40O BITMAP MOVEABLE PURE "bitmaps\\P40o.bmp" +N40O BITMAP MOVEABLE PURE "bitmaps\\N40o.bmp" +B40O BITMAP MOVEABLE PURE "bitmaps\\B40o.bmp" +R40O BITMAP MOVEABLE PURE "bitmaps\\R40o.bmp" +Q40O BITMAP MOVEABLE PURE "bitmaps\\Q40o.bmp" +K40O BITMAP MOVEABLE PURE "bitmaps\\K40o.bmp" +P40S BITMAP MOVEABLE PURE "bitmaps\\P40s.bmp" +N40S BITMAP MOVEABLE PURE "bitmaps\\N40s.bmp" +B40S BITMAP MOVEABLE PURE "bitmaps\\B40s.bmp" +R40S BITMAP MOVEABLE PURE "bitmaps\\R40s.bmp" +Q40S BITMAP MOVEABLE PURE "bitmaps\\Q40s.bmp" +K40S BITMAP MOVEABLE PURE "bitmaps\\K40s.bmp" +P40W BITMAP MOVEABLE PURE "bitmaps\\P40w.bmp" +N40W BITMAP MOVEABLE PURE "bitmaps\\N40w.bmp" +B40W BITMAP MOVEABLE PURE "bitmaps\\B40w.bmp" +R40W BITMAP MOVEABLE PURE "bitmaps\\R40w.bmp" +Q40W BITMAP MOVEABLE PURE "bitmaps\\Q40w.bmp" +K40W BITMAP MOVEABLE PURE "bitmaps\\K40w.bmp" +P45O BITMAP MOVEABLE PURE "bitmaps\\P45o.bmp" +N45O BITMAP MOVEABLE PURE "bitmaps\\N45o.bmp" +B45O BITMAP MOVEABLE PURE "bitmaps\\B45o.bmp" +R45O BITMAP MOVEABLE PURE "bitmaps\\R45o.bmp" +Q45O BITMAP MOVEABLE PURE "bitmaps\\Q45o.bmp" +K45O BITMAP MOVEABLE PURE "bitmaps\\K45o.bmp" +P45S BITMAP MOVEABLE PURE "bitmaps\\P45s.bmp" +N45S BITMAP MOVEABLE PURE "bitmaps\\N45s.bmp" +B45S BITMAP MOVEABLE PURE "bitmaps\\B45s.bmp" +R45S BITMAP MOVEABLE PURE "bitmaps\\R45s.bmp" +Q45S BITMAP MOVEABLE PURE "bitmaps\\Q45s.bmp" +K45S BITMAP MOVEABLE PURE "bitmaps\\K45s.bmp" +P45W BITMAP MOVEABLE PURE "bitmaps\\P45w.bmp" +N45W BITMAP MOVEABLE PURE "bitmaps\\N45w.bmp" +B45W BITMAP MOVEABLE PURE "bitmaps\\B45w.bmp" +R45W BITMAP MOVEABLE PURE "bitmaps\\R45w.bmp" +Q45W BITMAP MOVEABLE PURE "bitmaps\\Q45w.bmp" +K45W BITMAP MOVEABLE PURE "bitmaps\\K45w.bmp" +P49O BITMAP MOVEABLE PURE "bitmaps\\P49o.bmp" +N49O BITMAP MOVEABLE PURE "bitmaps\\N49o.bmp" +B49O BITMAP MOVEABLE PURE "bitmaps\\B49o.bmp" +R49O BITMAP MOVEABLE PURE "bitmaps\\R49o.bmp" +Q49O BITMAP MOVEABLE PURE "bitmaps\\Q49o.bmp" +K49O BITMAP MOVEABLE PURE "bitmaps\\K49o.bmp" +P49S BITMAP MOVEABLE PURE "bitmaps\\P49s.bmp" +N49S BITMAP MOVEABLE PURE "bitmaps\\N49s.bmp" +B49S BITMAP MOVEABLE PURE "bitmaps\\B49s.bmp" +R49S BITMAP MOVEABLE PURE "bitmaps\\R49s.bmp" +Q49S BITMAP MOVEABLE PURE "bitmaps\\Q49s.bmp" +K49S BITMAP MOVEABLE PURE "bitmaps\\K49s.bmp" +P49W BITMAP MOVEABLE PURE "bitmaps\\P49w.bmp" +N49W BITMAP MOVEABLE PURE "bitmaps\\N49w.bmp" +B49W BITMAP MOVEABLE PURE "bitmaps\\B49w.bmp" +R49W BITMAP MOVEABLE PURE "bitmaps\\R49w.bmp" +Q49W BITMAP MOVEABLE PURE "bitmaps\\Q49w.bmp" +K49W BITMAP MOVEABLE PURE "bitmaps\\K49w.bmp" +P54O BITMAP MOVEABLE PURE "bitmaps\\P54o.bmp" +N54O BITMAP MOVEABLE PURE "bitmaps\\N54o.bmp" +B54O BITMAP MOVEABLE PURE "bitmaps\\B54o.bmp" +R54O BITMAP MOVEABLE PURE "bitmaps\\R54o.bmp" +Q54O BITMAP MOVEABLE PURE "bitmaps\\Q54o.bmp" +K54O BITMAP MOVEABLE PURE "bitmaps\\K54o.bmp" +P54S BITMAP MOVEABLE PURE "bitmaps\\P54s.bmp" +N54S BITMAP MOVEABLE PURE "bitmaps\\N54s.bmp" +B54S BITMAP MOVEABLE PURE "bitmaps\\B54s.bmp" +R54S BITMAP MOVEABLE PURE "bitmaps\\R54s.bmp" +Q54S BITMAP MOVEABLE PURE "bitmaps\\Q54s.bmp" +K54S BITMAP MOVEABLE PURE "bitmaps\\K54s.bmp" +P54W BITMAP MOVEABLE PURE "bitmaps\\P54w.bmp" +N54W BITMAP MOVEABLE PURE "bitmaps\\N54w.bmp" +B54W BITMAP MOVEABLE PURE "bitmaps\\B54w.bmp" +R54W BITMAP MOVEABLE PURE "bitmaps\\R54w.bmp" +Q54W BITMAP MOVEABLE PURE "bitmaps\\Q54w.bmp" +K54W BITMAP MOVEABLE PURE "bitmaps\\K54w.bmp" +P58O BITMAP MOVEABLE PURE "bitmaps\\P58o.bmp" +N58O BITMAP MOVEABLE PURE "bitmaps\\N58o.bmp" +B58O BITMAP MOVEABLE PURE "bitmaps\\B58o.bmp" +R58O BITMAP MOVEABLE PURE "bitmaps\\R58o.bmp" +Q58O BITMAP MOVEABLE PURE "bitmaps\\Q58o.bmp" +K58O BITMAP MOVEABLE PURE "bitmaps\\K58o.bmp" +P58S BITMAP MOVEABLE PURE "bitmaps\\P58s.bmp" +N58S BITMAP MOVEABLE PURE "bitmaps\\N58s.bmp" +B58S BITMAP MOVEABLE PURE "bitmaps\\B58s.bmp" +R58S BITMAP MOVEABLE PURE "bitmaps\\R58s.bmp" +Q58S BITMAP MOVEABLE PURE "bitmaps\\Q58s.bmp" +K58S BITMAP MOVEABLE PURE "bitmaps\\K58s.bmp" +P58W BITMAP MOVEABLE PURE "bitmaps\\P58w.bmp" +N58W BITMAP MOVEABLE PURE "bitmaps\\N58w.bmp" +B58W BITMAP MOVEABLE PURE "bitmaps\\B58w.bmp" +R58W BITMAP MOVEABLE PURE "bitmaps\\R58w.bmp" +Q58W BITMAP MOVEABLE PURE "bitmaps\\Q58w.bmp" +K58W BITMAP MOVEABLE PURE "bitmaps\\K58w.bmp" +P64O BITMAP MOVEABLE PURE "bitmaps\\P64o.bmp" +N64O BITMAP MOVEABLE PURE "bitmaps\\N64o.bmp" +B64O BITMAP MOVEABLE PURE "bitmaps\\B64o.bmp" +R64O BITMAP MOVEABLE PURE "bitmaps\\R64o.bmp" +Q64O BITMAP MOVEABLE PURE "bitmaps\\Q64o.bmp" +K64O BITMAP MOVEABLE PURE "bitmaps\\K64o.bmp" +P64S BITMAP MOVEABLE PURE "bitmaps\\P64s.bmp" +N64S BITMAP MOVEABLE PURE "bitmaps\\N64s.bmp" +B64S BITMAP MOVEABLE PURE "bitmaps\\B64s.bmp" +R64S BITMAP MOVEABLE PURE "bitmaps\\R64s.bmp" +Q64S BITMAP MOVEABLE PURE "bitmaps\\Q64s.bmp" +K64S BITMAP MOVEABLE PURE "bitmaps\\K64s.bmp" +P64W BITMAP MOVEABLE PURE "bitmaps\\P64w.bmp" +N64W BITMAP MOVEABLE PURE "bitmaps\\N64w.bmp" +B64W BITMAP MOVEABLE PURE "bitmaps\\B64w.bmp" +R64W BITMAP MOVEABLE PURE "bitmaps\\R64w.bmp" +Q64W BITMAP MOVEABLE PURE "bitmaps\\Q64w.bmp" +K64W BITMAP MOVEABLE PURE "bitmaps\\K64w.bmp" +P72O BITMAP MOVEABLE PURE "bitmaps\\P72o.bmp" +N72O BITMAP MOVEABLE PURE "bitmaps\\N72o.bmp" +B72O BITMAP MOVEABLE PURE "bitmaps\\B72o.bmp" +R72O BITMAP MOVEABLE PURE "bitmaps\\R72o.bmp" +Q72O BITMAP MOVEABLE PURE "bitmaps\\Q72o.bmp" +K72O BITMAP MOVEABLE PURE "bitmaps\\K72o.bmp" +P72S BITMAP MOVEABLE PURE "bitmaps\\P72s.bmp" +N72S BITMAP MOVEABLE PURE "bitmaps\\N72s.bmp" +B72S BITMAP MOVEABLE PURE "bitmaps\\B72s.bmp" +R72S BITMAP MOVEABLE PURE "bitmaps\\R72s.bmp" +Q72S BITMAP MOVEABLE PURE "bitmaps\\Q72s.bmp" +K72S BITMAP MOVEABLE PURE "bitmaps\\K72s.bmp" +P72W BITMAP MOVEABLE PURE "bitmaps\\P72w.bmp" +N72W BITMAP MOVEABLE PURE "bitmaps\\N72w.bmp" +B72W BITMAP MOVEABLE PURE "bitmaps\\B72w.bmp" +R72W BITMAP MOVEABLE PURE "bitmaps\\R72w.bmp" +Q72W BITMAP MOVEABLE PURE "bitmaps\\Q72w.bmp" +K72W BITMAP MOVEABLE PURE "bitmaps\\K72w.bmp" +P80O BITMAP MOVEABLE PURE "bitmaps\\P80o.bmp" +N80O BITMAP MOVEABLE PURE "bitmaps\\N80o.bmp" +B80O BITMAP MOVEABLE PURE "bitmaps\\B80o.bmp" +R80O BITMAP MOVEABLE PURE "bitmaps\\R80o.bmp" +Q80O BITMAP MOVEABLE PURE "bitmaps\\Q80o.bmp" +K80O BITMAP MOVEABLE PURE "bitmaps\\K80o.bmp" +P80S BITMAP MOVEABLE PURE "bitmaps\\P80s.bmp" +N80S BITMAP MOVEABLE PURE "bitmaps\\N80s.bmp" +B80S BITMAP MOVEABLE PURE "bitmaps\\B80s.bmp" +R80S BITMAP MOVEABLE PURE "bitmaps\\R80s.bmp" +Q80S BITMAP MOVEABLE PURE "bitmaps\\Q80s.bmp" +K80S BITMAP MOVEABLE PURE "bitmaps\\K80s.bmp" +P80W BITMAP MOVEABLE PURE "bitmaps\\P80w.bmp" +N80W BITMAP MOVEABLE PURE "bitmaps\\N80w.bmp" +B80W BITMAP MOVEABLE PURE "bitmaps\\B80w.bmp" +R80W BITMAP MOVEABLE PURE "bitmaps\\R80w.bmp" +Q80W BITMAP MOVEABLE PURE "bitmaps\\Q80w.bmp" +K80W BITMAP MOVEABLE PURE "bitmaps\\K80w.bmp" +P87O BITMAP MOVEABLE PURE "bitmaps\\P87o.bmp" +N87O BITMAP MOVEABLE PURE "bitmaps\\N87o.bmp" +B87O BITMAP MOVEABLE PURE "bitmaps\\B87o.bmp" +R87O BITMAP MOVEABLE PURE "bitmaps\\R87o.bmp" +Q87O BITMAP MOVEABLE PURE "bitmaps\\Q87o.bmp" +K87O BITMAP MOVEABLE PURE "bitmaps\\K87o.bmp" +P87S BITMAP MOVEABLE PURE "bitmaps\\P87s.bmp" +N87S BITMAP MOVEABLE PURE "bitmaps\\N87s.bmp" +B87S BITMAP MOVEABLE PURE "bitmaps\\B87s.bmp" +R87S BITMAP MOVEABLE PURE "bitmaps\\R87s.bmp" +Q87S BITMAP MOVEABLE PURE "bitmaps\\Q87s.bmp" +K87S BITMAP MOVEABLE PURE "bitmaps\\K87s.bmp" +P87W BITMAP MOVEABLE PURE "bitmaps\\P87w.bmp" +N87W BITMAP MOVEABLE PURE "bitmaps\\N87w.bmp" +B87W BITMAP MOVEABLE PURE "bitmaps\\B87w.bmp" +R87W BITMAP MOVEABLE PURE "bitmaps\\R87w.bmp" +Q87W BITMAP MOVEABLE PURE "bitmaps\\Q87w.bmp" +K87W BITMAP MOVEABLE PURE "bitmaps\\K87w.bmp" +P95O BITMAP MOVEABLE PURE "bitmaps\\P95o.bmp" +N95O BITMAP MOVEABLE PURE "bitmaps\\N95o.bmp" +B95O BITMAP MOVEABLE PURE "bitmaps\\B95o.bmp" +R95O BITMAP MOVEABLE PURE "bitmaps\\R95o.bmp" +Q95O BITMAP MOVEABLE PURE "bitmaps\\Q95o.bmp" +K95O BITMAP MOVEABLE PURE "bitmaps\\K95o.bmp" +P95S BITMAP MOVEABLE PURE "bitmaps\\P95s.bmp" +N95S BITMAP MOVEABLE PURE "bitmaps\\N95s.bmp" +B95S BITMAP MOVEABLE PURE "bitmaps\\B95s.bmp" +R95S BITMAP MOVEABLE PURE "bitmaps\\R95s.bmp" +Q95S BITMAP MOVEABLE PURE "bitmaps\\Q95s.bmp" +K95S BITMAP MOVEABLE PURE "bitmaps\\K95s.bmp" +P95W BITMAP MOVEABLE PURE "bitmaps\\P95w.bmp" +N95W BITMAP MOVEABLE PURE "bitmaps\\N95w.bmp" +B95W BITMAP MOVEABLE PURE "bitmaps\\B95w.bmp" +R95W BITMAP MOVEABLE PURE "bitmaps\\R95w.bmp" +Q95W BITMAP MOVEABLE PURE "bitmaps\\Q95w.bmp" +K95W BITMAP MOVEABLE PURE "bitmaps\\K95w.bmp" +P108O BITMAP MOVEABLE PURE "bitmaps\\P108o.bmp" +N108O BITMAP MOVEABLE PURE "bitmaps\\N108o.bmp" +B108O BITMAP MOVEABLE PURE "bitmaps\\B108o.bmp" +R108O BITMAP MOVEABLE PURE "bitmaps\\R108o.bmp" +Q108O BITMAP MOVEABLE PURE "bitmaps\\Q108o.bmp" +K108O BITMAP MOVEABLE PURE "bitmaps\\K108o.bmp" +P108S BITMAP MOVEABLE PURE "bitmaps\\P108s.bmp" +N108S BITMAP MOVEABLE PURE "bitmaps\\N108s.bmp" +B108S BITMAP MOVEABLE PURE "bitmaps\\B108s.bmp" +R108S BITMAP MOVEABLE PURE "bitmaps\\R108s.bmp" +Q108S BITMAP MOVEABLE PURE "bitmaps\\Q108s.bmp" +K108S BITMAP MOVEABLE PURE "bitmaps\\K108s.bmp" +P108W BITMAP MOVEABLE PURE "bitmaps\\P108w.bmp" +N108W BITMAP MOVEABLE PURE "bitmaps\\N108w.bmp" +B108W BITMAP MOVEABLE PURE "bitmaps\\B108w.bmp" +R108W BITMAP MOVEABLE PURE "bitmaps\\R108w.bmp" +Q108W BITMAP MOVEABLE PURE "bitmaps\\Q108w.bmp" +K108W BITMAP MOVEABLE PURE "bitmaps\\K108w.bmp" +P116O BITMAP MOVEABLE PURE "bitmaps\\P116o.bmp" +N116O BITMAP MOVEABLE PURE "bitmaps\\N116o.bmp" +B116O BITMAP MOVEABLE PURE "bitmaps\\B116o.bmp" +R116O BITMAP MOVEABLE PURE "bitmaps\\R116o.bmp" +Q116O BITMAP MOVEABLE PURE "bitmaps\\Q116o.bmp" +K116O BITMAP MOVEABLE PURE "bitmaps\\K116o.bmp" +P116S BITMAP MOVEABLE PURE "bitmaps\\P116s.bmp" +N116S BITMAP MOVEABLE PURE "bitmaps\\N116s.bmp" +B116S BITMAP MOVEABLE PURE "bitmaps\\B116s.bmp" +R116S BITMAP MOVEABLE PURE "bitmaps\\R116s.bmp" +Q116S BITMAP MOVEABLE PURE "bitmaps\\Q116s.bmp" +K116S BITMAP MOVEABLE PURE "bitmaps\\K116s.bmp" +P116W BITMAP MOVEABLE PURE "bitmaps\\P116w.bmp" +N116W BITMAP MOVEABLE PURE "bitmaps\\N116w.bmp" +B116W BITMAP MOVEABLE PURE "bitmaps\\B116w.bmp" +R116W BITMAP MOVEABLE PURE "bitmaps\\R116w.bmp" +Q116W BITMAP MOVEABLE PURE "bitmaps\\Q116w.bmp" +K116W BITMAP MOVEABLE PURE "bitmaps\\K116w.bmp" +P129O BITMAP MOVEABLE PURE "bitmaps\\P129o.bmp" +N129O BITMAP MOVEABLE PURE "bitmaps\\N129o.bmp" +B129O BITMAP MOVEABLE PURE "bitmaps\\B129o.bmp" +R129O BITMAP MOVEABLE PURE "bitmaps\\R129o.bmp" +Q129O BITMAP MOVEABLE PURE "bitmaps\\Q129o.bmp" +K129O BITMAP MOVEABLE PURE "bitmaps\\K129o.bmp" +P129S BITMAP MOVEABLE PURE "bitmaps\\P129s.bmp" +N129S BITMAP MOVEABLE PURE "bitmaps\\N129s.bmp" +B129S BITMAP MOVEABLE PURE "bitmaps\\B129s.bmp" +R129S BITMAP MOVEABLE PURE "bitmaps\\R129s.bmp" +Q129S BITMAP MOVEABLE PURE "bitmaps\\Q129s.bmp" +K129S BITMAP MOVEABLE PURE "bitmaps\\K129s.bmp" +P129W BITMAP MOVEABLE PURE "bitmaps\\P129w.bmp" +N129W BITMAP MOVEABLE PURE "bitmaps\\N129w.bmp" +B129W BITMAP MOVEABLE PURE "bitmaps\\B129w.bmp" +R129W BITMAP MOVEABLE PURE "bitmaps\\R129w.bmp" +Q129W BITMAP MOVEABLE PURE "bitmaps\\Q129w.bmp" +K129W BITMAP MOVEABLE PURE "bitmaps\\K129w.bmp" +GALACTIC BITMAP MOVEABLE PURE "bitmaps\\galactic.bmp" +TIM BITMAP MOVEABLE PURE "bitmaps\\tim.bmp" + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#define APSTUDIO_HIDDEN_SYMBOLS\r\n" + "#include ""windows.h""\r\n" + "#undef APSTUDIO_HIDDEN_SYMBOLS\r\n" + "#include ""dlgs.h""\r\n" + "\r\n" + "\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// WAVE +// + +DING WAVE DISCARDABLE "sounds\\ding1.wav" +CHING WAVE DISCARDABLE "sounds\\ching.wav" +CLICK WAVE DISCARDABLE "sounds\\click.wav" +CYMBAL WAVE DISCARDABLE "sounds\\cymbal.wav" +DRIP WAVE DISCARDABLE "sounds\\drip.wav" +GONG WAVE DISCARDABLE "sounds\\gong.wav" +BEEPBEEP WAVE DISCARDABLE "sounds\\honkhonk.wav" +LASER WAVE DISCARDABLE "sounds\\laser.wav" +PENALTY WAVE DISCARDABLE "sounds\\penalty.wav" +PHONE WAVE DISCARDABLE "sounds\\phone.wav" +POP WAVE DISCARDABLE "sounds\\pop.wav" +POP2 WAVE DISCARDABLE "sounds\\pop2.wav" +SLAP WAVE DISCARDABLE "sounds\\slap.wav" +SQUEAK WAVE DISCARDABLE "sounds\\squeak.wav" +SWISH WAVE DISCARDABLE "sounds\\swish.wav" +THUD WAVE DISCARDABLE "sounds\\thud.wav" +WHIPCRACK WAVE DISCARDABLE "sounds\\whipcrak.wav" +MOVE WAVE DISCARDABLE "sounds\\move.wav" +ALARM WAVE DISCARDABLE "sounds\\alarm.wav" +CHALLENGE WAVE DISCARDABLE "sounds\\challenge.wav" +CHANNEL WAVE DISCARDABLE "sounds\\channel.wav" +CHANNEL1 WAVE DISCARDABLE "sounds\\channel1.wav" +DRAW WAVE DISCARDABLE "sounds\\draw.wav" +KIBITZ WAVE DISCARDABLE "sounds\\kibitz.wav" +LOSE WAVE DISCARDABLE "sounds\\lose.wav" +REQUEST WAVE DISCARDABLE "sounds\\request.wav" +SEEK WAVE DISCARDABLE "sounds\\seek.wav" +SHOUT WAVE DISCARDABLE "sounds\\shout.wav" +SSHOUT WAVE DISCARDABLE "sounds\\sshout.wav" +TELL WAVE DISCARDABLE "sounds\\tell.wav" +UNFINISHED WAVE DISCARDABLE "sounds\\unfinished.wav" +WIN WAVE DISCARDABLE "sounds\\win.wav" +#endif // Englisch (USA) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/winboard-dm-beta4/winboard.rtf b/winboard-dm-beta4/winboard.rtf new file mode 100755 index 0000000..d584bbc --- /dev/null +++ b/winboard-dm-beta4/winboard.rtf @@ -0,0 +1,1880 @@ +{\rtf1\ansi\ansicpg1252\uc1 \deff5\deflang1033\deflangfe1033{\fonttbl{\f0\froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f1\fswiss\fcharset0\fprq2{\*\panose 020b0604020202020204}Arial;} +{\f2\fmodern\fcharset0\fprq1{\*\panose 02070309020205020404}Courier New;}{\f3\froman\fcharset2\fprq2{\*\panose 05050102010706020507}Symbol;}{\f5\fswiss\fcharset0\fprq2{\*\panose 00000000000000000000}Helvetica{\*\falt Arial};} +{\f6\fmodern\fcharset0\fprq1{\*\panose 00000000000000000000}Courier;}{\f11\fswiss\fcharset0\fprq2{\*\panose 00000000000000000000}MS Sans Serif;}{\f27\fswiss\fcharset0\fprq2{\*\panose 020b0604030504040204}Tahoma;} +{\f226\fswiss\fcharset0\fprq0{\*\panose 00000000000000000000}Univers (WN);}{\f227\froman\fcharset0\fprq0{\*\panose 00000000000000000000}CG Times (WN);}{\f484\froman\fcharset238\fprq2 Times New Roman CE;} +{\f485\froman\fcharset204\fprq2 Times New Roman Cyr;}{\f487\froman\fcharset161\fprq2 Times New Roman Greek;}{\f488\froman\fcharset162\fprq2 Times New Roman Tur;}{\f489\froman\fcharset177\fprq2 Times New Roman (Hebrew);} +{\f490\froman\fcharset178\fprq2 Times New Roman (Arabic);}{\f491\froman\fcharset186\fprq2 Times New Roman Baltic;}{\f492\fswiss\fcharset238\fprq2 Arial CE;}{\f493\fswiss\fcharset204\fprq2 Arial Cyr;}{\f495\fswiss\fcharset161\fprq2 Arial Greek;} +{\f496\fswiss\fcharset162\fprq2 Arial Tur;}{\f497\fswiss\fcharset177\fprq2 Arial (Hebrew);}{\f498\fswiss\fcharset178\fprq2 Arial (Arabic);}{\f499\fswiss\fcharset186\fprq2 Arial Baltic;}{\f500\fmodern\fcharset238\fprq1 Courier New CE;} +{\f501\fmodern\fcharset204\fprq1 Courier New Cyr;}{\f503\fmodern\fcharset161\fprq1 Courier New Greek;}{\f504\fmodern\fcharset162\fprq1 Courier New Tur;}{\f505\fmodern\fcharset177\fprq1 Courier New (Hebrew);} +{\f506\fmodern\fcharset178\fprq1 Courier New (Arabic);}{\f507\fmodern\fcharset186\fprq1 Courier New Baltic;}{\f700\fswiss\fcharset238\fprq2 Tahoma CE;}{\f701\fswiss\fcharset204\fprq2 Tahoma Cyr;}{\f703\fswiss\fcharset161\fprq2 Tahoma Greek;} +{\f704\fswiss\fcharset162\fprq2 Tahoma Tur;}{\f705\fswiss\fcharset177\fprq2 Tahoma (Hebrew);}{\f706\fswiss\fcharset178\fprq2 Tahoma (Arabic);}{\f707\fswiss\fcharset186\fprq2 Tahoma Baltic;}}{\colortbl;\red0\green0\blue0;\red0\green0\blue255; +\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;\red128\green0\blue128;\red128\green0\blue0; +\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192;}{\stylesheet{\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \snext0 Normal;}{ +\s1\ql \li120\ri0\sb280\sa120\sl-320\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \b\f5\fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext26 heading 1;}{\s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext0 heading 2;}{\s3\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 +\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext0 heading 3;}{\s4\ql \fi-245\li360\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin360\itap0 +\f11\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \sbasedon2 \snext4 heading 4;}{\s5\ql \li120\ri0\sb80\sl-240\slmult0\keepn\nowidctlpar\faauto\outlinelevel4\adjustright\rin0\lin120\itap0 +\f5\fs20\ul\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext0 heading 5;}{\*\cs10 \additive Default Paragraph Font;}{\*\cs15 \additive \f5\fs18\up6\lang1033\langfe0\langnp1033 \sbasedon10 footnote reference;}{ +\s16\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext0 footnote text;}{\s17\ql \li360\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin360\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext0 Normal Indent;}{\s18\ql \fi-240\li600\ri0\sb60\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin600\itap0 +\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \snext18 Jli;}{\s19\ql \li120\ri0\sb60\sl-240\slmult0\keep\nowidctlpar\tx520\tx920\tx1320\tx1720\tx2120\faauto\adjustright\rin0\lin120\itap0 +\f6\fs16\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \snext19 Ex;}{\s20\ql \li120\ri0\sb160\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \snext29 Sa1;}{ +\s21\ql \fi-240\li360\ri0\sl-240\slmult0\nowidctlpar\tx360\faauto\adjustright\rin0\lin360\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \snext22 Lb1;}{\s22\ql \fi-240\li360\ri0\sb60\sl-240\slmult0\nowidctlpar +\tx360\faauto\adjustright\rin0\lin360\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \snext22 Lb2;}{\s23\ql \li360\ri0\sb60\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin360\itap0 +\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \snext22 Lp1;}{\s24\ql \fi-1800\li1920\ri0\sb120\sa40\sl-240\slmult0\nowidctlpar\brdrb\brdrs\brdrw15\brsp20 \brdrbtw\brdrs\brdrw15\brsp20 \tx1920\faauto\adjustright\rin0\lin1920\itap0 +\b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \snext25 Th;}{\s25\ql \fi-1800\li1920\ri0\sb60\sl-240\slmult0\nowidctlpar\tx1920\faauto\adjustright\rin0\lin1920\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \snext25 Tp;}{ +\s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \snext0 Normal 2;}{\s27\ql \li120\ri0\sb120\sa120\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 +\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \snext0 bitmap;}{\s28\ql \li120\ri0\sb120\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \snext29 Sa2;}{ +\s29\ql \fi-240\li360\ri0\sb60\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin360\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \snext29 Jl;}{\s30\ql \li120\ri0\sa60\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 +\f226\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \snext30 *body;}{\s31\ql \li120\ri0\sa60\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \b\f226\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \snext31 *heading;}{ +\s32\ql \li120\ri0\sa60\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f226\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \sbasedon30 \snext32 para;}{ +\s33\ql \fi-280\li400\ri0\sa60\nowidctlpar\faauto\adjustright\rin0\lin400\itap0 \f226\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \sbasedon30 \snext33 jump;}{\s34\ql \fi-280\li400\ri0\sa60\nowidctlpar\tx400\faauto\adjustright\rin0\lin400\itap0 +\f226\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \sbasedon30 \snext34 list bullet;}{\s35\ql \fi-280\li600\ri0\sa60\nowidctlpar\faauto\adjustright\rin0\lin600\itap0 \f226\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 +\sbasedon30 \snext35 jump indent;}{\s36\ql \li120\ri0\sa60\sl-40\slmult0\nowidctlpar\brdrb\brdrs\brdrw15\brsp20 \brdrbtw\brdrs\brdrw15\brsp20 \faauto\adjustright\rin0\lin120\itap0 \f226\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 +\sbasedon30 \snext36 table rule;}{\s37\ql \fi-280\li400\ri0\sa60\nowidctlpar\tqr\tx280\tx400\faauto\adjustright\rin0\lin400\itap0 \f226\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \sbasedon30 \snext37 list number;}{ +\s38\ql \li120\ri0\sb100\sa60\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \b\f226\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \sbasedon31 \snext33 see also;}{\s39\ql \li400\ri0\sa60\nowidctlpar\faauto\adjustright\rin0\lin400\itap0 +\f226\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \sbasedon30 \snext39 para indent;}{\s40\ql \fi-1800\li1920\ri0\nowidctlpar\tx1920\faauto\adjustright\rin0\lin1920\itap0 \b\f226\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 +\sbasedon31 \snext36 table head;}{\s41\ql \fi-1800\li1920\ri0\sa60\nowidctlpar\tx1920\faauto\adjustright\rin0\lin1920\itap0 \f226\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \sbasedon30 \snext41 table text;}{ +\s42\ql \li120\ri0\sb120\sa60\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f226\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \sbasedon30 \snext35 see also 2;}{\s43\ql \li120\ri0\sa60\keep\nowidctlpar +\tx520\tx920\tx1320\tx1720\tx2120\faauto\adjustright\rin0\lin120\itap0 \f6\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \sbasedon30 \snext43 code;}{\s44\ql \li0\ri0\sl-120\slmult0\nowidctlpar\faauto\adjustright\rin0\lin0\itap0 +\f227\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \snext32 *spacing;}{\s45\ql \li0\ri0\sl-120\slmult0\nowidctlpar\faauto\adjustright\rin0\lin0\itap0 \f227\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \sbasedon44 \snext45 s6;}{ +\s46\qj \li360\ri0\nowidctlpar\faauto\adjustright\rin0\lin360\itap0 \f5\fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext46 Help Text;}{\s47\ql \li115\ri0\sb120\sa40\sl-240\slmult0\nowidctlpar\brdrb\brdrs\brdrw15\brsp20 \brdrbtw +\brdrs\brdrw15\brsp20 \faauto\adjustright\rin0\lin115\itap0 \f11\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \sbasedon24 \snext25 Th2;}{\s48\ql \li115\ri0\sb120\sa40\sl-240\slmult0\nowidctlpar\brdrb\brdrs\brdrw15\brsp20 \brdrbtw +\brdrs\brdrw15\brsp20 \faauto\adjustright\rin0\lin115\itap0 \b\f11\fs16\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \sbasedon24 \snext25 Th3;}{\s49\ql \li115\ri0\sb200\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin115\itap0 +\f11\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext0 Normal 3;}{\s50\ql \fi-1800\li1915\ri0\sb120\sa40\sl-240\slmult0\nowidctlpar\brdrb\brdrs\brdrw15\brsp20 \brdrbtw\brdrs\brdrw15\brsp20 +\tx1915\faauto\adjustright\rin0\lin1915\itap0 \b\f11\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext51 Thh;}{\s51\ql \fi-1800\li1915\ri0\sb60\sl-240\slmult0\nowidctlpar\tx1915\faauto\adjustright\rin0\lin1915\itap0 +\f11\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext51 Tph;}{\s52\ql \li288\ri-432\sb80\sl-240\slmult0\nowidctlpar\tx288\tx864\tx1440\faauto\adjustright\rin-432\lin288\itap0 +\f5\fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext52 unixman1;}{\s53\ql \li1440\ri-432\sb80\sa240\sl-240\slmult0\nowidctlpar\tx288\tx864\tx1440\faauto\adjustright\rin-432\lin1440\itap0 +\f5\fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext53 unixman2;}{\s54\ql \li115\ri-432\sb80\sl-240\slmult0\nowidctlpar\tx288\tx864\tx1440\faauto\adjustright\rin-432\lin115\itap0 +\f5\fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \sbasedon52 \snext54 unixman0;}{\s55\ql \li288\ri-432\sb80\sa240\sl-240\slmult0\nowidctlpar\tx288\tx864\tx1440\faauto\adjustright\rin-432\lin288\itap0 +\f5\fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \sbasedon52 \snext55 unixman1a;}{\s56\ql \li115\ri0\sa60\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin115\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 +\sbasedon2 \snext56 heading 2a;}{\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext57 endnote text;}{\*\cs58 \additive \super \sbasedon10 +endnote reference;}{\*\cs59 \additive \ul\cf2 \sbasedon10 Hyperlink;}{\*\cs60 \additive \ul\cf12 \sbasedon10 FollowedHyperlink;}{\s61\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \cbpat9 +\f27\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext61 Document Map;}{\s62\ql \li480\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin480\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 +\sbasedon0 \snext62 Body Text 2;}{\s63\ql \fi-720\li1440\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin1440\itap0 \f2\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext63 Body Text Indent 2;}{ +\s64\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\tqc\tx4320\tqr\tx8640\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext64 header;}{\s65\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar +\tqc\tx4320\tqr\tx8640\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext65 footer;}}{\*\listtable{\list\listtemplateid67698703\listsimple{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0 +\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'02\'00.;}{\levelnumbers\'01;}\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1 \fi-360\li360\jclisttab\tx360 }{\listname ;}\listid74976790}{\list\listtemplateid67698703\listsimple +{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'02\'00.;}{\levelnumbers\'01;}\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1 \fi-360\li360\jclisttab\tx360 }{\listname +;}\listid349260549}{\list\listtemplateid67698689\listsimple{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'01\u-3913 ?;}{\levelnumbers;}\f3\chbrdr\brdrnone\brdrcf1 +\chshdng0\chcfpat1\chcbpat1\fbias0 \fi-360\li360\jclisttab\tx360 }{\listname ;}\listid470094698}{\list\listtemplateid67698703\listsimple{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext +\'02\'00.;}{\levelnumbers\'01;}\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1 \fi-360\li360\jclisttab\tx360 }{\listname ;}\listid640160996}{\list\listtemplateid67698689\listsimple{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0 +\levelstartat1\levelspace0\levelindent0{\leveltext\'01\u-3913 ?;}{\levelnumbers;}\f3\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1\fbias0 \fi-360\li360\jclisttab\tx360 }{\listname ;}\listid768165129}{\list\listtemplateid67698703\listsimple +{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'02\'00.;}{\levelnumbers\'01;}\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1 \fi-360\li360\jclisttab\tx360 }{\listname +;}\listid781152802}{\list\listtemplateid67698703\listsimple{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'02\'00.;}{\levelnumbers\'01;}\chbrdr\brdrnone\brdrcf1 +\chshdng0\chcfpat1\chcbpat1 \fi-360\li360\jclisttab\tx360 }{\listname ;}\listid903878531}{\list\listtemplateid67698689\listsimple{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext +\'01\u-3913 ?;}{\levelnumbers;}\f3\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1\fbias0 \fi-360\li360\jclisttab\tx360 }{\listname ;}\listid1002394966}{\list\listtemplateid67698703\listsimple{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0 +\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'02\'00.;}{\levelnumbers\'01;}\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1 \fi-360\li360\jclisttab\tx360 }{\listname ;}\listid1021513731}{\list\listtemplateid67698703\listsimple +{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'02\'00.;}{\levelnumbers\'01;}\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1 \fi-360\li360\jclisttab\tx360 }{\listname +;}\listid1099714113}{\list\listtemplateid67698703\listsimple{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'02\'00.;}{\levelnumbers\'01;}\chbrdr\brdrnone\brdrcf1 +\chshdng0\chcfpat1\chcbpat1 \fi-360\li360\jclisttab\tx360 }{\listname ;}\listid1240552867}{\list\listtemplateid67698703\listsimple{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext +\'02\'00.;}{\levelnumbers\'01;}\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1 \fi-360\li360\jclisttab\tx360 }{\listname ;}\listid1332292840}{\list\listtemplateid67698703\listsimple{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0 +\levelstartat1\levelspace0\levelindent0{\leveltext\'02\'00.;}{\levelnumbers\'01;}\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1 \fi-360\li360\jclisttab\tx360 }{\listname ;}\listid1358388700}{\list\listtemplateid67698689\listsimple{\listlevel +\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'01\u-3913 ?;}{\levelnumbers;}\f3\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1\fbias0 \fi-360\li360\jclisttab\tx360 }{\listname +;}\listid1405952460}{\list\listtemplateid67698689\listsimple{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'01\u-3913 ?;}{\levelnumbers;}\f3\chbrdr\brdrnone\brdrcf1 +\chshdng0\chcfpat1\chcbpat1\fbias0 \fi-360\li360\jclisttab\tx360 }{\listname ;}\listid2025940873}{\list\listtemplateid67698689\listsimple{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext +\'01\u-3913 ?;}{\levelnumbers;}\f3\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1\fbias0 \fi-360\li360\jclisttab\tx360 }{\listname ;}\listid2044863907}}{\*\listoverridetable{\listoverride\listid2025940873\listoverridecount0\ls1} +{\listoverride\listid1002394966\listoverridecount0\ls2}{\listoverride\listid470094698\listoverridecount0\ls3}{\listoverride\listid1099714113\listoverridecount0\ls4}{\listoverride\listid1358388700\listoverridecount0\ls5}{\listoverride\listid2044863907 +\listoverridecount0\ls6}{\listoverride\listid640160996\listoverridecount0\ls7}{\listoverride\listid768165129\listoverridecount0\ls8}{\listoverride\listid903878531\listoverridecount0\ls9}{\listoverride\listid781152802\listoverridecount0\ls10} +{\listoverride\listid1240552867\listoverridecount0\ls11}{\listoverride\listid640160996\listoverridecount0\ls12}{\listoverride\listid349260549\listoverridecount0\ls13}{\listoverride\listid1021513731\listoverridecount0\ls14}{\listoverride\listid1405952460 +\listoverridecount0\ls15}{\listoverride\listid1332292840\listoverridecount0\ls16}}{\*\revtbl {Unknown;}{Tim Mann;}}{\info{\title + $ # KWinBoard: Chessboard for Windows}{\author TRIO}{\operator Timothy Mann}{\creatim\yr2001\mo12\dy9\hr12\min56}{\revtim\yr2001\mo12\dy9\hr12\min56} +{\printim\yr1997\mo4\dy22\hr23\min5}{\version2}{\edmins2}{\nofpages60}{\nofwords12847}{\nofchars73230}{\*\company DEC SRC}{\nofcharsws89931}{\vern8269}} +\widowctrl\endnotes\aendnotes\ftnnrlc\aftnnar\noxlattoyen\expshrtn\noultrlspc\dntblnsbdb\nospaceforul\hyphcaps0\horzdoc\dghspace120\dgvspace120\dghorigin1701\dgvorigin1984\dghshow0\dgvshow3\jcompress\viewkind4\viewscale100\nolnhtadjtbl \fet1{\*\aftnsep +\pard\plain \ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\chftnsep +\par }}\sectd \linex0\sectdefaultcl {\*\pnseclvl1\pnucrm\pnstart1\pnindent720\pnhang{\pntxta .}}{\*\pnseclvl2\pnucltr\pnstart1\pnindent720\pnhang{\pntxta .}}{\*\pnseclvl3\pndec\pnstart1\pnindent720\pnhang{\pntxta .}}{\*\pnseclvl4 +\pnlcltr\pnstart1\pnindent720\pnhang{\pntxta )}}{\*\pnseclvl5\pndec\pnstart1\pnindent720\pnhang{\pntxtb (}{\pntxta )}}{\*\pnseclvl6\pnlcltr\pnstart1\pnindent720\pnhang{\pntxtb (}{\pntxta )}}{\*\pnseclvl7\pnlcrm\pnstart1\pnindent720\pnhang{\pntxtb (} +{\pntxta )}}{\*\pnseclvl8\pnlcltr\pnstart1\pnindent720\pnhang{\pntxtb (}{\pntxta )}}{\*\pnseclvl9\pnlcrm\pnstart1\pnindent720\pnhang{\pntxtb (}{\pntxta )}}\pard\plain \s1\ql \li120\ri0\sb280\sa120\sl-320\slmult0 +\nowidctlpar\faauto\outlinelevel0\adjustright\rin0\lin120\itap0 \b\f5\fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\fs20\super +{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super +}{\f1 main}}${\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super $}{\f1 Contents}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 Contents}}K{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Contents}}}{\i\f1\fs32 WinBoard}{\f1\fs32 : Chessboard for Windows +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Description}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 Description}}}{\f1 Description +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\i\f1 WinBoard}{\f1 + is a graphical user interface for chess. It displays a chessboard on the screen, accepts moves made with the mouse, and loads and saves game files in standard chess notation. WinBoard serves as a front-end for many different services, including: +\par {\pntext\pard\plain\f3\fs20 \loch\af3\dbch\af0\hich\f3 \'b7\tab}}\pard\plain \ql \fi-360\li480\ri0\sb80\sl-240\slmult0\nowidctlpar\jclisttab\tx480{\*\pn \pnlvlblt\ilvl0\ls3\pnrnot0\pnf3\pnstart1\pnindent360\pnsp120\pnhang{\pntxtb \'b7}} +\faauto\ls3\adjustright\rin0\lin480\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\b\i\f1 Chess engines}{\f1 + that run on your PC. You can play a game against an engine, set up arbitrary positions, force variations, or watch a game between two engines. }{\i\f1 GNU Chess}{\f1 is supplied with WinBoard, and over 10 +0 other free chess engines are available separately. Of these, Crafty is the most popular. See }{\f1\uldb Installing Chess Engines}{\v\f1 InstallingChessEngines}{\f1 for instructions on installing additional chess engines. +\par {\pntext\pard\plain\f3\fs20 \loch\af3\dbch\af0\hich\f3 \'b7\tab}}\pard \ql \fi-360\li480\ri0\sb80\sl-240\slmult0\nowidctlpar\jclisttab\tx480{\*\pn \pnlvlblt\ilvl0\ls3\pnrnot0\pnf3\pnstart1\pnindent360\pnsp120\pnhang{\pntxtb \'b7}} +\faauto\ls3\adjustright\rin0\lin480\itap0 {\b\i\f1 Chess servers}{\b\f1 }{\f1 on the Internet. You can play against other + Internet Chess Server (ICS) users, observe games they are playing, review games in the ICS libraries, chat, and more. WinBoard can also be used to run an automated computer player on the ICS, but this feature is for advanced users only and is subject to +some caveats; see the separate file zippy.README for information. +\par {\pntext\pard\plain\f3\fs20 \loch\af3\dbch\af0\hich\f3 \'b7\tab}}\pard \ql \fi-360\li480\ri0\sb80\sl-240\slmult0\nowidctlpar\jclisttab\tx480{\*\pn \pnlvlblt\ilvl0\ls3\pnrnot0\pnf3\pnstart1\pnindent360\pnsp120\pnhang{\pntxtb \'b7}} +\faauto\ls3\adjustright\rin0\lin480\itap0 {\b\i\f1 The Web}{\f1 and your own saved games. You can use WinBoard as a helper application to view files in your Web browser or the Explorer. You can use it to keep track of email postal games, browse ga +mes off the net, or review games you have saved. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\super K}{ Getting Started}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\super #}{ GettingStarted}}}{\f1 Getting Started +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 +WinBoard starts up in one of three major modes: chess engine mode, ICS client mode, or game viewer mode. You cannot change modes while WinBoard is running, but you can access all the game v +iewer features directly from the other two modes. Also, you can start WinBoard several times to get multiple chessboard windows running in any combination of modes. +\par }\pard\plain \s20\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {You will usually run WinBoard by choosing an item from the Windows Start menu that runs it +in the mode you want. If you just double-click on WinBoard.exe, you get a startup dialog asking which mode you want. If you choose chess engine mode, you can then select from the installed engines; if you choose ICS client mode, you can then select from a + list of known chess servers. More advanced users can }{\uldb customize}{\v icsNames}{ these lists or type in WinBoard }{\uldb command line options}{\v Options}{ directly. +\par }\pard\plain \ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 After starting WinBoard, you can make }{\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 move}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 move}}}{\f1 moves in several different ways. To move by dragging, press the left mouse +button while the cursor is on one of your pieces, move the cursor to another square, and release the button. You can also move by clicking the left mouse button once (press and release) over one of your pieces, moving the cursor to another square, and cli +c +king again. You drop new pieces on the board (when applicable) by selecting from a context menu. Press the right mouse button over a square to bring up the menu; no menu will come up in modes where dropping a new piece is not permitted. You can also make +moves by typing them in standard algebraic chess notation. Either a dialog box will pop up for you to type into, or in ICS mode, your typing will be redirected into the ICS interaction window. +\par When WinBoard}{\i\f1 }{\f1 is iconized, its }{\cs58\f1\super K{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 { +\cs58\f1\super K}{\f1 icon}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 icon}}}{\f1 +icon is a white knight if it is White's turn to move, a black knight if it is Black's turn. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Additional Information +\par }\pard\plain \s29\ql \fi-240\li360\ri0\sb60\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin360\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1\uldb Menus}{\v\f1\uldb Menus}{\f1\uldb +\par Shortcut Buttons}{\v\f1\uldb Buttons}{\f1\uldb +\par Command Line Options}{\v\f1 Options}{\f1 +\par }{\f1\uldb Initialization Files}{\v\f1\uldb Files}{\f1\uldb +\par Installing Chess Engines}{\v\f1\uldb InstallingChessEngines}{\f1\uldb +\par Firewalls}{\v\f1 Firewalls}{\f1 +\par }{\f1\uldb Limitations}{\v\f1 Limitations}{\f1\uldb +\par Authors}{\v\f1 Authors}{\f1 +\par }{\f1\uldb Copyright}{\v\f1 Copyright}{\f1 +\par }{\f1\uldb Frequently Asked Questions}{\v\f1 !ExecFile(FAQ.html)}{\f1 +\par }\pard\plain \s1\ql \li120\ri0\sb280\sa120\sl-320\slmult0\nowidctlpar\faauto\outlinelevel0\adjustright\rin0\lin120\itap0 \b\f5\fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1\fs20 \page }{\cs58\f1\fs20\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Menus}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 Menus}}${\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super $}{\f1 Menus}}+{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super +}{\f1 main}}}{\f1\fs20 MENUS +\par }\pard\plain \s29\ql \fi-240\li360\ri0\sb60\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin360\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1\uldb File Menu}{\v\f1 FileMenu}{\f1 +\par }{\f1\uldb Mode Menu}{\v\f1 ModeMenu}{\f1 +\par }{\f1\uldb Action Menu}{\v\f1 ActionMenu}{\f1 +\par }{\f1\uldb Step Menu}{\v\f1 StepMenu}{\f1 +\par }{\f1\uldb Options Menu}{\v\f1 OptionsMenu}{\f1 +\par }{\f1\uldb Help Menu}{\v\f1 HelpMenu}{\f1 +\par }{\f1\uldb ICS Interaction Context Menu}{\v\f1 ICSInteractionContextMenu}{\f1 +\par }\pard\plain \s1\ql \li120\ri0\sb280\sa120\sl-320\slmult0\nowidctlpar\faauto\outlinelevel0\adjustright\rin0\lin120\itap0 \b\f5\fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1\fs20 \page }{\cs58\f1\fs20\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 File Menu}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 FileMenu}}${\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super $}{\f1 File Menu}}+{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super +}{\f1 main}}}{\f1\fs18\up6 }{\f1\fs20 File Menu +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Reset}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 Reset}}}{\f1 Reset +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 +Resets WinBoard and the chess engine (if any) to the beginning of a new chess game. In Internet Chess Server mode, clears the current state of WinBoard, then resynchronizes with ICS by sending a }{\b\f1 refresh }{\f1 command. If you + want to stop playing, observing, or examining a game on ICS, use an appropriate command from the }{\f1\uldb Action}{\v\f1 ActionMenu}{\f1 menu, not Reset. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Load Game}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 LoadGame}}}{\f1 Load Game +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 +Plays a game from a record file. A popup dialog prompts you for the filename. If the file contains more than on +e game, a second popup dialog displays a list of games (with information drawn from their PGN tags, if any), and you can select the one you want. +\par }\pard\plain \ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 +The game file parser will accept PGN (portable game notation), or in fact almost any file that contains moves in algebraic notation. Notation of the form }{\i\f1 P@f7}{\f1 + is accepted for piece-drops in bughouse games; this is a nonstandard extension to PGN. If the file includes a PGN position (FEN tag), or a WinBoard position diagram bracketed by "[--" and "--]" before the fi +rst move, the game starts from that position. Text enclosed in parentheses, square brackets, or curly braces is assumed to be commentary and is displayed in a pop-up window. Any other text in the file is ignored. PGN variations (enclosed in parentheses) a +re treated as comments; WinBoard is not able to walk variation trees. The nonstandard PGN tag }{\f2 [Variant "varname"]}{\f1 functions similarly to the }{\f1\uldb variant}{\v\f1 variant }{\f1 +command-line option, allowing games in certain chess variants to be loaded. There is also a heuristic to recognize chess variants from the }{\f2 Event}{\f1 + tag, by looking for the strings that the Internet Chess Servers put there when saving variant ("wild") games. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Load Next Game}}#{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 LoadNextGame}}}{\f1 Load Next Game +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Loads the next game from the last game record file you loaded. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Load Previous Game}}#{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 LoadPreviousGame}}}{\f1 Load Previous Game +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 +Loads the previous game from the last game record file you loaded. Not available if the last game was loaded from a pipe. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Reload Same Game}}#{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 ReloadSameGame}}}{\f1 Reload Same Game +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Reloads the last game you loaded. Not available if the last game was loaded from a pipe. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Save Game}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 SaveGame}}}{\f1 Save Game +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Appends a r +ecord of the current game to a file. A popup dialog prompts you for the filename. If the game did not begin with the standard starting position, the game file includes the starting position used. Game files are saved in the PGN (portable game notation) fo +rmat, unless the }{\f1\uldb oldSaveStyle}{\v\f1 oldSaveStyle}{\f1 option is True, in which case they are saved in an older format that is specific to WinBoard}{\i\f1 .}{\f1 + Both formats are human-readable, and both can be read back by the Load Game command. Notation of the form }{\i\f1 P@f7}{\f1 is generated for piece-drops in bughouse games; this is a nonstandard extension to PGN. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Copy Game To Clipboard}}#{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 CopyGameToClipboard}}}{\f1 Copy Game To Clipboard +\par }\pard\plain \ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 { +Copies the record of the current game to the Windows clipboard in PGN (portable game notation) format. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Paste Game From Clipboard}}#{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 PasteGameFromClipboard}}}{\f1 Paste Game From Clipboard +\par }\pard\plain \ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {Plays a game from the Windows clipboard.}{\f1 See }{\f1\uldb Load Game}{\v\f1 LoadGame}{\f1 + for a discussion of game file format and parser behavior.}{ +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Load Position}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 LoadPosition}}}{\f1 Load Position +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 +Sets up a position from a position file. A popup dialog prompts you for the filename. Position files must be in FEN (Forsythe-Edwards notation), or in the format that the }{\f1\uldb Save Position}{\f1 command writes when }{\f1\uldb oldSaveStyle}{\v\f1 +oldSaveStyle}{\f1 is turned on. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Load Next Position}}#{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 LoadNextPosition}}}{\f1 Load Next Position +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Loads the next position from the last position file you loaded. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Load Previous Position}}#{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 LoadPreviousPosition}}}{\f1 Load Previous Position +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Loads the previous position from the l +ast position file you loaded. Not available if the last position was loaded from a pipe. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Reload Same Position}}#{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 ReloadSamePosition}}}{\f1 Reload Same Position +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 +Reloads the last position you loaded. Not available if the last position was loaded from a pipe. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Save Position}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 SavePosition}}}{\f1 Save Position +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Appends a diagram of the curr +ent position to a file. A popup dialog prompts you for the filename. Positions are saved in FEN (Forsythe-Edwards notation) format, unless the }{\f1\uldb oldSaveStyle}{\v\f1 oldSaveStyle}{\f1 + option is True, in which case they are saved in an older, human-readable format that is specific to WinBoard}{\i\f1 .}{\f1 + Both formats can be read back by the Load Position command; however, currently Load Position can load only the first position in a file. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Copy Position Clipboard}}#{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 CopyPositionToClipboard}}}{\f1 Copy Position To Clipboard +\par }\pard\plain \ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Places a diagram of the current position (in Forsythe-Edwards notat +ion) into the Windows clipboard. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Paste Position Clipboard}}#{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 PastePositionFromClipboard}}}{\f1 Paste Position From Clipboard +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 +Sets up a position from the Windows clipboard. Position must be in FEN (Forsythe-Edwards notation). Puts WinBoard into }{\f1\uldb Edit Game}{\v\f1 EditGame}{\f1 mode if it was not there already. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Exit}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 Exit}}}{\f1 Exit +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Exits from WinBoard. +\par }\pard\plain \s1\ql \li120\ri0\sb280\sa120\sl-320\slmult0\nowidctlpar\faauto\outlinelevel0\adjustright\rin0\lin120\itap0 \b\f5\fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1\fs20 \page }{\cs58\f1\fs20\super K{\footnote\ftnalt \pard\plain +\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Mode Menu}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 ModeMenu}}${\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super $}{\f1 Mode Menu}}+{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super +}{\f1 main}}}{\f1\fs20 Mode Menu +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Machine White}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 MachineWhite}}}{\f1 Machine White +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Forces the chess engine to play white. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Machine Black}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 MachineBlack}}}{\f1 Machine Black +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Forces the chess engine to play black. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Two Machines}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 TwoMachines}}}{\f1 Two Machines +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Starts a game between two chess engines. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Analysis Mode}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 AnalysisMode}}}{\f1 Analysis Mode +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 In this mode, you can make moves for both si +des on the board. After each move, the chess engine will think about possible replies and display its analysis in a separate window. This feature currently works only if Crafty is the chess engine. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Analyze File}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 AnalyzeFile}}}{\f1 Analyze File +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 In this mode, you can load a game from a f +ile, and the chess engine will analyze each move as in Analysis Mode. This feature currently works only if Crafty is the chess engine. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 ICS Client}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 ICSClient}}}{\f1 ICS Client +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 +This is the normal mode when WinBoard is connected to a chess server. If you have moved into Edit Game or Edit Position mode, you can select this option to get out. +\par }\pard\plain \ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 +When you run WinBoard in ICS mode, it starts up a console window in which you can type commands and receive text responses from the chess server. You can use the standard Windows editing keys to edi +t your command line before pressing Enter. The console window keeps a history of the last few commands you typed. Press the up-arrow key to go back to a previous command; press the down-arrow key to go forward again to a later command. Press the right mou +se button in the output area for a }{\f1\uldb context menu}{\v\f1 ICSInteractionContextMenu}{\f1 of editing commands and ICS command shortcuts. +\par Some useful ICS commands include }{\b\f1 who}{\f1 to see who is logged on, }{\b\f1 games}{\f1 to see what games are being played, }{\b\f1 match}{\f1 to challenge another player to a game, }{\b\f1 observe}{\f1 to observe an ongoing game, }{\b\f1 +examine}{\f1 or }{\b\f1 smoves}{\f1 to review a recently completed game, and of course }{\b\f1 help}{\f1 . +\par Whenever you ask to observe an ongoing game, review a completed game, or resume an adjourned game, WinBoard retrieves and parses the list of past moves from the ICS, so you can review them with }{\f1\uldb Forward}{\v\f1 Forward}{\f1 and }{\f1\uldb +Backward}{\v\f1 Backward}{\f1 or save them with }{\f1\uldb Save Game}{\v\f1 SaveGame}{\f1 . +\par Some special ICS Client features are activated when you are in }{\b\f1 examine}{\f1 or }{\b\f1 bsetup }{\f1 mode on ICS. See the descriptions of the menu commands }{\f1\uldb Forward}{\v\f1 Forward}{\f1 , }{\f1\uldb Backward}{\v\f1 Backward}{\f1 , }{ +\f1\uldb Pause}{\v\f1 Pause}{\f1 , and }{\f1\uldb Stop Examining}{\v\f1 StopExamining}{\f1 below. You can also issue the ICS position-editing commands with the mouse. Move pieces by dragging with the left mouse button, or by left-clicking once on the sta +rting square and once on the ending square. Press the right mouse button over a square for a context menu that lets you drop a new piece, empty the square, or clear the board. Click on the White or Black clock to set the side to play. You cannot set the s +i +de to play or drag pieces to arbitrary squares while examining on ICC, but you can do so in bsetup mode on FICS. You can also make moves by typing them into the ICS window; you may have to do this occasionally if you are playing a chess variant whose rule +s WinBoard does not understand, such as Fischer Random. +\par If you are playing a bughouse game on the ICS, a list of the offboard pieces that each player holds is shown in the window title bar. To drop an offboard piece, press the right mouse button over an emp +ty square to bring up a context menu. To observe your partner's games, start a second copy of WinBoard, log in as a guest, and use the ICS }{\b\f1 follow}{\f1 or }{\b\f1 pfollow}{\f1 command in the new window. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Edit Game}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 EditGame}}}{\f1 Edit Game +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Allows you to make moves for both Black and White, and to c +hange moves after backing up with the }{\f1\uldb Backward}{\v\f1 Backward}{\f1 command. The clocks do not run. +\par }\pard\plain \ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 +In chess engine mode, the chess engine continues to check moves for legality but does not participate in the game. You can bring the chess engine back into the game by selecting }{\f1\uldb Machine White}{\v\f1 MachineWhite}{\f1 , }{\f1\uldb Machine Black} +{\v\f1 MachineBlack}{\f1 , or }{\f1\uldb Two Machines}{\v\f1 TwoMachines}{\f1 . +\par In ICS mode, the moves are not sent to the ICS: Edit Game takes WinBoard out of ICS Client mode and lets you edit games locally. If you want to edit a game on ICS in a way that other ICS users can see, use the ICS }{\b\f1 examine}{\f1 + command or start an ICS match against yourself. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Edit Position}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 EditPosition}}}{\f1 Edit Position +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 +Lets you set up an arbitrary board position. Use the left mouse button to drag pieces to new squares, or to delete a piece by dragging + it off the board or dragging an empty square on top of it. To drop a new piece on a square, press the right mouse button over the square. This brings up a menu of pieces. Additional menu choices let you empty the square or clear the board. You can set th +e side to play next by clicking on the White or Black indicator at the top of the screen. +\par }\pard\plain \ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Selecting Edit Position causes WinBoard}{\i\f1 }{\f1 +to discard all remembered moves in the current game. +\par In ICS mode, change made to the position by Edit Position are not sent to +the ICS: Edit Position takes WinBoard out of ICS Client mode and lets you edit positions locally. If you want to edit positions on ICS in a way that other ICS users can see, use the ICS }{\b\f1 examine}{\f1 + command, or start an ICS match against yourself. (See also }{\f1\uldb ICS Client}{\v\f1 ICSClient}{\f1 above.) +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Training}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 Training}}}{\f1 Training +\par }\pard\plain \ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 { +Training mode lets you interactively guess the moves of a game for one of the players. While in Training mode, the navigation buttons are disabled. You guess the next move of the game by playing the move on the board (or using the }{\uldb Type In Move}{ +\v\uldb TypeInMove}{ command). If the move played matches the next move of the game, the move is accepted and the opponent\rquote s response is autoplayed. If the move played is incorrect, an error message is displayed. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Show Game List}}#{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 ShowGameList}}}{\f1 Show Game List +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Shows or hides the list of games generated by the last }{\f1\uldb Load Game}{\v\f1 LoadGame}{ +\f1 command. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Edit Tags}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 EditTags}}}{\f1 Edit Tags +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 +Lets you edit the PGN (portable game notation) tags for the current game. After editing, the tags must still conform to the PGN tag syntax: +\par }\pard\plain \s43\ql \li520\ri0\sa60\keep\nowidctlpar\tx520\tx920\tx1320\tx1720\tx2120\faauto\adjustright\rin0\lin520\itap0 \f6\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f2 \line ::= \line + \line ::= [ ]\line ::= \line ::= +\par }\pard\plain \s20\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 See the PGN Standard for full details. Here is an example: +\par }\pard\plain \s43\ql \li520\ri0\sa60\keep\nowidctlpar\tx520\tx920\tx1320\tx1720\tx2120\faauto\adjustright\rin0\lin520\itap0 \f6\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f2 \line [Event "Portoroz Interzonal"]\line [Site "Portoroz, Yugosl +avia"]\line [Date "1958.08.16"]\line [Round "8"]\line [White "Robert J. Fischer"]\line [Black "Bent Larsen"]\line [Result "1-0"] +\par }\pard\plain \ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 +Any characters that do not match this syntax are silently ignored. Note that the PGN standard requires all games to have at least the seven tags shown above. Any that you omit will be filled in by WinBoard with }{\f2 "?"}{\f1 (unknown value) or }{\f2 "-" +}{\f1 (inapplicable value). +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Edit Comment}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 EditComment}}}{\f1 Edit Comment +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Adds or modifies a comment on the current position. Comments are saved by }{\f1\uldb Save Game} +{\v\f1 SaveGame}{\f1 and are displayed by }{\f1\uldb Load Game}{\v\f1 LoadGame}{\f1 , }{\f1\uldb Forward}{\v\f1 Forward}{\f1 , and }{\f1\uldb Backward}{\v\f1 Backward}{\f1 . +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Pause}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 Pause}}}{\f1 Pause +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 +Pauses updates to the board, and if you are playing against a local chess engine, also pauses your clock. To continue, select Pause again, and the display will automatically update to the latest position. The }{\b\f1 P}{\f1 (or }{\b\f1 C}{\f1 +) button is equivalent to selecting Pause. +\par }\pard\plain \ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 If you select Pause when you are playing{\*\bkmkstart WHATSelSavT}{\*\bkmkend WHATSelSavT} +{\*\bkmkstart fWHATtopic}against{\*\bkmkend fWHATtopic} a chess engine and it is not your move, the chess engine\rquote s clock will continue to run and it will eventually make a move, at which point both clocks will sto +p. Since board updates are paused, however, you will not see the move until you exit from Pause mode (or select }{\f1\uldb Forward}{\v\f1 Forward}{\f1 ). This behavior is meant to simulate adjournment with a sealed move. +\par If you select Pause while you are in }{\b\f1 examine}{\f1 mode on ICS, yo +u can step backward and forward in the current history of the examined game without affecting the other examiners or observers. Select Pause again to reconnect yourself to the current state of the game on ICS. +\par If you select Pause while you are loading a game, the game stops loading. You can load more moves one at a time by selecting }{\f1\uldb Forward}{\v\f1 Forward}{\f1 , or resume automatic loading by selecting Pause again. +\par }\pard\plain \s1\ql \li120\ri0\sb280\sa120\sl-320\slmult0\nowidctlpar\faauto\outlinelevel0\adjustright\rin0\lin120\itap0 \b\f5\fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1\fs20 \page }{\cs58\f1\fs20\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Action Menu}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 ActionMenu}}${\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super $}{\f1 Action Menu}}+{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super +}{\f1 main}}}{\f1\fs20 Action Menu +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Most of these commands are available in chess server mode only. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Accept}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 Accept}}}{\f1 Accept +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Accepts a pendi +ng match offer. If there is more than one offer pending, you will have to type in a more specific command instead of using this menu choice. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Decline}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 Decline}}}{\f1 Decline +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 +Declines a pending offer (match, draw, etc.). If there is more than one offer pending, you will have to type in a more specific command instead of using this menu choice. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Rematch}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 Rematch}}}{\f1 Rematch +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Issues the ICS }{\b\f1 rematch}{\f1 + command, which asks for another game against your last opponent with the same time control and rule set. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Call Flag}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 CallFlag}}}{\f1 Call Flag +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Calls your opponent's flag, claiming +a win on time, or claiming a draw if you are both out of time. You can also call your opponent's flag by clicking on his clock. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Draw}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 Draw}}}{\f1 Draw +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 +Offers a draw to your opponent, accepts a pending draw offer from your opponent, or claims a draw by repetition or the 50-move rule, as appropriate. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Adjourn}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 Adjourn}}}{\f1 Adjourn +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 +Asks your opponent to agree to adjourning the current game, or agrees to a pending adjournment offer from your opponent. You continue an adjourned ICS game by challenging the same player again with the ICS }{\b\f1 match}{\f1 command. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Abort}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 Abort}}}{\f1 Abort +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 +Asks your opponent to agree to abort the current game, or agrees to a pending abort offer from your opponent. An aborted ICS game ends immediately without affecting either player's rating. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Resign}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 Resign}}}{\f1 Resign +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Resigns the game to your opponent. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Stop Observing}}#{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 StopObserving}}}{\f1 Stop Observing +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Ends your participation in observing a game, by issuing the ICS }{\b\f1 unobserve}{\f1 + command. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Stop Examining}}#{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 StopExamining}}}{\f1 Stop Examining +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Ends your participation in examining a game, by issuing the ICS }{\b\f1 unexamine}{\f1 + command. +\par }\pard\plain \s1\ql \li120\ri0\sb280\sa120\sl-320\slmult0\nowidctlpar\faauto\outlinelevel0\adjustright\rin0\lin120\itap0 \b\f5\fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1\fs20 \page }{\cs58\f1\fs20\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Step Menu}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 StepMenu}}${\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super $}{\f1 Step Menu}}+{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super +}{\f1 main}}}{\f1\fs20 Step Menu +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Type In Move}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 TypeInMove}}}{\f1 Type In Move +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Pops up a dialog box, into whi +ch you can type moves in standard algebraic chess notation. (You can also get this dialog box by simply starting to type over the chessboard, except in ICS mode, where such typing is redirected into the ICS interaction window.) +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Backward}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 Backward}}}{\f1 Backward +\par }\pard\plain \ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Steps backward through a series of remembered moves. The }{\b\f1 <}{\f1 + button is equivalent to selecting Backward.In most modes, Backward only lets you look back at old positions; it does not retract moves. This is the case if you are playing against a chess engine, playing or observ +ing a game on the ICS, or loading a game. If you select Backward in any of these situations, you will not be allowed to make a different move. Use }{\f1\uldb Retract Move}{\v\f1 RetractMove}{\f1 or }{\f1\uldb Edit Game}{\v\f1 EditGame}{\f1 + if you want to change past moves. +\par If you are examining a game on the ICS, the behavior of Backward depends on whether WinBoard}{\i\f1 }{\f1 is in }{\f1\uldb Pause}{\v\f1 Pause}{\f1 mode. If Pause mode is off, Backward issues the ICS command}{\b\f1 backward}{\f1 +, which backs up everyone's view of the game and allows you to make a different move. If Pause mode is on, Backward only backs up your local view. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Forward}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 Forward}}}{\f1 Forward +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Steps forward through a series of remembered moves (undoing the effect of }{\f1\uldb Backward}{ +\v\f1\uldb Backward}{\f1 ) or through a game file. The }{\b\f1 >}{\f1 button is equivalent. +\par }\pard\plain \ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 If you are examining a game on the ICS, the behavior of Forward depends on whether WinBoard}{ +\i\f1 }{\f1 is in }{\f1\uldb Pause}{\v\f1 Pause}{\f1 mode. If Pause mode is off, Forward issues the ICS command}{\b\f1 forward}{\f1 +, which moves everyone's view of the game forward along the current line. If Pause mode is on, Forward only moves your local view forward, and it will not go past the position the game was in when you paused. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Back to Start}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 BacktoStart}}}{\f1 Back to Start +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Jumps backward to the first remembered position in the game. The }{\b\f1 << }{\f1 +button is equivalent. +\par }\pard\plain \ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 In most modes, Back to Start only lets you look back at old positions; it does not +retract moves. This is the case if you are playing against a chess engine, playing or observing a game on the ICS, or loading a game. If you select Back to Start in any of these situations, you will not be allowed to make a different move. Use }{\f1\uldb +Retract Move}{\v\f1 RetractMove}{\f1 or }{\f1\uldb Edit Game}{\v\f1 EditGame}{\f1 if you want to change past moves; or use }{\f1\uldb Reset}{\v\f1 Reset}{\f1 to start a new game. +\par If you are examining a game on the ICS, the behavior of Back to Start depends on whether WinBoard}{\i\f1 }{\f1 is in }{\f1\uldb Pause}{\v\f1 Pause}{\f1 mode. If Pause mode is off, Backward issues the ICS command }{\b\f1 backward 999999}{\f1 +, which backs up everyone's view of the game to the start and allows you to make different moves. If Pause mode is on, Back to Start only backs up your local view. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Forward to End}}#{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 ForwardtoEnd}}}{\f1 Forward to End +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Jumps forward to the last position in the game. The }{\b\f1 >>}{\f1 button is equivalent. + +\par }\pard\plain \ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 +If you are examining a game on the ICS, the behavior of Forward to End depends on whether WinBoard}{\i\f1 }{\f1 is in }{\f1\uldb Pause}{\v\f1 Pause}{\f1 mode. If Pause mode is off, Forward to End issues the ICS command }{\b\f1 forward 999999}{\f1 +, which moves everyone's view of the game forward to the end of the current line. If Pause mode is on, Forward to End only moves your local view forward, and it will not go past the position the game was in when you paused. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Revert}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 Revert}}}{\f1 Revert +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 If you are examining a game on the ICS, issues the ICS command }{\b\f1 revert}{\f1 . +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Truncate Game}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 TruncateGame}}}{\f1 Truncate Game +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Discards all remembered moves of the game beyond the current position. Puts WinBoard into }{ +\f1\uldb Edit Game}{\v\f1 EditGame}{\f1 mode if it was not there already. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Move Now}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 MoveNow}}}{\f1 Move Now +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Forces the chess engine to move immediately. May not work with all chess engines. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Retract Move}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 RetractMove}}}{\f1 Retract Move +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Retracts your last move. +\par }\pard\plain \ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 +In chess engine mode, you can do this only after the chess engine has replied to your move. If the chess engine is still thinking, use }{\f1\uldb Move Now}{\v\f1 MoveNow}{\f1 first. +\par In ICS mode, Retract Move issues the command }{\b\f1 takeback 1 }{\f1 or }{\b\f1 takeback 2}{\f1 , depending on whether it is your opponent's move or yours. +\par }\pard\plain \s1\ql \li120\ri0\sb280\sa120\sl-320\slmult0\nowidctlpar\faauto\outlinelevel0\adjustright\rin0\lin120\itap0 \b\f5\fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1\fs20 \page }{\cs58\f1\fs20\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Options Menu}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 OptionsMenu}}${\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super $}{\f1 Options Menu}}+{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super +}{\f1 main}}}{\f1\fs20 Options Menu +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Flip View}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 FlipView}}}{\f1 }{\f1\ul Flip View}{\f1 +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Inverts your view of the chessboard. +\par }\pard\plain \ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 If you are playing a game on the ICS, the board is always oriented at the start of the + game so that your pawns move from the bottom of the window towards the top. Otherwise, the starting position is determined by the }{\f1\uldb flipView}{\v\f1 flipViewOption}{\f1 command line option. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\ul\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\super K}{ General Options}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\super #}{ GeneralOptions}}}{\f1\ul General}{\f1 +\par }{\cs58\f1\super K{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Always On Top}}#{\footnote\ftnalt +\pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 AlwaysOnTop}}}{\f1 Always On Top +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 If this option is on, WinBoard sets its chessboard to be a }{\i\f1 topmost}{\f1 + window, meaning that it always appears on top of all ordinary windows on the screen. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Always Queen}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 AlwaysQueen}}}{\f1 Always Queen +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 +If Always Queen is off, WinBoard brings up a dialog box whenever you move a pawn to the last rank, asking what piece you want to promote it to. If the option is on, your pawns are always promoted to queens. Your opponent can still underpromote, however. + +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Animate Dragging}}#{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 AnimateDragging}}}{\f1 Animate Dragging +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 +If Animate Dragging is on while you are dragging a piece with the mouse, an image of the piece follows the mouse cursor. If Animate Dragging is off, there is no visual feedback while you are +\par dragging a piece, but if Animate Moving is on, the move will be animated when it is complete. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Animate Moving}}#{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 AnimateMoving}}}{\f1 Animate Moving +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 If Animate Moving is on, all piece moves are animated. An image of the piece + is shown moving from the old square to the new square when the move is completed (unless the move was already animated by Animate Dragging). If Animate Moving is off, a moved piece instantly disappears from its old square and reappears on its new square +when the move is complete. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Auto Flag}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 AutoflagCmd}}}{\f1 Auto Flag +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 +If this option is on and one player runs out of time before the other, WinBoard will automatically call his flag, claiming a win on time. In ICS mode, Auto Flag will only call your opponent's flag, not yours, and the +ICS may award you a draw instead of a win if you have insufficient mating material. On most chess servers, you can now do}{\b\f1 set autoflag 1 }{\f1 +instead and have the server call the flag. In local chess engine mode, WinBoard may call either player's flag and will not take material into account. +\par }\pard\plain \ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\b\super K{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\super K}{ Auto Flip View}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\super #}{ AutoFlipView}}}{\b Auto Flip View +\par }{If this option is on when you}{\f1 start a game, the board will be automatically oriented so that your pawns move from the bottom of the window towards the top.}{ +\par }{\cs58\b\super K{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\super K}{ Auto Raise Board}}#{\footnote\ftnalt +\pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\super #}{ AutoRaiseBoard}}}{\b Auto Raise Board +\par }{If this}{\v autoFlipViewOption}{ option is on, whenever a new game begins, the chessboard window will be deiconized (if necessary) and raised to the top of the stack of windows on your screen. +\par }\pard\plain \s2\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\super K}{ Blindfold}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\super #}{ BlindfoldCmd}}}{Blindfold +\par }\pard\plain \ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {If Blindfold is on, WinBoard displays a blank board. Moves can still be entered with the + mouse, either by dragging the (invisible) piece or clicking the starting and ending square. You can also enter your move by typing it on the keyboard}{\f1 .}{ +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Highlight Dragging}}#{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 HighlightDragging}}}{\f1 Highlight Dragging +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 If Highlight Dragging is on while you are dragging a piece with the mouse, the sta +rting square and the square that the mouse cursor is over are highlighted. This option works even if Animate Dragging is off. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Highlight Last Move}}#{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 HighlightLastMove}}}{\f1 Highlight Last Move +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 +If Highlight Last Move is on, after a move is made, the starting and ending squares remain highlighted. In addition, after you use }{\f1\uldb Backward}{\v\f1 Backward}{\f1 or }{\f1\uldb Back to Start}{\v\f1 BackToStart}{\f1 +, the starting and ending squares of the last move to be }{\i\f1 unmade}{\f1 are highlighted. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Periodic Updates}}#{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 PeriodicUpdatesCmd}}}{\f1 Periodic Updates +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 If Periodic Updates is on, the Analysis window is updated every two seconds. If not, it + is updated only when the best move found changes. The Analysis window currently works only with Crafty, and Periodic Updates may not work with all versions of Crafty. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\nowidctlpar\faauto\pnrdate0\pnrnot1\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\revised\super\revauth1\revdttm-1506646559 K}{ +\f1\revised\revauth1\revdttm-1506646559 Ponder Next Move}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\nowidctlpar\faauto\pnrdate0\pnrnot1\adjustright\rin0\lin120\itap0 +\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\revised\super\revauth1\revdttm-1506646559 #}{\f1\revised\revauth1\revdttm-1506646559 PonderNextMoveCmd}}}{\f1 Ponder Next Move +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 If this option is off, the chess engine will think only when it is o +n move. If the option is on, the engine will also think while waiting for you to make your move. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Popup Exit Message}}#{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 PopupExitMessageCmd}}}{\f1 Popup Exit Message +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 +If this option is on, when WinBoard wants to display a message just before exiting, it brings up a modal dialog box and waits for you to click OK before exiting. If the option is off, WinBoard prints exits immediately without showing the message. If }{ +\f1\uldb debugMode}{\v\f1 debugMode}{\f1 is on, however, the message will appear in the debug log. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Popup Move Errors}}#{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 PopupMoveErrorsCmd}}}{\f1 Popup Move Errors +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 If this option is off, when you make an error + in moving (such as attempting an illegal move or moving the wrong color piece), the error message is displayed in the message area. If the option is on, move errors are displayed in small popup windows like other errors. You can dismiss an error popup ei +ther by clicking its OK button or by clicking anywhere on the board, including downclicking to start a move. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Show Button Bar}}#{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 ShowButtonBarCmd}}}{\f1 Show Button Bar +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 If Show Button Bar is on, WinBoard displays on-screen }{\f1\uldb buttons}{\v\f1 BUTTONS}{\f1 + to step forward, backward, or pause the game. If it is off, the buttons are hidden, making the message line wider. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Show Coords}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 ShowCoordsCmd}}}{\f1 Show Coords +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 If Sh +ow Coords is on, WinBoard displays algebraic coordinates along the board's left and bottom edges. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Show Thinking}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 ShowThinkingCmd}}}{\f1 Show Thinking +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 If this option is set, WinBoard displays the chess engine\rquote +s current search depth and its notion of the score and best line of play from the +current position as it is thinking. The score indicates how many pawns ahead (or if negative, behind) the engine thinks it is. In matches between two machines, the score is prefixed by W or B to indicate whether it is showing White's thinking or Black's. + +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Test Legality}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 TestLegalityCmd}}}{\f1 Test Legality +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 +If Test Legality is on, WinBoard tests whether the moves you enter with the mouse or read from game files are legal, and displays an error if they are not. Turn this option off if you are playing a chess variant that WinBoard does not under +stand. (Bughouse, suicide, and wild variants where the king may castle after starting on the }{\b\f1 d}{\f1 file are generally supported with Test Legality on.) +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\ul\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\super K}{ Board Options}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\super #}{ BoardOptions}}}{\f1\ul Board +\par }{\cs58\f1\super K{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Board Size}}#{\footnote\ftnalt +\pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 BoardSizeCmd}}}{\f1 Board Size +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Determines how large the board will be and what fonts and piece bitmaps will be used. +On a Titanic board the piece bitmaps are 129x129 pixels, on Colossal 116x116, Giant 108x108, Huge 95x95, Big 87x87, Large 80x80, Bulky 72x72, Medium 64x64, Moderate 58x58, Average 54x54, Middling 49x49, Mediocre 45x45, Small 40x40, Slim 37x37, Petite 33x3 +3, Dinky 29x29, Teeny 25x25, and Tiny 21x21. The smaller boards have no system menu, but you can minimize or close them from the File menu. +\par }\pard\plain \ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 +You can also change the board size by dragging the window edges or corners with the mouse. The board will snap to the largest size that fits into the area you outline. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Board Colors}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 BoardColors}}}{\f1 Board Colors +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Lets you change the colors WinBoard is using to draw the board and pieces. +\par }\pard\plain \s5\ql \li120\ri0\sb80\sl-240\slmult0\keepn\nowidctlpar\faauto\outlinelevel4\adjustright\rin0\lin120\itap0 \f5\fs20\ul\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\b +\par }{\cs58\b\super K{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\super K}{ ICS Options}}#{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\super #}{ ICSOptions}}}{\b ICS +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Auto Comment}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 AutoCommentCmd}}}{\f1 Auto Comment +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 If Auto Comment is on, any remarks made on ICS while you are observing or playing a game ar +e recorded as a comment on the current move. This includes remarks made with the ICS commands }{\b\f1 say, tell, whisper, }{\f1 and }{\b\f1 kibitz}{\f1 . Limitation: remarks that you type yourself are not +\par recognized; WinBoard scans only the output from ICS, not the input you type to it. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Auto Observe}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 AutobsCmd}}}{\f1 Auto Observe +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 If Auto Observe is on and you add a player to your }{\b\f1 gnotify}{\f1 + list on ICS, WinBoard will automatically observe all of that player's games, unless you are doing something else (such as observing or playing a game of your own) when one starts. On most chess servers, you can now do }{\b\f1 follow }{\b\i\f1 player}{ +\f1 instead, and the server will automatically observe all of }{\b\i\f1 player\rquote s}{\f1 games. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Get Move List}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 GetMoveListCmd}}}{\f1 Get Move List +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 If Get Move List is on, whenever WinBoard}{\i\f1 }{\f1 +receives the first board of a new ICS game (or a different ICS game + from the one it is currently displaying), it retrieves the list of past moves from the server. You can then review the moves with the Forward and Backward commands or save them with Save Game. You might want to turn off this option if you are observing s +everal blitz games at once, to keep from wasting time and network bandwidth fetching the move lists over and over. If you turn this option on while a game is in progress, WinBoard}{\i\f1 }{\f1 immediately fetches the current move list. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Local Line Editing}}#{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 LocalLineEditing}}}{\f1 Local Line Editing +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 If Local Line Editing is }{\b\f1 on}{\f1 +, your machine handles echoing, backspacing, etc., for the characters that you type into the ICS Interaction window. Output is forwarded to the ICS only when you hit Enter.The Enter key produces a newline character, also known as Ctrl+J, \\n, + LF, linefeed, or decimal ASCII code 10. In this mode you can force a control character into the edit buffer by preceding it with Ctrl+Q (\'93quote\'94 +); however, the edit buffer will not accept certain control characters even when they are quoted in this way. You can force a control character to be sent immediately to ICS, bypassing the edit buffer, by preceding it with Ctrl+S (\'93send\'94). +\par }\pard\plain \ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 +WinBoard keeps a history of lines you recently typed in Local Line Editing mode. You can bring back old lines by pressing the cursor up key in the text entry box. Press the cursor down key to go back down to newer lines. +\par If Local Line Editing is }{\b\f1 off}{\f1 , all characters are sent to ICS as you type them. The Enter key produces a carriage return character, also known as Ctrl+M, \\r, CR, o +r decimal ASCII code 13. Use Ctrl+Backspace if you need the ASCII DEL character. You can enter any character code by holding down the Alt key and typing its decimal value (always beginning with 0) on the numeric keypad; this is a little-known standard fea +ture of Windows. +\par In both modes, if WinBoard}{\i\f1 \rquote s }{\f1 internal telnet protocol implementation is active, it translates all \\n characters to the standard telnet end-of-line sequence \\r\\n just before sending them out to ICS; see }{\f1\uldb telnetProgram}{ +\v\f1 telnetProgram}{\f1 . +\par It is generally not a good idea to turn off this option while connected to ICS. If you are tempted to do so because everything you type is being echoed an extra time, see the paragraph about extra echoes under }{\f1\uldb LIMITATIONS}{\v\f1 LIMITATIONS}{ +\f1 below. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Quiet Play}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 QuietPlayCmd}}}{\f1 Quiet Play +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 If Quiet Play is on, WinBoard will automatically issue an ICS }{\b\f1 set shout 0}{\f1 + command whenever you start a game and a }{\b\f1 set shout 1}{\f1 command whenever you finish one. Thus you will not be distracted by shouts from other ICS users while playing. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Premove}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 PremoveCmd}}}{\f1 Premove +\par }\pard\plain \ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {Premove allows you to play a move on the board before you have received your opponent\rquote +s move. This move is highlighted on the board using the }{\uldb Premove Highlight}{\v\uldb premoveHighlightColor}{ color, and is sent to the ICS as soon as your opponent\rquote s move is received. To cancel a premove +, either click twice on the piece that was premoved or premove an illegal move. +\par This group of controls allows you to set the following options: }{\uldb premove}{\v premove}{, }{\uldb premoveWhite}{\v premoveWhite}{, }{\uldb premoveWhiteText}{\v premoveWhiteText}{, }{\uldb premoveBlack}{\v premoveBlack}{, }{\uldb premoveBlackText}{\v +premoveBlackText}{. +\par }\pard\plain \s2\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\super K}{ ICS Alarm}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\super #}{ ICSAlarm}}}{ICS Alarm +\par }\pard\plain \ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {When }{\b icsAlarm}{ is set to True, the }{\uldb alarm sound}{\v soundIcsAlarm}{ + is played when your clock counts down to }{\uldb icsAlarmTime}{\v icsAlarmTime}{ seconds. For ICS games with time controls that include an increment, the alarm will sound each time the clock counts down to the }{\uldb icsAlarmTime}{\v icsAlarmTime}{. + +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 ICS Interaction Colors}}#{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 ICSInteractionColors}}}{\f1 ICS Interaction Colors +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 +Lets you change the colors and type styles that WinBoard uses to distinguish between different types of messages in the ICS Interaction window. The types distinguished a +re: shout, sshout, channel 1 tell, other channel tell, kibitz (or whisper), personal tell (or new message notification), challenge, request (including abort, adjourn, draw, pause, and takeback), seek, and normal (all other messages). +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Fonts}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 Fonts}}}{\f1 }{\f1\ul Fonts}{\f1 +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Lets you chan +ge the fonts WinBoard is using. The clock font, message font and coordinates font are specific to each board size. The tags font, comments font and ICS Interaction font are not dependent on the current size of the board. The \'93Revert to Defaults\'94 + button will reset the clock font, message font and coordinates font for the current board size, and will set the tags font, message font and Ics Interaction font for all board sizes. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Sounds}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 Sounds}}}{\f1 }{\f1\ul Sounds}{\f1 +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Lets you change the sounds that WinBoard plays for various events. +\par }\pard\plain \ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Move Sound}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 MoveSound}}}{\f1 I +f the Move sound is on, WinBoard alerts you by playing a sound after each of your opponent's moves (or after every move if you are observing a game on the Internet Chess Server). The sound is not played after moves you make or moves read from a saved game + file. If you turn on the Move sound when using WinBoard with the Internet Chess Server, you will probably want to give the }{\b\f1 set bell 0}{\f1 + command to the ICS. Otherwise the ICS will send a bell character after every move (not just yours), causing WinBoard to pl +ay the ICS Bell sound too. Alternatively, you could turn off the ICS Bell sound in WinBoard, but that might cause you to miss ICS alerts for other interesting events. +\par The other sound events correspond directly to the types of messages that the }{\f1\uldb ICS Interaction Colors}{\v\f1 ICSInteractionColors}{\f1 option knows how to colorize. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Communications}}#{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 Communications}}}{\f1 }{\f1\ul Communications}{\f1 +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Lets you change the communication port parameters when the }{\f1\uldb +internetChessServerComPort}{\v\f1 internetChessServerComPort}{\f1 option is in use. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Load Game}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 LoadGameOptns}}}{\f1 }{\f1\ul Load Game}{\f1 +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Lets you change options used while loading games (}{\f1\uldb timeDelay}{\v\f1 timeDelay}{\f1 + option). +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Save Game}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 SaveGameOptns}}}{\f1 }{\f1\ul Save Game}{\f1 +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Lets you change options used for saving games (}{\f1\uldb autoSaveGames}{\v\f1 autoSaveGames}{ +\f1 , }{\f1\uldb oldSaveStyle}{\v\f1 oldSaveStyle}{\f1 , and }{\f1\uldb saveGameFile}{\v\f1 saveGameFile}{\f1 options). +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Time Control}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 TimeControlCmd}}}{\f1 }{\f1\ul Time Control}{\f1 +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Lets you change the time control to be used + in games against a chess engine. Two types of timing are available. +\par }\pard\plain \ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 With conventional chess clocks, each player begins with his clock set to the }{\f1\uldb +timeControl}{\v\f1 timeControl}{\f1 period. When both players have made }{\f1\uldb movesPerSession}{\v\f1 movesPerSession}{\f1 moves, a new time co +ntrol period begins. The time in the new period is added to whatever time the players have left on their clocks. +\par With incremental clocks, each player is given an initial time allotment, and a }{\f1\uldb timeIncrement}{\v\f1 timeIncrement}{\f1 is added to his clock after every mov +e. The increment may be zero, in which case the entire game must be finished within the initial time allotment. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Save Settings Now}}#{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 SaveSettings}}}{\f1 }{\f1\ul Save Settings Now}{\f1 +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 +Save the current option settings to a file, along with the current window sizes and positions, to be automatically reloaded next time WinBoard is run. See }{\f1\uldb Settings}{\v\f1 Settings}{\f1 for the fine points. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Save Settings on Exit}}#{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 SaveSettingsOnExit}}}{\f1 }{\f1\ul Save Settings on Exit}{\f1 +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 +If this option is on, the current settings are automatically saved when WinBoard exits, as with Save Settings Now. +\par }\pard\plain \s1\ql \li120\ri0\sb280\sa120\sl-320\slmult0\nowidctlpar\faauto\outlinelevel0\adjustright\rin0\lin120\itap0 \b\f5\fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1\fs20 \page }{\cs58\f1\fs20\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Help Menu}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 HelpMenu}}}{\b0\f1\fs18\up6 }{\cs58\f1\fs20\super ${\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super $}{\f1 Help Menu}}+{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super +}{\f1 main}}}{\f1\fs20 Help Menu +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Help Contents}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 HelpContents}}}{\f1 Help Contents +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Brings up this help file, starting at the Contents page. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Search for Help on}}#{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 SearchHelp}}}{\f1 Help Index +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Brings up this help file, starting at the Index/Find dialog. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 How to Use Help}}#{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 HelpHelp}}}{\f1 How to Use Help +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Brings up the standard help file that explains how to use Windows Help. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Hint}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 Hint}}}{\f1 Hint +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Displays a move hint from the chess engine. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Book}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 Book}}}{\f1 Book +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Displays a list of possible moves from the chess engine\rquote +s opening book. The first column gives moves, the second column gives one possible response for each move, and the third column shows the number of lines in the book that include the mo +ve from the first column. If you select this option and nothing happens, the engine is out of its book or does not support the book command. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 About WinBoard}}#{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 AboutWinBoard}}}{\f1 About WinBoard +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Displays the WinBoard version number. +\par }\pard\plain \s1\ql \li120\ri0\sb280\sa120\sl-320\slmult0\nowidctlpar\faauto\outlinelevel0\adjustright\rin0\lin120\itap0 \b\f5\fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1\fs20 \page }{\cs58\f1\fs20\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 ICS Interaction Context Menu}}#{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 ICSInteractionContextMenu}}}{\b0\f1\fs18\up6 }{\cs58\f1\fs20\super $ +{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super $}{\f1 ICS Interaction Context Menu}}+{\footnote\ftnalt +\pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super +}{\f1 main}}}{\f1\fs20 ICS Interaction Context Menu +\par }\pard\plain \ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 To see this menu, press +the right mouse button anywhere in the output (upper) pane of the ICS Interaction window. Pressing the right mouse button in the input (lower) pane gives a standard editing context menu, not described here. Use the }{\b\f1 help}{\f1 + command on ICS to learn what these commands mean. +\par You can customize the lower part of this menu (below the Paste option) by setting the }{\f1\uldb icsMenu}{\v\f1 icsMenu}{\f1 option. The easiest way to accomplish this is to edit your }{\f1\uldb settings file}{\v\f1 settings}{\f1 + with Notepad or another plain text editor. Sorry, there is no graphical user interface for customizing the menu. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Copy and Paste}}#{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 CopyAndPaste}}}{\f1 Copy and Paste +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 +Copies the current selection to the clipboard, then pastes it to the input box. As a shortcut to this function, you can press the middle mouse button (if you have one), or Shift plus the right mouse button. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Copy}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 Copy}}}{\f1 Copy +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Copies the current selection to the clipboard. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Paste}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 Paste}}}{\f1 Paste +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Pastes the clipboard contents to the input box. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\nowidctlpar\faauto\pnrdate0\pnrnot1\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\revised\super\revauth1\revdttm-1506646559 K}{ +\f1\revised\revauth1\revdttm-1506646559 Who}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\nowidctlpar\faauto\pnrdate0\pnrnot1\adjustright\rin0\lin120\itap0 +\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\revised\super\revauth1\revdttm-1506646559 #}{\f1\revised\revauth1\revdttm-1506646559 Who}}}{\f1 Who +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Sends the command \'93who\'94}{\b\i\f1 }{\f1 to ICS. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\nowidctlpar\faauto\pnrdate0\pnrnot1\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\revised\super\revauth1\revdttm-1506646559 K}{ +\f1\revised\revauth1\revdttm-1506646559 Players}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\nowidctlpar\faauto\pnrdate0\pnrnot1\adjustright\rin0\lin120\itap0 +\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\revised\super\revauth1\revdttm-1506646559 #}{\f1\revised\revauth1\revdttm-1506646559 Players}}}{\f1 Players +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Sends the command \'93players\'94}{\b\i\f1 }{\f1 to ICS. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\nowidctlpar\faauto\pnrdate0\pnrnot1\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\revised\super\revauth1\revdttm-1506646559 K}{ +\f1\revised\revauth1\revdttm-1506646559 Games}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\nowidctlpar\faauto\pnrdate0\pnrnot1\adjustright\rin0\lin120\itap0 +\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\revised\super\revauth1\revdttm-1506646559 #}{\f1\revised\revauth1\revdttm-1506646559 Games}}}{\f1 Games +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Sends the command \'93games\'94}{\b\i\f1 }{\f1 to ICS. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\nowidctlpar\faauto\pnrdate0\pnrnot1\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\revised\super\revauth1\revdttm-1506646559 K}{ +\f1\revised\revauth1\revdttm-1506646559 Sought}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\nowidctlpar\faauto\pnrdate0\pnrnot1\adjustright\rin0\lin120\itap0 +\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\revised\super\revauth1\revdttm-1506646559 #}{\f1\revised\revauth1\revdttm-1506646559 Sought}}}{\f1 Sought +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Sends the command \'93sought\'94}{\b\i\f1 }{\f1 to ICS. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Tell}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 Tell}}}{\f1 Tell (name) +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Inserts \'93tell }{\i\f1 name }{\f1 \'94}{\b\i\f1 }{\f1 into the input box. The string }{ +\i\f1 name }{\f1 is the current selection if it is not empty. Otherwise }{\i\f1 name }{\f1 is the word surrounding the mouse position, where a \'93word\'94 is a string of letters, digits, or hyphens (-), such as an ICS user handle or game number. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Message}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 Message}}}{\f1 Message (name) +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Inserts \'93message }{\i\f1 name }{\f1 \'94}{\b\i\f1 }{\f1 into the input box, where }{\i\f1 +name}{\f1 is as defined above. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Finger}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 Finger}}}{\f1 Finger (name) +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Sends the command \'93finger }{\i\f1 name}{\f1 \'94}{\b\i\f1 }{\f1 to ICS, where }{\i\f1 name} +{\f1 is as defined above. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Vars}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 Vars}}}{\f1 Vars (name) +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Sends the command \'93vars }{\i\f1 name}{\f1 \'94}{\b\i\f1 }{\f1 to ICS, where }{\i\f1 name}{ +\f1 is as defined above. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Observe}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 Observe}}}{\f1 Observe (name) +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Sends the command \'93observe }{\i\f1 name}{\f1 \'94}{\b\i\f1 }{\f1 to ICS, where }{\i\f1 name +}{\f1 is as defined above. Here }{\i\f1 name}{\f1 can be either a user handle or a game number. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Match}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 Match}}}{\f1 Match (name) +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Sends the command \'93match }{\i\f1 name}{\f1 \'94}{\b\i\f1 }{\f1 to ICS, where }{\i\f1 name}{ +\f1 is as defined above. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\nowidctlpar\faauto\pnrdate0\pnrnot1\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\revised\super\revauth1\revdttm-1506646559 K}{ +\f1\revised\revauth1\revdttm-1506646559 Play}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\nowidctlpar\faauto\pnrdate0\pnrnot1\adjustright\rin0\lin120\itap0 +\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\revised\super\revauth1\revdttm-1506646559 #}{\f1\revised\revauth1\revdttm-1506646559 Play}}}{\f1 Play (name) +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Sends the command \'93play }{\i\f1 name}{\f1 \'94}{\b\i\f1 }{\f1 to ICS, where }{\i\f1 name}{ +\f1 is as defined above. Here }{\i\f1 name}{\f1 can be either a user handle or a seek ad number. +\par }\pard\plain \s1\ql \li120\ri0\sb280\sa120\sl-320\slmult0\nowidctlpar\faauto\outlinelevel0\adjustright\rin0\lin120\itap0 \b\f5\fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1\fs20 \page }{\cs58\f1\fs20\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Buttons}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 Buttons}}${\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super $}{\f1 Buttons}}+{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super +}{\f1 main}}}{\b0\f1\fs18\up6 }{\f1\fs20 BUTTONS +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Back to Start}}}{\f1 << +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Same as }{\f1\uldb Back to Start}{\v\f1 BacktoStart}{\f1 . +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Backward}}}{\f1 < +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Same as }{\f1\uldb Backward}{\v\f1 Backward}{\f1 . +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Pause}}}{\f1 P +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Same as }{\f1\uldb Pause}{\v\f1 Pause}{\f1 . The button label changes to }{\b\f1 C}{\f1 + while WinBoard is pausing. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Forward}}}{\f1 > +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Same as }{\f1\uldb Forward}{\v\f1 Forward}{\f1 . +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Forward to End}}}{\f1 >> +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Same as }{\f1\uldb Forward to End}{\v\f1 ForwardtoEnd}{\f1 . +\par }\pard\plain \s1\ql \li120\ri0\sb280\sa120\sl-320\slmult0\nowidctlpar\faauto\outlinelevel0\adjustright\rin0\lin120\itap0 \b\f5\fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1\fs20 \page }{\cs58\f1\fs20\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Command Line Options}}K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Options}}}{\f1\fs20 }{\cs58\f1\fs20\super #{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 Options}}}{\f1\fs20 }{\cs58\f1\fs20\super ${\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super $}{\f1 Command Line Options}}}{\f1\fs20 }{\cs58\f1\fs20\super +{\footnote\ftnalt +\pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super +}{\f1 main}}}{\f1\fs20 COMMAND LINE OPTIONS +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 All WinBoard options can be set e +ither on the command line (if you start WinBoard by typing into an MSDOS Prompt box), in the Properties/Shortcut/Target box of a Windows shortcut, in a }{\f1\uldb settings file}{\v\f1 settings}{\f1 +, or in the Additional Options box of the WinBoard startup dialog. Exactly the same syntax is used in all four places. Most options can also be set from the menus and saved using }{\f1\uldb Save Settings Now}{\v\f1 SaveSettings}{\f1 or }{\f1\uldb +Save Settings on Exit}{\v\f1 SaveSettingsOnExit}{\f1 , so most people will not need to read this section. +\par }\pard\plain \ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Most options have two names, a long + one that is easy to read and a short one that is easy to type. To turn on a boolean (true/false) option }{\i\f1 opt}{\f1 , you can just give its short name preceded by a minus sign or slash (-}{\i\f1 opt}{\f1 or /}{\i\f1 opt}{\f1 +); to turn one off, prefix the short name by an \'93x\'94 or an extra minus sign (-x}{\i\f1 opt}{\f1 or /-}{\i\f1 opt}{\f1 +). To set any other kind of option, or to set a boolean option using its long name, give the value after the name, separated by a space, colon, or equal sign. (-}{\i\f1 opt}{\f1 23 or /}{\i\f1 option}{\f1 +:true). If a string option contains spaces or special characters, enclose it in double quotes and use the \\ quoting convention of C to name the special characters. Alternatively, you can enclose a string value in curly braces (/opt=\{string\} +), as long as the value does not contain a closing curly brace. If a filename option contains spaces, enclose it in either single or double quotes. In filename options, the \\ + character is not treated specially, so use single quotes around the outside of the value if it has double quotes inside (and vice versa). +\par When you star +t WinBoard, it will pop up the Startup dialog box unless you provide sufficient options on the command line for WinBoard to determine which major mode to be in and what engines to use or chess server to connect to. To bypass this box, you must at minimum +give one of the three options }{\f1\uldb /cp}{\v\f1 cp}{\f1 , /}{\f1\uldb ics}{\v\f1 ics}{\f1 , or /}{\f1\uldb ncp}{\v\f1 ncp}{\f1 . If you give the /cp option, you must also give the /}{\f1\uldb fcp}{\v\f1 fcp}{\f1 and /}{\f1\uldb scp}{\v\f1 scp}{\f1 + options. If you give the /ics option, you must also give the /}{\f1\uldb icshost}{\v\f1 icshost}{\f1 option. +\par }\pard\plain \s29\ql \fi-240\li360\ri0\sb60\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin360\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1\uldb Chess Engine Options}{\v\f1 ChessEngineOptions}{\f1 +\par }{\f1\uldb Internet Chess Server Options}{\v\f1 InternetChessServerOptions}{\f1 +\par }{\f1\uldb Load and Save Options}{\v\f1 LoadAndSaveOptions}{\f1 +\par }{\f1\uldb User Interface Options}{\v\f1 UserInterfaceOptions}{\f1 +\par }{\f1\uldb Other Options}{\v\f1 OtherOptions}{\f1 +\par }\pard\plain \s1\ql \li120\ri0\sb280\sa120\sl-320\slmult0\nowidctlpar\faauto\outlinelevel0\adjustright\rin0\lin120\itap0 \b\f5\fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1\fs20 \page }{\cs58\f1\fs20\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Chess Engine Options}}${\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super $}{\f1 Chess Engine Options}}#{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 ChessEngineOptions}}+{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super +}{\f1 main}}}{\f1\fs20 Chess Engine Options +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 cp}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 cp}}}{\f1 /cp}{\b0\f1 or}{\f1 /xcp}{\b0\f1 ,}{\f1 }{\b0\f1 or}{\f1 }{\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 chessProgram}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 chessProgram}}}{\f1 /chessProgram }{\i\f1 true|false +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 If true, puts WinBoard + in chess engine mode. In this mode, you can play against a chess program running on your PC or use it as an analysis partner. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 tc}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 tc}}}{\f1 /tc }{\b0\f1 or}{\f1 }{\cs58\f1\super K{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 timeControl}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 timeControl}}}{\f1 /timeControl }{\i\f1 minutes[:seconds] +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Each player begins with his clock set to the timeControl period. Default: 5 minutes. Th +e additional options movesPerSession and timeIncrement are mutually exclusive. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 mps}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 mps}}}{\f1 /mps }{\b0\f1 or}{\f1 }{\cs58\f1\super K{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 movesPerSession}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 movesPerSession}}}{\f1 /movesPerSession }{\i\f1 moves}{\f1 +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 +When both players have made movesPerSession moves, a new timeControl period is added to both clocks. Default: 40 moves. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 inc}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 inc}}}{\f1 /inc }{\b0\f1 or}{\f1 }{\cs58\f1\super K{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 timeIncrement}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 timeIncrement}}}{\f1 /timeIncrement }{\i\f1 seconds +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 +If this option is specified, movesPerSession is ignored. Instead, after each player's move, timeIncrement seconds are added to his clock. Use -timeIncrement 0 if you want to require the entire game to be played in one timeControl period, with +no increment. Default: -1, which specifies movesPerSession mode. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 clock }}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 clock }}}{\f1 /clock }{\b0\f1 or }{\f1 /xclock}{\b0\f1 , or}{\f1 }{\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 clockMode}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 clockMode}}}{\f1 /clockMode }{\i\f1 true|false +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 +Determines whether or not to display the chess clocks. If clockMode is False, the clocks are not shown, but the side that is to play next is +still highlighted. Also, unless searchTime is set, the chess engine still keeps track of the clock time and uses it to determine how fast to make its moves. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 st}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 st}}}{\f1 /st }{\b0\f1 or}{\f1 }{\cs58\f1\super K{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 searchTime }}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 searchTime }}}{\f1 /searchTime }{\i\f1 minutes[:seconds]}{\f1 +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Tells the chess engine to spend at most the given amount + of time searching for each of its moves. Without this option, the engine chooses its search time based on the number of moves and amount of time remaining until the next time control. Setting this option also sets clockMode to False. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 sd}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 sd}}}{\f1 /depth }{\b0\f1 or}{\f1 }{\cs58\f1\super K{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 searchDepth}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 searchDepth}}}{\f1 /searchDepth }{\i\f1 number}{\f1 +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 +Tells the chess engine to look ahead at most the given number of moves when searching for a move to make. Without this option, the engine chooses its search depth based on the number of moves and amount of time remaining until the next time +control. With the option, the engine will cut off its search early if it reaches the specified depth. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\nowidctlpar\faauto\pnrdate0\pnrnot1\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\revised\super\revauth1\revdttm-1506646559 K}{ +\f1\revised\revauth1\revdttm-1506646559 ponder}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\nowidctlpar\faauto\pnrdate0\pnrnot1\adjustright\rin0\lin120\itap0 +\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\revised\super\revauth1\revdttm-1506646559 #}{\f1\revised\revauth1\revdttm-1506646559 ponder}}}{\f1 /ponder}{\b0\f1 or }{\f1 /xponder}{\b0\f1 ,}{\f1 }{\b0\f1 or}{\f1 }{ +\cs58\f1\super K{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\nowidctlpar\faauto\pnrdate0\pnrnot1\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 { +\cs58\f1\revised\super\revauth1\revdttm-1506646559 K}{\f1\revised\revauth1\revdttm-1506646559 ponderNextMove}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto +\nowidctlpar\faauto\pnrdate0\pnrnot1\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\revised\super\revauth1\revdttm-1506646559 #}{\f1\revised\revauth1\revdttm-1506646559 ponderNextMove}}}{\f1 + /ponderNextMove }{\i\f1 true|false +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Sets the }{\f1\uldb Ponder Next Move}{\v\f1 ponderNextMoveCmd}{\f1 option. Default: True. + +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 thinking}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 thinking}}}{\f1 /thinking}{\b0\f1 or }{\f1 /xthinking}{\b0\f1 ,}{\f1 }{\b0\f1 or}{\f1 }{\cs58\f1\super K +{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 showThinking}}#{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 showThinking}}}{\f1 /showThinking }{\i\f1 true|false +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Sets the }{\f1\uldb Show Thinking}{\v\f1 showThinkingCmd}{\f1 option. Default: False. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 periodic }}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 periodic}}}{\f1 /periodic }{\b0\f1 or }{\f1 /xperiodic}{\b0\f1 , or}{\f1 }{\cs58\f1\super K{\footnote\ftnalt +\pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 periodicUpdates}}#{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 periodicUpdates}}}{\f1 /periodicUpdates }{\i\f1 true|false +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Sets the }{\f1\uldb Periodic Updates}{\v\f1 periodicUpdatesCmd}{\f1 option. Default: True. + +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 mg }}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 mg }}}{\f1 /mg }{\b0\f1 or}{\f1 }{\cs58\f1\super K{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 matchGames }}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 matchGames}}}{\f1 /matchGames }{\i\f1 n +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Automatically runs an }{\b\i\f1 n}{\i\f1 -}{\f1 +game match between two chess engines, with alternating colors. If the }{\f1\uldb loadGameFile}{\v\f1 loadGameFile}{\f1 or }{\f1\uldb loadPositionFile}{\v\f1 loadPositionFile}{\f1 + option is set, WinBoard will start each game with the given opening moves or the given position; otherwise, the games will start with the standard initial chess position. If the }{\f1\uldb saveGameFile}{\v\f1 saveGameFile}{\f1 + option is set, a move record for the match will be appended to the specified file. If the }{\f1\uldb savePositionFile}{\v\f1 savePositionFile}{\f1 option is set, the final position reached + in each game of the match will be appended to the specified file. When the match is over, WinBoard will display the match score and exit. Default: 0 (do not run a match). +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 mm }}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 mm }}}{\f1 /mm }{\b0\f1 or }{\f1 /xmm}{\b0\f1 , or}{\f1 }{\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 matchMode }}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 matchMode }}}{\f1 /matchMode }{\i\f1 true|false +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Provided for backward compatibility. If true and matchGames=0, sets matchGames=1. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 fd}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 fd }}}{\f1 /fd }{\b0\f1 or}{\f1 }{\cs58\f1\super K{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 firstDirectory}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 firstDirectory}}}{\f1 /firstDirectory }{\i\f1 dir\line }{\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 sd}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 sd }}}{\f1 /sd }{\b0\f1 or}{\f1 }{\cs58\f1\super K{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 secondDirectory}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 secondDirectory}}}{\f1 /secondDirectory }{\i\f1 dir}{\cs58\f1\super }{\f1 \line }{\cs58\f1\super K{\footnote\ftnalt +\pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 fcp }}#{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 fcp }}}{\f1 /fcp }{\b0\f1 or}{\f1 }{\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 firstChessProgram }}#{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 firstChessProgram }}}{\f1 /firstChessProgram }{\i\f1 command\line }{\cs58\f1\super +K{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 scp }}#{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 scp }}}{\f1 /scp }{\b0\f1 or}{\f1 }{\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 secondChessProgram }}#{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 secondChessProgram }}}{\f1 /secondChessProgram }{\i\f1 command}{\cs58\f1\super }{ +\f1 +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Names of the chess engines and working directories in which th +ey are to be run. The second chess engine is started only in Two Machines (match) mode. These arguments are parsed as filenames; that is, the \\ character is interpreted literally, not as a C-style escape. +\par }\pard\plain \ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 The }{\i\f1 dir}{\f1 argument specifies the initial working dire +ctory for the chess engine. It should usually be the directory where the engine and its working files are installed. If }{\i\f1 dir}{\f1 + is not an absolute pathname, it is interpreted relative to the directory from which WinBoard.exe itself was loaded. The }{\i\f1 dir}{\f1 argument + is ignored if the chess engine is being run on a remote machine (see firstHost and secondHost below). The default value for }{\i\f1 dir }{\f1 "", meaning that the chess engine is expected to be installed in the same directory as WinBoard. +\par The }{\i\f1 command}{\f1 argument is actually the command line to the chess engine, so if the engine itself needs command line arguments, you can include them by enclosing }{\i\f1 command}{\f1 + in single or double quotes. If the engine name or an engine argument has a space in it, use single quotes around the whole }{\i\f1 command, }{\f1 +and inside them use double quotes around each item that contains spaces. If the engine name has more than one period in it (for example, }{\f2 QChess1.5.exe}{\f1 ), you must include the "}{\f2 .exe}{\f1 +" extension; otherwise you can leave it out. The default value for }{\i\f1 command}{\f1 is "", which brings up the startup dialog to ask which engines you want. +\par Examples: +\par }\pard\plain \s19\ql \fi-518\li1036\ri0\sb60\sl-240\slmult0\keep\nowidctlpar\tx520\tx920\tx1320\tx1720\tx2120\faauto\adjustright\rin0\lin1036\itap0 \f6\fs16\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f2 WinBoard /cp /fd="C:\\Program Files\\ +Crafty" /fcp=WCrafty-15.12.exe /scp=GNUChess +\par WinBoard /cp /fd="C:\\Miracle Games" /fcp='"Miracle Chess.exe" /wow' /scp=GNUChess +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 fh }}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 fh }}}{\f1 /fh }{\b0\f1 or}{\f1 }{\cs58\f1\super K{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 firstHost }}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 firstHost }}}{\f1 /firstHost }{\i\f1 host\line }{\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 sh }}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 sh }}}{\f1 /sh }{\b0\f1 or}{\f1 }{\cs58\f1\super K{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 secondHost }}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 secondHost }}}{\f1 /secondHost }{\i\f1 host}{\f1 +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 +Hosts on which the chess engines are to run. The default for each is "localhost". If you specify another host, WinBoard}{\i\f1 }{\f1 uses }{\f1\uldb rsh}{\v\f1 rsh}{\f1 to run the chess program there. The /fd and /sd flags do not work + in conjunction with these flags; if you need a remote chess engine to run somewhere other than your default login directory on the remote machine, you will have to include a "cd" command in the argument to /fcp or /scp. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 initString}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 initString}}}{\f1 /firstInitString }{\b0\f1 or }{\f1 /initString }{\i\f1 string\line }{\cs58\f1\super K{\footnote\ftnalt +\pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 secondInitString}}#{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 secondInitString}}}{\f1 /secondInitString }{\i\f1 string}{\f1 +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 The strings that are sent to initialize the chess engines. Default: "new\\nrandom\\n". The "\\ +n" sequences represent newlines. You can type "\\n" on the command line or in a }{\f1\uldb settings file}{\v\f1 settings}{\f1 , and WinBoard will convert it to a newline. +\par }\pard\plain \ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 All chess engines require the "new" command to start a new game. +\par You can remove the "random" command if you like; including it causes GNU Chess to randomize its move selection slightly so that it doesn't play the same moves in every game. Ev +en without "random", GNU Chess randomizes its choice of moves from its opening book. You can also try adding other commands to the initString; see the GNU Chess documentati{\*\bkmkstart _Hlt386545814}o{\*\bkmkstart _Hlt386567280}{\*\bkmkend _Hlt386545814} +n{\*\bkmkend _Hlt386567280} (gnuchess.txt) for details. Crafty ignores the "random" command; see its documentation for the commands it accepts. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 initString}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 initString}}}{\f1 /firstComputerString }{\i\f1 string\line }{\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 secondInitString}}#{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 secondInitString}}}{\f1 /secondComputerString }{\i\f1 string}{\f1 +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 +If the chess engine is playing against another computer program (whether locally or on a chess server), by default the command "computer\\n" is sent to it. Som +e chess engines change their playing style when they receive this command. If you do not want the engine to know when it is playing another computer, you can set the string to "". +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 fb }}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 fb }}}{\f1 /fb }{\b0\f1 or }{\f1 /xfb}{\b0\f1 , or}{\f1 }{\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 firstPlaysBlack }}#{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 firstPlaysBlack}}}{\f1 /firstPlaysBlack }{\i\f1 true|false +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 In games between two chess + programs, the firstChessProgram normally plays white. (This is a change from earlier versions of WinBoard.) If this option is True, firstChessProgram plays black. In a multi-game match, this option affects the colors only for the first game; they still a +lternate in subsequent games. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 reuse}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 reuse}}}{\f1 /reuse}{\cs58\f1\super }{\b0\f1 or }{\f1 /xreuse}{\b0\f1 , or }{\cs58\f1\super K{\footnote\ftnalt +\pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 reuseFirst}}#{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 reuseFirst}}}{\f1 /reuseFirst}{\i\f1 true|false\line }{\cs58\f1\super K +{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 reuse2}}#{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 reuse2}}}{\f1 /reuse2}{\cs58\f1\super }{\b0\f1 or }{\f1 /xreuse2}{\b0\f1 , or }{ +\cs58\f1\super K{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 reuseSecond}}#{\footnote\ftnalt +\pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 reuseSecond}}}{\f1 /reuseSecond}{\i\f1 true|false}{\f1 +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 If this option is True (the default), WinBoard}{\i\f1 }{\f1 +uses the same chess engine process repeatedly when playing multiple games. If t +he option is False, WinBoard kills off the chess engine after every game and starts a fresh one for the next game. Starting a fresh chess engine can be slow, so it is not recommended. However, some chess engines may not work properly when reused, such as +versions of Crafty earlier than 12.0. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 firstProtocolVersion}}#{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 firstProtocolVersion}}}{\f1 /firstProtocolVersion }{\i\f1 ver\line }{\cs58\f1\super +K{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 secondProtocolVersion}}#{\footnote\ftnalt +\pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 secondProtocolVersion}}}{\f1 /secondProtocolVersion }{\i\f1 ver}{\f1 + +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 +This option specifies which version of the chess engine communication protocol to use. By default, version-number is 2. In version 1, the "protover" command is no +t sent to the engine; since version 1 is a subset of version 2, nothing else changes. Other values for version-number are not supported. +\par }\pard\plain \s1\ql \li120\ri0\sb280\sa120\sl-320\slmult0\nowidctlpar\faauto\outlinelevel0\adjustright\rin0\lin120\itap0 \b\f5\fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1\fs20 \page }{\cs58\f1\fs20\super +{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super +}{\f1 main}}K{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Internet Chess Server Options}}${\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super $}{\f1 Internet Chess Server Options}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 InternetChessServerOptions}}}{\f1\fs20 Internet Chess Server Options +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 ics }}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 ics }}}{\f1 /ics }{\b0\f1 or }{\f1 /xics}{\b0\f1 , or}{\f1 }{\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 internetChessServerMode}}#{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 internetChessServerMode}}}{\f1 /internetChessServerMode}{\i\f1 true|false}{\f1 + +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Connect with an Interne +t Chess Server to play chess against its other users, observe games they are playing, or review games that have recently finished. See }{\f1\uldb ICS Client}{\v\f1 ICSClient}{\f1 Default: False. +\par }\pard\plain \ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 You can create a script file containing ICS commands that WinBoard will type in for y +ou whenever you connect to the ICS. See }{\f1\uldb ICS Logon}{\v\f1 ICSLogon}{\f1 . +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 icshost }}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 icshost }}}{\f1 /icshost }{\b0\f1 or}{\f1 }{\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 internetChessServerHost }}#{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 internetChessServerHost }}}{\f1 /internetChessServerHost }{\i\f1 hostname}{\f1 + +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 +The host name or numeric address of the Internet Chess Server to connect to when in ICS mode. The default is the empty string, which causes WinBoard to pop up a menu of known ICS sites. The file ics-address{\*\bkmkstart _Hlt386546221}e +{\*\bkmkend _Hlt386546221}s.txt in the WinBoard distribution gives slightly more information on these sites. It includes their numeric addresses, which you can use if your site does not have a working name server. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 icsport }}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 icsport }}}{\f1 /icsport }{\b0\f1 or}{\f1 }{\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 internetChessServerPort }}#{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 internetChessServerPort }}}{\f1 /internetChessServerPort }{\i\f1 portnumber}{\f1 + +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 The port number to use when connecting to a chess server in ICS mode. Default: 5000. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 via }}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 via }}}{\f1 /icshelper }{\i\f1 program}{\f1 +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 An external helper program used to communicate with the chess server. Typically }{ +\cs58\f1\super K{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 timestamp}}}{\i\f1 timestamp}{\f1 + for the ICC (chessclub.com) or }{\cs58\f1\super K{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 + timeseal}}}{\i\f1 timeseal}{\f1 for FICS (freechess.org, eics.daimi.aau.dk, etc.). This option is shorthand for \'93/useTelnet /telnetProgram }{\i\f1 program}{\f1 \'94}{\b\f1 . +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 telnet}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 telnet}}}{\f1 /telnet}{\b0\f1 or }{\f1 /xtelnet}{\b0\f1 ,}{\f1 }{\b0\f1 or}{\f1 }{\cs58\f1\super K{\footnote\ftnalt +\pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 useTelnet}}#{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 useTelnet}}}{\f1 /useTelnet}{\i\f1 true|false}{\f1 +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 This option is poorly named; it should be called }{\b\f1 /useHelper}{\f1 +. If set to True, it instructs WinBoard to use an external helper program to communicate with the ICS, as specified by the telnetProgram option. The external program must be a pure console application that can communicate with WinBoard through pipes; the +Windows telnet application is not suitable. If the option is False (the default), WinBoard communicates with the ICS by opening a Winsock TCP socket and using its own internal implementation of the telnet protocol. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 gateway}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 gateway}}}{\f1 /gateway }{\i\f1 hostname}{\f1 +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 If this option is set to a host name, WinBoard uses }{\f1\uldb rsh}{\v\f1 rsh}{\f1 + to run the telnetProgram remotely on the given host to communicate with the Internet Chess Server instead of using its own internal implementation of the telnet protocol. See the }{\f1\uldb FIREWALLS}{\v\f1 FIREWALLS}{\f1 section below for an +explanation of when this option is useful. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 telnetProgram}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 telnetProgram}}}{\f1 /telnetProgram }{\i\f1 program}{\f1 +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 This option is poorly named; it should be called }{\b\f1 /helperProgram}{\f1 +. It gives the name of the remote or external helper program to be used with the gateway or useTelnet option. The default is +"telnet". The telnet program is invoked with the value of internetChessServer as the first argument and the value of internetChessServerPort as the second argument on its command line. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 icscom }}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 icscom }}}{\f1 /icscom }{\b0\f1 or}{\f1 }{\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 internetChessServerComPort }}#{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 internetChessServerComPort }}}{\f1 /internetChessServerComPort }{\i\f1 name}{\f1 + +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 If this option is set, +WinBoard communicates with the Internet Chess Server using a serial communication port instead of a network connection. Use this option if your machine is not connected to a network (not even via SLIP or PPP), but you do have Internet access through anoth +er machine by dialing in using a modem or by connecting directly to a serial terminal port. Example: +\par }\pard\plain \s19\ql \li120\ri0\sb60\sl-240\slmult0\keep\nowidctlpar\tx520\tx920\tx1320\tx1720\tx2120\faauto\adjustright\rin0\lin120\itap0 \f6\fs16\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f2 WinBoard /ics /icscom:com1 +\par }\pard\plain \ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 +After you start WinBoard in this way, type whatever modem commands are necessary to dial out to your Internet provider and log in. You may need to turn off }{\f1\uldb Local Line Editing}{\v\f1 LocalLineEditing}{\f1 + on the Options menu while typing commands to the modem, but turn it on again afterwards. Then telnet to the ICS, using a command like "telnet chessclub.com 5000". Important: See the paragraph in the }{\f1\uldb LIMITATIONS}{\v\f1 LIMITATIONS}{\f1 + section below about extra echoes. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 comPortSettings }}#{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 comPortSettings }}}{\f1 /comPortSettings}{\b0\f1 }{\i\f1 \'93 +dataRate,dataBits,parity,stopBits,flow\'94 +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 +This option allows serial port parameters to be set from the command line or a settings file. The values are simply filled in to the }{\f1\uldb Communications}{\v\f1 Communications}{\f1 dialog. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 icslogon }}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 icslogon }}}{\f1 /icslogon }{\b0\f1 or}{\f1 }{\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 internetChessServerLogonScript }}#{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 internetChessServerLogonScript }}}{\f1 /internetChessServerLogonScript }{\i\f1 +filename +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 This option lets you change the name used for the }{\f1\uldb ICS Logon}{\v\f1 ICSLogon}{\f1 + file. Default: "ICS.ini". The filename is interpreted relative to WinBoard's installation directory (the directory containing WinBoard.exe). +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 autocomm }}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 autocomm }}}{\f1 /autocomm }{\b0\f1 or }{\f1 /xautocomm}{\b0\f1 , or}{\f1 }{\cs58\f1\super K{\footnote\ftnalt +\pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 autoComment }}#{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 autoComment }}}{\f1 /autoComment}{\i\f1 true|false}{\f1 +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Sets the }{\f1\uldb Auto Comment}{\v\f1 AutoCommentCmd}{\f1 option. Default: False. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 autoflag }}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 autoflag }}}{\f1 /autoflag}{\b0\f1 or }{\f1 /xautoflag}{\b0\f1 ,}{\f1 }{\b0\f1 or}{\f1 }{\cs58\f1\super K +{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 autoCallFlag }}#{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 autoCallFlag }}}{\f1 /autoCallFlag}{\i\f1 true|false}{\f1 +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Sets the }{\f1\uldb Auto Flag}{\v\f1\uldb AutoFlag}{\f1 option. Default: False. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 autobs }}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 autobs }}}{\f1 /autobs}{\b0\f1 or }{\f1 /xautobs}{\b0\f1 ,}{\f1 }{\b0\f1 or}{\f1 }{\cs58\f1\super K{\footnote\ftnalt +\pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 autoObserve }}#{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 autoObserveCmd }}}{\f1 /autoObserve}{\i\f1 true|false}{\f1 +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Sets the }{\f1\uldb Auto Observe}{\v\f1 autoObserveCmd}{\f1 option. Default: False. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 moves }}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 moves }}}{\f1 /moves}{\b0\f1 or }{\f1 /xmoves}{\b0\f1 ,}{\f1 }{\b0\f1 or}{\f1 }{\cs58\f1\super K{\footnote\ftnalt +\pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 getMoveList }}#{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 getMoveList }}}{\f1 /getMoveList}{\i\f1 true|false}{\f1 +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Sets the }{\f1\uldb Get Move List}{\v\f1 getMoveListCmd}{\f1 option. Default: True. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 edit}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 edit}}}{\f1 /edit}{\cs58\f1\super }{\b0\f1 or }{\f1 /xedit}{\b0\f1 ,}{\f1 }{\b0\f1 or}{\f1 }{\cs58\f1\super K +{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 localLineEditing}}#{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 localLineEditingOption}}}{\f1 /localLineEditing}{\i\f1 true|false}{\f1 +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Sets the }{\f1\uldb Local Line Editing}{\v\f1 localLineEditing}{\f1 option. Default: True. + +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 quiet }}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 quiet }}}{\f1 /quiet }{\b0\f1 or }{\f1 /xquiet}{\b0\f1 , or}{\f1 }{\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 quietPlay }}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 quietPlay }}}{\f1 /quietPlay}{\i\f1 true|false}{\f1 +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Sets the }{\f1\uldb Quiet Play}{\v\f1 quietPlayCmd}{\f1 option. Default: False +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 blindfold (option)}}#{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 opt_blindfold }}}{\f1 /blindfold }{\i\f1 true|false}{\f1 +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Sets the }{\f1\uldb Blindfold}{\v\f1 BlindfoldCmd}{\f1 option. Default: False +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\super K}{ pre}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\super #}{ pre}}}{\f1 /pre }{\b0\f1 or}{\f1 }{\cs58\f1\super K{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\super K}{ xpre}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 +\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\super #}{ xpre}}}{\f1 /xpre}{\b0\f1 , or}{\f1 }{\cs58\f1\super K{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 +\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 premove (option)}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 +\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 premove}}}{\f1 /premove}{\i\f1 true|false +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Sets the }{\f1\uldb Premove}{\v\f1 PremoveCmd}{\f1 + option. If set to True, the premove feature is enabled. If set to False, premove is disabled and the other }{\f1\uldb Premove}{\v\f1 PremoveCmd}{\f1 settings are ignored. Default: False. +\par }\pard\plain \s2\ql \li115\ri0\sb120\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin115\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\super K}{ preWhite}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\super #}{ preWhite}}}{\f1 /prewhite }{\b0\f1 or}{\f1 }{\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\super K}{ xpreWhite}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\super #}{ xpreWhite}}}{\f1 /xprewhite}{\b0\f1 , or }{\cs58\f1\super K{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 premoveWhite}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 premoveWhite}}}{\f1 /premoveWhite}{\i\f1 true|false +\par }\pard \s2\ql \li115\ri0\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin115\itap0 {\cs58\f1\super K{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 +\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 premoveWhiteText}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 +\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 premoveWhiteText}}}{\f1 /premoveWhiteText}{\i\f1 movetext +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 If }{\b\f1 premoveWhite}{\f1 + is set to True and you are playing white in an ICS game, the text specified by the }{\b\f1 premoveWhiteText}{\f1 option is sent to the ICS as soon as the game starts. These options can be set from the }{\f1\uldb Premove}{\v\f1 PremoveCmd}{\f1 + section of the }{\f1\uldb ICS Options}{\v\f1\uldb ICSOptions}{\f1 dialog box. The default for }{\b\f1 premoveWhite}{\f1 is False. +\par }\pard\plain \s2\ql \li115\ri0\sb120\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin115\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\super K}{ preBlack}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\super #}{ preBlack}}}{\f1 /preblack }{\b0\f1 or}{\f1 }{\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\super K}{ xpreBlack}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\super #}{ xpreBlack}}}{\f1 /xpreblack}{\b0\f1 , or }{\cs58\f1\super K{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 premoveBlack}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 premoveBlack}}}{\f1 /premoveBlack}{\i\f1 true|false +\par }\pard \s2\ql \li115\ri0\sa120\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin115\itap0 {\cs58\f1\super K{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 +\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 premoveBlackText}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 +\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 premoveBlackText}}}{\f1 /premoveBlackText}{\i\f1 movetext +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 If }{\b\f1 premoveBlack}{\f1 + is set to True and you are playing black in an ICS game, the text specified by the }{\b\f1 premoveBlackText}{\f1 option is sent to the ICS as soon as the first move is received from your opponent, even if you make a different premove on the board befor +e the first white move is received. These options can be set from the }{\f1\uldb Premove}{\v\f1 PremoveCmd}{\f1 section of the }{\f1\uldb ICS Options}{\v\f1\uldb ICSOptions}{\f1 dialog box. The default for }{\b\f1 premoveBlack}{\f1 is False. +\par }\pard\plain \ql \li115\ri0\sb120\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin115\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\b\super K{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\super K}{ alarm}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 +\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\super #}{ alarm}}}{\b /alarm }{or}{\b }{\cs58\b\super K{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 +\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\super K}{ xalarm}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 +\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\super #}{ xalarm}}}{\b /xalarm}{, or }{\cs58\b\super K{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 +\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\super K}{ icsAlarm}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 +\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\super #}{ icsAlarm}}}{\b /icsAlarm }{\b\i true|false}{\b +\par }\pard \ql \li115\ri0\sa120\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin115\itap0 {\cs58\b\super K{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 +\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\super K}{ icsAlarmTime}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 +\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\super #}{ icsAlarmTime}}}{\b /icsAlarmTime }{\b\i milliseconds +\par }\pard \ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 {When }{\b icsAlarm}{ is set to True, the }{\uldb alarm sound}{\v soundIcsAlarm}{ is played when your clock counts down to }{\b icsAlarmTime}{ + seconds. For ICS games with time controls that include an increment, the alarm will sound each time the clock counts down to the }{\b icsAlarmTime}{. The }{\b icsAlarmTime}{ can be set by selecting }{\uldb ICS Alarm}{\v ICSAlarm}{ from the }{\uldb +ICS options}{\v\uldb ICSOptions}{ dialog. The default is 5 seconds. +\par }\pard\plain \s1\ql \li120\ri0\sb280\sa120\sl-320\slmult0\nowidctlpar\faauto\outlinelevel0\adjustright\rin0\lin120\itap0 \b\f5\fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1\fs20 \page }{\cs58\f1\fs20\super +{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super +}{\f1 main}}K{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Load and Save Options}}${\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super $}{\f1 Load and Save Options}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 LoadandSaveOptions}}}{\b0\f1\fs18\up6 }{\f1\fs20 Load and Save Options +\par }\pard\plain \s2\ql \li115\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin115\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 lgf }}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 lgf }}}{\f1 /lgf }{\b0\f1 or}{\f1 }{\cs58\f1\super K{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 loadGameFile }}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 loadGameFile }}}{\f1 /loadGameFile }{\i\f1 filename}{\f1 \line }{\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 lgi }}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 lgi }}}{\f1 /lgi }{\b0\f1 or}{\f1 }{\cs58\f1\super K{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 loadGameIndex }}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 loadGameIndex }}}{\f1 /loadGameIndex }{\i\f1 N}{\f1 +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 If loadGameFile is set, WinBoard rea +ds the specified game file at startup. You can leave out the name of this option and give just the file name, which is handy if you want to configure WinBoard as a game viewer with a browser such as the Windows Explorer or Netscape. The filename is interp +r +eted relative to WinBoard's initial working directory. The filename "-" specifies the standard input. If there is more than one game in the file, WinBoard pops up a menu of the available games, with entries based on their PGN tags. If loadGameIndex is set + to }{\i\f1 N, }{\f1 the menu is suppressed and the }{\i\f1 N}{\f1 th game found in the file is loaded immediately. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 td }}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 td }}}{\f1 /td }{\b0\f1 or}{\f1 }{\cs58\f1\super K{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 timeDelay }}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 timeDelay }}}{\f1 /timeDelay }{\i\f1 seconds}{\f1 +\par }\pard\plain \ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Time delay between moves during }{\f1\uldb Load Game}{\v\f1 LoadGame}{\f1 +. Fractional seconds are allowed; try 0.4. A time delay value of -1 tells WinBoard not to step through game files automatically. Default: 1 second. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 sgf }}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 sgf }}}{\f1 /sgf }{\b0\f1 or}{\f1 }{\cs58\f1\super K{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 saveGameFile }}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 saveGameFile }}}{\f1 /saveGameFile }{\i\f1 filename}{\f1 +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 +If this option is set, WinBoard appends a record of every game played to the specified file. The filename is interpreted relative to WinBoard's initial working directory. The filename "-" specifies the standard output. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 autosave }}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 autosave }}}{\f1 /autosave}{\b0\f1 or }{\f1 /xautosave}{\b0\f1 ,}{\f1 }{\b0\f1 or}{\f1 }{\cs58\f1\super K +{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 autoSaveGames }}#{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 autoSaveGames }}}{\f1 /autoSaveGames}{\i\f1 true|false}{\f1 +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 +If this option is True, at the end of every game WinBoard prompts you for a filename and appends a record of the game to the file you specify. Ignored if saveGameFile is set. Default: False. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 lpf}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 lpf}}}{\f1 /lpf }{\b0\f1 or}{\f1 }{\cs58\f1\super K{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 loadPositionFile }}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 loadPositionFile }}}{\f1 /loadPositionFile }{\i\f1 filename}{\f1 \line }{\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 lpi }}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 lpi }}}{\f1 /lpi }{\b0\f1 or}{\f1 }{\cs58\f1\super K{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 loadPositionIndex }}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 loadPositionIndex }}}{\f1 /loadPositionIndex }{\i\f1 N}{\f1 +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 +If loadPositionFile is set, WinBoard loads the specified position file at startup. The filename is interpreted relative to WinBoard's initial working directory. The filename "-" specifies the standard input. If loadPositionIndex is set to }{\i\f1 N}{\f1 +, the }{\i\f1 N}{\f1 th position found in the file is loaded; otherwise the first is loaded. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 spf }}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 spf }}}{\f1 /spf }{\b0\f1 or}{\f1 }{\cs58\f1\super K{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 savePositionFile }}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 savePositionFile }}}{\f1 /savePositionFile }{\i\f1 filename}{\f1 +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 If this option is set +, WinBoard appends the final position reached in every game played to the specified file. The filename is interpreted relative to WinBoard's initial working directory. The file name "-" specifies the standard output. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 oldsave }}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 oldsave }}}{\f1 /oldsave }{\b0\f1 or }{\f1 /xoldsave}{\b0\f1 , or}{\f1 }{\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 oldSaveStyle }}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 oldSaveStyle }}}{\f1 /oldSaveStyle}{\i\f1 true|false}{\f1 +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 +If this option is False (the default), WinBoard saves games in PGN (portable game notation) and positions in FEN (Forsythe-Edwards notation). If the option is True, a save style that is compatible with older versions of WinBoard (and of x +board) is used instead. +\par }\pard\plain \s1\ql \li120\ri0\sb280\sa120\sl-320\slmult0\nowidctlpar\faauto\outlinelevel0\adjustright\rin0\lin120\itap0 \b\f5\fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1\fs20 \page }{\cs58\f1\fs20\super +{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super +}{\f1 main}}K{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 User Interface Options}}${\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super $}{\f1 User Interface Options}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 UserInterfaceOptions}}}{\b0\f1\fs18\up6 }{\f1\fs20 User Interface Options +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 top}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 top}}}{\f1 /top }{\b0\f1 or }{\f1 /xtop}{\b0\f1 , or}{\f1 }{\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 alwaysOnTop}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 alwaysOnTopOpt}}}{\f1 /alwaysOnTop}{\i\f1 true|false}{\f1 +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Sets the }{\f1\uldb Always On Top}{\v\f1 AlwaysOnTop}{\f1 option. Default: False. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 queen}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 queen}}}{\f1 /queen}{\b0\f1 or }{\f1 /xqueen}{\b0\f1 ,}{\f1 }{\b0\f1 or}{\f1 }{\cs58\f1\super K{\footnote\ftnalt +\pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 alwaysPromoteToQueen}}#{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 alwaysPromoteToQueen}}}{\f1 /alwaysPromoteToQueen}{\i\f1 true|false}{\f1 +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Sets the }{\f1\uldb Always Queen}{\v\f1 AlwaysQueen}{\f1 option. Default: False. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 drag}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 drag}}}{\f1 /drag}{\b0\f1 or }{\f1 /xdrag}{\b0\f1 ,}{\f1 }{\b0\f1 or}{\f1 }{\cs58\f1\super K{\footnote\ftnalt +\pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 animateDragging}}#{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 animateDraggingOpt}}}{\f1 /animateDragging}{\i\f1 true|false}{\f1 +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Sets the }{\f1\uldb Animate Dragging}{\v\f1 animateDragging}{\f1 option. Default: True. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 animate}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 animate}}}{\f1 /animate }{\b0\f1 or }{\f1 /xanimate}{\b0\f1 , or}{\f1 }{\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 animateMoving}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 animateMovingOpt}}}{\f1 /animateMoving}{\i\f1 true|false}{\f1 +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Sets the }{\f1\uldb Animate Moving}{\v\f1 animateMoving}{\f1 option. Default: True. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 flip}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 flip}}}{\f1 /flip }{\b0\f1 or }{\f1 /xflip}{\b0\f1 , or}{\f1 }{\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 flipView}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 flipViewOption}}}{\f1 /flipView}{\i\f1 true|false}{\f1 +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 +If Auto Flip View is not set, or if you are observing but not participating in a game, then the positioning of the board at the start of each game depends on the flipView option. If flipView is False (the defaul +t), the board is positioned so that the white pawns move from the bottom to the top; if True, the black pawns move from the bottom to the top. In any case, the }{\f1\uldb Flip View}{\v\f1 FlipView}{\f1 + menu command can be used to flip the board after the game starts +\par }\pard\plain \ql \li115\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin115\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\b\super K{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\super K}{ autoflip}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 +\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\super #}{ autoflip}}}{\b /autoflip}{ or }{\b /xautoflip}{, or }{\cs58\super K{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\super K}{ autoFlipView}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\super #}{ autoFlipViewOption}}}{\b /autoFlipView }{\b\i true|false +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Sets the }{\f1\uldb Auto Flip View}{\v\f1 AutoFlipView}{\f1 option. Default: True. +\par }\pard\plain \ql \li115\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin115\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\b\super K{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\super K}{ autoraise}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\super #}{ autoraise}}}{\b /autoraise}{ or }{\b /xautoraise}{, or }{\cs58\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\super K}{ autoRaiseBoardOption}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\super #}{ autoRaiseBoardOption}}}{\b /autoRaiseBoard }{\b\i true|false +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Sets the }{\f1\uldb Auto Raise Board}{\v\f1 AutoFlipView}{\f1 option. Default: True. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 highdrag}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 highdrag}}}{\f1 /highdrag }{\b0\f1 or }{\f1 /xhighdrag}{\b0\f1 , or}{\f1 }{\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 highlightDragging\tab \tab }}#{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 highlightDraggingOpt}}}{\f1 /highlightDragging }{\i\f1 true|false}{\f1 +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Sets the }{\f1\uldb Highlight Dragging}{\v\f1 highlightDragging}{\f1 option. Default: False. + +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 highlight}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 highlight}}}{\f1 /highlight }{\b0\f1 or }{\f1 /xhighlight}{\b0\f1 , or}{\f1 }{\cs58\f1\super K{\footnote\ftnalt +\pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 highlightLastMove}}#{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 highlightLastMoveOpt}}}{\f1 /highlightLastMove}{\i\f1 true|false}{\f1 +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Sets the }{\f1\uldb Highlight Last Move}{\v\f1 highlightLastMoveOpt}{\f1 + option. Default: False. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 popup}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 popup}}}{\f1 /exit}{\b0\f1 or }{\f1 /xexit}{\b0\f1 ,}{\f1 }{\b0\f1 or}{\f1 }{\cs58\f1\super K{\footnote\ftnalt +\pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 popupMoveErrors}}#{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 popupMoveErrorsOpt}}}{\f1 /popupExitMessage}{\i\f1 true|false}{\f1 +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Sets the }{\f1\uldb Popup Exit Message}{\v\f1 popupExitMessageCmd}{\f1 + menu option. Default: False. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 popup}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 popup}}}{\f1 /popup}{\b0\f1 or }{\f1 /xpopup}{\b0\f1 ,}{\f1 }{\b0\f1 or}{\f1 }{\cs58\f1\super K{\footnote\ftnalt +\pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 popupMoveErrors}}#{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 popupMoveErrorsOpt}}}{\f1 /popupMoveErrors}{\i\f1 true|false}{\f1 +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Sets the }{\f1\uldb Popup Move Errors}{\v\f1 popupMoveErrorsCmd}{\f1 + menu option. Default: False. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 coords }}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 coords }}}{\f1 /coords }{\b0\f1 or }{\f1 /xcoords}{\b0\f1 , or}{\f1 }{\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 showCoords}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 showCoords}}}{\f1 /showCoords}{\i\f1 true|false}{\f1 +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Sets the }{\f1\uldb Show Coords}{\v\f1 showCoords}{\f1 option. Default: False. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 legal }}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 legal }}}{\f1 /legal }{\b0\f1 or }{\f1 /xlegal}{\b0\f1 , or}{\f1 }{\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 testLegality }}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 testLegality }}}{\f1 /testLegality}{\i\f1 true|false}{\f1 +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Sets the }{\f1\uldb Test Legality}{\v\f1 testLegalityCmd}{\f1 option. Default: True. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 size }}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 size }}}{\f1 /size }{\b0\f1 or}{\f1 }{\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 boardSize }}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 boardSize }}}{\f1 /boardSize }{\i\f1 sizename}{\f1 +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Sets the }{\f1\uldb Board Size}{\v\f1 BoardSizeCmd}{\f1 + option. Also chooses which board size any following Font options will affect. The default is the largest size that will fit on your screen. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\super K}{ wpc}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\super #}{ wpc}}}{\f1 /wpc}{\b0\f1 or }{\cs58\b0\f1\super K{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 whitePieceColor}}}{\cs58\f1\super #{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 whitePieceColor}}}{\f1 /whitePieceColor }{\i\f1 color\line }{\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\super K}{ bpc}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\super #}{ bpc}}}{\f1 /bpc }{\b0\f1 or }{\cs58\f1\super K{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 blackPieceColor}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 blackPieceColor}}}{\f1 /blackPieceColor }{\i\f1 color\line }{\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\super K}{ lsc}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\super #}{ lsc}}}{\f1 /lsc }{\b0\f1 or}{\i\f1 }{\cs58\f1\super K{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 lightSquareColor}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 lightSquareColor}}}{\f1 /lightSquareColor }{\i\f1 color}{\cs58\f1\super }{\f1 \line }{\cs58\f1\super K{\footnote\ftnalt +\pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\super K}{ dsc}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\super #}{ dsc}}}{\f1 /dsc }{\b0\f1 or}{\f1 }{\cs58\f1\super K{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 darkSquareColor}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 darkSquareColor}}}{\f1 /darkSquareColor }{\i\f1 color}{\cs58\f1\super }{\f1 +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 +Color specifications for white pieces, black pieces, light squares, and dark squares. Colors can be specified only by red/green/blue intensity, either in hexadecimal (as }{\i\f1 #rrggbb}{\f1 ) or in decimal (as }{\i\f1 rrr,ggg,bbb}{\f1 +). In the latter format, you must enclose the string in quotation marks if you leave spaces after the commas. The defaults are respectively #FFFFCC, #202020, #C8C365, and #77A26D. Available on the }{\f1\uldb Board Colors}{\v\f1 BoardColors}{\f1 + section of the }{\f1\uldb Board Options}{\v\f1 BoardOptions}{\f1 dialog. +\par }\pard\plain \ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 If you are using a }{\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 grayscale}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 grayscale}}}{\f1 grayscale monitor, try setting the colors to: +\par }\pard\plain \s19\ql \li520\ri0\sb60\sl-240\slmult0\keep\nowidctlpar\tx520\tx920\tx1320\tx1720\tx2120\faauto\adjustright\rin0\lin520\itap0 \f6\fs16\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f2\fs20 -whitePieceColor:#FFFFFF\line +-blackPieceColor:#000000\line -lightSquareColor:#CCCCCC\line -darkSquareColor:#999999 +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\super K}{ hsc}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\super #}{ hsc}}}{\f1 /hsc }{\b0\f1 or}{\f1 }{\cs58\f1\super K{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 highlightSquareColor}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 highlightSquareColor}}}{\f1 /highlightSquareColor }{\i\f1 color}{\cs58\f1\super }{\f1 \line }{\cs58\f1\super K +{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\super K}{ phc}}#{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\super #}{ phc}}}{\f1 /phc }{\b0\f1 or }{\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 premoveHighlightColor}}#{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 premoveHighlightColor}}}{\f1 /premoveHighlightColor }{\i\f1 color}{\cs58\f1\super +}{\f1 +\par }{\b0\f1 Color specifications for the }{\b0\f1\uldb Highlight Last Move}{\b0\v\f1 HighlightLastMove}{\b0\f1 and }{\b0\f1\uldb Premove}{\b0\v\f1 PremoveCmd}{\b0\f1 + options, respectively. Colors can be specified only by red/green/blue intensity, either in hexadecimal (as }{\b0\i\f1 #rrggbb}{\b0\f1 ) or in decimal (as }{\b0\i\f1 rrr,ggg,bbb}{\b0\f1 ). In the + latter format, you must enclose the string in quotation marks if you leave spaces after the commas. The defaults are respectively #FFFF00 and #FF0000, respectively. +\par }{\cs58\f1\super K{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 mono }}#{\footnote\ftnalt +\pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 mono }}}{\f1 /mono}{\b0\f1 or }{\f1 /xmono}{\b0\f1 ,}{\f1 }{\b0\f1 or +}{\f1 }{\cs58\f1\super K{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 monoMode}}#{\footnote\ftnalt +\pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 monoMode}}}{\f1 /monoMode}{\i\f1 true|false}{\f1 +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Determines whether WinBoard displays its pi +eces and squares in black and white (True) or color (False, the default). Available in the }{\f1\uldb Board Colors}{\v\f1 BoardColors}{\f1 section of the }{\f1\uldb Board Options}{\v\f1 BoardOptions}{\f1 dialog. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 colorShout}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 colorShout}}}{\f1 /colorShout}{\i\f1 \'93effects color\'94\line }{\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 colorSShout}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 colorSShout}}}{\f1 /colorSShout }{\i\f1 \'93effects color\'94\line }{\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 colorChannel1}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 colorChannel1}}}{\f1 /colorChannel1 }{\i\f1 \'93effects color\'94}{\f1 \line }{\cs58\f1\super K{\footnote\ftnalt +\pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 colorChannel}}#{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 colorChannel}}}{\f1 /colorChannel }{\i\f1 \'93effects color\'94}{\f1 \line }{ +\cs58\f1\super K{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 colorKibitz}}#{\footnote\ftnalt +\pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 colorKibitz}}}{\f1 /colorKibitz }{\i\f1 \'93effects color\'94}{\f1 +\line }{\cs58\f1\super K{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 colorTell}}#{\footnote\ftnalt +\pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 colorTell}}}{\f1 /colorTell }{\i\f1 \'93effects color\'94}{\f1 \line }{ +\cs58\f1\super K{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 colorChallenge}}#{\footnote\ftnalt +\pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 colorChallenge}}}{\f1 /colorChallenge }{\i\f1 \'93effects color\'94}{ +\f1 \line }{\cs58\f1\super K{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 colorRequest}}# +{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 colorRequest}}}{\f1 /colorRequest }{\i\f1 \'93 +effects color\'94}{\f1 \line }{\cs58\f1\super K{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 + colorSeek}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 colorSeek}}}{\f1 /colorSeek }{\i\f1 \'93 +effects color\'94}{\f1 \line }{\cs58\f1\super K{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 + colorNormal}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 colorNormal}}}{\f1 /colorNormal }{ +\i\f1 \'93effects color\'94 +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Select colors and effects +to colorize messages in the ICS Interaction window. The effects may be any combination of }{\b\f1 b}{\f1 old, }{\b\f1 i}{\f1 talic, }{\b\f1 u}{\f1 nderline, and }{\b\f1 s}{\f1 trikeout. Colors are specified as for squares and pieces. Available on the }{ +\f1\uldb ICS Interaction Colors}{\v\f1 ICSInteractionColors}{\f1 section of the }{\f1\uldb ICS Options}{\v\f1 ICSOptions}{\f1 + dialog. Limitation: On 256 color displays, Windows chooses the nearest solid color from the system palette, which will not always be close to the color you selected. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 colorBackground}}#{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 colorBackground}}}{\f1 /colorBackground }{\i\f1 color +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Sets the background color for the ICS Interaction window. Available on the }{\f1\uldb +ICS Interaction Colors}{\v\f1 ICSInteractionColors}{\f1 section of the }{\f1\uldb ICS Options}{\v\f1 ICSOptions}{\f1 dialog. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 colorize}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 colorize}}}{\f1 /colorize}{\cs58\f1\super }{\b0\f1 or }{\f1 /xcolorize}{\b0\f1 , or}{\f1 }{\cs58\f1\super K +{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 colorizeMessages}}#{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 colorizeMessages}}}{\f1 /colorizeMessages}{\i\f1 true|false}{\f1 +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 If True, WinBoard colorizes messages in the ICS Interaction window with the + colors listed above. Default: True. Available in the }{\f1\uldb ICS Interaction Colors}{\v\f1 ICSInteractionColors}{\f1 section of the }{\f1\uldb ICS Options}{\v\f1 ICSOptions}{\f1 dialog. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 clockFont}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 clockFont}}}{\f1 /clockFont \'93}{\i\f1 fontname:size effects}{\f1 \'94\line }{\cs58\f1\super K{\footnote\ftnalt +\pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 messageFont}}#{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 messageFont}}}{\f1 /messageFont \'93}{\i\f1 fontname:size effects}{\f1 \'94\line }{ +\cs58\f1\super K{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 coordFont}}#{\footnote\ftnalt +\pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 coordFont}}}{\f1 /coordFont \'93}{\i\f1 fontname:size effects}{\f1 \'94 +\line }{\cs58\f1\super K{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 tagsFont}}#{\footnote\ftnalt +\pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 tagsFont}}}{\f1 /tagsFont \'93}{\i\f1 fontname:size effects}{\f1 \'94 +\line }{\cs58\f1\super K{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 commentFont}}# +{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 commentFont}}}{\f1 /commentFont \'93}{\i\f1 +fontname:size effects}{\f1 \'94\line }{\cs58\f1\super K{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 + icsFont}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 icsFont}}}{\f1 /icsFont \'93}{\i\f1 +fontname:size effects}{\f1 \'94 +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 +The fonts used respectively for the clocks, the message display line, rank and file coordinate labels, the Edit Tags dialog, the Edit Comment + dialog, and the ICS Interaction window. These options may be given more than once. Each occurrence affects the fonts for the current board size; that is, the size given in the last preceding /boardSize option, if any, or else the default size. The font s +ize may contain a decimal point, and the effects may be any combination of }{\b\f1 b}{\f1 old, }{\b\f1 i}{\f1 talic, }{\b\f1 u}{\f1 nderline, and }{\b\f1 s}{\f1 trikeout. Example: }{\f2\fs16 /clockFont="Arial:20.0 bi".}{\f1 Available on the }{\f1\uldb +Fonts}{\v\f1 Fonts}{\f1 menu.}{\f2\fs16 +\par }\pard\plain \s2\ql \li115\ri0\sb120\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin115\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 soundShout}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 soundShout}}}{ /soundShout}{\i sound\line }{\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 soundSShout}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 soundSShout}}}{ /soundSShout }{\i sound\line }{\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 soundChannel1}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 soundChannel1}}}{ /soundChannel1 }{\i sound}{\line }{\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 soundChannel}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 soundChannel}}}{ /soundChannel }{\i sound}{\line }{\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 soundKibitz}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 soundKibitz}}}{ /soundKibitz }{\i sound}{\line }{\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 soundTell}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 soundTell}}}{ /soundTell }{\i sound}{\line }{\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 soundChallenge}}#{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 soundChallenge}}}{ /soundChallenge }{\i sound}{\line }{\cs58\f1\super K +{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 soundRequest}}#{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 soundRequest}}}{ /soundRequest }{\i sound}{\line }{\cs58\f1\super K +{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 soundMove}}#{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 soundMove}}}{ /soundMove }{\i sound}{\cs58\f1\super }{\line }{\cs58\f1\super K +{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 soundBell}}#{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 soundBell}}}{ /soundBell }{\i sound}{\cs58\f1\super }{ +\par }\pard \s2\ql \li115\ri0\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin115\itap0 {\cs58\f1\super K{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 +\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 soundIcsWin}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 +\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 soundIcsWin}}}{\f1 /soundIcsWin }{\i\f1 sound}{\f1 \line }{\cs58\f1\super K{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 soundIcsLoss}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 soundIcsLoss}}}{\f1 /soundIcsLoss }{\i\f1 sound}{\cs58\f1\super }{\f1 \line }{\cs58\f1\super K{\footnote\ftnalt +\pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 soundIcsDraw}}#{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 soundIcsDraw}}}{\f1 /soundIcsDraw }{\i\f1 sound}{\cs58\f1\super }{\f1 \line }{ +\cs58\f1\super K{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 soundIcsUnfinished}}# +{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 soundIcsUnfinished}}}{\f1 /soundIcsUnfinished }{ +\i\f1 sound}{\cs58\f1\super }{\f1 +\par }\pard \s2\ql \li115\ri0\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin115\itap0 {\cs58\f1\super K{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 +\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 soundIcsAlarm}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 +\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 soundIcsAlarm}}}{\f1 /soundIcsAlarm }{\i\f1 sound}{\cs58\f1\super }{\f1 +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 +Associate sounds with WinBoard events. Most of the events are the same ones that cause text colorization. In addition, }{\b\f1 soundMove}{\f1 is played if a chess engine or another player makes a move. }{\b\f1 SoundBell}{\f1 + is played if the chess server sends an ASCII BEL character (Ctrl+G). Available on the }{\f1\uldb Sounds}{\v\f1 Sounds}{\f1 menu. +\par }\pard\plain \ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\b SoundIcsWin}{, }{\b soundIcsLoss}{, }{\b soundIcsDraw}{ and }{\b soundIcsUnfinished}{ + are played at the conclusion of an ICS game. The result of the game determines which sound is played. +\par }{\b SoundIcsAlarm}{ is played when your game clock counts down to }{\uldb icsAlarmTime}{\v\uldb icsAlarmTime}{. +\par }\pard \ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\jclisttab\tx480\faauto\adjustright\rin0\lin120\itap0 {\f1 The }{\i\f1 sound}{\f1 argument may be one of the following: +\par {\pntext\pard\plain\f3\fs20 \loch\af3\dbch\af0\hich\f3 \'b7\tab}}\pard \ql \fi-360\li480\ri0\sb80\sl-240\slmult0\nowidctlpar\jclisttab\tx480{\*\pn \pnlvlblt\ilvl0\ls2\pnrnot0\pnf3\pnstart1\pnindent360\pnsp120\pnhang{\pntxtb \'b7}} +\faauto\ls2\adjustright\rin0\lin480\itap0 {\f1 The name of a }{\f2 .wav}{\f1 file. The filename is interpreted relative to WinBoard's installation directory (the directory containing WinBoard.exe). +\par {\pntext\pard\plain\f3\fs20 \loch\af3\dbch\af0\hich\f3 \'b7\tab}}\pard \ql \fi-360\li480\ri0\sb80\sl-240\slmult0\nowidctlpar\jclisttab\tx480{\*\pn \pnlvlblt\ilvl0\ls2\pnrnot0\pnf3\pnstart1\pnindent360\pnsp120\pnhang{\pntxtb \'b7}} +\faauto\ls2\adjustright\rin0\lin480\itap0 {\f2 $}{\f1 , indicating the default system sound. +\par {\pntext\pard\plain\f3\fs20 \loch\af3\dbch\af0\hich\f3 \'b7\tab}}\pard \ql \fi-360\li480\ri0\sb80\sl-240\slmult0\nowidctlpar\jclisttab\tx480{\*\pn \pnlvlblt\ilvl0\ls2\pnrnot0\pnf3\pnstart1\pnindent360\pnsp120\pnhang{\pntxtb \'b7}} +\faauto\ls2\adjustright\rin0\lin480\itap0 {\f2 !}{\f1 followed by the name of a built-in WinBoard wave resource. +\par {\pntext\pard\plain\f3\fs20 \loch\af3\dbch\af0\hich\f3 \'b7\tab}}\pard \ql \fi-360\li480\ri0\sb80\sl-240\slmult0\nowidctlpar\jclisttab\tx480{\*\pn \pnlvlblt\ilvl0\ls2\pnrnot0\pnf3\pnstart1\pnindent360\pnsp120\pnhang{\pntxtb \'b7}} +\faauto\ls2\adjustright\rin0\lin480\itap0 {\f2 !}{\f1 alone, or \'93\'94 (empty string), indicating silence. +\par }\pard \ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 {\f1 The default for soundMove and soundBell is }{\f2 $}{\f1 , while the others default to silence. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 icsMenu}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 icsMenu}}}{\f1 /icsMenu=\{}{\i\f1 entries}{\f1 \} }{\b0\f1 or }{\f1 /icsMenu=@}{\i\f1 filename +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 This option lets you customize the right-button }{\f1\uldb context menu}{\v\f1 +ICSInteractionContextMenu}{\f1 that is available in the upper (output) pane of the ICS Interaction window. It consists of a list of menu entries, one per line. If the option value st +arts with an @ sign, it is the name of a file that contains the entries. Each entry contains either four fields separated by commas or the single character }{\f2 "-"}{\f1 . The fields are: +\par {\pntext\pard\plain\f5\fs20 \hich\af5\dbch\af0\loch\f5 1.\tab}}\pard\plain \ql \fi-360\li480\ri0\sb80\sl-240\slmult0\nowidctlpar\jclisttab\tx480{\*\pn \pnlvlbody\ilvl0\ls14\pnrnot0\pndec\pnstart1\pnindent360\pnsp120\pnhang{\pntxta .}} +\faauto\ls14\adjustright\rin0\lin480\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {The menu text. If this field begins with }{\f2 "|"}{, the item begins a new column in the menu and the }{\f2 "|"}{ + is not shown. If this field contains an }{\f2 "&"}{, the character after the ampersand is underlined in the menu and acts as a keyboard shortcut for the item when the menu is displayed. Do not assign the same shortcut key to two different menu items. + +\par {\pntext\pard\plain\s26 \f1\fs20 \hich\af1\dbch\af0\loch\f1 2.\tab}}\pard\plain \s26\ql \fi-360\li480\ri0\sl-240\slmult0\nowidctlpar\jclisttab\tx480{\*\pn \pnlvlbody\ilvl0\ls14\pnrnot0\pndec\pnstart1\pnindent360\pnsp120\pnhang{\pntxta .}} +\faauto\ls14\adjustright\rin0\lin480\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Text to insert into the input pane. The text cannot include a comma. You can use ICS aliases to get around this limitation. +\par {\pntext\pard\plain\s26 \f1\fs20 \hich\af1\dbch\af0\loch\f1 3.\tab}}\pard \s26\ql \fi-360\li480\ri0\sl-240\slmult0\nowidctlpar\jclisttab\tx480{\*\pn \pnlvlbody\ilvl0\ls14\pnrnot0\pndec\pnstart1\pnindent360\pnsp120\pnhang{\pntxta .}} +\faauto\ls14\adjustright\rin0\lin480\itap0 {\f1 A flag (1 or 0) saying whether to insert a space and }{\i\f1 name }{\f1 (see }{\f1\uldb above}{\v\f1 Tell}{\f1 ) after the text. If you set this flag, you might als +o want to put "(name)" into the menu text as a memory aid. +\par {\pntext\pard\plain\s26 \f1\fs20 \hich\af1\dbch\af0\loch\f1 4.\tab}}\pard \s26\ql \fi-360\li480\ri0\sl-240\slmult0\nowidctlpar\jclisttab\tx480{\*\pn \pnlvlbody\ilvl0\ls14\pnrnot0\pndec\pnstart1\pnindent360\pnsp120\pnhang{\pntxta .}} +\faauto\ls14\adjustright\rin0\lin480\itap0 {\f1 A flag (1 or 0) saying whether the result should be sent immediately to ICS or left in the input pane for further editing. +\par }\pard\plain \ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {The entry }{\f2 "-"}{ produces a separator line in the menu. The top three menu en +tries are always }{\b Copy and Paste}{, }{\b Copy}{, and }{\b Paste}{, but you have full control over the rest of the menu. +\par }{\f1 The default menu is: +\par }\pard\plain \s19\ql \li520\ri0\sb60\sl-240\slmult0\keep\nowidctlpar\tx520\tx920\tx1320\tx1720\tx2120\faauto\adjustright\rin0\lin520\itap0 \f6\fs16\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f2\fs20 \endash \line &Who,who,0,1\line +Playe&rs,players,0,1\line &Games,games,0,1\line &Sought,sought,0,1\line |&Tell (name),tell,1,0\line M&essage (name),message,1,0\line \endash \line &Finger (name),finger,1,1\line &Vars (name),vars,1,1\line &Observe (name),observe,1,1\line +&Match (name),match,1,1\line Pl&ay (name),play,1,1 +\par }\pard\plain \ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 There is no graphical user interface to set this option. To change it, edit your }{\f1\uldb +settings}{\v\f1 settings}{\f1 file with a plain text editor such as Notepad. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 icsNames}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 icsNames}}}{\f1 /icsNames=\{}{\i\f1 names}{\f1 \} }{\b0\f1 or }{\f1 /icsNames=@}{\i\f1 filename +\par }\pard\plain \ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 +This option lets you customize the drop-down list of ICS names that appears in the WinBoard startup dialog. It consists of a list of strings, one per line. If the option value starts with an @ sign, it is the +name of a file that contains the strings. When you select a string from the drop-down list, WinBoard prepends the text \'94/ics /icsHost=\'94 + and adds the result to the command-line options. There is no graphical user interface to set this option. To change it, edit your }{\f1\uldb settings}{\v\f1 settings}{\f1 file with a plain text editor such as Notepad. +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 firstChessProgramNames}}#{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 firstChessProgramNames}}}{\f1 /firstChessProgramNames=\{}{\i\f1 names}{\f1 \} }{ +\b0\f1 or }{\f1 /firstChessProgramNames="@}{\i\f1 filename}{\f1 " +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 +This option lets you customize the first drop-down list of chess engine names that appears in the WinBoard s +tartup dialog. It consists of a list of strings, one per line. If the option value starts with an @ sign, it is the name of a file that contains the strings. When you select a string from the drop-down list, WinBoard prepends the text \'94 +/cp /firstChessProgram=\'94 and adds the result to the command-line options. +\par +\par There is no graphical user interface to set this option. To change it, edit your }{\f1\uldb settings}{\v\f1 settings}{\f1 file with a plain text editor such as Notepad. Example: +\par }\pard\plain \s19\ql \li520\ri0\sb60\sl-240\slmult0\keep\nowidctlpar\tx520\tx920\tx1320\tx1720\tx2120\faauto\adjustright\rin0\lin520\itap0 \f6\fs16\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f2 /firstChessProgramNames=\{GNUChess\line WCrafty-15_1 +1 /fd="C:\\Program Files\\Crafty"\line ArasanX /fd="C:\\Program Files\\Arasan\\Arasan 4.1"\line "EXchess xb" /fd=C:\\EXchess\line Comet-WB /fd=C:\\Comet\line \} +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 secondChessProgramNames}}#{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 secondChessProgramNames}}}{\f1 /secondChessProgramNames=\{}{\i\f1 names}{\f1 \}}{ +\b0\f1 or }{\f1 /secondChessProgramNames="@}{\i\f1 filename}{\f1 "}{\i\f1 +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 This option lets you customize the second drop-d +own list of chess engine names that appears in the WinBoard startup dialog. It consists of a list of strings, one per line. If the option value starts with an @ sign, it is the name of a file that contains the strings. When you select a string from the dr +op-down list, WinBoard prepends the text \'94/cp /secondChessProgram=\'94 and adds the result to the command-line options. +\par +\par There is no graphical user interface to set this option. To change it, edit your }{\f1\uldb settings}{\v\f1 settings}{\f1 file with a plain text editor such as Notepad. Example: +\par }\pard\plain \s19\ql \li520\ri0\sb60\sl-240\slmult0\keep\nowidctlpar\tx520\tx920\tx1320\tx1720\tx2120\faauto\adjustright\rin0\lin520\itap0 \f6\fs16\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {/secondChessProgramNames=\{GNUChess\line +WCrafty-15_11 /sd="C:\\\\Program Files\\\\Crafty\\"\line ArasanX /sd="C:\\Program Files\\Arasan\\Arasan 4.1"\line "EXchess xb" /sd=C:\\EXchess\line Comet-WB /sd=C:\\Comet\line \}}{\f1 +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 xy coordinates of board}}#{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 xy}}}{\f1 /x=}{\i\f1 xcoord }{\f1 /y=}{\i\f1 ycoord +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Sets the initial location of the bo +ard window, giving the screen coordinates of the upper left-hand corner. Both arguments must be given together. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 xywh coordinates of Analysis window}}#{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 xywh}}}{\f1 /analysisX=}{\i\f1 xcoord }{\f1 /analysisY=}{\i\f1 ycoord}{\f1 + /analysisW=}{\i\f1 width}{\f1 /analysisH=}{\i\f1 height +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Sets the initial location and size of the Analysis window, giving th +e screen coordinates of the upper left-hand corner, the width, and the height. All four arguments must be given together. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 xywh coordinates of Comment window}}#{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 xywh}}}{\f1 /commentX=}{\i\f1 xcoord }{\f1 /commentY=}{\i\f1 ycoord}{\f1 + /commentW=}{\i\f1 width}{\f1 /commentH=}{\i\f1 height +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Sets the initial location and size of the Comment window, givi +ng the screen coordinates of the upper left-hand corner, the width, and the height. All four arguments must be given together. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 xywh coordinates of Game List window}}#{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 xywh}}}{\f1 /gameListX=}{\i\f1 xcoord }{\f1 /gameListY=}{\i\f1 ycoord}{\f1 + /gameListW=}{\i\f1 width}{\f1 /gameListH=}{\i\f1 height +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Sets the initial location and size of the Game List w +indow, giving the screen coordinates of the upper left-hand corner, the width, and the height. All four arguments must be given together. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 xywh coordinates of ICS Interaction window}}#{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 xywh}}}{\f1 /icsX=}{\i\f1 xcoord }{\f1 /icsY=}{\i\f1 ycoord}{\f1 /icsW=}{\i\f1 +width}{\f1 /icsH=}{\i\f1 height +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Sets the initial location and size of the ICS Interaction wind +ow, giving the screen coordinates of the upper left-hand corner, the width, and the height. All four arguments must be given together. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 xywh coordinates of Tags window}}#{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 xywh}}}{\f1 /tagsX=}{\i\f1 xcoord }{\f1 /tagsY=}{\i\f1 ycoord}{\f1 /tagsW=}{ +\i\f1 width}{\f1 /tagsH=}{\i\f1 height +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Sets the initial location and size of the Tags window, giving + the screen coordinates of the upper left-hand corner, the width, and the height. All four arguments must be given together. +\par }\pard\plain \s1\ql \li120\ri0\sb280\sa120\sl-320\slmult0\nowidctlpar\faauto\outlinelevel0\adjustright\rin0\lin120\itap0 \b\f5\fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1\fs20 \page }{\cs58\f1\fs20\super +{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super +}{\f1 main}}K{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Other Options}}${\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super $}{\f1 Other Options}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 OtherOptions}}}{\b0\f1\fs18\up6 }{\f1\fs20 Other Options +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 ncp }}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 ncp }}}{\f1 /ncp}{\b0\f1 or }{\f1 /xncp}{\b0\f1 ,}{\f1 }{\b0\f1 or}{\f1 }{\cs58\f1\super K{\footnote\ftnalt +\pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 noChessProgram}}#{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 noChessProgram}}}{\f1 /noChessProgram}{\i\f1 true|false}{\f1 +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 If this option is True, WinBoard acts as a passive chessboar +d; it does not start a chess program or connect to ICS. This option also sets clockMode to False. Default: False. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 mode}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 mode}}}{\f1 /mode}{\b0\f1 or }{\cs58\f1\super K{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 initialMode}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 initialMode}}}{\f1 /initialMode }{\i\f1 modename +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 If this option is given, WinBoard selects the given }{\i\f1 modename}{\f1 from the }{\f1\uldb +Mode menu}{\v\f1 ModeMenu }{\f1 after starting and (if applicable) processing the }{\f1\uldb loadGameFile}{\v\f1 loadGameFile }{\f1 or }{\f1\uldb loadPositionFile}{\v\f1 loadPositionFile }{\f1 +option. Default: "". Other supported values are TwoMachines, AnalyzeFile, Analysis, MachineWhite, MachineBlack, EditGame, EditPosition, and Training. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 variant}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 variant}}}{\f1 /variant}{\b0\f1 }{\i\f1 varname}{\f1 +\par }\pard\plain \ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 { +Activates preliminary, partial support for playing chess variants against a local engine or editing variant games. This flag is not needed in ICS mode. Recognized variant names are: +\par normal\tab Normal chess\line wildcastle\tab Shuffle chess, king can castle from d file\line nocastle\tab Shuffle chess, no castling allowed\line fischerandom\tab Fischer Random shuffle chess\line bughouse\tab Bughouse, ICC/FICS rules\line crazyhouse\tab +Crazyhouse, ICC/FICS rules\line losers \tab Lose all pieces or get mated (ICC wild 17)\line suicide\tab Lose all pieces including king (FICS)\line giveaway\tab Try to have no legal moves (ICC wild 26)\line twokings\tab Weird ICC wild 9\line kriegspiel +\tab Opponent's pieces are invisible\line atomic \tab Capturing piece explodes (ICC wild 27)\line 3check\tab Win by giving check 3 times (ICC wild 25) +\par In the shuffle variants, WinBo +ard does not shuffle the pieces, but you can do it by hand using Edit Position. Some variants are supported only in ICS mode, including fischerandom, bughouse, and kriegspiel. The winning/drawing conditions in crazyhouse (offboard interposition on mate), +losers, suicide, giveaway, atomic, and 3check are not fully understood. In crazyhouse, WinBoard does not yet keep track of offboard pieces. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 debug}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 debug}}}{\f1 /debug}{\b0\f1 or }{\f1 /xdebug}{\b0\f1 ,}{\f1 }{\b0\f1 or}{\f1 }{\cs58\f1\super K{\footnote\ftnalt +\pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 debugMode}}#{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 debugMode}}}{\f1 /debugMode}{\i\f1 true|false}{\f1 +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Writes debugging information to the file \'93WinBoard.debug\'94, includin +g all commands sent to the chess engine, all output received from it, and all commands sent to ICS. You can press Ctrl+Alt+F12 to turn this option on or off while WinBoard is running. Each time you turn it on, any existing debug file is overwritten. + +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 rsh }}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 rsh }}}{\f1 /rsh }{\b0\f1 or}{\f1 }{\cs58\f1\super K{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 remoteShell }}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 remoteShell }}}{\f1 /remoteShell }{\i\f1 shellname}{\f1 +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Name of the command used to run programs remotely. If this option is not given, WinBoard}{ +\i\f1 }{\f1 uses its own built-in implementation of the Unix }{\i\f1 rcmd}{\f1 protocol (the protocol used by }{\i\f1 rsh}{\f1 ). +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 ruser }}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 ruser }}}{\f1 /ruser }{\b0\f1 or}{\f1 }{\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 remoteUser }}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 remoteUser }}}{\f1 /remoteUser }{\i\f1 username}{\f1 +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 User nam +e on the remote system when running programs with the remoteShell. The default is your local user name. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 ini }}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 ini }}}{\f1 /ini }{\b0\f1 or}{\f1 }{\cs58\f1\super K{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 settingsFile }}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 settingsFile }}}{\f1 /settingsFile }{\i\f1 filename\line }{\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 at sign}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 atsign }}}{\f1 @ }{\i\f1 file-name +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 See }{\f1\uldb Settings}{\v\f1 Settings}{\f1 . +\par }\pard\plain \s1\ql \li120\ri0\sb280\sa120\sl-320\slmult0\nowidctlpar\faauto\outlinelevel0\adjustright\rin0\lin120\itap0 \b\f5\fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1\fs20 \page }{\cs58\f1\fs20\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Initialization files}}K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Files}}${\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super $}{\f1 Files}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 Files}}+{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super +}{\f1 main}}}{\f1\fs20 INITIALIZATION FILES +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Settings }}}{\f1\fs18\up6 }{\cs58\f1\super #{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 Settings }}}{\f1 Settings +\par }\pard\plain \ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {When WinBoard starts up, it reads option settings from a file named }{\i WinBoard.ini }{ +in its installation directory (the directory containing WinBoard.exe). Options in this file have the same format as }{\uldb command line options}{\v Options}{, except that they do not all have to be on a single line. You can put + a comment in a settings file by preceding it with a semicolon (}{\f2 ;}{). +\par The WinBoard.ini file is read before the command line is processed, so any options you give on the command line override options in the file. +\par }{\f1 If WinBoard encounters a /}{\f1\uldb settingsFile}{\v\f1 settingsFile}{\f1 }{\i\f1 filename }{\f1 or }{\f1\uldb @}{\v\f1 atsign}{\i\f1 filename }{\f1 +option while reading settings (whether from the command line or a file), it reads more settings from the given file before reading the next option. +\par The }{\f1\uldb Save Settings Now}{\v\f1 SaveSettings}{\f1 menu command writes the current values of most options to a file. In addition, settings are saved automatically when WinBoard exits if }{\f1\uldb Save Settings on Exit}{\v\f1 SaveSettingsOnExit}{ +\f1 is checked. The settings are written to the last file named in a /settingsFile command, if any; otherwise to WinBoard.ini}{\i\f1 .}{\f1 The @ option does not affect which file settings are saved to. +\par Warning: Because Save Settings overwrites the last settings file (usually WinBoard.ini) and only saves a subset of WinBoard's options, you should not add settings of more options to such a fil +e with a text editor. If you do this, your additional options will be lost on the next Save Settings. You can change the values of existing settings freely, using Notepad or any plain text editor. Be careful not to do this while WinBoard is running, howev +er, unless you know that Save Settings on Exit is off. Otherwise all your changes will be overwritten and lost when WinBoard exits. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 ICS Logon}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 ICSLogon}}}{\f1 ICS Logon +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Whenever WinBoard connects to the Internet Chess Server, if it finds a file called }{\i\f1 +ICS.ini }{\f1 in its installation directory}{\i\f1 ,}{\f1 it feeds the file's contents to the ICS as commands. Usually the first two lines of the file should be your ICS user name and password. You can specify a different name instead of }{\i\f1 ICS.ini} +{\f1 by using the }{\f1\uldb icslogon}{\v\f1 icslogon}{\f1 command line option. +\par }\pard\plain \s1\ql \li120\ri0\sb280\sa120\sl-320\slmult0\nowidctlpar\faauto\outlinelevel0\adjustright\rin0\lin120\itap0 \b\f5\fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1\fs20 \page }{\cs58\f1\fs20\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Installing Chess Engines}}${\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super $}{\f1 Installing Chess Engines}}#{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 InstallingChessEngines}}+{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super +}{\f1 main}}}{\f1\fs20 INSTALLING CHESS ENGINES +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Introduction +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 +WinBoard is capable of operating with many different chess engines. You can play chess against a compatible engine, set up matches between two engines, or (advanced users only) run an automated computer player on an ICS. +\par }\pard\plain \ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 +Typically, the main difficulty in installing a new chess engine for use by WinBoard comes in getting the engine itself running and setting its options appropriately. The connection to WinBoard is relatively straightforward. +\par WinBoard-compatible chess engi +nes are Win32 command line programs that you can run by hand in an MS-DOS Prompt box and type human-readable commands to. WinBoard connects to an engine simply by starting the engine up in the background and communicating with it through a pair of pipes. +Therefore the basic procedure for installing an engine is: +\par }\pard\plain \s20\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 1. Get a copy of the engine and any supporting files it needs. +\par }\pard\plain \ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 +2. Install and configure the engine as a command-line program by following the instructions that come with it. Try it out by running it from the command line in an MS-DOS Prompt box and make sure it works. +\par 3. Optional, but recommended: Try out the WinBoard plus engine combination by running WinBoard with the proper command line arguments in an MS-DOS Prompt box. +\par 4. Create a shortcut on your desktop or Start menu to run the engine with WinBoard. +\par 5. Optionally edit your WinBoard.ini file to add the engine to the drop-down lists on WinBoard's startup dialog. +\par This document cannot explain steps 1 and 2 in detail for all engines, but we will take you through all five steps in outline, using Crafty as an example. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Example: Crafty +\par }\pard\plain \ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 1. Choose a directory to put Crafty in. We'll use }{\f2 C:\\Program Files\\Crafty}{\f1 + in this example. Download your copy of Crafty into this directory from its author's FTP site, }{\f2 ftp://ftp.cis.uab.edu/pub/hyatt}{\f1 . At this writing, you will need at least the following files: +\par }\pard\plain \s19\ql \li520\ri0\sb60\sl-240\slmult0\keep\nowidctlpar\tx520\tx920\tx1320\tx1720\tx2120\faauto\adjustright\rin0\lin520\itap0 \f6\fs16\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f2\fs20 read.me\line v15/crafty.doc\line v15/crafty.faq +\line v15/wcrafty-15.*.exe}{\f1\fs20 (where * is replaced by the largest number there)\line }{\f2\fs20 common/start.zip}{\fs20 \line }{\f2\fs20 common/medium.zip}{\fs20 }{\f1\fs20 (or another book). +\par }\pard\plain \s16\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 2. + The first three files are documentation that you can read with a text editor. Read the read.me file first and follow the instructions carefully. This will take some time. Do not write to the author of WinBoard if you have trouble with the instructions in + the Crafty read.me. Try running Crafty from an MS-DOS Prompt box and make sure it works before you go on. +\par }\pard\plain \ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 3. Optional, but recommended: In an MS-DOS Prompt box,}{ }{\f2 cd }{\f1 +to the directory where WinBoard is installed, typically }{\f2 "C:\\Program Files\\WinBoard"}{\f1 . Then type the following command line. Use the actual name of the wcrafty file you downloaded, not an }{\f2 *}{\f1 +, and if your browser changed the first period to an underscore when you downloaded the file, make that change in the command line too. +\par }\pard\plain \s63\ql \fi-720\li1440\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin1440\itap0 \f2\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {WinBoard /cp /fcp=WCrafty-15.* /fd="C:\\Program Files\\ +Crafty" /scp=WCrafty-15.* /sd="C:\\Program Files\\Crafty" +\par }\pard\plain \s16\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 +WinBoard should start up, with Crafty running as its chess engine. Check that you can play chess against Crafty. +\par }\pard\plain \ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 4. To make a shortcut or Start menu entry for Crafty: Right +-click on the desktop and select New/Shortcut. Use the Browse button to find your winboard.exe file and get its name into the Command Line box. (It usually will be "C:\\Program Files\\WinBoard\\ +winboard.exe".) Click in the Command Line box and hit the End key to go to the end. Add the following to the end of the command line, }{\i\f1 after}{\f1 the closing quotation mark. Use the actual name of the wcrafty file you downloaded, not an }{\f2 *}{ +\f1 , and if your browser changed the first period to an underscore when you downloaded the file, make that change in the command line too. +\par }\pard\plain \s63\ql \fi-720\li1440\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin1440\itap0 \f2\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {/cp /fcp=WCrafty-15.* /fd="C:\\Program Files\\Crafty" \line /scp=WCrafty-15.* /sd="C: +\\Program Files\\Crafty" +\par }\pard\plain \s62\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 +Press Next, choose a name for the shortcut, and press Finish. You can now use this shortcut to run WinBoard with Crafty. Double-click it to check that it works. You can drag or copy the shortcut into your Start menu if you like. +\par }\pard\plain \ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 5. To add Crafty as an option in the WinBoard Startup dialog, edit your }{\f1\uldb +WinBoard.ini file}{\v\f1 Settings}{\f1 with Notepad or another plain text editor, carefully following the example shown under }{\f1\uldb /firstChessProgramNames}{\v\f1 firstChessProgramNames}{\f1 above. +\par }\pard\plain \s2\ql \li120\ri0\sb120\sa60\sl-240\slmult0\nowidctlpar\faauto\outlinelevel1\adjustright\rin0\lin120\itap0 \b\f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 For more information +\par }\pard\plain \ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 If you would like to run an automated computer player on the ICS, see the separate file }{\f2 +zippy.README}{\f1 . If you would like to write your own engine to interface to WinBoard, see the separate file }{\f2 engine-intf.html}{\f1 +, and join the mailing list mentioned there. Both files are included in the WinBoard distribution. You might also want to get the source code for WinBoard. It is available from the author's Web page, http://www.tim-mann.org/chess.html}{\f2 .}{\f1 +\par }\pard\plain \s1\ql \li120\ri0\sb280\sa120\sl-320\slmult0\nowidctlpar\faauto\outlinelevel0\adjustright\rin0\lin120\itap0 \b\f5\fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1\fs20 \page }{\cs58\f1\fs20\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Firewalls}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 Firewalls}}${\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super $}{\f1 Firewalls}}+{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super +}{\f1 main}}}{\f1\fs18\up6 }{\f1\fs20 FIREWALLS +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 By default, "WinBoard /ics"}{\i\f1 }{\f1 +communicates with an Internet Chess Server by opening a TCP socket directly from the machine it is running on to the ICS. If there is a firewall between yo +ur machine and the ICS, this won't work. Here are some recipes for getting around common kinds of firewalls using special options to WinBoard}{\i\f1 .}{\f1 Important: See the paragraph in the }{\f1\uldb LIMITATIONS}{\v\f1 LIMITATIONS}{\f1 + section below about extra echoes. +\par }\pard\plain \ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Suppose that you can +'t telnet directly to ICS, but you can telnet to a firewall host, log in, and then telnet from there to ICS. Let's say the firewall is called fire.wall.com. Set command-line options as follows: +\par }\pard\plain \s19\ql \li520\ri0\sb60\sl-240\slmult0\keep\nowidctlpar\tx520\tx920\tx1320\tx1720\tx2120\faauto\adjustright\rin0\lin520\itap0 \f6\fs16\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f2\fs20 +WinBoard -ics -icshost fire.wall.com -icsport 23 +\par }\pard\plain \ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Then when you run WinBoard}{\i\f1 }{\f1 +in ICS mode, you will be prompted to log in to the firewall host. (This works because port 23 is the standard telnet login service.) Do so, then telnet to ICS, using a command like "telnet chessclub.com 5000", or whatever command the firewal +l provides for telnetting to port 5000. +\par If your firewall lets you telnet (or rlogin) to remote hosts, but doesn't let you telnet to port 5000, you will have to find some other host outside the firewall that does let you do this, and hop through it. For ins +tance, suppose you have an account at foo.edu. Follow the recipe above, but instead of typing "telnet chessclub.com 5000" to the firewall, type "telnet foo.edu" (or "rlogin foo.edu"), log in there, and then type "telnet chessclub.com 5000". +\par Exception: chessclub.com itself lets you connect to the chess server on the default telnet port (23), which is what you get if you don\rquote t specify a port to the telnet program. But the other chess servers don\rquote t allow this. +\par Suppose that you can't telnet directly to ICS, but you can use rsh to run programs on a firewall host, and that host can telnet to ICS. Let's say the firewall is called rsh.wall.com. Set command-line options as follows: +\par }\pard\plain \s19\ql \li520\ri0\sb60\sl-240\slmult0\keep\nowidctlpar\tx520\tx920\tx1320\tx1720\tx2120\faauto\adjustright\rin0\lin520\itap0 \f6\fs16\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f2\fs20 +WinBoard -ics -gateway rsh.wall.com -icshost chessclub.com +\par }\pard\plain \ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Then when you run WinBoard}{\i\f1 }{\f1 +in ICS mode, it will connect to the ICS by using rsh to run the command "telnet chessclub.com 5000" on host rsh.wall.com. +\par ICC timestamp and FICS timeseal do not work through many}{\b\f1 }{\f1 firewalls. You can use them only if your firewall gives a clean TCP connecti +on with a full 8-bit wide path. If your firewall allows you to get out only by running a special telnet program, you can't use timestamp or timeseal across it. But if you have access to a computer just outside your firewall, and you have much lower netlag + +when talking to that computer than to the ICS, it might be worthwhile running timestamp there. Follow the instructions above for hopping through a host outside the firewall (foo.edu in the example), but run timestamp or timeseal on that host instead of te +lnet. +\par }\pard\plain \s20\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 +Suppose that you have a SOCKS firewall that requires you to go through some extra level of authentication, but after that will give you a clean 8-bit wide TCP connection to the chess server. In that case, if you are using timestamp or timeseal, you ne +ed to somehow socksify it; if not, you need to socksify WinBoard itself. Socksification is beyond the scope of this document, but see the SOCKS Web site at http://www.socks.nec.com/how2socksify.html. +\par }\pard\plain \s1\ql \li120\ri0\sb280\sa120\sl-320\slmult0\nowidctlpar\faauto\outlinelevel0\adjustright\rin0\lin120\itap0 \b\f5\fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1\fs20 \page }{\cs58\f1\fs20\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Limitations}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 Limitations}}${\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super $}{\f1 Limitations}}+{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super +}{\f1 main}}}{\f1\fs18\up6 }{\f1\fs20 LIMITATIONS +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 WinBoard}{\i\f1 }{\f1 is a Win32 application. It ru +ns only on Windows NT and Windows 95. It does not work on Windows 3.11 or earlier, even with the Win32s compatibility package. +\par }\pard\plain \ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\i\f1 CMail, }{\f1 +the companion program to xboard for playing electronic mail correspondence chess, has not been ported to Win32. +\par There is no way for two people running copies of WinBoard}{\i\f1 }{\f1 to play each other without going through the Internet Chess Server. +\par Under some circumstances, your ICS password may be echoed when you log on. +\par If you are connecting to the ICS by running telnet, timestamp, or + timeseal on an Internet provider host, you may find that each line you type is echoed back an extra time after you hit Enter. You can probably turn this echo off. If your Internet provider is a Unix system, type "}{\f2 stty -echo}{\f1 +" after you log in to the provider but before you run telnet, timestamp, or timeseal. In addition, you may need to type the sequence \'93}{\f2 Ctrl+Q Ctrl+E Enter}{\f1 \'93 after you have finished logging in to ICS. On VMS, type \'93}{\f2 +set terminal /noecho /nowrap}{\f1 \'94, and after you telnet to the ICS, type \'93}{\f2 Ctrl+Q Ctrl+] Enter set mode char Enter Enter}{\f1 \'94 +. It is a good idea to turn off the extra remote echo if you can, because otherwise it can get interleaved with output from the ICS and confuse WinBoard's parsing routines. Don\rquote t just turn off }{\f1\uldb Local Line Editing}{\v\f1 localLineEditing}{ +\f1 so that you see only the remote echo and not the local one; that will make the interleaving problem worse. +\par The game parser recognizes only algebraic notation. +\par The internal move legality tester does not look at the game history, so in some cases it misses illegal castling or en passant captures. It permits castling with the king on the }{\b\f1 d}{\f1 + file because this is possible in some "wild 1" games on ICS. It does not check piece drops in bughouse to see if you actually hold the piece you are trying to dr +op. However, if you attempt an illegal move when using a chess engine or the ICS, WinBoard will accept the error message that comes back, undo the move, and let you try another. +\par FEN positions saved by WinBoard}{\i\f1 }{\f1 do not include correct information about whether castling or en passant are legal. +\par }\pard\plain \s20\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 +The mate detector does not understand that non-contact mate is not really mate in bughouse. The only problem this causes while playing is minor: a "#" (mate indicator) character will show up after a non-contact mating m +ove in the move list. WinBoard will not assume the game is over at that point. +\par }\pard\plain \ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 +Edit Game mode always uses non-bughouse rules. Although you can load and edit games that contain piece drops, the piece menus are not active, so you cannot insert piece drops. Also, WinBoard}{\i\f1 }{\f1 +thinks an edited game is over when a mating move is inserted, even if the mate is non-contact. +\par Fischer Random castling is not understood. You can probably play Fischer Random successfully on ICS by typing castling moves into the ICS Interac +tion window, but they will not be animated correctly, and saved games will not be loaded correctly if castling occurs. +\par The }{\f1\uldb ICS logon}{\v\f1 ICSLogon}{\f1 file does not work properly when you connect to ICS through a Unix gateway host by setting }{\f1\uldb icsPort}{\v\f1 icsPort}{\f1 to 23. The Unix login process apparently discards type-ahead. +\par Some WinBoard functions may not work with versions of GNU Chess earlier than 4.0, patchlevel 77. The current version of WinBoard}{\i\f1 }{\f1 works best with Crafty version 15.11 or later. +\par Also see the ToDo file included with the distribution for many other possible bugs, limitations, and ideas for improvement that have been suggested. +\par }\pard\plain \s1\ql \li120\ri0\sb280\sa120\sl-320\slmult0\nowidctlpar\faauto\outlinelevel0\adjustright\rin0\lin120\itap0 \b\f5\fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1\fs20 \page }{\cs58\f1\fs20\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Authors}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 Authors}}${\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super $}{\f1 Authors}}+{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super +}{\f1 main}}}{\f1\fs18\up6 }{\f1\fs20 AUTHORS AND CONTRIBUTORS +\par }\pard\plain \ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 WinBoard is partly based on }{\i\f1 xboard}{\f1 +, a chessboard program for Unix and the X Window System. Tim Mann has been responsible for all versions of WinBoard,}{\i\f1 }{\f1 and for xboard versions 1.3 and beyond. +\par Mark Williams added many features to WinBoard 4.1.0, including copy/paste, premove, icsAlarm, autoFlipView, training mode, auto raise, and blindfold. Hugh Fischer adde +d piece animation to xboard, and Henrik Gram added it to WinBoard. Frank McIngvale contributed many xboard}{\i\f1 }{\f1 user interface improvements and improved Crafty support. Jochen Wiedmann ported xboard}{\i\f1 }{\f1 to the Amiga, creating }{\i\f1 +AmyBoard}{\f1 , and converted the documentation to texinfo. Elmar Bartel contributed the new piece bitmaps for version 3.2. Evan Welsh wrote }{\i\f1 CMail. }{\f1 +John Chanak contributed the initial implementation of ICS mode. The color scheme and the old 80x80 piece bitmaps (available in the WinBoard}{\i\f1 }{\f1 distribution in subdirectory "bitmaps.xchess") were taken from Wayne Christopher's }{\i\f1 XChess }{ +\f1 program. Chris Sears and Dan Sears wrote the original xboard}{\i\f1 . }{\f1 They were responsible for xboard}{\i\f1 }{\f1 versions 1.0 through 1.2. +\par Send bug reports to . Please run WinBoard with the /debug option and include the output from the resulting WinBoard.debug file in your message. +\par }\pard\plain \s1\ql \li120\ri0\sb280\sa120\sl-320\slmult0\nowidctlpar\faauto\outlinelevel0\adjustright\rin0\lin120\itap0 \b\f5\fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1\fs20 \page }{\cs58\f1\fs20\super K{\footnote\ftnalt \pard\plain +\s57\ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super K}{\f1 Copyright}}#{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super #}{\f1 Copyright}}${\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super $}{\f1 Copyright}}+{\footnote\ftnalt \pard\plain \s57\ql \li120\ri0\sb80\sl-240\slmult0 +\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\cs58\f1\super +}{\f1 main}}}{\f1\fs18\up6 }{\f1\fs20 COPYRIGHT +\par }\pard\plain \s26\ql \li120\ri0\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts. \line +Enhancements Copyright 1992-2000 Free Software Foundation, Inc. +\par }\pard\plain \ql \li120\ri0\sb80\sl-240\slmult0\nowidctlpar\faauto\adjustright\rin0\lin120\itap0 \f5\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1 +WinBoard's alternative piece bitmaps (bitmaps.xchess) are derived from the bitmaps in the XChess program, which was written and is copyrighted by Wayne Christopher. +\par The following terms apply to Digital Equipment Corporation's copyright interest in WinBoard: +\par All Rights Reserved +\par 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 not +ice 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. +\par 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, WH +ETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +\par The following terms apply to the enhanced version of WinBoard distributed by the Free Software Foundation: +\par 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. +\par 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. +\par You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +\par }} \ No newline at end of file diff --git a/winboard-dm-beta4/woptions.c b/winboard-dm-beta4/woptions.c new file mode 100755 index 0000000..ee51f15 --- /dev/null +++ b/winboard-dm-beta4/woptions.c @@ -0,0 +1,2763 @@ +/* + * woptions.c -- Options dialog box routines for WinBoard + * $Id$ + * + * Copyright 2000 Free Software Foundation, Inc. + * + * ------------------------------------------------------------------------ + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * ------------------------------------------------------------------------ + */ + +#include "config.h" + +#include /* required for all Windows applications */ +#include +#include + +#include "common.h" +#include "winboard.h" +#include "backend.h" +#include "woptions.h" +#include "defaults.h" +#include "wedittags.h" +#include + +#if __GNUC__ +#include +#include +#endif + +/* Imports from winboard.c */ + +extern MyFont *font[NUM_SIZES][NUM_FONTS]; +extern HINSTANCE hInst; /* current instance */ +extern HWND hwndMain; /* root window*/ +extern BOOLEAN alwaysOnTop; +extern RECT boardRect; +extern COLORREF lightSquareColor, darkSquareColor, whitePieceColor, + blackPieceColor, highlightSquareColor, premoveHighlightColor; +extern HPALETTE hPal; +extern BoardSize boardSize; +extern COLORREF consoleBackgroundColor; +extern MyColorizeAttribs colorizeAttribs[]; /* do I need the size? */ +extern MyTextAttribs textAttribs[]; +extern MySound sounds[]; +extern ColorClass currentColorClass; +extern HWND hwndConsole; +extern char *defaultTextAttribs[]; +extern HWND commentDialog; +extern char installDir[]; +extern HWND hCommPort; /* currently open comm port */ +extern DCB dcb; +extern BOOLEAN chessProgram; +extern int ics_gamenum; + +/* types */ + +typedef struct { + char *label; + unsigned value; +} ComboData; + +typedef struct { + char *label; + char *name; +} SoundComboData; + +/* module prototypes */ + +LRESULT CALLBACK GeneralOptions(HWND, UINT, WPARAM, LPARAM); +LRESULT CALLBACK BoardOptions(HWND, UINT, WPARAM, LPARAM); +LRESULT CALLBACK IcsOptions(HWND, UINT, WPARAM, LPARAM); +LRESULT CALLBACK FontOptions(HWND, UINT, WPARAM, LPARAM); +LRESULT CALLBACK CommPortOptions(HWND, UINT, WPARAM, LPARAM); +LRESULT CALLBACK LoadOptions(HWND, UINT, WPARAM, LPARAM); +LRESULT CALLBACK SaveOptions(HWND, UINT, WPARAM, LPARAM); +LRESULT CALLBACK TimeControl(HWND, UINT, WPARAM, LPARAM); +VOID ChangeBoardSize(BoardSize newSize); +VOID PaintSampleSquare( + HWND hwnd, + int ctrlid, + COLORREF squareColor, + COLORREF pieceColor, + COLORREF squareOutlineColor, + COLORREF pieceDetailColor, + BOOL isWhitePiece, + BOOL isMono, + HBITMAP pieces[3] + ); +VOID PaintColorBlock(HWND hwnd, int ctrlid, COLORREF color); +VOID SetBoardOptionEnables(HWND hDlg); +BoardSize BoardOptionsWhichRadio(HWND hDlg); +BOOL APIENTRY MyCreateFont(HWND hwnd, MyFont *font); +VOID UpdateSampleText(HWND hDlg, int id, MyColorizeAttribs *mca); +LRESULT CALLBACK ColorizeTextDialog(HWND , UINT, WPARAM, LPARAM); +VOID icsAnalyzeAdvPopup(HWND hwnd); +LRESULT CALLBACK icsAnalyzeAdvDialog(HWND, UINT, WPARAM, LPARAM); +LRESULT CALLBACK icsZippyDrawDialog(HWND, UINT, WPARAM, LPARAM); +VOID ColorizeTextPopup(HWND hwnd, ColorClass cc); +VOID SetIcsOptionEnables(HWND hDlg); +VOID SetGerneralOptionEnables(HWND hDlg); +VOID SetSampleFontText(HWND hwnd, int id, const MyFont *mf); +VOID CopyFont(MyFont *dest, const MyFont *src); +void InitSoundComboData(SoundComboData *scd); +void ResetSoundComboData(SoundComboData *scd); +void InitSoundCombo(HWND hwndCombo, SoundComboData *scd); +int SoundDialogWhichRadio(HWND hDlg); +VOID SoundDialogSetEnables(HWND hDlg, int radio); +char * SoundDialogGetName(HWND hDlg, int radio); +void DisplaySelectedSound(HWND hDlg, HWND hCombo, const char *name); +VOID ParseCommSettings(char *arg, DCB *dcb); +VOID PrintCommSettings(FILE *f, char *name, DCB *dcb); +void InitCombo(HANDLE hwndCombo, ComboData *cd); +void SelectComboValue(HANDLE hwndCombo, ComboData *cd, unsigned value); +VOID SetLoadOptionEnables(HWND hDlg); +VOID SetSaveOptionEnables(HWND hDlg); +VOID SetTimeControlEnables(HWND hDlg); + +/* safe state of IcsAnalyzeWindow */ +static int oldAnalyzeWindow; + + +/*---------------------------------------------------------------------------*\ + * + * General Options Dialog functions + * +\*---------------------------------------------------------------------------*/ + +VOID +SetGerneralOptionEnables(HWND hDlg) +{ + /* ITEM for furure too */ + #define ENABLE_DLG_ITEM(x,y) EnableWindow(GetDlgItem(hDlg,(x)), (y)) + if (appData.noChessProgram) { + EnableWindow(GetDlgItem(hDlg, OPT_AnalysisWindow), FALSE); + } else { + if (!appData.icsAnalyze) { + EnableWindow(GetDlgItem(hDlg, OPT_AnalysisWindow), + IsDlgButtonChecked(hDlg, OPT_ShowThinking)); + } + /* PopUp automaticly */ + if (gameMode == AnalyzeMode || gameMode == AnalyzeFile || + gameMode == TwoMachinesPlay) { + EnableWindow(GetDlgItem(hDlg, OPT_AnalysisWindow), FALSE); + } + } + /* engineRoom control periodic updates */ + if (appData.AnalysisWindow) { + EnableWindow(GetDlgItem(hDlg, OPT_PeriodicUpdates), FALSE); + } + #undef ENABLE_DLG_ITEM +} + +LRESULT CALLBACK +GeneralOptionsDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + static Boolean oldShowCoords; + static Boolean oldBlindfold; + static Boolean oldShowButtonBar; + + switch (message) { + case WM_INITDIALOG: /* message: initialize dialog box */ + oldShowCoords = appData.showCoords; + oldBlindfold = appData.blindfold; + oldShowButtonBar = appData.showButtonBar; + + /* Center the dialog over the application window */ + CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER)); + + /* Initialize the dialog items */ +#define CHECK_BOX(x,y) CheckDlgButton(hDlg, (x), (BOOL)(y)) + + CHECK_BOX(OPT_AlwaysOnTop, alwaysOnTop); + CHECK_BOX(OPT_AlwaysQueen, appData.alwaysPromoteToQueen); + CHECK_BOX(OPT_AnimateDragging, appData.animateDragging); + CHECK_BOX(OPT_AnimateMoving, appData.animate); + CHECK_BOX(OPT_AutoFlag, appData.autoCallFlag); + CHECK_BOX(OPT_AutoFlipView, appData.autoFlipView); + CHECK_BOX(OPT_AutoRaiseBoard, appData.autoRaiseBoard); + CHECK_BOX(OPT_Blindfold, appData.blindfold); + CHECK_BOX(OPT_HighlightDragging, appData.highlightDragging); + CHECK_BOX(OPT_HighlightLastMove, appData.highlightLastMove); + CHECK_BOX(OPT_PeriodicUpdates, appData.periodicUpdates); + CHECK_BOX(OPT_PonderNextMove, appData.ponderNextMove); + CHECK_BOX(OPT_PopupExitMessage, appData.popupExitMessage); + CHECK_BOX(OPT_PopupMoveErrors, appData.popupMoveErrors); + CHECK_BOX(OPT_ShowButtonBar, appData.showButtonBar); + CHECK_BOX(OPT_ShowCoordinates, appData.showCoords); + CHECK_BOX(OPT_ShowThinking, appData.showThinking); + CHECK_BOX(OPT_AnalysisWindow, appData.AnalysisWindow); + CHECK_BOX(OPT_TestLegality, appData.testLegality); + +#undef CHECK_BOX + + EnableWindow(GetDlgItem(hDlg, OPT_AutoFlag), + appData.icsActive || !appData.noChessProgram); + EnableWindow(GetDlgItem(hDlg, OPT_AutoFlipView), + appData.icsActive || !appData.noChessProgram); + EnableWindow(GetDlgItem(hDlg, OPT_PonderNextMove), + !appData.noChessProgram); + EnableWindow(GetDlgItem(hDlg, OPT_PeriodicUpdates), + !appData.noChessProgram && !appData.icsActive); + EnableWindow(GetDlgItem(hDlg, OPT_ShowThinking), + !appData.noChessProgram); + EnableWindow(GetDlgItem(hDlg, OPT_AnalysisWindow), + !appData.noChessProgram); + + SetGerneralOptionEnables(hDlg); + return TRUE; + + case WM_COMMAND: /* message: received a command */ + switch (LOWORD(wParam)) { + case IDOK: + /* Read changed options from the dialog box */ + +#define IS_CHECKED(x) (Boolean)IsDlgButtonChecked(hDlg, (x)) + + alwaysOnTop = IS_CHECKED(OPT_AlwaysOnTop); + appData.alwaysPromoteToQueen = IS_CHECKED(OPT_AlwaysQueen); + appData.animateDragging = IS_CHECKED(OPT_AnimateDragging); + appData.animate = IS_CHECKED(OPT_AnimateMoving); + appData.autoCallFlag = IS_CHECKED(OPT_AutoFlag); + appData.autoFlipView = IS_CHECKED(OPT_AutoFlipView); + appData.autoRaiseBoard = IS_CHECKED(OPT_AutoRaiseBoard); + appData.blindfold = IS_CHECKED(OPT_Blindfold); + appData.highlightDragging = IS_CHECKED(OPT_HighlightDragging); + appData.highlightLastMove = IS_CHECKED(OPT_HighlightLastMove); + PeriodicUpdatesEvent( IS_CHECKED(OPT_PeriodicUpdates)); + PonderNextMoveEvent( IS_CHECKED(OPT_PonderNextMove)); + appData.popupExitMessage = IS_CHECKED(OPT_PopupExitMessage); + appData.popupMoveErrors = IS_CHECKED(OPT_PopupMoveErrors); + appData.showButtonBar = IS_CHECKED(OPT_ShowButtonBar); + appData.showCoords = IS_CHECKED(OPT_ShowCoordinates); + ShowThinkingEvent( IS_CHECKED(OPT_ShowThinking)); + appData.testLegality = IS_CHECKED(OPT_TestLegality); + appData.AnalysisWindow = IS_CHECKED(OPT_AnalysisWindow); + +#undef IS_CHECKED + + /* a little bit faster or we wait if engine give us a result */ + if (appData.showThinking && appData.AnalysisWindow) IcsAnalyzeWindowUp(); + /* pop down */ + if (!appData.AnalysisWindow) AnalysisPopDown(); + + if (!appData.showThinking && appData.AnalysisWindow) { + AnalysisPopDown(); + appData.AnalysisWindow = FALSE; + } + + SetWindowPos(hwndMain, alwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST, + 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE); +#if AOT_CONSOLE + if (hwndConsole) { + SetWindowPos(hwndConsole, alwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST, + 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE); + } +#endif + if (!appData.highlightLastMove) { + ClearHighlights(); + DrawPosition(FALSE, NULL); + } + /* + * for some reason the redraw seems smoother when we invalidate + * the board rect after the call to EndDialog() + */ + EndDialog(hDlg, TRUE); + + if (oldShowButtonBar != appData.showButtonBar) { + InitDrawingSizes(boardSize, 0); + } else if ((oldShowCoords != appData.showCoords) || + (oldBlindfold != appData.blindfold)) { + InvalidateRect(hwndMain, &boardRect, FALSE); + } + + return TRUE; + + case IDCANCEL: + EndDialog(hDlg, FALSE); + return TRUE; + + default: + SetGerneralOptionEnables(hDlg); + break; + } + break; + } + return FALSE; +} + +VOID +GeneralOptionsPopup(HWND hwnd) +{ + FARPROC lpProc; + + lpProc = MakeProcInstance((FARPROC)GeneralOptionsDialog, hInst); + DialogBox(hInst, MAKEINTRESOURCE(DLG_GeneralOptions), hwnd, + (DLGPROC) lpProc); + FreeProcInstance(lpProc); +} +/*---------------------------------------------------------------------------*\ + * + * Board Options Dialog functions + * +\*---------------------------------------------------------------------------*/ + +const int SAMPLE_SQ_SIZE = 54; + +VOID +ChangeBoardSize(BoardSize newSize) +{ + if (newSize != boardSize) { + boardSize = newSize; + InitDrawingSizes(boardSize, 0); + } +} + +VOID +PaintSampleSquare( + HWND hwnd, + int ctrlid, + COLORREF squareColor, + COLORREF pieceColor, + COLORREF squareOutlineColor, + COLORREF pieceDetailColor, + BOOL isWhitePiece, + BOOL isMono, + HBITMAP pieces[3] + ) +{ + HBRUSH brushSquare; + HBRUSH brushSquareOutline; + HBRUSH brushPiece; + HBRUSH brushPieceDetail; + HBRUSH oldBrushPiece; + HBRUSH oldBrushSquare; + HBITMAP oldBitmapMem; + HBITMAP oldBitmapTemp; + HBITMAP bufferBitmap; + RECT rect; + HDC hdcScreen, hdcMem, hdcTemp; + HPEN pen, oldPen; + HWND hCtrl = GetDlgItem(hwnd, ctrlid); + int x, y; + + const int SOLID = 0; + const int WHITE = 1; + const int OUTLINE = 2; + const int BORDER = 4; + + InvalidateRect(hCtrl, NULL, TRUE); + UpdateWindow(hCtrl); + GetClientRect(hCtrl, &rect); + x = rect.left + (BORDER / 2); + y = rect.top + (BORDER / 2); + hdcScreen = GetDC(hCtrl); + hdcMem = CreateCompatibleDC(hdcScreen); + hdcTemp = CreateCompatibleDC(hdcScreen); + + bufferBitmap = CreateCompatibleBitmap(hdcScreen, rect.right-rect.left+1, + rect.bottom-rect.top+1); + oldBitmapMem = SelectObject(hdcMem, bufferBitmap); + if (!isMono) { + SelectPalette(hdcMem, hPal, FALSE); + } + brushSquare = CreateSolidBrush(squareColor); + brushSquareOutline = CreateSolidBrush(squareOutlineColor); + brushPiece = CreateSolidBrush(pieceColor); + brushPieceDetail = CreateSolidBrush(pieceDetailColor); + + /* + * first draw the rectangle + */ + pen = CreatePen(PS_SOLID, BORDER, squareOutlineColor); + oldPen = (HPEN) SelectObject(hdcMem, pen); + oldBrushSquare = (HBRUSH)SelectObject(hdcMem, brushSquare); + Rectangle(hdcMem, rect.left, rect.top, rect.right, rect.bottom); + + /* + * now draw the piece + */ + if (isMono) { + oldBitmapTemp = SelectObject(hdcTemp, pieces[OUTLINE]); + BitBlt(hdcMem, x, y, SAMPLE_SQ_SIZE, SAMPLE_SQ_SIZE, hdcTemp, 0, 0, + isWhitePiece ? SRCCOPY : NOTSRCCOPY); + SelectObject(hdcTemp, oldBitmapTemp); + } else { + if (isWhitePiece) { + oldBitmapTemp = SelectObject(hdcTemp, pieces[WHITE]); + oldBrushPiece = SelectObject(hdcMem, brushPiece); + BitBlt(hdcMem, x, y, SAMPLE_SQ_SIZE, SAMPLE_SQ_SIZE, + hdcTemp, 0, 0, 0x00B8074A); +#if 0 + /* Use pieceDetailColor for outline of white pieces */ + SelectObject(hdcTemp, pieces[OUTLINE]); + SelectObject(hdcMem, brushPieceDetail); + BitBlt(hdcMem, x, y, SAMPLE_SQ_SIZE, SAMPLE_SQ_SIZE, + hdcTemp, 0, 0, 0x00B8074A); +#else + /* Use black for outline of white pieces */ + SelectObject(hdcTemp, pieces[OUTLINE]); + BitBlt(hdcMem, x, y, SAMPLE_SQ_SIZE, SAMPLE_SQ_SIZE, + hdcTemp, 0, 0, SRCAND); +#endif + } else { +#if 0 + /* Use pieceDetailColor for details of black pieces */ + /* Requires filled-in solid bitmaps (BLACK_PIECE class); the + WHITE_PIECE ones aren't always the right shape. */ + oldBitmapTemp = SelectObject(hdcTemp, pieces[BLACK]); + oldBrushPiece = SelectObject(hdcMem, brushPieceDetail); + BitBlt(hdcMem, x, y, SAMPLE_SQ_SIZE, SAMPLE_SQ_SIZE, + hdcTemp, 0, 0, 0x00B8074A); + SelectObject(hdcTemp, pieces[SOLID]); + SelectObject(hdcMem, brushPiece); + BitBlt(hdcMem, x, y, SAMPLE_SQ_SIZE, SAMPLE_SQ_SIZE, + hdcTemp, 0, 0, 0x00B8074A); +#else + /* Use square color for details of black pieces */ + oldBitmapTemp = SelectObject(hdcTemp, pieces[SOLID]); + oldBrushPiece = SelectObject(hdcMem, brushPiece); + BitBlt(hdcMem, x, y, SAMPLE_SQ_SIZE, SAMPLE_SQ_SIZE, + hdcTemp, 0, 0, 0x00B8074A); +#endif + } + SelectObject(hdcMem, oldBrushPiece); + SelectObject(hdcTemp, oldBitmapTemp); + } + /* + * copy the memory dc to the screen + */ + SelectObject(hdcMem, bufferBitmap); + BitBlt(hdcScreen, rect.left, rect.top, + rect.right - rect.left, + rect.bottom - rect.top, + hdcMem, rect.left, rect.top, SRCCOPY); + SelectObject(hdcMem, oldBitmapMem); + /* + * clean up + */ + SelectObject(hdcMem, oldBrushPiece); + SelectObject(hdcMem, oldPen); + DeleteObject(brushPiece); + DeleteObject(brushPieceDetail); + DeleteObject(brushSquare); + DeleteObject(brushSquareOutline); + DeleteObject(pen); + DeleteDC(hdcTemp); + DeleteDC(hdcMem); + ReleaseDC(hCtrl, hdcScreen); +} + + +VOID +PaintColorBlock(HWND hwnd, int ctrlid, COLORREF color) +{ + HDC hdc; + HBRUSH brush, oldBrush; + RECT rect; + HWND hCtrl = GetDlgItem(hwnd, ctrlid); + + hdc = GetDC(hCtrl); + InvalidateRect(hCtrl, NULL, TRUE); + UpdateWindow(hCtrl); + GetClientRect(hCtrl, &rect); + brush = CreateSolidBrush(color); + oldBrush = (HBRUSH)SelectObject(hdc, brush); + Rectangle(hdc, rect.left, rect.top, rect.right, rect.bottom); + SelectObject(hdc, oldBrush); + DeleteObject(brush); + ReleaseDC(hCtrl, hdc); +} + + +VOID +SetBoardOptionEnables(HWND hDlg) +{ + if (IsDlgButtonChecked(hDlg, OPT_Monochrome)) { + ShowWindow(GetDlgItem(hDlg, OPT_LightSquareColor), SW_HIDE); + ShowWindow(GetDlgItem(hDlg, OPT_DarkSquareColor), SW_HIDE); + ShowWindow(GetDlgItem(hDlg, OPT_WhitePieceColor), SW_HIDE); + ShowWindow(GetDlgItem(hDlg, OPT_BlackPieceColor), SW_HIDE); + + EnableWindow(GetDlgItem(hDlg, OPT_ChooseLightSquareColor), FALSE); + EnableWindow(GetDlgItem(hDlg, OPT_ChooseDarkSquareColor), FALSE); + EnableWindow(GetDlgItem(hDlg, OPT_ChooseWhitePieceColor), FALSE); + EnableWindow(GetDlgItem(hDlg, OPT_ChooseBlackPieceColor), FALSE); + } else { + ShowWindow(GetDlgItem(hDlg, OPT_LightSquareColor), SW_SHOW); + ShowWindow(GetDlgItem(hDlg, OPT_DarkSquareColor), SW_SHOW); + ShowWindow(GetDlgItem(hDlg, OPT_WhitePieceColor), SW_SHOW); + ShowWindow(GetDlgItem(hDlg, OPT_BlackPieceColor), SW_SHOW); + + EnableWindow(GetDlgItem(hDlg, OPT_ChooseLightSquareColor), TRUE); + EnableWindow(GetDlgItem(hDlg, OPT_ChooseDarkSquareColor), TRUE); + EnableWindow(GetDlgItem(hDlg, OPT_ChooseWhitePieceColor), TRUE); + EnableWindow(GetDlgItem(hDlg, OPT_ChooseBlackPieceColor), TRUE); + } +} + +BoardSize +BoardOptionsWhichRadio(HWND hDlg) +{ + return (IsDlgButtonChecked(hDlg, OPT_SizeTiny) ? SizeTiny : + (IsDlgButtonChecked(hDlg, OPT_SizeTeeny) ? SizeTeeny : + (IsDlgButtonChecked(hDlg, OPT_SizeDinky) ? SizeDinky : + (IsDlgButtonChecked(hDlg, OPT_SizePetite) ? SizePetite : + (IsDlgButtonChecked(hDlg, OPT_SizeSlim) ? SizeSlim : + (IsDlgButtonChecked(hDlg, OPT_SizeSmall) ? SizeSmall : + (IsDlgButtonChecked(hDlg, OPT_SizeMediocre) ? SizeMediocre : + (IsDlgButtonChecked(hDlg, OPT_SizeMiddling) ? SizeMiddling : + (IsDlgButtonChecked(hDlg, OPT_SizeAverage) ? SizeAverage : + (IsDlgButtonChecked(hDlg, OPT_SizeModerate) ? SizeModerate : + (IsDlgButtonChecked(hDlg, OPT_SizeMedium) ? SizeMedium : + (IsDlgButtonChecked(hDlg, OPT_SizeBulky) ? SizeBulky : + (IsDlgButtonChecked(hDlg, OPT_SizeLarge) ? SizeLarge : + (IsDlgButtonChecked(hDlg, OPT_SizeBig) ? SizeBig : + (IsDlgButtonChecked(hDlg, OPT_SizeHuge) ? SizeHuge : + (IsDlgButtonChecked(hDlg, OPT_SizeGiant) ? SizeGiant : + (IsDlgButtonChecked(hDlg, OPT_SizeColossal) ? SizeColossal : + SizeTitanic ))))))))))))))))); +} + + + +LRESULT CALLBACK +BoardOptionsDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + static Boolean mono; + static BoardSize size; + static COLORREF lsc, dsc, wpc, bpc, hsc, phc; + static HBITMAP pieces[3]; + + switch (message) { + case WM_INITDIALOG: /* message: initialize dialog box */ + /* Center the dialog over the application window */ + CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER)); + /* Initialize the dialog items */ + switch (boardSize) { + case SizeTiny: + CheckDlgButton(hDlg, OPT_SizeTiny, TRUE); + break; + case SizeTeeny: + CheckDlgButton(hDlg, OPT_SizeTeeny, TRUE); + break; + case SizeDinky: + CheckDlgButton(hDlg, OPT_SizeDinky, TRUE); + break; + case SizePetite: + CheckDlgButton(hDlg, OPT_SizePetite, TRUE); + break; + case SizeSlim: + CheckDlgButton(hDlg, OPT_SizeSlim, TRUE); + break; + case SizeSmall: + CheckDlgButton(hDlg, OPT_SizeSmall, TRUE); + break; + case SizeMediocre: + CheckDlgButton(hDlg, OPT_SizeMediocre, TRUE); + break; + case SizeMiddling: + CheckDlgButton(hDlg, OPT_SizeMiddling, TRUE); + break; + case SizeAverage: + CheckDlgButton(hDlg, OPT_SizeAverage, TRUE); + break; + case SizeModerate: + CheckDlgButton(hDlg, OPT_SizeModerate, TRUE); + break; + case SizeMedium: + CheckDlgButton(hDlg, OPT_SizeMedium, TRUE); + break; + case SizeBulky: + CheckDlgButton(hDlg, OPT_SizeBulky, TRUE); + break; + case SizeLarge: + CheckDlgButton(hDlg, OPT_SizeLarge, TRUE); + break; + case SizeBig: + CheckDlgButton(hDlg, OPT_SizeBig, TRUE); + break; + case SizeHuge: + CheckDlgButton(hDlg, OPT_SizeHuge, TRUE); + break; + case SizeGiant: + CheckDlgButton(hDlg, OPT_SizeGiant, TRUE); + break; + case SizeColossal: + CheckDlgButton(hDlg, OPT_SizeColossal, TRUE); + break; + case SizeTitanic: + CheckDlgButton(hDlg, OPT_SizeTitanic, TRUE); + } + + if (appData.monoMode) + CheckDlgButton(hDlg, OPT_Monochrome, TRUE); + + pieces[0] = DoLoadBitmap(hInst, "n", SAMPLE_SQ_SIZE, "s"); + pieces[1] = DoLoadBitmap(hInst, "n", SAMPLE_SQ_SIZE, "w"); + pieces[2] = DoLoadBitmap(hInst, "n", SAMPLE_SQ_SIZE, "o"); + + lsc = lightSquareColor; + dsc = darkSquareColor; + wpc = whitePieceColor; + bpc = blackPieceColor; + hsc = highlightSquareColor; + phc = premoveHighlightColor; + mono = appData.monoMode; + size = boardSize; + + SetBoardOptionEnables(hDlg); + return TRUE; + + case WM_PAINT: + PaintColorBlock(hDlg, OPT_LightSquareColor, lsc); + PaintColorBlock(hDlg, OPT_DarkSquareColor, dsc); + PaintColorBlock(hDlg, OPT_WhitePieceColor, wpc); + PaintColorBlock(hDlg, OPT_BlackPieceColor, bpc); + PaintColorBlock(hDlg, OPT_HighlightSquareColor, hsc); + PaintColorBlock(hDlg, OPT_PremoveHighlightColor, phc); + PaintSampleSquare(hDlg, OPT_SampleLightSquare, lsc, wpc, hsc, bpc, + TRUE, mono, pieces); + PaintSampleSquare(hDlg, OPT_SampleDarkSquare, dsc, bpc, phc, wpc, + FALSE, mono, pieces); + + return FALSE; + + case WM_COMMAND: /* message: received a command */ + switch (LOWORD(wParam)) { + case IDOK: + /* + * if we call EndDialog() after the call to ChangeBoardSize(), + * then ChangeBoardSize() does not take effect, although the new + * boardSize is saved. Go figure... + */ + EndDialog(hDlg, TRUE); + + size = BoardOptionsWhichRadio(hDlg); + + /* + * did any settings change? + */ + if (size != boardSize) { + ChangeBoardSize(size); + } + + if ((mono != appData.monoMode) || + (lsc != lightSquareColor) || + (dsc != darkSquareColor) || + (wpc != whitePieceColor) || + (bpc != blackPieceColor) || + (hsc != highlightSquareColor) || + (phc != premoveHighlightColor)) { + + lightSquareColor = lsc; + darkSquareColor = dsc; + whitePieceColor = wpc; + blackPieceColor = bpc; + highlightSquareColor = hsc; + premoveHighlightColor = phc; + appData.monoMode = mono; + + InitDrawingColors(); + InitDrawingSizes(boardSize, 0); + InvalidateRect(hwndMain, &boardRect, FALSE); + } + DeleteObject(pieces[0]); + DeleteObject(pieces[1]); + DeleteObject(pieces[2]); + return TRUE; + + case IDCANCEL: + DeleteObject(pieces[0]); + DeleteObject(pieces[1]); + DeleteObject(pieces[2]); + EndDialog(hDlg, FALSE); + return TRUE; + + case OPT_ChooseLightSquareColor: + if (ChangeColor(hDlg, &lsc)) + PaintColorBlock(hDlg, OPT_LightSquareColor, lsc); + PaintSampleSquare(hDlg, OPT_SampleLightSquare, lsc, wpc, hsc, bpc, + TRUE, mono, pieces); + break; + + case OPT_ChooseDarkSquareColor: + if (ChangeColor(hDlg, &dsc)) + PaintColorBlock(hDlg, OPT_DarkSquareColor, dsc); + PaintSampleSquare(hDlg, OPT_SampleDarkSquare, dsc, bpc, phc, wpc, + FALSE, mono, pieces); + break; + + case OPT_ChooseWhitePieceColor: + if (ChangeColor(hDlg, &wpc)) + PaintColorBlock(hDlg, OPT_WhitePieceColor, wpc); + PaintSampleSquare(hDlg, OPT_SampleLightSquare, lsc, wpc, hsc, bpc, + TRUE, mono, pieces); + break; + + case OPT_ChooseBlackPieceColor: + if (ChangeColor(hDlg, &bpc)) + PaintColorBlock(hDlg, OPT_BlackPieceColor, bpc); + PaintSampleSquare(hDlg, OPT_SampleDarkSquare, dsc, bpc, phc, wpc, + FALSE, mono, pieces); + break; + + case OPT_ChooseHighlightSquareColor: + if (ChangeColor(hDlg, &hsc)) + PaintColorBlock(hDlg, OPT_HighlightSquareColor, hsc); + PaintSampleSquare(hDlg, OPT_SampleLightSquare, lsc, wpc, hsc, bpc, + TRUE, mono, pieces); + break; + + case OPT_ChoosePremoveHighlightColor: + if (ChangeColor(hDlg, &phc)) + PaintColorBlock(hDlg, OPT_PremoveHighlightColor, phc); + PaintSampleSquare(hDlg, OPT_SampleDarkSquare, dsc, bpc, phc, wpc, + FALSE, mono, pieces); + break; + + case OPT_DefaultBoardColors: + lsc = ParseColorName(LIGHT_SQUARE_COLOR); + dsc = ParseColorName(DARK_SQUARE_COLOR); + wpc = ParseColorName(WHITE_PIECE_COLOR); + bpc = ParseColorName(BLACK_PIECE_COLOR); + hsc = ParseColorName(HIGHLIGHT_SQUARE_COLOR); + phc = ParseColorName(PREMOVE_HIGHLIGHT_COLOR); + mono = FALSE; + CheckDlgButton(hDlg, OPT_Monochrome, FALSE); + PaintColorBlock(hDlg, OPT_LightSquareColor, lsc); + PaintColorBlock(hDlg, OPT_DarkSquareColor, dsc); + PaintColorBlock(hDlg, OPT_WhitePieceColor, wpc); + PaintColorBlock(hDlg, OPT_BlackPieceColor, bpc); + PaintColorBlock(hDlg, OPT_HighlightSquareColor, hsc); + PaintColorBlock(hDlg, OPT_PremoveHighlightColor, phc); + SetBoardOptionEnables(hDlg); + PaintSampleSquare(hDlg, OPT_SampleLightSquare, lsc, wpc, hsc, bpc, + TRUE, mono, pieces); + PaintSampleSquare(hDlg, OPT_SampleDarkSquare, dsc, bpc, phc, wpc, + FALSE, mono, pieces); + break; + + case OPT_Monochrome: + mono = !mono; + SetBoardOptionEnables(hDlg); + break; + } + break; + } + return FALSE; +} + + +VOID +BoardOptionsPopup(HWND hwnd) +{ + FARPROC lpProc = MakeProcInstance((FARPROC)BoardOptionsDialog, hInst); + DialogBox(hInst, MAKEINTRESOURCE(DLG_BoardOptions), hwnd, + (DLGPROC) lpProc); + FreeProcInstance(lpProc); +} + +/*---------------------------------------------------------------------------*\ + * + * ICS Options Dialog functions + * +\*---------------------------------------------------------------------------*/ + +BOOL APIENTRY +MyCreateFont(HWND hwnd, MyFont *font) +{ + CHOOSEFONT cf; + HFONT hf; + + /* Initialize members of the CHOOSEFONT structure. */ + cf.lStructSize = sizeof(CHOOSEFONT); + cf.hwndOwner = hwnd; + cf.hDC = (HDC)NULL; + cf.lpLogFont = &font->lf; + cf.iPointSize = 0; + cf.Flags = CF_SCREENFONTS|/*CF_ANSIONLY|*/CF_INITTOLOGFONTSTRUCT; + cf.rgbColors = RGB(0,0,0); + cf.lCustData = 0L; + cf.lpfnHook = (LPCFHOOKPROC)NULL; + cf.lpTemplateName = (LPSTR)NULL; + cf.hInstance = (HINSTANCE) NULL; + cf.lpszStyle = (LPSTR)NULL; + cf.nFontType = SCREEN_FONTTYPE; + cf.nSizeMin = 0; + cf.nSizeMax = 0; + + /* Display the CHOOSEFONT common-dialog box. */ + if (!ChooseFont(&cf)) { + return FALSE; + } + + /* Create a logical font based on the user's */ + /* selection and return a handle identifying */ + /* that font. */ + hf = CreateFontIndirect(cf.lpLogFont); + if (hf == NULL) { + return FALSE; + } + + font->hf = hf; + font->mfp.pointSize = (float) (cf.iPointSize / 10.0); + font->mfp.bold = (font->lf.lfWeight >= FW_BOLD); + font->mfp.italic = font->lf.lfItalic; + font->mfp.underline = font->lf.lfUnderline; + font->mfp.strikeout = font->lf.lfStrikeOut; + strcpy(font->mfp.faceName, font->lf.lfFaceName); + return TRUE; +} + + +VOID +UpdateSampleText(HWND hDlg, int id, MyColorizeAttribs *mca) +{ + CHARFORMAT cf; + cf.cbSize = sizeof(CHARFORMAT); + cf.dwMask = + CFM_COLOR|CFM_BOLD|CFM_ITALIC|CFM_UNDERLINE|CFM_STRIKEOUT|CFM_FACE|CFM_SIZE; + cf.crTextColor = mca->color; + cf.dwEffects = mca->effects; + strcpy(cf.szFaceName, font[boardSize][CONSOLE_FONT]->mfp.faceName); + /* + * The 20.0 below is in fact documented. yHeight is expressed in twips. + * A twip is 1/20 of a font's point size. See documentation of CHARFORMAT. + * --msw + */ + cf.yHeight = (int)(font[boardSize][CONSOLE_FONT]->mfp.pointSize * 20.0 + 0.5); + cf.bCharSet = DEFAULT_CHARSET; /* should be ignored anyway */ + cf.bPitchAndFamily = DEFAULT_PITCH|FF_DONTCARE; + SendDlgItemMessage(hDlg, id, EM_SETCHARFORMAT, SCF_ALL, (LPARAM)&cf); +} + +LRESULT CALLBACK +ColorizeTextDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + static MyColorizeAttribs mca; + static ColorClass cc; + COLORREF background = (COLORREF)0; + + switch (message) { + case WM_INITDIALOG: + cc = (ColorClass)lParam; + mca = colorizeAttribs[cc]; + /* Center the dialog over the application window */ + CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER)); + /* Initialize the dialog items */ + CheckDlgButton(hDlg, OPT_Bold, (mca.effects & CFE_BOLD) != 0); + CheckDlgButton(hDlg, OPT_Italic, (mca.effects & CFE_ITALIC) != 0); + CheckDlgButton(hDlg, OPT_Underline, (mca.effects & CFE_UNDERLINE) != 0); + CheckDlgButton(hDlg, OPT_Strikeout, (mca.effects & CFE_STRIKEOUT) != 0); + + /* get the current background color from the parent window */ + SendMessage(GetWindow(hDlg, GW_OWNER),WM_COMMAND, + (WPARAM)WM_USER_GetConsoleBackground, + (LPARAM)&background); + + /* set the background color */ + SendDlgItemMessage(hDlg, OPT_Sample, EM_SETBKGNDCOLOR, FALSE, background); + + SetDlgItemText(hDlg, OPT_Sample, mca.name); + UpdateSampleText(hDlg, OPT_Sample, &mca); + return TRUE; + + case WM_COMMAND: /* message: received a command */ + switch (LOWORD(wParam)) { + case IDOK: + /* Read changed options from the dialog box */ + colorizeAttribs[cc] = mca; + textAttribs[cc].color = mca.color; + textAttribs[cc].effects = mca.effects; + Colorize(currentColorClass, TRUE); + if (cc == ColorNormal) { + CHARFORMAT cf; + cf.cbSize = sizeof(CHARFORMAT); + cf.dwMask = CFM_COLOR; + cf.crTextColor = mca.color; + SendDlgItemMessage(hwndConsole, OPT_ConsoleInput, + EM_SETCHARFORMAT, SCF_ALL, (LPARAM)&cf); + } + EndDialog(hDlg, TRUE); + return TRUE; + + case IDCANCEL: + EndDialog(hDlg, FALSE); + return TRUE; + + case OPT_ChooseColor: + ChangeColor(hDlg, &mca.color); + UpdateSampleText(hDlg, OPT_Sample, &mca); + return TRUE; + + default: + mca.effects = + (IsDlgButtonChecked(hDlg, OPT_Bold) ? CFE_BOLD : 0) | + (IsDlgButtonChecked(hDlg, OPT_Italic) ? CFE_ITALIC : 0) | + (IsDlgButtonChecked(hDlg, OPT_Underline) ? CFE_UNDERLINE : 0) | + (IsDlgButtonChecked(hDlg, OPT_Strikeout) ? CFE_STRIKEOUT : 0); + UpdateSampleText(hDlg, OPT_Sample, &mca); + break; + } + break; + } + return FALSE; +} + +VOID +ColorizeTextPopup(HWND hwnd, ColorClass cc) +{ + FARPROC lpProc; + + lpProc = MakeProcInstance((FARPROC)ColorizeTextDialog, hInst); + DialogBoxParam(hInst, MAKEINTRESOURCE(DLG_Colorize), + hwnd, (DLGPROC)lpProc, (LPARAM) cc); + FreeProcInstance(lpProc); +} + +VOID +icsAnalyzeAdvPopup(HWND hwnd) +{ + /* LPARAM reseverd for future !! */ + FARPROC wndProc; + wndProc = MakeProcInstance((FARPROC)icsAnalyzeAdvDialog, hInst); + DialogBoxParam(hInst, MAKEINTRESOURCE(DLG_icsAnalyze), hwnd, (DLGPROC)wndProc, + (LPARAM) ics_gamenum); + FreeProcInstance(wndProc); +} + +LRESULT CALLBACK +icsAnalyzeAdvDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM ics_gamenum) +{ + + switch (message) { + case WM_INITDIALOG: + #define CHECK_BOX(x,y) CheckDlgButton(hDlg, (x), (BOOL)(y)) + if (!appData.icsWBprotoAgr) appData.icsWBprotoNorm = TRUE; + CHECK_BOX(OPT_icsWBprotoNorm, appData.icsWBprotoNorm); + CHECK_BOX(OPT_icsWBprotoAgr, appData.icsWBprotoAgr); + CHECK_BOX(OPT_icsSmartQueueBlitz, appData.icsSmartQueueBlitz); + CHECK_BOX(OPT_icsSmartQueueStd, appData.icsSmartQueueStd); + #undef CHECK_BOX + + CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER)); + #define IS_CHECKED(x) (Boolean)IsDlgButtonChecked(hDlg, (x)) + if (!appData.smartQueue) { + EnableWindow(GetDlgItem(hDlg, OPT_icsSmartQueueBlitz), FALSE); + EnableWindow(GetDlgItem(hDlg, OPT_icsSmartQueueStd), FALSE); + } + return TRUE; + + case WM_COMMAND: + switch (LOWORD(wParam)) { + case IDOK: + appData.icsWBprotoNorm = IS_CHECKED(OPT_icsWBprotoNorm); + appData.icsWBprotoAgr = IS_CHECKED(OPT_icsWBprotoAgr); + appData.icsSmartQueueBlitz = IS_CHECKED(OPT_icsSmartQueueBlitz); + appData.icsSmartQueueStd = IS_CHECKED(OPT_icsSmartQueueStd); + #undef IS_CHECKED + /* wb proto will use direct boolean */ + /* smart queue can have more option */ + if (appData.icsSmartQueueBlitz) appData.icsSmartQueue = 1; + if (appData.icsSmartQueueStd) appData.icsSmartQueue = 0; + if (appData.icsWBprotoAgr) appData.icsWBproto = 1; + if (appData.icsWBprotoNorm) appData.icsWBproto = 0; + EndDialog(hDlg, TRUE); + return TRUE; + + case IDCANCEL: + EndDialog(hDlg, FALSE); + return TRUE; + + default: + break; + } + break; + } + return FALSE; +} + +VOID +icsZippyDrawPopUp(HWND hwnd) +{ + FARPROC lpProc; + + lpProc = MakeProcInstance((FARPROC)icsZippyDrawDialog, hInst); + DialogBoxParam(hInst, MAKEINTRESOURCE(DLG_ZippyDraw), hwnd, (DLGPROC) lpProc, (LPARAM) 0); + FreeProcInstance(lpProc); +} + +LRESULT CALLBACK +icsZippyDrawDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch (message) { + case WM_INITDIALOG: + #define CHECK_BOX(x,y) CheckDlgButton(hDlg, (x), (BOOL)(y)) + /* Center the dialog over the application window */ + CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER)); + break; + return TRUE; + + case WM_COMMAND: + break; + } + return 1; + +} + + +VOID +SetIcsOptionEnables(HWND hDlg) +{ +#define ENABLE_DLG_ITEM(x,y) EnableWindow(GetDlgItem(hDlg,(x)), (y)) + + UINT state = IsDlgButtonChecked(hDlg, OPT_Premove); + ENABLE_DLG_ITEM(OPT_PremoveWhite, state); + ENABLE_DLG_ITEM(OPT_PremoveWhiteText, state); + ENABLE_DLG_ITEM(OPT_PremoveBlack, state); + ENABLE_DLG_ITEM(OPT_PremoveBlackText, state); + + ENABLE_DLG_ITEM(OPT_IcsAlarmTime, IsDlgButtonChecked(hDlg, OPT_IcsAlarm)); + ENABLE_DLG_ITEM(OPT_icsKillPVs, IsDlgButtonChecked(hDlg, OPT_icsKillPV)); + ENABLE_DLG_ITEM(OPT_icsTells, IsDlgButtonChecked(hDlg, OPT_icsTell)); + + if(gameMode == IcsPlayingBlack || gameMode == IcsPlayingWhite) { + EnableWindow(GetDlgItem(hDlg, OPT_icsAnalyze), FALSE); + } else { + if (appData.noChessProgram == FALSE) { + EnableWindow(GetDlgItem(hDlg, OPT_icsAnalyze), TRUE); + } else { + EnableWindow(GetDlgItem(hDlg, OPT_icsAnalyze), FALSE); + } + } + if (appData.AnalysisWindow) EnableWindow(GetDlgItem(hDlg, OPT_icsAnalyzeWindow), FALSE); + if (IsDlgButtonChecked(hDlg, OPT_icsAnalyze)) { + if(!appData.AnalysisWindow) { + EnableWindow(GetDlgItem(hDlg, OPT_icsAnalyzeWindow), TRUE); + } else { + EnableWindow(GetDlgItem(hDlg, OPT_icsAnalyzeWindow), FALSE); + } + if (!appData.userVersion) { + EnableWindow(GetDlgItem(hDlg, OPT_icsWhisper), TRUE); + EnableWindow(GetDlgItem(hDlg, OPT_icsKibitz), TRUE); + EnableWindow(GetDlgItem(hDlg, OPT_icsTell), TRUE); + EnableWindow(GetDlgItem(hDlg, OPT_icsNone), TRUE); + } else { + EnableWindow(GetDlgItem(hDlg, OPT_icsWhisper), FALSE); + EnableWindow(GetDlgItem(hDlg, OPT_icsKibitz), FALSE); + EnableWindow(GetDlgItem(hDlg, OPT_icsTell), FALSE); + EnableWindow(GetDlgItem(hDlg, OPT_icsNone), FALSE); + } +} else { + EnableWindow(GetDlgItem(hDlg, OPT_icsWhisper), FALSE); + EnableWindow(GetDlgItem(hDlg, OPT_icsKibitz), FALSE); + EnableWindow(GetDlgItem(hDlg, OPT_icsTell), FALSE); + if (!appData.userVersion) { + EnableWindow(GetDlgItem(hDlg, OPT_icsNone), FALSE); + /*EnableWindow(GetDlgItem(hDlg, OPT_icsNone), TRUE);*/ + } else { + EnableWindow(GetDlgItem(hDlg, OPT_icsNone), FALSE); + } +} + /* Set state */ + if (!appData.icsAnalyze) { + appData.icsEngineNone = TRUE; + appData.icsEngineWhisper = FALSE; + appData.icsEngineKibitz = FALSE; + appData.icsEngineTell = FALSE; + appData.icsAnalyzeOutPut = 4; + } + EnableWindow(GetDlgItem(hDlg, OPT_ADV), + IsDlgButtonChecked(hDlg, OPT_icsAnalyze)); + + if (IsDlgButtonChecked(hDlg, OPT_icsNone)) { + EnableWindow(GetDlgItem(hDlg, OPT_smartQueue), FALSE); + EnableWindow(GetDlgItem(hDlg, OPT_dropMoves), FALSE); + EnableWindow(GetDlgItem(hDlg, OPT_icsKillPV), FALSE); + EnableWindow(GetDlgItem(hDlg, OPT_icsKillPVs), FALSE); + } + if (IsDlgButtonChecked(hDlg, OPT_icsTell) || + IsDlgButtonChecked(hDlg, OPT_icsKibitz) || + IsDlgButtonChecked(hDlg, OPT_icsWhisper)) { + EnableWindow(GetDlgItem(hDlg, OPT_smartQueue), TRUE); + EnableWindow(GetDlgItem(hDlg, OPT_dropMoves), TRUE); + EnableWindow(GetDlgItem(hDlg, OPT_icsKillPV), TRUE); + } + +#undef ENABLE_DLG_ITEM +} + +LRESULT CALLBACK +IcsOptionsDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + char buf[MSG_SIZ]; + char buf2[MSG_SIZ]; + char buf3[MSG_SIZ]; + int number; + int PV; + int i; + static COLORREF cbc; + static MyColorizeAttribs *mca; + COLORREF *colorref; + + switch (message) { + case WM_INITDIALOG: /* message: initialize dialog box */ + + mca = colorizeAttribs; + + for (i=0; i < NColorClasses - 1; i++) { + mca[i].color = textAttribs[i].color; + mca[i].effects = textAttribs[i].effects; + } + cbc = consoleBackgroundColor; + + /* Center the dialog over the application window */ + CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER)); + + /* Initialize the dialog items */ +#define CHECK_BOX(x,y) CheckDlgButton(hDlg, (x), (BOOL)(y)) + + /* safe analyze state before we edit it */ + oldAnalyzeWindow = appData.icsAnalyzeWindow; + + CHECK_BOX(OPT_AutoComment, appData.autoComment); + CHECK_BOX(OPT_AutoObserve, appData.autoObserve); + CHECK_BOX(OPT_GetMoveList, appData.getMoveList); + CHECK_BOX(OPT_LocalLineEditing, appData.localLineEditing); + CHECK_BOX(OPT_QuietPlay, appData.quietPlay); + CHECK_BOX(OPT_Premove, appData.premove); + CHECK_BOX(OPT_PremoveWhite, appData.premoveWhite); + CHECK_BOX(OPT_PremoveBlack, appData.premoveBlack); + CHECK_BOX(OPT_IcsAlarm, appData.icsAlarm); + CHECK_BOX(OPT_DontColorize, !appData.colorize); + CHECK_BOX(OPT_icsAnalyze, appData.icsAnalyze); + CHECK_BOX(OPT_icsKillPV, appData.icsEngineKillPV); + CHECK_BOX(OPT_icsWhisper, appData.icsEngineWhisper); + CHECK_BOX(OPT_icsKibitz, appData.icsEngineKibitz); + CHECK_BOX(OPT_icsTell, appData.icsEngineTell); + CHECK_BOX(OPT_icsNone, appData.icsEngineNone); + CHECK_BOX(OPT_icsAnalyzeWindow, appData.icsAnalyzeWindow); + CHECK_BOX(OPT_icsTell, appData.icsEngineTell); + CHECK_BOX(OPT_smartQueue, appData.smartQueue); + CHECK_BOX(OPT_dropMoves, appData.windowMove); + +#undef CHECK_BOX + /* daniel */ + /* Only enable if we have a engine */ + EnableWindow(GetDlgItem(hDlg, OPT_icsAnalyze), !appData.noChessProgram); + EnableWindow(GetDlgItem(hDlg, OPT_icsKillPV), !appData.noChessProgram); + EnableWindow(GetDlgItem(hDlg, OPT_icsWhisper), !appData.noChessProgram); + EnableWindow(GetDlgItem(hDlg, OPT_icsKibitz), !appData.noChessProgram); + EnableWindow(GetDlgItem(hDlg, OPT_icsTell), !appData.noChessProgram); + EnableWindow(GetDlgItem(hDlg, OPT_icsNone), !appData.noChessProgram); + EnableWindow(GetDlgItem(hDlg, OPT_icsAnalyzeWindow), !appData.noChessProgram); + EnableWindow(GetDlgItem(hDlg, OPT_smartQueue), !appData.noChessProgram); + EnableWindow(GetDlgItem(hDlg, OPT_dropMoves), !appData.noChessProgram); + EnableWindow(GetDlgItem(hDlg, OPT_ADV), !appData.noChessProgram); + + + sprintf(buf, "%d", appData.icsAlarmTime / 1000); + if (icsQueue[ics_gamenum].killPv == 0) { + sprintf(buf2, "%d", appData.icsKillPVs); + } else { + sprintf(buf2, "%d", icsQueue[ics_gamenum].killPv); + } + if (appData.icsTells[0] == NULLCHAR) { + strcpy(buf3, "211"); + } else { + strcpy(buf3, appData.icsTells); + } + SetDlgItemText(hDlg, OPT_IcsAlarmTime, buf); + SetDlgItemText(hDlg, OPT_icsKillPVs, buf2); + SetDlgItemText(hDlg, OPT_icsTells, buf3); + SetDlgItemText(hDlg, OPT_PremoveWhiteText, appData.premoveWhiteText); + SetDlgItemText(hDlg, OPT_PremoveBlackText, appData.premoveBlackText); + + SendDlgItemMessage(hDlg, OPT_SampleShout, EM_SETBKGNDCOLOR, 0, cbc); + SendDlgItemMessage(hDlg, OPT_SampleSShout, EM_SETBKGNDCOLOR, 0, cbc); + SendDlgItemMessage(hDlg, OPT_SampleChannel1, EM_SETBKGNDCOLOR, 0, cbc); + SendDlgItemMessage(hDlg, OPT_SampleChannel, EM_SETBKGNDCOLOR, 0, cbc); + SendDlgItemMessage(hDlg, OPT_SampleKibitz, EM_SETBKGNDCOLOR, 0, cbc); + SendDlgItemMessage(hDlg, OPT_SampleTell, EM_SETBKGNDCOLOR, 0, cbc); + SendDlgItemMessage(hDlg, OPT_SampleChallenge, EM_SETBKGNDCOLOR, 0, cbc); + SendDlgItemMessage(hDlg, OPT_SampleRequest, EM_SETBKGNDCOLOR, 0, cbc); + SendDlgItemMessage(hDlg, OPT_SampleSeek, EM_SETBKGNDCOLOR, 0, cbc); + SendDlgItemMessage(hDlg, OPT_SampleNormal, EM_SETBKGNDCOLOR, 0, cbc); + + SetDlgItemText(hDlg, OPT_SampleShout, mca[ColorShout].name); + SetDlgItemText(hDlg, OPT_SampleSShout, mca[ColorSShout].name); + SetDlgItemText(hDlg, OPT_SampleChannel1, mca[ColorChannel1].name); + SetDlgItemText(hDlg, OPT_SampleChannel, mca[ColorChannel].name); + SetDlgItemText(hDlg, OPT_SampleKibitz, mca[ColorKibitz].name); + SetDlgItemText(hDlg, OPT_SampleTell, mca[ColorTell].name); + SetDlgItemText(hDlg, OPT_SampleChallenge, mca[ColorChallenge].name); + SetDlgItemText(hDlg, OPT_SampleRequest, mca[ColorRequest].name); + SetDlgItemText(hDlg, OPT_SampleSeek, mca[ColorSeek].name); + SetDlgItemText(hDlg, OPT_SampleNormal, mca[ColorNormal].name); + + UpdateSampleText(hDlg, OPT_SampleShout, &mca[ColorShout]); + UpdateSampleText(hDlg, OPT_SampleSShout, &mca[ColorSShout]); + UpdateSampleText(hDlg, OPT_SampleChannel1, &mca[ColorChannel1]); + UpdateSampleText(hDlg, OPT_SampleChannel, &mca[ColorChannel]); + UpdateSampleText(hDlg, OPT_SampleKibitz, &mca[ColorKibitz]); + UpdateSampleText(hDlg, OPT_SampleTell, &mca[ColorTell]); + UpdateSampleText(hDlg, OPT_SampleChallenge, &mca[ColorChallenge]); + UpdateSampleText(hDlg, OPT_SampleRequest, &mca[ColorRequest]); + UpdateSampleText(hDlg, OPT_SampleSeek, &mca[ColorSeek]); + UpdateSampleText(hDlg, OPT_SampleNormal, &mca[ColorNormal]); + + SetIcsOptionEnables(hDlg); + return TRUE; + + case WM_COMMAND: /* message: received a command */ + switch (LOWORD(wParam)) { + + case WM_USER_GetConsoleBackground: + /* the ColorizeTextDialog needs the current background color */ + colorref = (COLORREF *)lParam; + *colorref = cbc; + return FALSE; + + case IDOK: + /* daniel */ + /* Read changed options from the dialog box */ + GetDlgItemText(hDlg, OPT_IcsAlarmTime, buf, MSG_SIZ); + GetDlgItemText(hDlg, OPT_icsKillPVs, buf2, MSG_SIZ); + GetDlgItemText(hDlg, OPT_icsTells, buf3, MSG_SIZ); + + if (sscanf(buf, "%d", &number) != 1 || (number < 0)){ + MessageBox(hDlg, "Invalid ICS Alarm Time", + "Option Error", MB_OK|MB_ICONEXCLAMATION); + return FALSE; + } + + if(sscanf(buf2, "%d", &PV) != 1 || (PV < 1) || (PV > 20)) { + if (PV == 0) { + PV = appData.icsKillPVs; + } else { + MessageBox(hDlg, "Invalid KillPV value - avaible: 1-20", + "Option Error", MB_OK|MB_ICONEXCLAMATION); + return FALSE; + } + } + +#define IS_CHECKED(x) (Boolean)IsDlgButtonChecked(hDlg, (x)) + + appData.icsAlarm = IS_CHECKED(OPT_IcsAlarm); + appData.premove = IS_CHECKED(OPT_Premove); + appData.premoveWhite = IS_CHECKED(OPT_PremoveWhite); + appData.premoveBlack = IS_CHECKED(OPT_PremoveBlack); + appData.autoComment = IS_CHECKED(OPT_AutoComment); + appData.autoObserve = IS_CHECKED(OPT_AutoObserve); + appData.getMoveList = IS_CHECKED(OPT_GetMoveList); + appData.localLineEditing = IS_CHECKED(OPT_LocalLineEditing); + appData.quietPlay = IS_CHECKED(OPT_QuietPlay); + appData.icsEngineKibitz = IS_CHECKED(OPT_icsKibitz); + appData.icsEngineKillPV = IS_CHECKED(OPT_icsKillPV); + appData.icsEngineNone = IS_CHECKED(OPT_icsNone); + appData.icsEngineTell = IS_CHECKED(OPT_icsTell); + appData.icsTells[MSG_SIZ] = IS_CHECKED(OPT_icsTells); + appData.icsEngineWhisper = IS_CHECKED(OPT_icsWhisper); + appData.icsAnalyze = IS_CHECKED(OPT_icsAnalyze); + appData.icsAnalyzeWindow = IS_CHECKED(OPT_icsAnalyzeWindow); + appData.smartQueue = IS_CHECKED(OPT_smartQueue); + appData.windowMove = IS_CHECKED(OPT_dropMoves); + +#undef IS_CHECKED + + if (appData.icsAnalyze && first.initDone && \ + !first.analyzing) IcsAnalyze(TRUE); + if (!appData.icsAnalyze) { + if(first.analyzing) IcsAnalyze(FALSE); + appData.icsAnalyzeOutPut = 4; + appData.icsEngineKillPV = FALSE; + appData.icsEngineTell = FALSE; + if(appData.icsAnalyzeWindow || oldAnalyzeWindow) { + AnalysisPopDown(); + appData.icsAnalyzeWindow=FALSE; + } + } + if (appData.icsEngineKibitz) appData.icsAnalyzeOutPut = 2; + if (appData.icsEngineWhisper) appData.icsAnalyzeOutPut = 1; + if (appData.icsEngineNone) appData.icsAnalyzeOutPut = 4; + if (appData.icsEngineTell) appData.icsAnalyzeOutPut = 3; + if (appData.icsAnalyzeOutPut != 4 && !appData.icsAnalyze) { + MessageBox(hDlg, "You must first enable the engine", + "Option Error", MB_OK|MB_ICONEXCLAMATION); + appData.icsAnalyzeOutPut = 4; + return FALSE; + } + + /* Engine must run before we do that */ + if (appData.icsAnalyze && appData.icsAnalyzeWindow) IcsAnalyzeWindowUp(); + if (!appData.icsAnalyzeWindow && oldAnalyzeWindow \ + && appData.icsAnalyze) { + AnalysisPopDown(); + } + if (!appData.icsAnalyze && appData.icsAnalyzeWindow) { + appData.icsAnalyzeWindow = FALSE; + } + + /* Obsolete + if (appData.icsEngineKillPV && appData.icsAnalyzeOutPut == 4) { + MessageBox(hDlg, "KillPV only works if you're using a output", + "Option Error", MB_OK|MB_ICONEXCLAMATION); + appData.icsEngineKillPV = FALSE; + return FALSE; + } + */ + + if (appData.icsAnalyzeOutPut == 4) appData.icsEngineKillPV = FALSE; + + if(sizeof(buf3) > MSG_SIZ){ + MessageBox(hDlg, "Name or Channel to long", + "Option Error", MB_OK|MB_ICONEXCLAMATION); + } else { + strcpy(appData.icsTells, buf3); + } + + appData.icsAlarmTime = number * 1000; + /* appData.icsKillPVs = PV; */ + icsQueue[ics_gamenum].killPv = PV; + GetDlgItemText(hDlg, OPT_PremoveWhiteText, appData.premoveWhiteText, 5); + GetDlgItemText(hDlg, OPT_PremoveBlackText, appData.premoveBlackText, 5); + + if (appData.localLineEditing) { + DontEcho(); + EchoOn(); + } else { + DoEcho(); + EchoOff(); + } + + + appData.colorize = + (Boolean)!IsDlgButtonChecked(hDlg, OPT_DontColorize); + + if (!appData.colorize) { + CHARFORMAT cf; + COLORREF background = ParseColorName(COLOR_BKGD); + /* + SetDefaultTextAttribs(); + Colorize(currentColorClass); + */ + cf.cbSize = sizeof(CHARFORMAT); + cf.dwMask = CFM_COLOR; + cf.crTextColor = ParseColorName(COLOR_NORMAL); + + SendDlgItemMessage(hwndConsole, OPT_ConsoleInput, + EM_SETCHARFORMAT, SCF_ALL, (LPARAM)&cf); + SendDlgItemMessage(hwndConsole, OPT_ConsoleText, + EM_SETBKGNDCOLOR, FALSE, background); + SendDlgItemMessage(hwndConsole, OPT_ConsoleInput, + EM_SETBKGNDCOLOR, FALSE, background); + } + + if (cbc != consoleBackgroundColor) { + consoleBackgroundColor = cbc; + if (appData.colorize) { + SendDlgItemMessage(hwndConsole, OPT_ConsoleText, + EM_SETBKGNDCOLOR, FALSE, consoleBackgroundColor); + SendDlgItemMessage(hwndConsole, OPT_ConsoleInput, + EM_SETBKGNDCOLOR, FALSE, consoleBackgroundColor); + } + } + + for (i=0; i < NColorClasses - 1; i++) { + textAttribs[i].color = mca[i].color; + textAttribs[i].effects = mca[i].effects; + } + + EndDialog(hDlg, TRUE); + return TRUE; + + case IDCANCEL: + EndDialog(hDlg, FALSE); + return TRUE; + + case OPT_ADV: + icsAnalyzeAdvPopup(hDlg); + break; + + case OPT_ChooseShoutColor: + ColorizeTextPopup(hDlg, ColorShout); + UpdateSampleText(hDlg, OPT_SampleShout, &mca[ColorShout]); + break; + + case OPT_ChooseSShoutColor: + ColorizeTextPopup(hDlg, ColorSShout); + UpdateSampleText(hDlg, OPT_SampleSShout, &mca[ColorSShout]); + break; + + case OPT_ChooseChannel1Color: + ColorizeTextPopup(hDlg, ColorChannel1); + UpdateSampleText(hDlg, OPT_SampleChannel1, + &colorizeAttribs[ColorChannel1]); + break; + + case OPT_ChooseChannelColor: + ColorizeTextPopup(hDlg, ColorChannel); + UpdateSampleText(hDlg, OPT_SampleChannel, &mca[ColorChannel]); + break; + + case OPT_ChooseKibitzColor: + ColorizeTextPopup(hDlg, ColorKibitz); + UpdateSampleText(hDlg, OPT_SampleKibitz, &mca[ColorKibitz]); + break; + + case OPT_ChooseTellColor: + ColorizeTextPopup(hDlg, ColorTell); + UpdateSampleText(hDlg, OPT_SampleTell, &mca[ColorTell]); + break; + + case OPT_ChooseChallengeColor: + ColorizeTextPopup(hDlg, ColorChallenge); + UpdateSampleText(hDlg, OPT_SampleChallenge, &mca[ColorChallenge]); + break; + + case OPT_ChooseRequestColor: + ColorizeTextPopup(hDlg, ColorRequest); + UpdateSampleText(hDlg, OPT_SampleRequest, &mca[ColorRequest]); + break; + + case OPT_ChooseSeekColor: + ColorizeTextPopup(hDlg, ColorSeek); + UpdateSampleText(hDlg, OPT_SampleSeek, &mca[ColorSeek]); + break; + + case OPT_ChooseNormalColor: + ColorizeTextPopup(hDlg, ColorNormal); + UpdateSampleText(hDlg, OPT_SampleNormal, &mca[ColorNormal]); + break; + + case OPT_ChooseBackgroundColor: + if (ChangeColor(hDlg, &cbc)) { + SendDlgItemMessage(hDlg, OPT_SampleShout, EM_SETBKGNDCOLOR, 0, cbc); + SendDlgItemMessage(hDlg, OPT_SampleSShout, EM_SETBKGNDCOLOR, 0, cbc); + SendDlgItemMessage(hDlg, OPT_SampleChannel1, EM_SETBKGNDCOLOR, 0, cbc); + SendDlgItemMessage(hDlg, OPT_SampleChannel, EM_SETBKGNDCOLOR, 0, cbc); + SendDlgItemMessage(hDlg, OPT_SampleKibitz, EM_SETBKGNDCOLOR, 0, cbc); + SendDlgItemMessage(hDlg, OPT_SampleTell, EM_SETBKGNDCOLOR, 0, cbc); + SendDlgItemMessage(hDlg, OPT_SampleChallenge, EM_SETBKGNDCOLOR, 0, cbc); + SendDlgItemMessage(hDlg, OPT_SampleRequest, EM_SETBKGNDCOLOR, 0, cbc); + SendDlgItemMessage(hDlg, OPT_SampleSeek, EM_SETBKGNDCOLOR, 0, cbc); + SendDlgItemMessage(hDlg, OPT_SampleNormal, EM_SETBKGNDCOLOR, 0, cbc); + } + break; + + case OPT_DefaultColors: + for (i=0; i < NColorClasses - 1; i++) + ParseAttribs(&mca[i].color, + &mca[i].effects, + defaultTextAttribs[i]); + + cbc = ParseColorName(COLOR_BKGD); + SendDlgItemMessage(hDlg, OPT_SampleShout, EM_SETBKGNDCOLOR, 0, cbc); + SendDlgItemMessage(hDlg, OPT_SampleSShout, EM_SETBKGNDCOLOR, 0, cbc); + SendDlgItemMessage(hDlg, OPT_SampleChannel1, EM_SETBKGNDCOLOR, 0, cbc); + SendDlgItemMessage(hDlg, OPT_SampleChannel, EM_SETBKGNDCOLOR, 0, cbc); + SendDlgItemMessage(hDlg, OPT_SampleKibitz, EM_SETBKGNDCOLOR, 0, cbc); + SendDlgItemMessage(hDlg, OPT_SampleTell, EM_SETBKGNDCOLOR, 0, cbc); + SendDlgItemMessage(hDlg, OPT_SampleChallenge, EM_SETBKGNDCOLOR, 0, cbc); + SendDlgItemMessage(hDlg, OPT_SampleRequest, EM_SETBKGNDCOLOR, 0, cbc); + SendDlgItemMessage(hDlg, OPT_SampleSeek, EM_SETBKGNDCOLOR, 0, cbc); + SendDlgItemMessage(hDlg, OPT_SampleNormal, EM_SETBKGNDCOLOR, 0, cbc); + + UpdateSampleText(hDlg, OPT_SampleShout, &mca[ColorShout]); + UpdateSampleText(hDlg, OPT_SampleSShout, &mca[ColorSShout]); + UpdateSampleText(hDlg, OPT_SampleChannel1, &mca[ColorChannel1]); + UpdateSampleText(hDlg, OPT_SampleChannel, &mca[ColorChannel]); + UpdateSampleText(hDlg, OPT_SampleKibitz, &mca[ColorKibitz]); + UpdateSampleText(hDlg, OPT_SampleTell, &mca[ColorTell]); + UpdateSampleText(hDlg, OPT_SampleChallenge, &mca[ColorChallenge]); + UpdateSampleText(hDlg, OPT_SampleRequest, &mca[ColorRequest]); + UpdateSampleText(hDlg, OPT_SampleSeek, &mca[ColorSeek]); + UpdateSampleText(hDlg, OPT_SampleNormal, &mca[ColorNormal]); + break; + + default: + SetIcsOptionEnables(hDlg); + break; + } + break; + } + return FALSE; +} + +VOID +IcsOptionsPopup(HWND hwnd) +{ + FARPROC lpProc = MakeProcInstance((FARPROC)IcsOptionsDialog, hInst); + DialogBox(hInst, MAKEINTRESOURCE(DLG_IcsOptions), hwnd, + (DLGPROC) lpProc); + FreeProcInstance(lpProc); +} + +/*---------------------------------------------------------------------------*\ + * + * Fonts Dialog functions + * +\*---------------------------------------------------------------------------*/ + +VOID +SetSampleFontText(HWND hwnd, int id, const MyFont *mf) +{ + char buf[MSG_SIZ]; + HWND hControl; + HDC hdc; + CHARFORMAT cf; + SIZE size; + RECT rectClient, rectFormat; + HFONT oldFont; + POINT center; + int len; + + len = sprintf(buf, "%.0f pt. %s%s%s\n", + mf->mfp.pointSize, mf->mfp.faceName, + mf->mfp.bold ? " bold" : "", + mf->mfp.italic ? " italic" : ""); + SetDlgItemText(hwnd, id, buf); + + hControl = GetDlgItem(hwnd, id); + hdc = GetDC(hControl); + SetMapMode(hdc, MM_TEXT); /* 1 pixel == 1 logical unit */ + oldFont = SelectObject(hdc, mf->hf); + + /* get number of logical units necessary to display font name */ + GetTextExtentPoint32(hdc, buf, len, &size); + + /* calculate formatting rectangle in the rich edit control. + * May be larger or smaller than the actual control. + */ + GetClientRect(hControl, &rectClient); + center.x = (rectClient.left + rectClient.right) / 2; + center.y = (rectClient.top + rectClient.bottom) / 2; + rectFormat.top = center.y - (size.cy / 2) - 1; + rectFormat.bottom = center.y + (size.cy / 2) + 1; + rectFormat.left = center.x - (size.cx / 2) - 1; + rectFormat.right = center.x + (size.cx / 2) + 1; + +#if 0 + fprintf(debugFP, "\nfont: %s\n" + "center.x %d, centerY %d\n" + "size.cx %d, size.cy %d\n" + "client.top %d, bottom %d, left %d, right %d\n" + "format.top %d, bottom %d, left %d, right %d\n", + buf, + center.x, center.y, + size.cx, size.cy, + rectClient.top, rectClient.bottom, rectClient.left, + rectClient.right, + rectFormat.top, rectFormat.bottom, rectFormat.left, + rectFormat.right); +#endif + + cf.cbSize = sizeof(CHARFORMAT); + cf.dwMask = CFM_FACE|CFM_SIZE|CFM_CHARSET|CFM_BOLD|CFM_ITALIC; + cf.dwEffects = 0; + if (mf->lf.lfWeight == FW_BOLD) cf.dwEffects |= CFE_BOLD; + if (mf->lf.lfItalic) cf.dwEffects |= CFE_ITALIC; + strcpy(cf.szFaceName, mf->mfp.faceName); + /* + * yHeight is expressed in twips. A twip is 1/20 of a font's point + * size. See documentation of CHARFORMAT. --msw + */ + cf.yHeight = (int)(mf->mfp.pointSize * 20.0 + 0.5); + cf.bCharSet = mf->lf.lfCharSet; + cf.bPitchAndFamily = mf->lf.lfPitchAndFamily; + + /* format the text in the rich edit control */ + SendMessage(hControl, EM_SETCHARFORMAT, SCF_ALL, (LPARAM) &cf); + SendMessage(hControl, EM_SETRECT, (WPARAM)0, (LPARAM) &rectFormat); + + /* clean up */ + SelectObject(hdc, oldFont); + ReleaseDC(hControl, hdc); +} + +VOID +CopyFont(MyFont *dest, const MyFont *src) +{ + dest->mfp.pointSize = src->mfp.pointSize; + dest->mfp.bold = src->mfp.bold; + dest->mfp.italic = src->mfp.italic; + dest->mfp.underline = src->mfp.underline; + dest->mfp.strikeout = src->mfp.strikeout; + lstrcpy(dest->mfp.faceName, src->mfp.faceName); + CreateFontInMF(dest); +} + + +LRESULT CALLBACK +FontOptionsDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + static MyFont workFont[NUM_FONTS]; + static BOOL firstPaint; + int i; + RECT rect; + + switch (message) { + case WM_INITDIALOG: + + /* copy the current font settings into a working copy */ + for (i=0; i < NUM_FONTS; i++) + CopyFont(&workFont[i], font[boardSize][i]); + + if (!appData.icsActive) + EnableWindow(GetDlgItem(hDlg, OPT_ChooseConsoleFont), FALSE); + + firstPaint = TRUE; /* see rant below */ + + /* If I don't call SetFocus(), the dialog won't respond to the keyboard + * when first drawn. Why is this the only dialog that behaves this way? Is + * is the WM_PAINT stuff below?? Sigh... + */ + SetFocus(GetDlgItem(hDlg, IDOK)); + break; + + case WM_PAINT: + /* This should not be necessary. However, if SetSampleFontText() is called + * in response to WM_INITDIALOG, the strings are not properly centered in + * the controls when the dialog first appears. I can't figure out why, so + * this is the workaround. --msw + */ + if (firstPaint) { + SetSampleFontText(hDlg, OPT_SampleClockFont, &workFont[CLOCK_FONT]); + SetSampleFontText(hDlg, OPT_SampleMessageFont, &workFont[MESSAGE_FONT]); + SetSampleFontText(hDlg, OPT_SampleCoordFont, &workFont[COORD_FONT]); + SetSampleFontText(hDlg, OPT_SampleTagFont, &workFont[EDITTAGS_FONT]); + SetSampleFontText(hDlg, OPT_SampleCommentsFont, &workFont[COMMENT_FONT]); + SetSampleFontText(hDlg, OPT_SampleConsoleFont, &workFont[CONSOLE_FONT]); + firstPaint = FALSE; + } + break; + + case WM_COMMAND: /* message: received a command */ + switch (LOWORD(wParam)) { + + case IDOK: + /* again, it seems to avoid redraw problems if we call EndDialog first */ + EndDialog(hDlg, FALSE); + + /* copy modified settings back to the fonts array */ + for (i=0; i < NUM_FONTS; i++) + CopyFont(font[boardSize][i], &workFont[i]); + + /* a sad necessity due to the original design of having a separate + * console font, tags font, and comment font for each board size. IMHO + * these fonts should not be dependent on the current board size. I'm + * running out of time, so I am doing this hack rather than redesign the + * data structure. Besides, I think if I redesigned the data structure, I + * might break backwards compatibility with old winboard.ini files. + * --msw + */ + for (i=0; i < NUM_SIZES; i++) { + CopyFont(font[i][EDITTAGS_FONT], &workFont[EDITTAGS_FONT]); + CopyFont(font[i][CONSOLE_FONT], &workFont[CONSOLE_FONT]); + CopyFont(font[i][COMMENT_FONT], &workFont[COMMENT_FONT]); + } + /* end sad necessity */ + + InitDrawingSizes(boardSize, 0); + InvalidateRect(hwndMain, NULL, TRUE); + + if (commentDialog) { + SendDlgItemMessage(commentDialog, OPT_CommentText, + WM_SETFONT, (WPARAM)font[boardSize][COMMENT_FONT]->hf, + MAKELPARAM(TRUE, 0)); + GetClientRect(GetDlgItem(commentDialog, OPT_CommentText), &rect); + InvalidateRect(commentDialog, &rect, TRUE); + } + + if (editTagsDialog) { + SendDlgItemMessage(editTagsDialog, OPT_TagsText, + WM_SETFONT, (WPARAM)font[boardSize][EDITTAGS_FONT]->hf, + MAKELPARAM(TRUE, 0)); + GetClientRect(GetDlgItem(editTagsDialog, OPT_TagsText), &rect); + InvalidateRect(editTagsDialog, &rect, TRUE); + } + + if (hwndConsole) { + ChangedConsoleFont(); + } + + for (i=0; idef, &workFont[i].mfp); + CreateFontInMF(&workFont[i]); + } + SetSampleFontText(hDlg, OPT_SampleClockFont, &workFont[CLOCK_FONT]); + SetSampleFontText(hDlg, OPT_SampleMessageFont, &workFont[MESSAGE_FONT]); + SetSampleFontText(hDlg, OPT_SampleCoordFont, &workFont[COORD_FONT]); + SetSampleFontText(hDlg, OPT_SampleTagFont, &workFont[EDITTAGS_FONT]); + SetSampleFontText(hDlg, OPT_SampleCommentsFont, &workFont[COMMENT_FONT]); + SetSampleFontText(hDlg, OPT_SampleConsoleFont, &workFont[CONSOLE_FONT]); + break; + } + } + return FALSE; +} + +VOID +FontsOptionsPopup(HWND hwnd) +{ + FARPROC lpProc = MakeProcInstance((FARPROC)FontOptionsDialog, hInst); + DialogBox(hInst, MAKEINTRESOURCE(DLG_Fonts), hwnd, + (DLGPROC) lpProc); + FreeProcInstance(lpProc); +} + +/*---------------------------------------------------------------------------*\ + * + * Sounds Dialog functions + * +\*---------------------------------------------------------------------------*/ + + +SoundComboData soundComboData[] = { + {"Move", NULL}, + {"Bell", NULL}, + {"ICS Alarm", NULL}, + {"ICS Win", NULL}, + {"ICS Loss", NULL}, + {"ICS Draw", NULL}, + {"ICS Unfinished", NULL}, + {"Shout", NULL}, + {"SShout/CShout", NULL}, + {"Channel 1", NULL}, + {"Channel", NULL}, + {"Kibitz", NULL}, + {"Tell", NULL}, + {"Challenge", NULL}, + {"Request", NULL}, + {"Seek", NULL}, + {NULL, NULL}, +}; + + +void +InitSoundComboData(SoundComboData *scd) +{ + SoundClass sc; + ColorClass cc; + int index; + + /* copy current sound settings to combo array */ + + for ( sc = (SoundClass)0; sc < NSoundClasses; sc++) { + scd[sc].name = strdup(sounds[sc].name); + } + for ( cc = (ColorClass)0; cc < NColorClasses - 2; cc++) { + index = (int)cc + (int)NSoundClasses; + scd[index].name = strdup(textAttribs[cc].sound.name); + } +} + + +void +ResetSoundComboData(SoundComboData *scd) +{ + while (scd->label) { + if (scd->name != NULL) { + free (scd->name); + scd->name = NULL; + } + scd++; + } +} + +void +InitSoundCombo(HWND hwndCombo, SoundComboData *scd) +{ + char buf[255]; + DWORD err; + DWORD cnt = 0; + SendMessage(hwndCombo, CB_RESETCONTENT, 0, 0); + + /* send the labels to the combo box */ + while (scd->label) { + err = SendMessage(hwndCombo, CB_ADDSTRING, 0, (LPARAM) scd->label); + if (err != cnt++) { + sprintf(buf, "InitSoundCombo(): err '%d', cnt '%d'\n", + err, cnt); + MessageBox(NULL, buf, NULL, MB_OK); + } + scd++; + } + SendMessage(hwndCombo, CB_SETCURSEL, (WPARAM) 0, (LPARAM) 0); +} + +int +SoundDialogWhichRadio(HWND hDlg) +{ + if (IsDlgButtonChecked(hDlg, OPT_NoSound)) return OPT_NoSound; + if (IsDlgButtonChecked(hDlg, OPT_DefaultBeep)) return OPT_DefaultBeep; + if (IsDlgButtonChecked(hDlg, OPT_BuiltInSound)) return OPT_BuiltInSound; + if (IsDlgButtonChecked(hDlg, OPT_WavFile)) return OPT_WavFile; + return -1; +} + +VOID +SoundDialogSetEnables(HWND hDlg, int radio) +{ + EnableWindow(GetDlgItem(hDlg, OPT_BuiltInSoundName), + radio == OPT_BuiltInSound); + EnableWindow(GetDlgItem(hDlg, OPT_WavFileName), radio == OPT_WavFile); + EnableWindow(GetDlgItem(hDlg, OPT_BrowseSound), radio == OPT_WavFile); +} + +char * +SoundDialogGetName(HWND hDlg, int radio) +{ + static char buf[MSG_SIZ], buf2[MSG_SIZ], buf3[MSG_SIZ]; + char *dummy, *ret; + switch (radio) { + case OPT_NoSound: + default: + return ""; + case OPT_DefaultBeep: + return "$"; + case OPT_BuiltInSound: + buf[0] = '!'; + GetDlgItemText(hDlg, OPT_BuiltInSoundName, buf + 1, sizeof(buf) - 1); + return buf; + case OPT_WavFile: + GetDlgItemText(hDlg, OPT_WavFileName, buf, sizeof(buf)); + GetCurrentDirectory(MSG_SIZ, buf3); + SetCurrentDirectory(installDir); + if (GetFullPathName(buf, MSG_SIZ, buf2, &dummy)) { + ret = buf2; + } else { + ret = buf; + } + SetCurrentDirectory(buf3); + return ret; + } +} + +void +DisplaySelectedSound(HWND hDlg, HWND hCombo, const char *name) +{ + int radio; + /* + * I think it's best to clear the combo and edit boxes. It looks stupid + * to have a value from another sound event sitting there grayed out. + */ + SetDlgItemText(hDlg, OPT_WavFileName, ""); + SendMessage(hCombo, CB_SETCURSEL, (WPARAM) -1, (LPARAM) 0); + + if (appData.debugMode) + fprintf(debugFP, "DisplaySelectedSound(,,'%s'):\n", name); + switch (name[0]) { + case NULLCHAR: + radio = OPT_NoSound; + break; + case '$': + if (name[1] == NULLCHAR) { + radio = OPT_DefaultBeep; + } else { + radio = OPT_WavFile; + SetDlgItemText(hDlg, OPT_WavFileName, name); + } + break; + case '!': + if (name[1] == NULLCHAR) { + radio = OPT_NoSound; + } else { + radio = OPT_BuiltInSound; + if (SendMessage(hCombo, CB_SELECTSTRING, (WPARAM) -1, + (LPARAM) (name + 1)) == CB_ERR) { + SendMessage(hCombo, CB_SETCURSEL, (WPARAM) -1, (LPARAM) 0); + SendMessage(hCombo, WM_SETTEXT, (WPARAM) 0, (LPARAM) (name + 1)); + } + } + break; + default: + radio = OPT_WavFile; + SetDlgItemText(hDlg, OPT_WavFileName, name); + break; + } + SoundDialogSetEnables(hDlg, radio); + CheckRadioButton(hDlg, OPT_NoSound, OPT_WavFile, radio); +} + + +char *builtInSoundNames[] = BUILT_IN_SOUND_NAMES; + +LRESULT CALLBACK +SoundOptionsDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + static HWND hSoundCombo; + static DWORD index; + static HWND hBISN; + int radio; + MySound tmp; + FILE *f; + char buf[MSG_SIZ]; + char *newName; + SoundClass sc; + ColorClass cc; + SoundComboData *scd; + + switch (message) { + case WM_INITDIALOG: + /* Center the dialog over the application window */ + CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER)); + + /* Initialize the built-in sounds combo */ + hBISN = GetDlgItem(hDlg, OPT_BuiltInSoundName); + InitComboStrings(hBISN, builtInSoundNames); + + /* Initialize the sound events combo */ + index = 0; + InitSoundComboData(soundComboData); + hSoundCombo = GetDlgItem(hDlg, CBO_Sounds); + InitSoundCombo(hSoundCombo, soundComboData); + + /* update the dialog */ + DisplaySelectedSound(hDlg, hBISN, soundComboData[index].name); + return TRUE; + + case WM_COMMAND: /* message: received a command */ + + if (((HWND)lParam == hSoundCombo) && + (HIWORD(wParam) == CBN_SELCHANGE)) { + /* + * the user has selected a new sound event. We must store the name for + * the previously selected event, then retrieve the name for the + * newly selected event and update the dialog. + */ + radio = SoundDialogWhichRadio(hDlg); + newName = strdup(SoundDialogGetName(hDlg, radio)); + + if (strcmp(newName, soundComboData[index].name) != 0) { + free(soundComboData[index].name); + soundComboData[index].name = newName; + } else { + free(newName); + newName = NULL; + } + /* now get the settings for the newly selected event */ + index = SendMessage(hSoundCombo, CB_GETCURSEL, (WPARAM)0, (LPARAM)0); + DisplaySelectedSound(hDlg, hBISN, soundComboData[index].name); + + return TRUE; + } + switch (LOWORD(wParam)) { + case IDOK: + /* + * save the name for the currently selected sound event + */ + radio = SoundDialogWhichRadio(hDlg); + newName = strdup(SoundDialogGetName(hDlg, radio)); + + if (strcmp(soundComboData[index].name, newName) != 0) { + free(soundComboData[index].name); + soundComboData[index].name = newName; + } else { + free(newName); + newName = NULL; + } + + /* save all the sound names that changed and load the sounds */ + + for ( sc = (SoundClass)0; sc < NSoundClasses; sc++) { + if (strcmp(soundComboData[sc].name, sounds[sc].name) != 0) { + free(sounds[sc].name); + sounds[sc].name = strdup(soundComboData[sc].name); + MyLoadSound(&sounds[sc]); + } + } + for ( cc = (ColorClass)0; cc < NColorClasses - 2; cc++) { + index = (int)cc + (int)NSoundClasses; + if (strcmp(soundComboData[index].name, + textAttribs[cc].sound.name) != 0) { + free(textAttribs[cc].sound.name); + textAttribs[cc].sound.name = strdup(soundComboData[index].name); + MyLoadSound(&textAttribs[cc].sound); + } + } + + ResetSoundComboData(soundComboData); + EndDialog(hDlg, TRUE); + return TRUE; + + case IDCANCEL: + ResetSoundComboData(soundComboData); + EndDialog(hDlg, FALSE); + return TRUE; + + case OPT_DefaultSounds: + /* can't use SetDefaultSounds() because we need to be able to "undo" if + * user selects "Cancel" later on. So we do it the hard way here. + */ + scd = &soundComboData[0]; + while (scd->label != NULL) { + if (scd->name != NULL) free(scd->name); + scd->name = strdup(""); + scd++; + } + free(soundComboData[(int)SoundBell].name); + soundComboData[(int)SoundBell].name = strdup(SOUND_BELL); + DisplaySelectedSound(hDlg, hBISN, soundComboData[index].name); + break; + + case OPT_PlaySound: + radio = SoundDialogWhichRadio(hDlg); + tmp.name = strdup(SoundDialogGetName(hDlg, radio)); + tmp.data = NULL; + MyLoadSound(&tmp); + MyPlaySound(&tmp); + if (tmp.data != NULL) free(tmp.data); + if (tmp.name != NULL) free(tmp.name); + return TRUE; + + case OPT_BrowseSound: + f = OpenFileDialog(hDlg, FALSE, NULL, "wav", SOUND_FILT, + "Browse for Sound File", NULL, NULL, buf); + if (f != NULL) { + fclose(f); + SetDlgItemText(hDlg, OPT_WavFileName, buf); + } + return TRUE; + + default: + radio = SoundDialogWhichRadio(hDlg); + SoundDialogSetEnables(hDlg, radio); + break; + } + break; + } + return FALSE; +} + + +VOID SoundOptionsPopup(HWND hwnd) +{ + FARPROC lpProc; + + lpProc = MakeProcInstance((FARPROC)SoundOptionsDialog, hInst); + DialogBox(hInst, MAKEINTRESOURCE(DLG_Sound), hwnd, (DLGPROC)lpProc); + FreeProcInstance(lpProc); +} + + +/*---------------------------------------------------------------------------*\ + * + * Comm Port dialog functions + * +\*---------------------------------------------------------------------------*/ + + +#define FLOW_NONE 0 +#define FLOW_XOFF 1 +#define FLOW_CTS 2 +#define FLOW_DSR 3 + +#define PORT_NONE + +ComboData cdPort[] = { {"None", PORT_NONE}, {"COM1", 1}, {"COM2", 2}, + {"COM3", 3}, {"COM4", 4}, {NULL, 0} }; +ComboData cdDataRate[] = { {"110", 110}, {"300", 300}, {"600", 600}, {"1200", 1200}, + {"2400", 2400}, {"4800", 4800}, {"9600", 9600}, {"19200", 19200}, + {"38400", 38400}, {NULL, 0} }; +ComboData cdDataBits[] = { {"5", 5}, {"6", 6}, {"7", 7}, {"8", 8}, {NULL, 0} }; +ComboData cdParity[] = { {"None", NOPARITY}, {"Odd", ODDPARITY}, {"Even", EVENPARITY}, + {"Mark", MARKPARITY}, {"Space", SPACEPARITY}, {NULL, 0} }; +ComboData cdStopBits[] = { {"1", ONESTOPBIT}, {"1.5", ONE5STOPBITS}, + {"2", TWOSTOPBITS}, {NULL, 0} }; +ComboData cdFlow[] = { {"None", FLOW_NONE}, {"Xoff/Xon", FLOW_XOFF}, {"CTS", FLOW_CTS}, + {"DSR", FLOW_DSR}, {NULL, 0} }; + + +VOID +ParseCommSettings(char *arg, DCB *dcb) +{ + int dataRate, count; + char bits[MSG_SIZ], parity[MSG_SIZ], stopBits[MSG_SIZ], flow[MSG_SIZ]; + ComboData *cd; + count = sscanf(arg, "%d%*[, ]%[^, ]%*[, ]%[^, ]%*[, ]%[^, ]%*[, ]%[^, ]", + &dataRate, bits, parity, stopBits, flow); + if (count != 5) goto cant_parse; + dcb->BaudRate = dataRate; + cd = cdDataBits; + while (cd->label != NULL) { + if (StrCaseCmp(cd->label, bits) == 0) { + dcb->ByteSize = cd->value; + break; + } + cd++; + } + if (cd->label == NULL) goto cant_parse; + cd = cdParity; + while (cd->label != NULL) { + if (StrCaseCmp(cd->label, parity) == 0) { + dcb->Parity = cd->value; + break; + } + cd++; + } + if (cd->label == NULL) goto cant_parse; + cd = cdStopBits; + while (cd->label != NULL) { + if (StrCaseCmp(cd->label, stopBits) == 0) { + dcb->StopBits = cd->value; + break; + } + cd++; + } + cd = cdFlow; + if (cd->label == NULL) goto cant_parse; + while (cd->label != NULL) { + if (StrCaseCmp(cd->label, flow) == 0) { + switch (cd->value) { + case FLOW_NONE: + dcb->fOutX = FALSE; + dcb->fOutxCtsFlow = FALSE; + dcb->fOutxDsrFlow = FALSE; + break; + case FLOW_CTS: + dcb->fOutX = FALSE; + dcb->fOutxCtsFlow = TRUE; + dcb->fOutxDsrFlow = FALSE; + break; + case FLOW_DSR: + dcb->fOutX = FALSE; + dcb->fOutxCtsFlow = FALSE; + dcb->fOutxDsrFlow = TRUE; + break; + case FLOW_XOFF: + dcb->fOutX = TRUE; + dcb->fOutxCtsFlow = FALSE; + dcb->fOutxDsrFlow = FALSE; + break; + } + break; + } + cd++; + } + if (cd->label == NULL) goto cant_parse; + return; +cant_parse: + ExitArgError("Can't parse com port settings", arg); +} + + +VOID PrintCommSettings(FILE *f, char *name, DCB *dcb) +{ + char *flow = "??", *parity = "??", *stopBits = "??"; + ComboData *cd; + + cd = cdParity; + while (cd->label != NULL) { + if (dcb->Parity == cd->value) { + parity = cd->label; + break; + } + cd++; + } + cd = cdStopBits; + while (cd->label != NULL) { + if (dcb->StopBits == cd->value) { + stopBits = cd->label; + break; + } + cd++; + } + if (dcb->fOutX) { + flow = cdFlow[FLOW_XOFF].label; + } else if (dcb->fOutxCtsFlow) { + flow = cdFlow[FLOW_CTS].label; + } else if (dcb->fOutxDsrFlow) { + flow = cdFlow[FLOW_DSR].label; + } else { + flow = cdFlow[FLOW_NONE].label; + } + fprintf(f, "/%s=%d,%d,%s,%s,%s\n", name, + dcb->BaudRate, dcb->ByteSize, parity, stopBits, flow); +} + + +void +InitCombo(HANDLE hwndCombo, ComboData *cd) +{ + SendMessage(hwndCombo, CB_RESETCONTENT, 0, 0); + + while (cd->label != NULL) { + SendMessage(hwndCombo, CB_ADDSTRING, 0, (LPARAM) cd->label); + cd++; + } +} + +void +SelectComboValue(HANDLE hwndCombo, ComboData *cd, unsigned value) +{ + int i; + + i = 0; + while (cd->label != NULL) { + if (cd->value == value) { + SendMessage(hwndCombo, CB_SETCURSEL, (WPARAM) i, (LPARAM) 0); + return; + } + cd++; + i++; + } +} + +LRESULT CALLBACK +CommPortOptionsDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + char buf[MSG_SIZ]; + HANDLE hwndCombo; + char *p; + LRESULT index; + unsigned value; + int err; + + switch (message) { + case WM_INITDIALOG: /* message: initialize dialog box */ + /* Center the dialog over the application window */ + CenterWindow (hDlg, GetWindow(hDlg, GW_OWNER)); + /* Initialize the dialog items */ + /* !! There should probably be some synchronization + in accessing hCommPort and dcb. Or does modal nature + of this dialog box do it for us? + */ + hwndCombo = GetDlgItem(hDlg, OPT_Port); + InitCombo(hwndCombo, cdPort); + p = strrchr(appData.icsCommPort, '\\'); + if (p++ == NULL) p = appData.icsCommPort; + if ((*p == '\0') || + (SendMessage(hwndCombo, CB_SELECTSTRING, (WPARAM) -1, (LPARAM) p) == CB_ERR)) { + SendMessage(hwndCombo, CB_SELECTSTRING, (WPARAM) -1, (LPARAM) "None"); + } + EnableWindow(hwndCombo, hCommPort == NULL); /*!! don't allow change for now*/ + + hwndCombo = GetDlgItem(hDlg, OPT_DataRate); + InitCombo(hwndCombo, cdDataRate); + sprintf(buf, "%u", dcb.BaudRate); + if (SendMessage(hwndCombo, CB_SELECTSTRING, (WPARAM) -1, (LPARAM) buf) == CB_ERR) { + SendMessage(hwndCombo, CB_SETCURSEL, (WPARAM) -1, (LPARAM) 0); + SendMessage(hwndCombo, WM_SETTEXT, (WPARAM) 0, (LPARAM) buf); + } + + hwndCombo = GetDlgItem(hDlg, OPT_Bits); + InitCombo(hwndCombo, cdDataBits); + SelectComboValue(hwndCombo, cdDataBits, dcb.ByteSize); + + hwndCombo = GetDlgItem(hDlg, OPT_Parity); + InitCombo(hwndCombo, cdParity); + SelectComboValue(hwndCombo, cdParity, dcb.Parity); + + hwndCombo = GetDlgItem(hDlg, OPT_StopBits); + InitCombo(hwndCombo, cdStopBits); + SelectComboValue(hwndCombo, cdStopBits, dcb.StopBits); + + hwndCombo = GetDlgItem(hDlg, OPT_Flow); + InitCombo(hwndCombo, cdFlow); + if (dcb.fOutX) { + SelectComboValue(hwndCombo, cdFlow, FLOW_XOFF); + } else if (dcb.fOutxCtsFlow) { + SelectComboValue(hwndCombo, cdFlow, FLOW_CTS); + } else if (dcb.fOutxDsrFlow) { + SelectComboValue(hwndCombo, cdFlow, FLOW_DSR); + } else { + SelectComboValue(hwndCombo, cdFlow, FLOW_NONE); + } + return TRUE; + + case WM_COMMAND: /* message: received a command */ + switch (LOWORD(wParam)) { + case IDOK: + /* Read changed options from the dialog box */ +#ifdef NOTDEF + /* !! Currently we can't change comm ports in midstream */ + hwndCombo = GetDlgItem(hDlg, OPT_Port); + index = SendMessage(hwndCombo, CB_GETCURSEL, (WPARAM) 0, (LPARAM) 0); + if (index == PORT_NONE) { + appData.icsCommPort = ""; + if (hCommPort != NULL) { + CloseHandle(hCommPort); + hCommPort = NULL; + } + EndDialog(hDlg, TRUE); + return TRUE; + } + SendMessage(hwndCombo, WM_GETTEXT, (WPARAM) MSG_SIZ, (LPARAM) buf); + appData.icsCommPort = strdup(buf); + if (hCommPort != NULL) { + CloseHandle(hCommPort); + hCommPort = NULL; + } + /* now what?? can't really do this; have to fix up the ChildProc + and InputSource records for the comm port that we gave to the + back end. */ +#endif /*NOTDEF*/ + + hwndCombo = GetDlgItem(hDlg, OPT_DataRate); + SendMessage(hwndCombo, WM_GETTEXT, (WPARAM) MSG_SIZ, (LPARAM) buf); + if (sscanf(buf, "%u", &value) != 1) { + MessageBox(hDlg, "Invalid data rate", + "Option Error", MB_OK|MB_ICONEXCLAMATION); + return TRUE; + } + dcb.BaudRate = value; + + hwndCombo = GetDlgItem(hDlg, OPT_Bits); + index = SendMessage(hwndCombo, CB_GETCURSEL, (WPARAM) 0, (LPARAM) 0); + dcb.ByteSize = cdDataBits[index].value; + + hwndCombo = GetDlgItem(hDlg, OPT_Parity); + index = SendMessage(hwndCombo, CB_GETCURSEL, (WPARAM) 0, (LPARAM) 0); + dcb.Parity = cdParity[index].value; + + hwndCombo = GetDlgItem(hDlg, OPT_StopBits); + index = SendMessage(hwndCombo, CB_GETCURSEL, (WPARAM) 0, (LPARAM) 0); + dcb.StopBits = cdStopBits[index].value; + + hwndCombo = GetDlgItem(hDlg, OPT_Flow); + index = SendMessage(hwndCombo, CB_GETCURSEL, (WPARAM) 0, (LPARAM) 0); + switch (cdFlow[index].value) { + case FLOW_NONE: + dcb.fOutX = FALSE; + dcb.fOutxCtsFlow = FALSE; + dcb.fOutxDsrFlow = FALSE; + break; + case FLOW_CTS: + dcb.fOutX = FALSE; + dcb.fOutxCtsFlow = TRUE; + dcb.fOutxDsrFlow = FALSE; + break; + case FLOW_DSR: + dcb.fOutX = FALSE; + dcb.fOutxCtsFlow = FALSE; + dcb.fOutxDsrFlow = TRUE; + break; + case FLOW_XOFF: + dcb.fOutX = TRUE; + dcb.fOutxCtsFlow = FALSE; + dcb.fOutxDsrFlow = FALSE; + break; + } + if (!SetCommState(hCommPort, (LPDCB) &dcb)) { + err = GetLastError(); + switch(MessageBox(hDlg, + "Failed to set comm port state;\r\ninvalid options?", + "Option Error", MB_ABORTRETRYIGNORE|MB_ICONQUESTION)) { + case IDABORT: + DisplayFatalError("Failed to set comm port state", err, 1); + exit(1); /*is it ok to do this from here?*/ + + case IDRETRY: + return TRUE; + + case IDIGNORE: + EndDialog(hDlg, TRUE); + return TRUE; + } + } + + EndDialog(hDlg, TRUE); + return TRUE; + + case IDCANCEL: + EndDialog(hDlg, FALSE); + return TRUE; + + default: + break; + } + break; + } + return FALSE; +} + +VOID +CommPortOptionsPopup(HWND hwnd) +{ + FARPROC lpProc = MakeProcInstance((FARPROC)CommPortOptionsDialog, hInst); + DialogBox(hInst, MAKEINTRESOURCE(DLG_CommPort), hwnd, (DLGPROC) lpProc); + FreeProcInstance(lpProc); +} + +/*---------------------------------------------------------------------------*\ + * + * Load Options dialog functions + * +\*---------------------------------------------------------------------------*/ + +VOID +SetLoadOptionEnables(HWND hDlg) +{ + UINT state; + + state = IsDlgButtonChecked(hDlg, OPT_Autostep); + EnableWindow(GetDlgItem(hDlg, OPT_ASTimeDelay), state); + EnableWindow(GetDlgItem(hDlg, OPT_AStext1), state); +} + +LRESULT CALLBACK +LoadOptions(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + char buf[MSG_SIZ]; + float fnumber; + + switch (message) { + case WM_INITDIALOG: /* message: initialize dialog box */ + /* Center the dialog over the application window */ + CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER)); + /* Initialize the dialog items */ + if (appData.timeDelay >= 0.0) { + CheckDlgButton(hDlg, OPT_Autostep, TRUE); + sprintf(buf, "%.2g", appData.timeDelay); + SetDlgItemText(hDlg, OPT_ASTimeDelay, buf); + } else { + CheckDlgButton(hDlg, OPT_Autostep, FALSE); + } + SetLoadOptionEnables(hDlg); + return TRUE; + + case WM_COMMAND: /* message: received a command */ + switch (LOWORD(wParam)) { + case IDOK: + /* Read changed options from the dialog box */ + if (IsDlgButtonChecked(hDlg, OPT_Autostep)) { + GetDlgItemText(hDlg, OPT_ASTimeDelay, buf, MSG_SIZ); + if (sscanf(buf, "%f", &fnumber) != 1) { + MessageBox(hDlg, "Invalid load game step rate", + "Option Error", MB_OK|MB_ICONEXCLAMATION); + return FALSE; + } + appData.timeDelay = fnumber; + } else { + appData.timeDelay = (float) -1.0; + } + EndDialog(hDlg, TRUE); + return TRUE; + + case IDCANCEL: + EndDialog(hDlg, FALSE); + return TRUE; + + default: + SetLoadOptionEnables(hDlg); + break; + } + break; + } + return FALSE; +} + + +VOID +LoadOptionsPopup(HWND hwnd) +{ + FARPROC lpProc = MakeProcInstance((FARPROC)LoadOptions, hInst); + DialogBox(hInst, MAKEINTRESOURCE(DLG_LoadOptions), hwnd, (DLGPROC) lpProc); + FreeProcInstance(lpProc); +} + +/*---------------------------------------------------------------------------*\ + * + * Save Options dialog functions + * +\*---------------------------------------------------------------------------*/ + +VOID +SetSaveOptionEnables(HWND hDlg) +{ + UINT state; + + state = IsDlgButtonChecked(hDlg, OPT_Autosave); + EnableWindow(GetDlgItem(hDlg, OPT_AVPrompt), state); + EnableWindow(GetDlgItem(hDlg, OPT_AVToFile), state); + if (state && !IsDlgButtonChecked(hDlg, OPT_AVPrompt) && + !IsDlgButtonChecked(hDlg, OPT_AVToFile)) { + CheckRadioButton(hDlg, OPT_AVPrompt, OPT_AVToFile, OPT_AVPrompt); + } + + state = state && IsDlgButtonChecked(hDlg, OPT_AVToFile); + EnableWindow(GetDlgItem(hDlg, OPT_AVFilename), state); + EnableWindow(GetDlgItem(hDlg, OPT_AVBrowse), state); +} + +LRESULT CALLBACK +SaveOptionsDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + char buf[MSG_SIZ]; + FILE *f; + + switch (message) { + case WM_INITDIALOG: /* message: initialize dialog box */ + /* Center the dialog over the application window */ + CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER)); + /* Initialize the dialog items */ + if (*appData.saveGameFile != NULLCHAR) { + CheckDlgButton(hDlg, OPT_Autosave, (UINT) TRUE); + CheckRadioButton(hDlg, OPT_AVPrompt, OPT_AVToFile, OPT_AVToFile); + SetDlgItemText(hDlg, OPT_AVFilename, appData.saveGameFile); + } else if (appData.autoSaveGames) { + CheckDlgButton(hDlg, OPT_Autosave, (UINT) TRUE); + CheckRadioButton(hDlg, OPT_AVPrompt, OPT_AVToFile, OPT_AVPrompt); + } else { + CheckDlgButton(hDlg, OPT_Autosave, (UINT) FALSE); + } + if (appData.oldSaveStyle) { + CheckRadioButton(hDlg, OPT_PGN, OPT_Old, OPT_Old); + } else { + CheckRadioButton(hDlg, OPT_PGN, OPT_Old, OPT_PGN); + } + SetSaveOptionEnables(hDlg); + return TRUE; + + case WM_COMMAND: /* message: received a command */ + switch (LOWORD(wParam)) { + case IDOK: + /* Read changed options from the dialog box */ + if (IsDlgButtonChecked(hDlg, OPT_Autosave)) { + appData.autoSaveGames = TRUE; + if (IsDlgButtonChecked(hDlg, OPT_AVPrompt)) { + appData.saveGameFile = ""; + } else /*if (IsDlgButtonChecked(hDlg, OPT_AVToFile))*/ { + GetDlgItemText(hDlg, OPT_AVFilename, buf, MSG_SIZ); + if (*buf == NULLCHAR) { + MessageBox(hDlg, "Invalid save game file name", + "Option Error", MB_OK|MB_ICONEXCLAMATION); + return FALSE; + } + if ((isalpha(buf[0]) && buf[1] == ':') || + (buf[0] == '\\' && buf[1] == '\\')) { + appData.saveGameFile = strdup(buf); + } else { + char buf2[MSG_SIZ], buf3[MSG_SIZ]; + char *dummy; + GetCurrentDirectory(MSG_SIZ, buf3); + SetCurrentDirectory(installDir); + if (GetFullPathName(buf, MSG_SIZ, buf2, &dummy)) { + appData.saveGameFile = strdup(buf2); + } else { + appData.saveGameFile = strdup(buf); + } + SetCurrentDirectory(buf3); + } + } + } else { + appData.autoSaveGames = FALSE; + appData.saveGameFile = ""; + } + appData.oldSaveStyle = IsDlgButtonChecked(hDlg, OPT_Old); + EndDialog(hDlg, TRUE); + return TRUE; + + case IDCANCEL: + EndDialog(hDlg, FALSE); + return TRUE; + + case OPT_AVBrowse: + f = OpenFileDialog(hDlg, TRUE, NULL, + appData.oldSaveStyle ? "gam" : "pgn", + GAME_FILT, "Browse for Auto Save File", + NULL, NULL, buf); + if (f != NULL) { + fclose(f); + SetDlgItemText(hDlg, OPT_AVFilename, buf); + } + break; + + default: + SetSaveOptionEnables(hDlg); + break; + } + break; + } + return FALSE; +} + +VOID +SaveOptionsPopup(HWND hwnd) +{ + FARPROC lpProc = MakeProcInstance((FARPROC)SaveOptionsDialog, hInst); + DialogBox(hInst, MAKEINTRESOURCE(DLG_SaveOptions), hwnd, (DLGPROC) lpProc); + FreeProcInstance(lpProc); +} + +/*---------------------------------------------------------------------------*\ + * + * Time Control Options dialog functions + * +\*---------------------------------------------------------------------------*/ + +VOID +SetTimeControlEnables(HWND hDlg) +{ + UINT state; + + state = IsDlgButtonChecked(hDlg, OPT_TCUseMoves); + EnableWindow(GetDlgItem(hDlg, OPT_TCTime), state); + EnableWindow(GetDlgItem(hDlg, OPT_TCMoves), state); + EnableWindow(GetDlgItem(hDlg, OPT_TCtext1), state); + EnableWindow(GetDlgItem(hDlg, OPT_TCtext2), state); + EnableWindow(GetDlgItem(hDlg, OPT_TCTime2), !state); + EnableWindow(GetDlgItem(hDlg, OPT_TCInc), !state); + EnableWindow(GetDlgItem(hDlg, OPT_TCitext1), !state); + EnableWindow(GetDlgItem(hDlg, OPT_TCitext2), !state); + EnableWindow(GetDlgItem(hDlg, OPT_TCitext3), !state); +} + + +LRESULT CALLBACK +TimeControl(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + char buf[MSG_SIZ]; + int mps, increment; + BOOL ok; + + switch (message) { + case WM_INITDIALOG: /* message: initialize dialog box */ + /* Center the dialog over the application window */ + CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER)); + /* Initialize the dialog items */ + if (appData.clockMode && !appData.icsActive) { + if (appData.timeIncrement == -1) { + CheckRadioButton(hDlg, OPT_TCUseMoves, OPT_TCUseInc, + OPT_TCUseMoves); + SetDlgItemText(hDlg, OPT_TCTime, appData.timeControl); + SetDlgItemInt(hDlg, OPT_TCMoves, appData.movesPerSession, + FALSE); + SetDlgItemText(hDlg, OPT_TCTime2, ""); + SetDlgItemText(hDlg, OPT_TCInc, ""); + } else { + CheckRadioButton(hDlg, OPT_TCUseMoves, OPT_TCUseInc, + OPT_TCUseInc); + SetDlgItemText(hDlg, OPT_TCTime, ""); + SetDlgItemText(hDlg, OPT_TCMoves, ""); + SetDlgItemText(hDlg, OPT_TCTime2, appData.timeControl); + SetDlgItemInt(hDlg, OPT_TCInc, appData.timeIncrement, FALSE); + } + SetTimeControlEnables(hDlg); + } + return TRUE; + + case WM_COMMAND: /* message: received a command */ + switch (LOWORD(wParam)) { + case IDOK: + /* Read changed options from the dialog box */ + if (IsDlgButtonChecked(hDlg, OPT_TCUseMoves)) { + increment = -1; + mps = GetDlgItemInt(hDlg, OPT_TCMoves, &ok, FALSE); + if (!ok || mps <= 0) { + MessageBox(hDlg, "Invalid moves per time control", + "Option Error", MB_OK|MB_ICONEXCLAMATION); + return FALSE; + } + GetDlgItemText(hDlg, OPT_TCTime, buf, MSG_SIZ); + if (!ParseTimeControl(buf, increment, mps)) { + MessageBox(hDlg, "Invalid minutes per time control", + "Option Error", MB_OK|MB_ICONEXCLAMATION); + return FALSE; + } + } else { + increment = GetDlgItemInt(hDlg, OPT_TCInc, &ok, FALSE); + mps = appData.movesPerSession; + if (!ok || increment < 0) { + MessageBox(hDlg, "Invalid increment", + "Option Error", MB_OK|MB_ICONEXCLAMATION); + return FALSE; + } + GetDlgItemText(hDlg, OPT_TCTime2, buf, MSG_SIZ); + if (!ParseTimeControl(buf, increment, mps)) { + MessageBox(hDlg, "Invalid initial time", + "Option Error", MB_OK|MB_ICONEXCLAMATION); + return FALSE; + } + } + appData.timeControl = strdup(buf); + appData.movesPerSession = mps; + appData.timeIncrement = increment; + Reset(TRUE, TRUE); + EndDialog(hDlg, TRUE); + return TRUE; + + case IDCANCEL: + EndDialog(hDlg, FALSE); + return TRUE; + + default: + SetTimeControlEnables(hDlg); + break; + } + break; + } + return FALSE; +} + +VOID +TimeControlOptionsPopup(HWND hwnd) +{ + if (gameMode != BeginningOfGame) { + DisplayError("Changing time control during a game is not implemented", 0); + } else { + FARPROC lpProc = MakeProcInstance((FARPROC)TimeControl, hInst); + DialogBox(hInst, MAKEINTRESOURCE(DLG_TimeControl), hwnd, (DLGPROC) lpProc); + FreeProcInstance(lpProc); + } +} + + diff --git a/winboard-dm-beta4/woptions.h b/winboard-dm-beta4/woptions.h new file mode 100755 index 0000000..a8a1f70 --- /dev/null +++ b/winboard-dm-beta4/woptions.h @@ -0,0 +1,35 @@ +/* + * woptions.h -- Options dialog box routines for WinBoard + * $Id: + * + * Copyright 2000 Free Software Foundation, Inc. + * + * ------------------------------------------------------------------------ + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * ------------------------------------------------------------------------ + */ + +#include + +VOID GeneralOptionsPopup(HWND hwnd); +VOID BoardOptionsPopup(HWND hwnd); +VOID IcsOptionsPopup(HWND hwnd); +VOID FontsOptionsPopup(HWND hwnd); +VOID SoundOptionsPopup(HWND hwnd); +VOID CommPortOptionsPopup(HWND hwnd); +VOID LoadOptionsPopup(HWND hwnd); +VOID SaveOptionsPopup(HWND hwnd); +VOID TimeControlOptionsPopup(HWND hwnd); +VOID icsZippyDrawPopUp(HWND hwnd); diff --git a/winboard-dm-beta4/wsockerr.c b/winboard-dm-beta4/wsockerr.c new file mode 100755 index 0000000..33a6822 --- /dev/null +++ b/winboard-dm-beta4/wsockerr.c @@ -0,0 +1,60 @@ +/* Windows sockets error map */ +/* These messages ought to be in the Windows message catalog! */ + +#include +#include +#include "wsockerr.h" + +ErrorMap errmap[] = +{ {WSAEINTR, "Interrupted system call"}, + {WSAEBADF, "Bad file number"}, + {WSAEACCES, "Permission denied"}, + {WSAEFAULT, "Bad address"}, + {WSAEINVAL, "Invalid argument"}, + {WSAEMFILE, "Too many open files"}, + {WSAEWOULDBLOCK, "Operation would block"}, + {WSAEINPROGRESS, "Operation now in progress"}, + {WSAEALREADY, "Operation already in progress"}, + {WSAENOTSOCK, "Socket operation on non-socket"}, + {WSAEMSGSIZE, "Message too long"}, + {WSAEPROTOTYPE, "Protocol wrong type for socket"}, + {WSAENOPROTOOPT, "Protocol not available"}, + {WSAEPROTONOSUPPORT, "Protocol not supported"}, + {WSAESOCKTNOSUPPORT, "Socket type not supported"}, + {WSAEOPNOTSUPP, "Operation not supported on socket"}, + {WSAEPFNOSUPPORT, "Protocol family not supported"}, + {WSAEAFNOSUPPORT, "Address family not supported by protocol family"}, + {WSAEADDRINUSE, "Address already in use"}, + {WSAEADDRNOTAVAIL, "Can't assign requested address"}, + {WSAENETDOWN, "Network is down"}, + {WSAENETUNREACH, "Network is unreachable"}, + {WSAENETRESET, "Network dropped connection on reset"}, + {WSAECONNABORTED, "Software caused connection abort"}, + {WSAECONNRESET, "Connection reset by peer"}, + {WSAENOBUFS, "No buffer space available"}, + {WSAEISCONN, "Socket is already connected"}, + {WSAENOTCONN, "Socket is not connected"}, + {WSAESHUTDOWN, "Can't send after socket shutdown"}, + {WSAETOOMANYREFS, "Too many references: can't splice"}, + {WSAETIMEDOUT, "Connection timed out"}, + {WSAECONNREFUSED, "Connection refused"}, + {WSAELOOP, "Too many levels of symbolic links"}, + {WSAENAMETOOLONG, "File name too long"}, + {WSAEHOSTDOWN, "Host is down"}, + {WSAEHOSTUNREACH, "No route to host"}, + {WSAENOTEMPTY, "Directory not empty"}, + {WSAEPROCLIM, "Too many processes"}, + {WSAEUSERS, "Too many users"}, + {WSAEDQUOT, "Disc quota exceeded"}, + {WSAESTALE, "Stale NFS file handle"}, + {WSAEREMOTE, "Too many levels of remote in path"}, + {WSAEDISCON, "Undocumented Winsock error code WSAEDISCON"}, + {WSASYSNOTREADY, "Winsock subsystem unusable"}, + {WSAVERNOTSUPPORTED, "Required Winsock version is not supported"}, + {WSANOTINITIALISED, "Winsock not initialized"}, + {WSAHOST_NOT_FOUND, "Host name not found by name server (authoritative)"}, + {WSATRY_AGAIN, "Host name not found by name server (nonauthoritative), or name server failure"}, + {WSANO_RECOVERY, "Nonrecoverable name server error"}, + {WSANO_DATA, "Host name has no address data of required type"}, + {0, NULL} +}; diff --git a/winboard-dm-beta4/wsockerr.h b/winboard-dm-beta4/wsockerr.h new file mode 100755 index 0000000..577b417 --- /dev/null +++ b/winboard-dm-beta4/wsockerr.h @@ -0,0 +1,10 @@ +/* Windows sockets error map */ +/* These messages ought to be in the Windows message catalog! */ + +typedef struct { + int err; + char* msg; +} ErrorMap; + +extern ErrorMap errmap[]; + diff --git a/winboard-dm-beta4/zippy.c b/winboard-dm-beta4/zippy.c new file mode 100755 index 0000000..1ad3e60 --- /dev/null +++ b/winboard-dm-beta4/zippy.c @@ -0,0 +1,1218 @@ +/* + * zippy.c -- Implements Zippy the Pinhead chess player on ICS in XBoard + * $Id$ + * + * Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts. + * Enhancements Copyright 1992-2001 Free Software Foundation, Inc. + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * ------------------------------------------------------------------------ + */ + +#include "config.h" + +#include +#include +#include +#include +#include + +#if STDC_HEADERS +# include +# include +#else /* not STDC_HEADERS */ +extern char *getenv(); +# if HAVE_STRING_H +# include +# else /* not HAVE_STRING_H */ +# include +# endif /* not HAVE_STRING_H */ +#endif /* not STDC_HEADERS */ + +#if TIME_WITH_SYS_TIME +# include +# include +#else +# if HAVE_SYS_TIME_H +# include +# else +# include +# endif +#endif +#define HI "hlelo " + +#if HAVE_UNISTD_H +# include +#endif + +#include "common.h" +#include "zippy.h" +#include "frontend.h" +#include "backend.h" +#include "backendz.h" + +static char zippyPartner[MSG_SIZ]; +static char zippyLastOpp[MSG_SIZ]; +static int zippyConsecGames; +static time_t zippyLastGameEnd; + +extern int currentMove; /* from backend.c */ + +void ZippyInit() +{ + char *p; + + /* Get name of Zippy lines file */ + p = getenv("ZIPPYLINES"); + if (p != NULL) { + appData.zippyLines = p; + } + + /* Get word that Zippy thinks is insulting */ + p = getenv("ZIPPYPINHEAD"); + if (p != NULL) { + appData.zippyPinhead = p; + } + + /* What password is used for remote control? */ + p = getenv("ZIPPYPASSWORD"); + if (p != NULL) { + appData.zippyPassword = p; + } + + /* What password is used for remote commands to gnuchess? */ + p = getenv("ZIPPYPASSWORD2"); + if (p != NULL) { + appData.zippyPassword2 = p; + } + + /* What password is used for GUI commands? */ + p = getenv("ZIPPYPASSWORD3"); + if (p != NULL) { + appData.zippyPassword3 = p; + } + + /* Joke feature for people who try an old password */ + p = getenv("ZIPPYWRONGPASSWORD"); + if (p != NULL) { + appData.zippyWrongPassword = p; + } + + /* While testing, I want to accept challenges from only one person + (namely, my "anonymous" account), so I set an environment + variable ZIPPYACCEPTONLY. */ + p = getenv("ZIPPYACCEPTONLY"); + if ( p != NULL ) { + appData.zippyAcceptOnly = p; + } + + /* Should Zippy use "i" command? */ + /* Defaults to 1=true */ + p = getenv("ZIPPYUSEI"); + if (p != NULL) { + appData.zippyUseI = atoi(p); + } + + /* How does Zippy handle bughouse partnering? */ + /* 0=say we can't play, 1=manual partnering, 2=auto partnering */ + p = getenv("ZIPPYBUGHOUSE"); + if (p != NULL) { + appData.zippyBughouse = atoi(p); + } + + /* Does Zippy abort games with Crafty? */ + /* Defaults to 0=false */ + p = getenv("ZIPPYNOPLAYCRAFTY"); + if (p != NULL) { + appData.zippyNoplayCrafty = atoi(p); + } + + /* What ICS command does Zippy send at game end? Default: "gameend". */ + p = getenv("ZIPPYGAMEEND"); + if (p != NULL) { + appData.zippyGameEnd = p; + } + + /* What ICS command does Zippy send at game start? Default: none. */ + p = getenv("ZIPPYGAMESTART"); + if (p != NULL) { + appData.zippyGameStart = p; + } + + /* Should Zippy accept adjourns? */ + /* Defaults to 0=false */ + p = getenv("ZIPPYADJOURN"); + if (p != NULL) { + appData.zippyAdjourn = atoi(p); + } + + /* Should Zippy accept aborts? */ + /* Defaults to 0=false */ + p = getenv("ZIPPYABORT"); + if (p != NULL) { + appData.zippyAbort = atoi(p); + } + + /* Should Zippy play chess variants (besides bughouse)? */ + p = getenv("ZIPPYVARIANTS"); + if (p != NULL) { + appData.zippyVariants = p; + } + strcpy(first.variants, appData.zippyVariants); + + srandom(time(NULL)); +} + +/* + * Routines to implement Zippy talking + */ + + +char *swifties[] = { + "i acclaims:", "i admonishes:", "i advertises:", "i advises:", + "i advocates:", "i affirms:", "i alleges:", "i anathematizes:", + "i animadverts:", "i announces:", "i apostrophizes:", + "i appeals:", "i applauds:", "i approves:", "i argues:", + "i articulates:", "i asserts:", "i asseverates:", "i attests:", + "i avers:", "i avows:", "i baas:", "i babbles:", "i banters:", + "i barks:", "i bawls:", "i bays:", "i begs:", "i belches:", + "i bellows:", "i belts out:", "i berates:", "i beshrews:", + "i blabbers:", "i blabs:", "i blares:", "i blasphemes:", + "i blasts:", "i blathers:", "i bleats:", "i blithers:", + "i blubbers:", "i blurts out:", "i blusters:", "i boasts:", + "i brags:", "i brays:", "i broadcasts:", "i burbles:", + "i buzzes:", "i cachinnates:", "i cackles:", "i caterwauls:", + "i calumniates:", "i caws:", "i censures:", "i chants:", + "i chatters:", "i cheeps:", "i cheers:", "i chides:", "i chins:", + "i chirps:", "i chortles:", "i chuckles:", "i claims:", + "i clamors:", "i clucks:", "i commands:", "i commends:", + "i comments:", "i commiserates:", "i communicates:", + "i complains:", "i concludes:", "i confabulates:", "i confesses:", + "i coos:", "i coughs:", "i counsels:", "i cries:", "i croaks:", + "i crows:", "i curses:", "i daydreams:", "i debates:", + "i declaims:", "i declares:", "i delivers:", "i denounces:", + "i deposes:", "i directs:", "i discloses:", "i disparages:", + "i discourses:", "i divulges:", "i documents:", "i drawls:", + "i dreams:", "i drivels:", "i drones:", "i effuses:", + /*"i ejaculates:",*/ "i elucidates:", "i emotes:", "i endorses:", + "i enthuses:", "i entreats:", "i enunciates:", "i eulogizes:", + "i exclaims:", "i execrates:", "i exhorts:", "i expatiates:", + "i explains:", "i explicates:", "i explodes:", "i exposes:", + "i exposits:", "i expounds:", "i expresses:", "i extols:", + "i exults:", "i fantasizes:", "i fibs:", "i filibusters:", + "i flatters:", "i flutes:", "i fools:", "i free-associates:", + "i fulminates:", "i gabbles:", "i gabs:", "i gasps:", + "i giggles:", "i gossips:", "i gripes:", "i groans:", "i growls:", + "i grunts:", "i guesses:", "i guffaws:", "i gushes:", "i hails:", + "i hallucinates:", "i harangues:", "i harmonizes:", "i hectors:", + "i hints:", "i hisses:", "i hollers:", "i honks:", "i hoots:", + "i hosannas:", "i howls:", "i hums:", "i hypothecates:", + "i hypothesizes:", "i imagines:", "i implies:", "i implores:", + "i imprecates:", "i indicates:", "i infers:", + "i informs everyone:", "i instructs:", "i interjects:", + "i interposes:", "i intimates:", "i intones:", "i introspects:", + "i inveighs:", "i jabbers:", "i japes:", "i jests:", "i jibes:", + "i jives:", "i jokes:", "i joshes:", "i keens:", "i laments:", + "i lauds:", "i laughs:", "i lectures:", "i lies:", "i lilts:", + "i lisps:", "i maintains:", "i maledicts:", "i maunders:", + "i meows:", "i mewls:", "i mimes:", "i minces:", "i moans:", + "i moos:", "i mourns:", "i mouths:", "i mumbles:", "i murmurs:", + "i muses:", "i mutters:", "i nags:", "i natters:", "i neighs:", + "i notes:", "i nuncupates:", "i objurgates:", "i observes:", + "i offers:", "i oinks:", "i opines:", "i orates:", "i orders:", + "i panegyrizes:", "i pantomimes:", "i pants:", "i peals:", + "i peeps:", "i perorates:", "i persuades:", "i petitions:", + "i phonates:", "i pipes up:", "i pitches:", "i pleads:", + "i points out:", "i pontificates:", "i postulates:", "i praises:", + "i prates:", "i prattles:", "i preaches:", "i prescribes:", + "i prevaricates:", "i proclaims:", "i projects:", "i pronounces:", + "i proposes:", "i proscribes:", "i quacks:", "i queries:", + "i questions:", "i quips:", "i quotes:", "i rages:", "i rambles:", + "i rants:", "i raps:", "i rasps:", "i rattles:", "i raves:", + "i reacts:", "i recites:", "i recommends:", "i records:", + "i reiterates:", "i rejoins:", "i releases:", "i remarks:", + "i reminisces:", "i remonstrates:", "i repeats:", "i replies:", + "i reports:", "i reprimands:", "i reproaches:", "i reproves:", + "i resounds:", "i responds:", "i retorts:", "i reveals:", + "i reviles:", "i roars:", "i rumbles:", "i sanctions:", + "i satirizes:", "i sauces:", "i scolds:", "i screams:", + "i screeches:", "i semaphores:", "i sends:", "i sermonizes:", + "i shrieks:", "i sibilates:", "i sighs:", "i signals:", + "i signifies:", "i signs:", "i sings:", "i slurs:", "i snaps:", + "i snarls:", "i sneezes:", "i snickers:", "i sniggers:", + "i snivels:", "i snores:", "i snorts:", "i sobs:", + "i soliloquizes:", "i sounds off:", "i sounds out:", "i speaks:", + "i spews:", "i spits out:", "i splutters:", "i spoofs:", + "i spouts:", "i sputters:", "i squalls:", "i squawks:", + "i squeaks:", "i squeals:", "i stammers:", "i states:", + "i stresses:", "i stutters:", "i submits:", "i suggests:", + "i summarizes:", "i sums up:", "i swears:", "i talks:", + "i tattles:", "i teases:", "i telegraphs:", "i testifies:", + "i threatens:", "i thunders:", "i titters:", "i tongue-lashes:", + "i toots:", "i transcribes:", "i transmits:", "i trills:", + "i trumpets:", "i twaddles:", "i tweets:", "i twitters:", + "i types:", "i upbraids:", "i urges:", "i utters:", "i ventures:", + "i vibrates:", "i vilifies:", "i vituperates:", "i vocalizes:", + "i vociferates:", "i voices:", "i waffles:", "i wails:", + "i warbles:", "i warns:", "i weeps:", "i wheezes:", "i whimpers:", + "i whines:", "i whinnies:", "i whistles:", "i wisecracks:", + "i witnesses:", "i woofs:", "i writes:", "i yammers:", "i yawps:", + "i yells:", "i yelps:", "i yodels:", "i yowls:", "i zings:", +}; + +#define MAX_SPEECH 250 + +void Speak(how, whom) + char *how, *whom; +{ + static FILE *zipfile = NULL; + static struct stat zipstat; + char zipbuf[MAX_SPEECH + 1]; + static time_t lastShout = 0; + time_t now; + char *p; + int c, speechlen; + Boolean done; + + if (strcmp(how, "shout") == 0) { + now = time((time_t *) NULL); + if (now - lastShout < 1*60) return; + lastShout = now; + if (appData.zippyUseI) { + how = swifties[random() % (sizeof(swifties)/sizeof(char *))]; + } + } + + if (zipfile == NULL) { + zipfile = fopen(appData.zippyLines, "r"); + if (zipfile == NULL) { + DisplayFatalError("Can't open Zippy lines file", errno, 1); + return; + } + fstat(fileno(zipfile), &zipstat); + } + + for (;;) { + fseek(zipfile, random() % zipstat.st_size, 0); + do { + c = getc(zipfile); + } while (c != NULLCHAR && c != '^' && c != EOF); + if (c == EOF) continue; + while ((c = getc(zipfile)) == '\n') ; + if (c == EOF) continue; + break; + } + done = FALSE; + + /* Don't use ics_prefix; we need to let FICS expand the alias i -> it, + but use the real command "i" on ICC */ + strcpy(zipbuf, how); + strcat(zipbuf, " "); + if (whom != NULL) { + strcat(zipbuf, whom); + strcat(zipbuf, " "); + } + speechlen = strlen(zipbuf); + p = zipbuf + speechlen; + + while (++speechlen < MAX_SPEECH) { + if (c == NULLCHAR || c == '^') { + *p++ = '\n'; + *p = '\0'; + SendToICS(zipbuf); + return; + } else if (c == '\n') { + *p++ = ' '; + do { + c = getc(zipfile); + } while (c == ' '); + } else if (c == EOF) { + break; + } else { + *p++ = c; + c = getc(zipfile); + } + } + /* Tried to say something too long, or junk at the end of the + file. Try something else. */ + Speak(how, whom); /* tail recursion */ +} + +int ZippyCalled(str) + char *str; +{ + return ics_handle[0] != NULLCHAR && StrCaseStr(str, ics_handle) != NULL; +} + +static char opp_name[128][32]; +static int num_opps=0; + +int ZippyControl(buf, i) + char *buf; + int *i; +{ + char *player; + char reply[MSG_SIZ]; + +#if TRIVIA +#include "trivia.c" +#endif + + /* Possibly reject Crafty as opponent */ + if (appData.zippyPlay && appData.zippyNoplayCrafty && forwardMostMove < 4 + && looking_at(buf, i, "* kibitzes: Hello from Crafty")) { + player = StripHighlightAndTitle(star_match[0]); + if ((gameMode == IcsPlayingWhite && + StrCaseCmp(player, gameInfo.black) == 0) || + (gameMode == IcsPlayingBlack && + StrCaseCmp(player, gameInfo.white) == 0)) { + + sprintf(reply, "%ssay This computer does not play Crafty clones\n%sabort\n%s+noplay %s\n", + ics_prefix, ics_prefix, ics_prefix, player); + SendToICS(reply); + } + return TRUE; + } + + /* If this is a computer, save the name. Then later, once the */ + /* game is really started, we will send the "computer" notice to */ + /* the engine. */ + if (appData.zippyPlay && + looking_at(buf, i, "* is in the computer list")) { + int i; + + for (i=0;i= num_opps) strcpy(opp_name[num_opps++],star_match[0]); + } + if (appData.zippyPlay && looking_at(buf, i, "* * is a computer *")) { + int i; + + for (i=0;i= num_opps) strcpy(opp_name[num_opps++],star_match[1]); + } + + /* Tells and says */ + if (appData.zippyPlay && + (looking_at(buf, i, "* offers to be your bughouse partner") || + looking_at(buf, i, "* tells you: [automatic message] I chose you"))) { + player = StripHighlightAndTitle(star_match[0]); + if (appData.zippyBughouse > 1 && first.initDone) { + sprintf(reply, "%spartner %s\n", ics_prefix, player); + SendToICS(reply); + if (strcmp(zippyPartner, player) != 0) { + strcpy(zippyPartner, player); + SendToProgram(reply + strlen(ics_prefix), &first); + } + } else if (appData.zippyBughouse > 0) { + sprintf(reply, "%sdecline %s\n", ics_prefix, player); + SendToICS(reply); + } else { + sprintf(reply, "%stell %s This computer cannot play bughouse\n", + ics_prefix, player); + SendToICS(reply); + } + return TRUE; + } + + if (appData.zippyPlay && appData.zippyBughouse && first.initDone && + looking_at(buf, i, "* agrees to be your partner")) { + player = StripHighlightAndTitle(star_match[0]); + sprintf(reply, "partner %s\n", player); + if (strcmp(zippyPartner, player) != 0) { + strcpy(zippyPartner, player); + SendToProgram(reply, &first); + } + return TRUE; + } + + if (appData.zippyPlay && appData.zippyBughouse && first.initDone && + (looking_at(buf, i, "are no longer *'s partner") || + looking_at(buf, i, + "* tells you: [automatic message] I'm no longer your"))) { + player = StripHighlightAndTitle(star_match[0]); + if (strcmp(zippyPartner, player) == 0) { + zippyPartner[0] = NULLCHAR; + SendToProgram("partner\n", &first); + } + return TRUE; + } + + if (appData.zippyPlay && appData.zippyBughouse && first.initDone && + (looking_at(buf, i, "no longer have a bughouse partner") || + looking_at(buf, i, "partner has disconnected") || + looking_at(buf, i, "partner has just chosen a new partner"))) { + zippyPartner[0] = NULLCHAR; + SendToProgram("partner\n", &first); + return TRUE; + } + + if (appData.zippyPlay && appData.zippyBughouse && first.initDone && + looking_at(buf, i, "* (your partner) tells you: *")) { + /* This pattern works on FICS but not ICC */ + player = StripHighlightAndTitle(star_match[0]); + if (strcmp(zippyPartner, player) != 0) { + strcpy(zippyPartner, player); + sprintf(reply, "partner %s\n", player); + SendToProgram(reply, &first); + } + sprintf(reply, "ptell %s\n", star_match[1]); + SendToProgram(reply, &first); + return TRUE; + } + + if (looking_at(buf, i, "* tells you: *") || + looking_at(buf, i, "* says: *")) { + player = StripHighlightAndTitle(star_match[0]); + if (appData.zippyBughouse && first.initDone && + strcmp(player, zippyPartner) == 0) { + SendToProgram("ptell ", &first); + SendToProgram(star_match[1], &first); + SendToProgram("\n", &first); + } else if (strncmp(star_match[1], HI, 6) == 0) { + extern char* programVersion; + sprintf(reply, "%stell %s %s\n", + ics_prefix, player, programVersion); + SendToICS(reply); + } else if (strncmp(star_match[1], "W0W!! ", 6) == 0) { + extern char* programVersion; + sprintf(reply, "%stell %s %s\n", ics_prefix, + player, programVersion); + SendToICS(reply); + } else if (appData.zippyTalk && ((random() % 10) < 9)) { + if (strcmp(player, ics_handle) != 0) { + Speak("tell", player); + } + } + return TRUE; + } + + if (looking_at(buf, i, "* spoofs you:")) { + player = StripHighlightAndTitle(star_match[0]); + sprintf(reply, "spoofedby %s\n", player); + SendToICS(reply); + sprintf(reply, "tell %s Yes sir, i do it \n", player); + SendToICS(reply); + } + return FALSE; +} + +int ZippyConverse(buf, i) + char *buf; + int *i; +{ + static char lastgreet[MSG_SIZ]; + char reply[MSG_SIZ]; + int oldi; + + /* Shouts and emotes */ + if (looking_at(buf, i, "--> * *") || + looking_at(buf, i, "* shouts: *")) { + if (appData.zippyTalk) { + char *player = StripHighlightAndTitle(star_match[0]); + if (strcmp(player, ics_handle) == 0) { + return TRUE; + } else if (appData.zippyPinhead[0] != NULLCHAR && + StrCaseStr(star_match[1], appData.zippyPinhead) != NULL) { + sprintf(reply, "insult %s\n", player); + SendToICS(reply); + } else if (ZippyCalled(star_match[1])) { + Speak("shout", NULL); + } + } + return TRUE; + } + + if (looking_at(buf, i, "* kibitzes: *")) { + if (appData.zippyTalk && (random() % 10) < 9) { + char *player = StripHighlightAndTitle(star_match[0]); + if (strcmp(player, ics_handle) != 0) { + Speak("kibitz", NULL); + } + } + return TRUE; + } + + if (looking_at(buf, i, "* whispers: *")) { + if (appData.zippyTalk && (random() % 10) < 9) { + char *player = StripHighlightAndTitle(star_match[0]); + if (strcmp(player, ics_handle) != 0) { + Speak("whisper", NULL); + } + } + return TRUE; + } + + /* Messages */ + if ((looking_at(buf, i, ". * (*:*): *") && isdigit(star_match[1][0])) || + looking_at(buf, i, ". * at *:*: *")) { + if (appData.zippyTalk) { + FILE *f; + char *player = StripHighlightAndTitle(star_match[0]); + + if (strcmp(player, ics_handle) != 0) { + if ((random() % 10) < 9) + Speak("message", player); + f = fopen("zippy.messagelog", "a"); + fprintf(f, "%s (%s:%s): %s\n", player, + star_match[1], star_match[2], star_match[3]); + fclose(f); + } + } + return TRUE; + } + + /* Channel tells */ + oldi = *i; + if (looking_at(buf, i, "*(*: *")) { + char *player; + char *channel; + if (star_match[0][0] == NULLCHAR || + strchr(star_match[0], ' ') || + strchr(star_match[1], ' ')) { + /* Oops, did not want to match this; probably a message */ + *i = oldi; + return FALSE; + } + if (appData.zippyTalk) { + player = StripHighlightAndTitle(star_match[0]); + channel = strrchr(star_match[1], '('); + if (channel == NULL) { + channel = star_match[1]; + } else { + channel++; + } + channel[strlen(channel)-1] = NULLCHAR; +#if 0 + /* Always tell to the channel (probability 90%) */ + if (strcmp(player, ics_handle) != 0 && (random() % 10) < 9) { + Speak("tell", channel); + } +#else + /* Tell to the channel only if someone mentions our name */ + if (ZippyCalled(star_match[2])) { + Speak("tell", channel); + } +#endif + } + return TRUE; + } + + if (!appData.zippyTalk) return FALSE; + + if ((looking_at(buf, i, "You have * message") && + atoi(star_match[0]) != 0) || + looking_at(buf, i, "* has left a message for you") || + looking_at(buf, i, "* just sent you a message")) { + sprintf(reply, "%smessages\n%sclearmessages *\n", + ics_prefix, ics_prefix); + SendToICS(reply); + return TRUE; + } + + if (looking_at(buf, i, "Notification: * has arrived")) { + if ((random() % 3) == 0) { + char *player = StripHighlightAndTitle(star_match[0]); + strcpy(lastgreet, player); + sprintf(reply, "greet %s\n", player); + SendToICS(reply); + Speak("tell", player); + } + } + + if (looking_at(buf, i, "Notification: * has departed")) { + if ((random() % 3) == 0) { + char *player = StripHighlightAndTitle(star_match[0]); + sprintf(reply, "farewell %s\n", player); + SendToICS(reply); + } + } + + if (looking_at(buf, i, "Not sent -- * is censoring you")) { + char *player = StripHighlightAndTitle(star_match[0]); + if (strcmp(player, lastgreet) == 0) { + sprintf(reply, "%s-notify %s\n", ics_prefix, player); + SendToICS(reply); + } + } + + if (looking_at(buf, i, "command is currently turned off")) { + appData.zippyUseI = 0; + } + + return FALSE; +} + +void ZippyGameStart(white, black) + char *white, *black; +{ + if (!first.initDone) { + /* Game is starting prematurely. We can't deal with this */ + SendToICS(ics_prefix); + SendToICS("abort\n"); + SendToICS(ics_prefix); + SendToICS("say Sorry, the chess program is not initialized yet.\n"); + return; + } + + if (appData.zippyGameStart[0] != NULLCHAR) { + SendToICS(appData.zippyGameStart); + SendToICS("\n"); + } +} + +void ZippyGameEnd(result, resultDetails) + ChessMove result; + char *resultDetails; +{ + if (appData.zippyAcceptOnly[0] == NULLCHAR && + appData.zippyGameEnd[0] != NULLCHAR) { + SendToICS(appData.zippyGameEnd); + SendToICS("\n"); + } + zippyLastGameEnd = time(0); +} + +/* + * Routines to implement Zippy playing chess + */ + +void ZippyHandleChallenge(srated, swild, sbase, sincrement, opponent) + char *srated, *swild, *sbase, *sincrement, *opponent; +{ + char buf[MSG_SIZ]; + int base, increment; + char rated; + VariantClass variant; + char *varname; + + rated = srated[0]; + variant = StringToVariant(swild); + varname = VariantName(variant); + base = atoi(sbase); + increment = atoi(sincrement); + + /* If desired, you can insert more code here to decline matches + based on rated, variant, base, and increment, but it is + easier to use the ICS formula feature instead. */ + + if (variant == VariantLoadable) { + sprintf(buf, + "%stell %s This computer can't play wild type %s\n%sdecline %s\n", + ics_prefix, opponent, swild, ics_prefix, opponent); + SendToICS(buf); + return; + } + if (StrStr(appData.zippyVariants, varname) == NULL) { + sprintf(buf, + "%stell %s This computer can't play %s [%s], only %s\n%sdecline %s\n", + ics_prefix, opponent, swild, varname, appData.zippyVariants, + ics_prefix, opponent); + SendToICS(buf); + return; + } + + /* Are we blocking match requests from all but one person? */ + if (appData.zippyAcceptOnly[0] != NULLCHAR && + StrCaseCmp(opponent, appData.zippyAcceptOnly)) { + /* Yes, and this isn't him. Ignore challenge. */ + return; + } + + /* Too many consecutive games with same opponent? If so, make him + wait until someone else has played or a timeout has elapsed. */ + if (appData.zippyMaxGames && + strcmp(opponent, zippyLastOpp) == 0 && + zippyConsecGames >= appData.zippyMaxGames && + difftime(time(0), zippyLastGameEnd) < appData.zippyReplayTimeout) { + sprintf(buf, "%stell %s Sorry, you have just played %d consecutive games against %s. To give others a chance, please wait %d seconds or until someone else has played.\n%sdecline %s\n", + ics_prefix, opponent, zippyConsecGames, ics_handle, + appData.zippyReplayTimeout, ics_prefix, opponent); + SendToICS(buf); + return; + } + + /* Engine not yet initialized or still thinking about last game? */ + if (!first.initDone || first.lastPing != first.lastPong) { + sprintf(buf, "%stell %s I'm not quite ready for a new game yet; try again soon.\n%sdecline %s\n", + ics_prefix, opponent, ics_prefix, opponent); + SendToICS(buf); + return; + } + + sprintf(buf, "%saccept %s\n", ics_prefix, opponent); + SendToICS(buf); + if (appData.zippyTalk) { + Speak("tell", opponent); + } +} + + +/* Accept matches */ +int ZippyMatch(buf, i, player) + char *buf; + int *i; + char *player; +{ + char reply[128]; + player = StripHighlightAndTitle(star_match[0]); + + if (looking_at(buf, i, "* * match * * requested with * (*)")) { + + /* don't accept matches if ICS analyze run */ + if (gameMode == IcsObserving || gameMode == IcsExamining) { + sprintf(reply, "tell %s Sorry, i'm analysis a game and don't accept matches. Please try it later again \n", player); + SendToICS(reply); + return FALSE; + } + + ZippyHandleChallenge(star_match[0], star_match[1], + star_match[2], star_match[3], + StripHighlightAndTitle(star_match[4])); + return TRUE; + } + + /* Old FICS 0-increment form */ + if (looking_at(buf, i, "* * match * requested with * (*)")) { + + /* don't accept matches if ICS analyze run */ + if (gameMode == IcsObserving || gameMode == IcsExamining) { + sprintf(reply, "tell %s Sorry, i'm analysis a game and don't accept matches. Please try it later again \n", player); + SendToICS(reply); + return FALSE; + } + + ZippyHandleChallenge(star_match[0], star_match[1], + star_match[2], "0", + StripHighlightAndTitle(star_match[3])); + return TRUE; + } + + if (looking_at(buf, i, + "* has made an alternate proposal of * * match * *.")) { + + /* don't accept matches if ICS analyze run */ + if (gameMode == IcsObserving || gameMode == IcsExamining) { + sprintf(reply, "tell %s Sorry, i'm analysis a game and don't accept matches. Please try it later again \n", player); + SendToICS(reply); + return FALSE; + } + + ZippyHandleChallenge(star_match[1], star_match[2], + star_match[3], star_match[4], + StripHighlightAndTitle(star_match[0])); + return TRUE; + } + + /* FICS wild/nonstandard forms */ + if (looking_at(buf, i, "Challenge: * (*) *(*) * * * * Loaded from *")) { + + /* don't accept matches if ICS analyze run */ + if (gameMode == IcsObserving || gameMode == IcsExamining) { + sprintf(reply, "tell %s Sorry, i'm analysis a game and don't accept matches. Please try it later again \n", player); + SendToICS(reply); + return FALSE; + } + + /* note: star_match[2] can include "[white] " or "[black] " + before our own name. */ + ZippyHandleChallenge(star_match[4], star_match[8], + star_match[6], star_match[7], + StripHighlightAndTitle(star_match[0])); + return TRUE; + } + + if (looking_at(buf, i, + "Challenge: * (*) *(*) * * * * : * * Loaded from *")) { + + /* don't accept matches if ICS analyze run */ + if (gameMode == IcsObserving || gameMode == IcsExamining) { + sprintf(reply, "tell %s Sorry, i'm analysis a game and don't accept matches. Please try it later again \n", player); + SendToICS(reply); + return FALSE; + } + + /* note: star_match[2] can include "[white] " or "[black] " + before our own name. */ + ZippyHandleChallenge(star_match[4], star_match[10], + star_match[8], star_match[9], + StripHighlightAndTitle(star_match[0])); + return TRUE; + } + + /* Regular forms */ + if (looking_at(buf, i, "Challenge: * (*) *(*) * * * * : * *") | + looking_at(buf, i, "Challenge: * (*) *(*) * * * * * *")) { + + /* don't accept matches if ICS analyze run */ + if (gameMode == IcsObserving || gameMode == IcsExamining) { + sprintf(reply, "tell %s Sorry, i'm analysis a game and don't accept matches. Please try it later again \n", player); + SendToICS(reply); + return FALSE; + } + + /* note: star_match[2] can include "[white] " or "[black] " + before our own name. */ + ZippyHandleChallenge(star_match[4], star_match[5], + star_match[8], star_match[9], + StripHighlightAndTitle(star_match[0])); + return TRUE; + } + + if (looking_at(buf, i, "Challenge: * (*) *(*) * * * *")) { + + /* don't accept matches if ICS analyze run */ + if (gameMode == IcsObserving || gameMode == IcsExamining) { + sprintf(reply, "tell %s Sorry, i'm analysis a game and don't accept matches. Please try it later again \n", player); + SendToICS(reply); + return FALSE; + } + + /* note: star_match[2] can include "[white] " or "[black] " + before our own name. */ + ZippyHandleChallenge(star_match[4], star_match[5], + star_match[6], star_match[7], + StripHighlightAndTitle(star_match[0])); + return TRUE; + } + /* works now at backend.c + if (looking_at(buf, i, "offers you a draw")) { + if (first.sendDrawOffers && first.initDone) { + SendToProgram("draw\n", &first); + } + return TRUE; + } + */ + if (looking_at(buf, i, "requests that the game be aborted") || + looking_at(buf, i, "would like to abort")) { + if (appData.zippyAbort || + (gameMode == IcsPlayingWhite && whiteTimeRemaining < 0) || + (gameMode == IcsPlayingBlack && blackTimeRemaining < 0)) { + SendToICS(ics_prefix); + SendToICS("abort\n"); + } else { + SendToICS(ics_prefix); + if (appData.zippyTalk) + SendToICS("say Whoa no! I am having FUN!!\n"); + else + SendToICS("say Sorry, this computer doesn't accept aborts.\n"); + } + return TRUE; + } + + if (looking_at(buf, i, "requests adjournment") || + looking_at(buf, i, "would like to adjourn")) { + if (appData.zippyAdjourn) { + SendToICS(ics_prefix); + SendToICS("adjourn\n"); + } else { + SendToICS(ics_prefix); + if (appData.zippyTalk) + SendToICS("say Whoa no! I am having FUN playing NOW!!\n"); + else + SendToICS("say Sorry, this computer doesn't accept adjourns.\n"); + } + return TRUE; + } + + return FALSE; +} + +/* Initialize chess program with data from the first board + * of a new or resumed game. + */ +void ZippyFirstBoard(moveNum, basetime, increment) + int moveNum, basetime, increment; +{ + char buf[MSG_SIZ]; + int w, b; + char *opp = (gameMode==IcsPlayingWhite ? gameInfo.black : gameInfo.white); + Boolean sentPos = FALSE; + + if (!first.initDone) { + /* Game is starting prematurely. We can't deal with this */ + SendToICS(ics_prefix); + SendToICS("abort\n"); + SendToICS(ics_prefix); + SendToICS("say Sorry, the chess program is not initialized yet.\n"); + return; + } + + /* reset ZippyDraw for a new or resumed game */ + if (appData.zippyDraw) ZippyDraw(2, 0, 0); + + /* Send the variant command if needed */ + if (gameInfo.variant != VariantNormal) { + sprintf(buf, "variant %s\n", VariantName(gameInfo.variant)); + SendToProgram(buf, &first); + } + + if ((startedFromSetupPosition && moveNum == 0) || + (!appData.getMoveList && moveNum > 0)) { + SendToProgram("force\n", &first); + SendBoard(&first, moveNum); + sentPos = TRUE; + } + + sprintf(buf, "level 0 %d %d\n", basetime, increment); + SendToProgram(buf, &first); + + /* Count consecutive games from one opponent */ + if (strcmp(opp, zippyLastOpp) == 0) { + zippyConsecGames++; + } else { + zippyConsecGames = 1; + strcpy(zippyLastOpp, opp); + } + + /* Send the "computer" command if the opponent is in the list + we've been gathering. */ + for (w=0; w= 0) ? gameInfo.whiteRating : 0; + b = (gameInfo.blackRating >= 0) ? gameInfo.blackRating : 0; + + firstMove = FALSE; + if (gameMode == IcsPlayingWhite) { + if (first.sendName) { + sprintf(buf, "name %s\n", gameInfo.black); + SendToProgram(buf, &first); + } + strcpy(ics_handle, gameInfo.white); + sprintf(buf, "rating %d %d\n", w, b); + SendToProgram(buf, &first); + if (sentPos) { + /* Position sent above, engine is in force mode */ + if (WhiteOnMove(moveNum)) { + /* Engine is on move now */ + if (first.sendTime) { + if (first.useColors) { + SendToProgram("black\n", &first); /*gnu kludge*/ + SendTimeRemaining(&first, TRUE); + SendToProgram("white\n", &first); + } else { + SendTimeRemaining(&first, TRUE); + } + } + SendToProgram("go\n", &first); + } else { + /* Engine's opponent is on move now */ + if (first.usePlayother) { + if (first.sendTime) { + SendTimeRemaining(&first, TRUE); + } + SendToProgram("playother\n", &first); + } else { + /* Need to send a "go" after opponent moves */ + firstMove = TRUE; + } + } + } else { + /* Position not sent above, move list might be sent later */ + if (moveNum == 0) { + /* No move list coming; at start of game */ + if (first.sendTime) { + if (first.useColors) { + SendToProgram("black\n", &first); /*gnu kludge*/ + SendTimeRemaining(&first, TRUE); + SendToProgram("white\n", &first); + } else { + SendTimeRemaining(&first, TRUE); + } + } + SendToProgram("go\n", &first); + } + } + } else if (gameMode == IcsPlayingBlack) { + if (first.sendName) { + sprintf(buf, "name %s\n", gameInfo.white); + SendToProgram(buf, &first); + } + strcpy(ics_handle, gameInfo.black); + sprintf(buf, "rating %d %d\n", b, w); + SendToProgram(buf, &first); + if (sentPos) { + /* Position sent above, engine is in force mode */ + if (!WhiteOnMove(moveNum)) { + /* Engine is on move now */ + if (first.sendTime) { + if (first.useColors) { + SendToProgram("white\n", &first); /*gnu kludge*/ + SendTimeRemaining(&first, FALSE); + SendToProgram("black\n", &first); + } else { + SendTimeRemaining(&first, FALSE); + } + } + SendToProgram("go\n", &first); + } else { + /* Engine's opponent is on move now */ + if (first.usePlayother) { + if (first.sendTime) { + SendTimeRemaining(&first, FALSE); + } + SendToProgram("playother\n", &first); + } else { + /* Need to send a "go" after opponent moves */ + firstMove = TRUE; + } + } + } else { + /* Position not sent above, move list might be sent later */ + /* Nothing needs to be done here */ + } + } +} + + +void +ZippyHoldings(white_holding, black_holding, new_piece) + char *white_holding, *black_holding, *new_piece; +{ + char buf[MSG_SIZ]; + if (gameMode != IcsPlayingBlack && gameMode != IcsPlayingWhite) return; + sprintf(buf, "holding [%s] [%s] %s\n", + white_holding, black_holding, new_piece); + SendToProgram(buf, &first); +} + +void +ZippyDraw(request, score, depth) +int request; /* 0 no request 1 opponent offer draw 2 New Game */ +int score; +int depth; +{ + static int drawCounter; /* 0.00 engine score */ + static int lastDrawMove; /* Last move we offer a draw */ + static int RatingDiff; /* Diff between our rating */ + int drawFactor = 0; /* Setup which score is draw. Default is 0 */ + + char str[MSG_SIZ]; + + /* If request 1 we only become a offer from opponent. We + don't save engine score and looking about some stuff to + accept or decline the draw. + If resquest 0 the engine make a new move and we looking + to the last program score before that move. If 0.00 the + counter will be ++. + + If the score is not zero we reset the counter to zero. + */ + + if (request == 0) { + if (score == drawFactor || (score < 0 && score > -10)) { + if (depth > 1) drawCounter++; + if (drawCounter >= 5 && (currentMove - lastDrawMove) > 20 && + currentMove > 40 && depth > 1) { + /* rating check */ + if (RatingDiff > 50) { + sprintf(str, "whisper Winboard-DM: ZippyDraw: No draw offer - Rating of opponent to low \n"); + SendToICS(str); + drawCounter = 0; + return; + } + if (appData.debugMode) fprintf(debugFP, + "Offer draw. counter: %d\n", drawCounter); + sprintf(str, "kibitz Winboard-DM: ZippyDraw = counter %d; LastDraw: %d; \n", + drawCounter, lastDrawMove); + SendToICS(str); + sprintf(str, "draw \n"); + SendToICS(str); + lastDrawMove = currentMove; + } + } else { + drawCounter = 0; + } + } else if (request == 1) { + if (drawCounter >= 5 && currentMove > 40 && depth >= 1 && score <= drawFactor && + RatingDiff < 50) { + if (appData.debugMode) fprintf(debugFP, "accept draw \n"); + sprintf(str, "kibitz Winboard-DM: ZippyDraw = counter %d; LastDraw: %d; score %d R-Diff %d \n", + drawCounter, lastDrawMove, score, RatingDiff); + SendToICS(str); + sprintf(str, "draw\n"); + SendToICS(str); + return; + + } + if (score < -50 && depth > 1) { + if (appData.debugMode) fprintf(debugFP, "draw \n"); + sprintf(str, "kibitz Winboard-DM: ZippyDraw = counter %d; LastDraw: %d; score %d R-Diff %d \n", + drawCounter, lastDrawMove, score, RatingDiff); + SendToICS(str); + sprintf(str, "draw\n"); + SendToICS(str); + return; + } else { + if (appData.debugMode) fprintf(debugFP, "decline Draw \n"); + sprintf(str, "kibitz Winboard-DM: ZippyDraw = counter %d; LastDraw: %d; R-Diff %d\n", + drawCounter, lastDrawMove, RatingDiff); + + SendToICS(str); + sprintf(str, "kibitz No thank you. I wanna play \n"); + SendToICS(str); + } + } else { + /* request 2 = new game - reset data */ + + drawCounter = 0; + lastDrawMove = 0; + /* read rating */ + + if (gameMode == IcsPlayingBlack) { + RatingDiff = gameInfo.blackRating - gameInfo.whiteRating; + } else if (gameMode == IcsPlayingWhite) { + RatingDiff = gameInfo.whiteRating - gameInfo.blackRating; + } + sprintf(str, "whisper Winboard-DM: ZippyDraw = enable dynamic draw; R-Diff %d \n", RatingDiff); + SendToICS(str); + } +} diff --git a/winboard-dm-beta4/zippy.h b/winboard-dm-beta4/zippy.h new file mode 100755 index 0000000..d1c4a63 --- /dev/null +++ b/winboard-dm-beta4/zippy.h @@ -0,0 +1,58 @@ +/* + * zippy.h -- Interface to zippy.c module in XBoard + * $Id$ + * + * Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts. + * Enhancements Copyright 1992-95 Free Software Foundation, Inc. + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * ------------------------------------------------------------------------ + */ + +void ZippyInit P((void)); +int ZippyControl P((char *buf, int *i)); +int ZippyConverse P((char *buf, int *i)); +void ZippyGameStart P((char *white, char *black)); +int ZippyMatch P((char *buf, int *i, char *player)); +void ZippyFirstBoard P((int moveNum, int basetime, int increment)); +void ZippyGameEnd P((ChessMove result, char *resultDetails)); +void ZippyHoldings P((char *white_holding, char *black_holding, + char *new_piece)); +void ZippyDraw P((int request, int score, int depth)); -- 1.7.0.4