X-Git-Url: http://winboard.nl/cgi-bin?p=xboard.git;a=blobdiff_plain;f=xboard.c;h=0e8b132d0e9d7b9c9f4f07632fd5af69c1379f6f;hp=06212e60f1f98b12b6d11a0f89af2794cf970826;hb=d016fb202fe45795e630e22ba516e754cf694ea6;hpb=05bc30b15e31c427ce208495a889e9ff36e6642b diff --git a/xboard.c b/xboard.c index 06212e6..0e8b132 100644 --- a/xboard.c +++ b/xboard.c @@ -1,9 +1,11 @@ /* * xboard.c -- X front end for XBoard - * $Id$ * - * Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts. - * Enhancements Copyright 1992-2001 Free Software Foundation, Inc. + * Copyright 1991 by Digital Equipment Corporation, Maynard, + * Massachusetts. + * + * Enhancements Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006, + * 2007, 2008, 2009 Free Software Foundation, Inc. * * The following terms apply to Digital Equipment Corporation's copyright * interest in XBoard: @@ -27,26 +29,25 @@ * SOFTWARE. * ------------------------------------------------------------------------ * - * The following terms apply to the enhanced version of XBoard distributed - * by the Free Software Foundation: + * 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 + * + * GNU XBoard 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. + * the Free Software Foundation, either version 3 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. + * GNU XBoard 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. - * ------------------------------------------------------------------------ + * along with this program. If not, see http://www.gnu.org/licenses/. * * - * See the file ChangeLog for a revision history. - */ + *------------------------------------------------------------------------ + ** See the file ChangeLog for a revision history. */ #include "config.h" @@ -169,6 +170,9 @@ extern char *getenv(); #include #endif +// [HGM] bitmaps: put before incuding the bitmaps / pixmaps, to know how many piece types there are. +#include "common.h" + #if HAVE_LIBXPM #include #include "pixmaps/pixmaps.h" @@ -182,7 +186,6 @@ extern char *getenv(); #include "bitmaps/icon_black.bm" #include "bitmaps/checkmark.bm" -#include "common.h" #include "frontend.h" #include "backend.h" #include "moves.h" @@ -191,14 +194,15 @@ extern char *getenv(); #include "xgamelist.h" #include "xhistory.h" #include "xedittags.h" +#include "gettext.h" -#if !DEFINED_SYS_ERRLIST -extern char *sys_errlist[]; -#endif +// must be moved to xengineoutput.h + +void EngineOutputProc P((Widget w, XEvent *event, + String *prms, Cardinal *nprms)); + +void EngineOutputPopDown(); -#ifdef __CYGWIN__ -#define sys_errlist _sys_errlist -#endif #ifdef __EMX__ #ifndef HAVE_USLEEP @@ -207,6 +211,14 @@ extern char *sys_errlist[]; #define usleep(t) _sleep2(((t)+500)/1000) #endif +#ifdef ENABLE_NLS +# define _(s) gettext (s) +# define N_(s) gettext_noop (s) +#else +# define _(s) (s) +# define N_(s) s +#endif + typedef struct { String string; XtActionProc proc; @@ -248,7 +260,7 @@ void BlackClock P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); void DrawPositionProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); -void XDrawPosition P((Widget w, /*Boolean*/int repaint, +void XDrawPosition P((Widget w, /*Boolean*/int repaint, Board board)); void CommentPopUp P((char *title, char *label)); void CommentPopDown P((void)); @@ -334,6 +346,9 @@ void DrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); void AbortProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); void AdjournProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); void ResignProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); +void AdjuWhiteProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); +void AdjuBlackProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); +void AdjuDrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); void EnterKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); void StopObservingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); @@ -391,6 +406,8 @@ void ShowCoordsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); void ShowThinkingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); +void HideThinkingProc P((Widget w, XEvent *event, String *prms, + Cardinal *nprms)); void TestLegalityProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); void InfoProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); @@ -415,7 +432,20 @@ static void DragPieceMove P((int x, int y)); static void DragPieceEnd P((int x, int y)); static void DrawDragPiece P((void)); char *ModeToWidgetName P((GameMode mode)); - +void EngineOutputUpdate( FrontEndProgramStats * stats ); +void ShuffleMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); +void EngineMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); +void UciMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); +void TimeControlProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); +void NewVariantProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); +void FirstSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); +void SecondSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); +void ShufflePopDown P(()); +void EnginePopDown P(()); +void UciPopDown P(()); +void TimeControlPopDown P(()); +void NewVariantPopDown P(()); +void SettingsPopDown P(()); /* * XBoard depends on Xt R4 or higher */ @@ -426,30 +456,33 @@ Display *xDisplay; Window xBoardWindow; Pixel lightSquareColor, darkSquareColor, whitePieceColor, blackPieceColor, jailSquareColor, highlightSquareColor, premoveHighlightColor; +Pixel lowTimeWarningColor; GC lightSquareGC, darkSquareGC, jailSquareGC, lineGC, wdPieceGC, wlPieceGC, bdPieceGC, blPieceGC, wbPieceGC, bwPieceGC, coordGC, highlineGC, - wjPieceGC, bjPieceGC, prelineGC; + wjPieceGC, bjPieceGC, prelineGC, countGC; Pixmap iconPixmap, wIconPixmap, bIconPixmap, xMarkPixmap; -Widget shellWidget, layoutWidget, formWidget, boardWidget, messageWidget, - whiteTimerWidget, blackTimerWidget, titleWidget, widgetList[16], +Widget shellWidget, layoutWidget, formWidget, boardWidget, messageWidget, + whiteTimerWidget, blackTimerWidget, titleWidget, widgetList[16], commentShell, promotionShell, whitePieceMenu, blackPieceMenu, dropMenu, menuBarWidget, buttonBarWidget, editShell, errorShell, analysisShell, ICSInputShell, fileNameShell, askQuestionShell; XSegment gridSegments[(BOARD_SIZE + 1) * 2]; XSegment jailGridSegments[(BOARD_SIZE + 3) * 2]; -Font clockFontID, coordFontID; -XFontStruct *clockFontStruct, *coordFontStruct; +Font clockFontID, coordFontID, countFontID; +XFontStruct *clockFontStruct, *coordFontStruct, *countFontStruct; XtAppContext appContext; char *layoutName; char *oldICSInteractionTitle; FileProc fileProc; char *fileOpenMode; +char installDir[] = "."; // [HGM] UCI: needed for UCI; probably needs run-time initializtion Position commentX = -1, commentY = -1; Dimension commentW, commentH; int squareSize, smallLayout = 0, tinyLayout = 0, + marginW, marginH, // [HGM] for run-time resizing fromX = -1, fromY = -1, toX, toY, commentUp = False, analysisUp = False, ICSInputBoxUp = False, askQuestionUp = False, filenameUp = False, promotionUp = False, pmFromX = -1, pmFromY = -1, @@ -461,17 +494,20 @@ char *chessDir, *programName, *programVersion, #define SOLID 0 #define OUTLINE 1 -Pixmap pieceBitmap[2][6]; -Pixmap xpmPieceBitmap[4][6]; /* LL, LD, DL, DD */ +Pixmap pieceBitmap[2][(int)BlackPawn]; +Pixmap pieceBitmap2[2][(int)BlackPawn+4]; /* [HGM] pieces */ +Pixmap xpmPieceBitmap[4][(int)BlackPawn]; /* LL, LD, DL, DD actually used*/ +Pixmap xpmPieceBitmap2[4][(int)BlackPawn+4]; /* LL, LD, DL, DD set to select from */ Pixmap xpmLightSquare, xpmDarkSquare, xpmJailSquare; int useImages, useImageSqs; -XImage *ximPieceBitmap[4][6]; /* LL, LD, DL, DD */ -Pixmap ximMaskPm[6]; /* clipmasks, used for XIM pieces */ +XImage *ximPieceBitmap[4][(int)BlackPawn+4]; /* LL, LD, DL, DD */ +Pixmap ximMaskPm[(int)BlackPawn]; /* clipmasks, used for XIM pieces */ +Pixmap ximMaskPm2[(int)BlackPawn+4]; /* clipmasks, used for XIM pieces */ XImage *ximLightSquare, *ximDarkSquare; XImage *xim_Cross; -#define pieceToSolid(piece) &pieceBitmap[SOLID][((int)(piece)) % 6] -#define pieceToOutline(piece) &pieceBitmap[OUTLINE][((int)(piece)) % 6] +#define pieceToSolid(piece) &pieceBitmap[SOLID][(piece) % (int)BlackPawn] +#define pieceToOutline(piece) &pieceBitmap[OUTLINE][(piece) % (int)BlackPawn] #define White(piece) ((int)(piece) < (int)BlackPawn) @@ -507,137 +543,153 @@ static Pixmap xpmMask[BlackKing + 1]; SizeDefaults sizeDefaults[] = SIZE_DEFAULTS; MenuItem fileMenu[] = { - {"Reset Game", ResetProc}, + {N_("New Game"), ResetProc}, + {N_("New Shuffle Game ..."), ShuffleMenuProc}, + {N_("New Variant ..."), NewVariantProc}, // [HGM] variant: not functional yet {"----", NothingProc}, - {"Load Game", LoadGameProc}, - {"Load Next Game", LoadNextGameProc}, - {"Load Previous Game", LoadPrevGameProc}, - {"Reload Same Game", ReloadGameProc}, - {"Save Game", SaveGameProc}, + {N_("Load Game"), LoadGameProc}, + {N_("Load Next Game"), LoadNextGameProc}, + {N_("Load Previous Game"), LoadPrevGameProc}, + {N_("Reload Same Game"), ReloadGameProc}, + {N_("Save Game"), SaveGameProc}, {"----", NothingProc}, - {"Copy Game", CopyGameProc}, - {"Paste Game", PasteGameProc}, + {N_("Copy Game"), CopyGameProc}, + {N_("Paste Game"), PasteGameProc}, {"----", NothingProc}, - {"Load Position", LoadPositionProc}, - {"Load Next Position", LoadNextPositionProc}, - {"Load Previous Position", LoadPrevPositionProc}, - {"Reload Same Position", ReloadPositionProc}, - {"Save Position", SavePositionProc}, + {N_("Load Position"), LoadPositionProc}, + {N_("Load Next Position"), LoadNextPositionProc}, + {N_("Load Previous Position"), LoadPrevPositionProc}, + {N_("Reload Same Position"), ReloadPositionProc}, + {N_("Save Position"), SavePositionProc}, {"----", NothingProc}, - {"Copy Position", CopyPositionProc}, - {"Paste Position", PastePositionProc}, + {N_("Copy Position"), CopyPositionProc}, + {N_("Paste Position"), PastePositionProc}, {"----", NothingProc}, - {"Mail Move", MailMoveProc}, - {"Reload CMail Message", ReloadCmailMsgProc}, + {N_("Mail Move"), MailMoveProc}, + {N_("Reload CMail Message"), ReloadCmailMsgProc}, {"----", NothingProc}, - {"Exit", QuitProc}, + {N_("Exit"), QuitProc}, {NULL, NULL} }; MenuItem modeMenu[] = { - {"Machine White", MachineWhiteProc}, - {"Machine Black", MachineBlackProc}, - {"Two Machines", TwoMachinesProc}, - {"Analysis Mode", AnalyzeModeProc}, - {"Analyze File", AnalyzeFileProc }, - {"ICS Client", IcsClientProc}, - {"Edit Game", EditGameProc}, - {"Edit Position", EditPositionProc}, - {"Training", TrainingProc}, + {N_("Machine White"), MachineWhiteProc}, + {N_("Machine Black"), MachineBlackProc}, + {N_("Two Machines"), TwoMachinesProc}, + {N_("Analysis Mode"), AnalyzeModeProc}, + {N_("Analyze File"), AnalyzeFileProc }, + {N_("ICS Client"), IcsClientProc}, + {N_("Edit Game"), EditGameProc}, + {N_("Edit Position"), EditPositionProc}, + {N_("Training"), TrainingProc}, {"----", NothingProc}, - {"Show Game List", ShowGameListProc}, - {"Show Move List", HistoryShowProc}, - {"Edit Tags", EditTagsProc}, - {"Edit Comment", EditCommentProc}, - {"ICS Input Box", IcsInputBoxProc}, - {"Pause", PauseProc}, + {N_("Show Engine Output"), EngineOutputProc}, + {N_("Show Evaluation Graph"), NothingProc}, // [HGM] evalgr: not functional yet + {N_("Show Game List"), ShowGameListProc}, + {"Show Move History", HistoryShowProc}, // [HGM] hist: activate 4.2.7 code + {"----", NothingProc}, + {N_("Edit Tags"), EditTagsProc}, + {N_("Edit Comment"), EditCommentProc}, + {N_("ICS Input Box"), IcsInputBoxProc}, + {N_("Pause"), PauseProc}, {NULL, NULL} }; MenuItem actionMenu[] = { - {"Accept", AcceptProc}, - {"Decline", DeclineProc}, - {"Rematch", RematchProc}, - {"----", NothingProc}, - {"Call Flag", CallFlagProc}, - {"Draw", DrawProc}, - {"Adjourn", AdjournProc}, - {"Abort", AbortProc}, - {"Resign", ResignProc}, - {"----", NothingProc}, - {"Stop Observing", StopObservingProc}, - {"Stop Examining", StopExaminingProc}, + {N_("Accept"), AcceptProc}, + {N_("Decline"), DeclineProc}, + {N_("Rematch"), RematchProc}, + {"----", NothingProc}, + {N_("Call Flag"), CallFlagProc}, + {N_("Draw"), DrawProc}, + {N_("Adjourn"), AdjournProc}, + {N_("Abort"), AbortProc}, + {N_("Resign"), ResignProc}, + {"----", NothingProc}, + {N_("Stop Observing"), StopObservingProc}, + {N_("Stop Examining"), StopExaminingProc}, + {"----", NothingProc}, + {N_("Adjudicate to White"), AdjuWhiteProc}, + {N_("Adjudicate to Black"), AdjuBlackProc}, + {N_("Adjudicate Draw"), AdjuDrawProc}, {NULL, NULL} }; MenuItem stepMenu[] = { - {"Backward", BackwardProc}, - {"Forward", ForwardProc}, - {"Back to Start", ToStartProc}, - {"Forward to End", ToEndProc}, - {"Revert", RevertProc}, - {"Truncate Game", TruncateGameProc}, - {"----", NothingProc}, - {"Move Now", MoveNowProc}, - {"Retract Move", RetractMoveProc}, + {N_("Backward"), BackwardProc}, + {N_("Forward"), ForwardProc}, + {N_("Back to Start"), ToStartProc}, + {N_("Forward to End"), ToEndProc}, + {N_("Revert"), RevertProc}, + {N_("Truncate Game"), TruncateGameProc}, + {"----", NothingProc}, + {N_("Move Now"), MoveNowProc}, + {N_("Retract Move"), RetractMoveProc}, {NULL, NULL} -}; +}; MenuItem optionsMenu[] = { - {"Always Queen", AlwaysQueenProc}, - {"Animate Dragging", AnimateDraggingProc}, - {"Animate Moving", AnimateMovingProc}, - {"Auto Comment", AutocommProc}, - {"Auto Flag", AutoflagProc}, - {"Auto Flip View", AutoflipProc}, - {"Auto Observe", AutobsProc}, - {"Auto Raise Board", AutoraiseProc}, - {"Auto Save", AutosaveProc}, - {"Blindfold", BlindfoldProc}, - {"Flash Moves", FlashMovesProc}, - {"Flip View", FlipViewProc}, - {"Get Move List", GetMoveListProc}, + {N_("Flip View"), FlipViewProc}, + {"----", NothingProc}, + {N_("Adjudications ..."), EngineMenuProc}, + {N_("General Settings ..."), UciMenuProc}, + {N_("Engine #1 Settings ..."), FirstSettingsProc}, + {N_("Engine #2 Settings ..."), SecondSettingsProc}, + {N_("Time Control ..."), TimeControlProc}, + {"----", NothingProc}, + {N_("Always Queen"), AlwaysQueenProc}, + {N_("Animate Dragging"), AnimateDraggingProc}, + {N_("Animate Moving"), AnimateMovingProc}, + {N_("Auto Comment"), AutocommProc}, + {N_("Auto Flag"), AutoflagProc}, + {N_("Auto Flip View"), AutoflipProc}, + {N_("Auto Observe"), AutobsProc}, + {N_("Auto Raise Board"), AutoraiseProc}, + {N_("Auto Save"), AutosaveProc}, + {N_("Blindfold"), BlindfoldProc}, + {N_("Flash Moves"), FlashMovesProc}, + {N_("Get Move List"), GetMoveListProc}, #if HIGHDRAG - {"Highlight Dragging", HighlightDraggingProc}, + {N_("Highlight Dragging"), HighlightDraggingProc}, #endif - {"Highlight Last Move", HighlightLastMoveProc}, - {"Move Sound", MoveSoundProc}, - {"ICS Alarm", IcsAlarmProc}, - {"Old Save Style", OldSaveStyleProc}, - {"Periodic Updates", PeriodicUpdatesProc}, - {"Ponder Next Move", PonderNextMoveProc}, - {"Popup Exit Message", PopupExitMessageProc}, - {"Popup Move Errors", PopupMoveErrorsProc}, - {"Premove", PremoveProc}, - {"Quiet Play", QuietPlayProc}, - {"Show Coords", ShowCoordsProc}, - {"Show Thinking", ShowThinkingProc}, - {"Test Legality", TestLegalityProc}, + {N_("Highlight Last Move"), HighlightLastMoveProc}, + {N_("Move Sound"), MoveSoundProc}, + {N_("ICS Alarm"), IcsAlarmProc}, + {N_("Old Save Style"), OldSaveStyleProc}, + {N_("Periodic Updates"), PeriodicUpdatesProc}, + {N_("Ponder Next Move"), PonderNextMoveProc}, + {N_("Popup Exit Message"), PopupExitMessageProc}, + {N_("Popup Move Errors"), PopupMoveErrorsProc}, + {N_("Premove"), PremoveProc}, + {N_("Quiet Play"), QuietPlayProc}, + {N_("Show Coords"), ShowCoordsProc}, + {N_("Hide Thinking"), HideThinkingProc}, + {N_("Test Legality"), TestLegalityProc}, {NULL, NULL} }; MenuItem helpMenu[] = { - {"Info XBoard", InfoProc}, - {"Man XBoard", ManProc}, + {N_("Info XBoard"), InfoProc}, + {N_("Man XBoard"), ManProc}, {"----", NothingProc}, - {"Hint", HintProc}, - {"Book", BookProc}, + {N_("Hint"), HintProc}, + {N_("Book"), BookProc}, {"----", NothingProc}, - {"About XBoard", AboutProc}, + {N_("About XBoard"), AboutProc}, {NULL, NULL} }; Menu menuBar[] = { - {"File", fileMenu}, - {"Mode", modeMenu}, - {"Action", actionMenu}, - {"Step", stepMenu}, - {"Options", optionsMenu}, - {"Help", helpMenu}, + {N_("File"), fileMenu}, + {N_("Mode"), modeMenu}, + {N_("Action"), actionMenu}, + {N_("Step"), stepMenu}, + {N_("Options"), optionsMenu}, + {N_("Help"), helpMenu}, {NULL, NULL} }; -#define PAUSE_BUTTON "P" +#define PAUSE_BUTTON N_("P") MenuItem buttonBar[] = { {"<<", ToStartProc}, {"<", BackwardProc}, @@ -647,26 +699,32 @@ MenuItem buttonBar[] = { {NULL, NULL} }; -#define PIECE_MENU_SIZE 11 +#define PIECE_MENU_SIZE 18 String pieceMenuStrings[2][PIECE_MENU_SIZE] = { - { "White", "----", "Pawn", "Knight", "Bishop", "Rook", "Queen", "King", - "----", "Empty square", "Clear board" }, - { "Black", "----", "Pawn", "Knight", "Bishop", "Rook", "Queen", "King", - "----", "Empty square", "Clear board" }, - }; + { N_("White"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"), + N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"), + N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"), + N_("Empty square"), N_("Clear board") }, + { N_("Black"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"), + N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"), + N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"), + N_("Empty square"), N_("Clear board") } +}; /* must be in same order as PieceMenuStrings! */ ChessSquare pieceMenuTranslation[2][PIECE_MENU_SIZE] = { { WhitePlay, (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop, - WhiteRook, WhiteQueen, WhiteKing, - (ChessSquare) 0, EmptySquare, ClearBoard }, + WhiteRook, WhiteQueen, WhiteKing, (ChessSquare) 0, WhiteAlfil, + WhiteCannon, WhiteAngel, WhiteMarshall, (ChessSquare) 0, + PromotePiece, DemotePiece, EmptySquare, ClearBoard }, { BlackPlay, (ChessSquare) 0, BlackPawn, BlackKnight, BlackBishop, - BlackRook, BlackQueen, BlackKing, - (ChessSquare) 0, EmptySquare, ClearBoard }, + BlackRook, BlackQueen, BlackKing, (ChessSquare) 0, BlackAlfil, + BlackCannon, BlackAngel, BlackMarshall, (ChessSquare) 0, + PromotePiece, DemotePiece, EmptySquare, ClearBoard }, }; #define DROP_MENU_SIZE 6 String dropMenuStrings[DROP_MENU_SIZE] = { - "----", "Pawn", "Knight", "Bishop", "Rook", "Queen" + "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"), N_("Queen") }; /* must be in same order as PieceMenuStrings! */ ChessSquare dropMenuTranslation[DROP_MENU_SIZE] = { @@ -740,7 +798,7 @@ XtResource clientResources[] = { BLACK_PIECE_COLOR }, { "lightSquareColor", "lightSquareColor", XtRString, sizeof(String), XtOffset(AppDataPtr, lightSquareColor), - XtRString, LIGHT_SQUARE_COLOR }, + XtRString, LIGHT_SQUARE_COLOR }, { "darkSquareColor", "darkSquareColor", XtRString, sizeof(String), XtOffset(AppDataPtr, darkSquareColor), XtRString, DARK_SQUARE_COLOR }, @@ -783,9 +841,9 @@ XtResource clientResources[] = { { "secondHost", "secondHost", XtRString, sizeof(String), XtOffset(AppDataPtr, secondHost), XtRString, SECOND_HOST }, { "firstDirectory", "firstDirectory", XtRString, sizeof(String), - XtOffset(AppDataPtr, firstDirectory), XtRString, "" }, + XtOffset(AppDataPtr, firstDirectory), XtRString, "." }, { "secondDirectory", "secondDirectory", XtRString, sizeof(String), - XtOffset(AppDataPtr, secondDirectory), XtRString, "" }, + XtOffset(AppDataPtr, secondDirectory), XtRString, "." }, { "bitmapDirectory", "bitmapDirectory", XtRString, sizeof(String), XtOffset(AppDataPtr, bitmapDirectory), XtRString, "" }, @@ -888,7 +946,7 @@ XtResource clientResources[] = { XtOffset(AppDataPtr, searchTime), XtRString, (XtPointer) "" }, { "searchDepth", "searchDepth", XtRInt, sizeof(int), - XtOffset(AppDataPtr, searchDepth), XtRImmediate, + XtOffset(AppDataPtr, searchDepth), XtRImmediate, (XtPointer) 0 }, { "showCoords", "showCoords", XtRBoolean, sizeof(Boolean), XtOffset(AppDataPtr, showCoords), XtRImmediate, @@ -898,7 +956,7 @@ XtResource clientResources[] = { (XtPointer) 0 }, { "showThinking", "showThinking", XtRBoolean, sizeof(Boolean), XtOffset(AppDataPtr, showThinking), XtRImmediate, - (XtPointer) False }, + (XtPointer) True }, { "ponderNextMove", "ponderNextMove", XtRBoolean, sizeof(Boolean), XtOffset(AppDataPtr, ponderNextMove), XtRImmediate, (XtPointer) True }, @@ -964,7 +1022,7 @@ XtResource clientResources[] = { { "localLineEditing", "localLineEditing", XtRBoolean, sizeof(Boolean), XtOffset(AppDataPtr, localLineEditing), XtRImmediate, (XtPointer) True }, /* not implemented, must be True */ -#ifdef ZIPPY +#if ZIPPY { "zippyTalk", "zippyTalk", XtRBoolean, sizeof(Boolean), XtOffset(AppDataPtr, zippyTalk), XtRImmediate, (XtPointer) ZIPPY_TALK }, @@ -1011,6 +1069,9 @@ XtResource clientResources[] = { { "zippyReplayTimeout", "zippyReplayTimeout", XtRInt, sizeof(int), XtOffset(AppDataPtr, zippyReplayTimeout), XtRImmediate, (XtPointer) ZIPPY_REPLAY_TIMEOUT }, + { "zippyShortGame", "zippyShortGame", XtRInt, sizeof(int), + XtOffset(AppDataPtr, zippyShortGame), XtRImmediate, + (XtPointer) 0 }, #endif { "flashCount", "flashCount", XtRInt, sizeof(int), XtOffset(AppDataPtr, flashCount), XtRImmediate, @@ -1026,7 +1087,7 @@ XtResource clientResources[] = { (XtPointer) MS_LOGIN_DELAY }, { "colorizeMessages", "colorizeMessages", XtRBoolean, sizeof(Boolean), XtOffset(AppDataPtr, colorize), - XtRImmediate, (XtPointer) False }, + XtRImmediate, (XtPointer) False }, { "colorShout", "colorShout", XtRString, sizeof(String), XtOffset(AppDataPtr, colorShout), XtRString, COLOR_SHOUT }, @@ -1056,7 +1117,7 @@ XtResource clientResources[] = { XtRString, COLOR_SEEK }, { "colorNormal", "colorNormal", XtRString, sizeof(String), XtOffset(AppDataPtr, colorNormal), - XtRString, COLOR_NORMAL }, + XtRString, COLOR_NORMAL }, { "soundProgram", "soundProgram", XtRString, sizeof(String), XtOffset(AppDataPtr, soundProgram), XtRString, "play" }, @@ -1144,6 +1205,205 @@ XtResource clientResources[] = { { "showButtonBar", "showButtonBar", XtRBoolean, sizeof(Boolean), XtOffset(AppDataPtr, showButtonBar), XtRImmediate, (XtPointer) True }, + { "lowTimeWarningColor", "lowTimeWarningColor", XtRString, + sizeof(String), XtOffset(AppDataPtr, lowTimeWarningColor), + XtRString, COLOR_LOWTIMEWARNING }, + { "lowTimeWarning", "lowTimeWarning", XtRBoolean, + sizeof(Boolean), XtOffset(AppDataPtr, lowTimeWarning), + XtRImmediate, (XtPointer) False }, + {"icsEngineAnalyze", "icsEngineAnalyze", XtRBoolean, /* [DM] icsEngineAnalyze */ + sizeof(Boolean), XtOffset(AppDataPtr, icsEngineAnalyze), + XtRImmediate, (XtPointer) False }, + { "firstScoreAbs", "firstScoreAbs", XtRBoolean, + sizeof(Boolean), XtOffset(AppDataPtr, firstScoreIsAbsolute), + XtRImmediate, (XtPointer) False }, + { "secondScoreAbs", "secondScoreAbs", XtRBoolean, + sizeof(Boolean), XtOffset(AppDataPtr, secondScoreIsAbsolute), + XtRImmediate, (XtPointer) False }, + { "pgnExtendedInfo", "pgnExtendedInfo", XtRBoolean, + sizeof(Boolean), XtOffset(AppDataPtr, saveExtendedInfoInPGN), + XtRImmediate, (XtPointer) False }, + { "hideThinkingFromHuman", "hideThinkingFromHuman", XtRBoolean, + sizeof(Boolean), XtOffset(AppDataPtr, hideThinkingFromHuman), + XtRImmediate, (XtPointer) True }, + { "adjudicateLossThreshold", "adjudicateLossThreshold", XtRInt, + sizeof(int), XtOffset(AppDataPtr, adjudicateLossThreshold), + XtRImmediate, (XtPointer) 0}, + { "adjudicateDrawMoves", "adjudicateDrawMoves", XtRInt, + sizeof(int), XtOffset(AppDataPtr, adjudicateDrawMoves), + XtRImmediate, (XtPointer) 0}, + { "pgnEventHeader", "pgnEventHeader", XtRString, + sizeof(String), XtOffset(AppDataPtr, pgnEventHeader), + XtRImmediate, (XtPointer) "Computer Chess Game" }, + { "defaultFrcPosition", "defaultFrcPositon", XtRInt, + sizeof(int), XtOffset(AppDataPtr, defaultFrcPosition), + XtRImmediate, (XtPointer) -1}, + { "gameListTags", "gameListTags", XtRString, + sizeof(String), XtOffset(AppDataPtr, gameListTags), + XtRImmediate, (XtPointer) GLT_DEFAULT_TAGS }, + + // [HGM] 4.3.xx options + { "boardWidth", "boardWidth", XtRInt, + sizeof(int), XtOffset(AppDataPtr, NrFiles), + XtRImmediate, (XtPointer) -1}, + { "boardHeight", "boardHeight", XtRInt, + sizeof(int), XtOffset(AppDataPtr, NrRanks), + XtRImmediate, (XtPointer) -1}, + { "matchPause", "matchPause", XtRInt, + sizeof(int), XtOffset(AppDataPtr, matchPause), + XtRImmediate, (XtPointer) 10000}, + { "holdingsSize", "holdingsSize", XtRInt, + sizeof(int), XtOffset(AppDataPtr, holdingsSize), + XtRImmediate, (XtPointer) -1}, + { "flipBlack", "flipBlack", XtRBoolean, + sizeof(Boolean), XtOffset(AppDataPtr, upsideDown), + XtRImmediate, (XtPointer) False}, + { "allWhite", "allWhite", XtRBoolean, + sizeof(Boolean), XtOffset(AppDataPtr, allWhite), + XtRImmediate, (XtPointer) False}, + { "pieceToCharTable", "pieceToCharTable", XtRString, + sizeof(String), XtOffset(AppDataPtr, pieceToCharTable), + XtRImmediate, (XtPointer) 0}, + { "alphaRank", "alphaRank", XtRBoolean, + sizeof(Boolean), XtOffset(AppDataPtr, alphaRank), + XtRImmediate, (XtPointer) False}, + { "testClaims", "testClaims", XtRBoolean, + sizeof(Boolean), XtOffset(AppDataPtr, testClaims), + XtRImmediate, (XtPointer) True}, + { "checkMates", "checkMates", XtRBoolean, + sizeof(Boolean), XtOffset(AppDataPtr, checkMates), + XtRImmediate, (XtPointer) True}, + { "materialDraws", "materialDraws", XtRBoolean, + sizeof(Boolean), XtOffset(AppDataPtr, materialDraws), + XtRImmediate, (XtPointer) True}, + { "trivialDraws", "trivialDraws", XtRBoolean, + sizeof(Boolean), XtOffset(AppDataPtr, trivialDraws), + XtRImmediate, (XtPointer) False}, + { "ruleMoves", "ruleMoves", XtRInt, + sizeof(int), XtOffset(AppDataPtr, ruleMoves), + XtRImmediate, (XtPointer) 51}, + { "repeatsToDraw", "repeatsToDraw", XtRInt, + sizeof(int), XtOffset(AppDataPtr, drawRepeats), + XtRImmediate, (XtPointer) 6}, + { "engineDebugOutput", "engineDebugOutput", XtRInt, + sizeof(int), XtOffset(AppDataPtr, engineComments), + XtRImmediate, (XtPointer) 1}, + { "userName", "userName", XtRString, + sizeof(int), XtOffset(AppDataPtr, userName), + XtRImmediate, (XtPointer) 0}, + { "autoKibitz", "autoKibitz", XtRBoolean, + sizeof(Boolean), XtOffset(AppDataPtr, autoKibitz), + XtRImmediate, (XtPointer) False}, + { "firstTimeOdds", "firstTimeOdds", XtRInt, + sizeof(int), XtOffset(AppDataPtr, firstTimeOdds), + XtRImmediate, (XtPointer) 1}, + { "secondTimeOdds", "secondTimeOdds", XtRInt, + sizeof(int), XtOffset(AppDataPtr, secondTimeOdds), + XtRImmediate, (XtPointer) 1}, + { "timeOddsMode", "timeOddsMode", XtRInt, + sizeof(int), XtOffset(AppDataPtr, timeOddsMode), + XtRImmediate, (XtPointer) 0}, + { "firstAccumulateTC", "firstAccumulateTC", XtRInt, + sizeof(int), XtOffset(AppDataPtr, firstAccumulateTC), + XtRImmediate, (XtPointer) 1}, + { "secondAccumulateTC", "secondAccumulateTC", XtRInt, + sizeof(int), XtOffset(AppDataPtr, secondAccumulateTC), + XtRImmediate, (XtPointer) 1}, + { "firstNPS", "firstNPS", XtRInt, + sizeof(int), XtOffset(AppDataPtr, firstNPS), + XtRImmediate, (XtPointer) -1}, + { "secondNPS", "secondNPS", XtRInt, + sizeof(int), XtOffset(AppDataPtr, secondNPS), + XtRImmediate, (XtPointer) -1}, + { "serverMoves", "serverMoves", XtRString, + sizeof(String), XtOffset(AppDataPtr, serverMovesName), + XtRImmediate, (XtPointer) 0}, + { "serverPause", "serverPause", XtRInt, + sizeof(int), XtOffset(AppDataPtr, serverPause), + XtRImmediate, (XtPointer) 0}, + { "suppressLoadMoves", "suppressLoadMoves", XtRBoolean, + sizeof(Boolean), XtOffset(AppDataPtr, suppressLoadMoves), + XtRImmediate, (XtPointer) False}, + { "userName", "userName", XtRString, + sizeof(String), XtOffset(AppDataPtr, userName), + XtRImmediate, (XtPointer) 0}, + { "egtFormats", "egtFormats", XtRString, + sizeof(String), XtOffset(AppDataPtr, egtFormats), + XtRImmediate, (XtPointer) 0}, + { "rewindIndex", "rewindIndex", XtRInt, + sizeof(int), XtOffset(AppDataPtr, rewindIndex), + XtRImmediate, (XtPointer) 0}, + { "sameColorGames", "sameColorGames", XtRInt, + sizeof(int), XtOffset(AppDataPtr, sameColorGames), + XtRImmediate, (XtPointer) 0}, + { "smpCores", "smpCores", XtRInt, + sizeof(int), XtOffset(AppDataPtr, smpCores), + XtRImmediate, (XtPointer) 1}, + { "niceEngines", "niceEngines", XtRInt, + sizeof(int), XtOffset(AppDataPtr, niceEngines), + XtRImmediate, (XtPointer) 0}, + { "nameOfDebugFile", "nameOfDebugFile", XtRString, + sizeof(String), XtOffset(AppDataPtr, nameOfDebugFile), + XtRImmediate, (XtPointer) "xboard.debug"}, + { "engineDebugOutput", "engineDebugOutput", XtRInt, + sizeof(int), XtOffset(AppDataPtr, engineComments), + XtRImmediate, (XtPointer) 1}, + { "noGUI", "noGUI", XtRBoolean, + sizeof(Boolean), XtOffset(AppDataPtr, noGUI), + XtRImmediate, (XtPointer) 0}, + { "firstOptions", "firstOptions", XtRString, + sizeof(String), XtOffset(AppDataPtr, firstOptions), + XtRImmediate, (XtPointer) "" }, + { "secondOptions", "secondOptions", XtRString, + sizeof(String), XtOffset(AppDataPtr, secondOptions), + XtRImmediate, (XtPointer) "" }, + { "firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XtRString, + sizeof(String), XtOffset(AppDataPtr, fenOverride1), + XtRImmediate, (XtPointer) 0 }, + { "secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XtRString, + sizeof(String), XtOffset(AppDataPtr, fenOverride2), + XtRImmediate, (XtPointer) 0 }, + + // [HGM] Winboard_x UCI options + { "firstIsUCI", "firstIsUCI", XtRBoolean, + sizeof(Boolean), XtOffset(AppDataPtr, firstIsUCI), + XtRImmediate, (XtPointer) False}, + { "secondIsUCI", "secondIsUCI", XtRBoolean, + sizeof(Boolean), XtOffset(AppDataPtr, secondIsUCI), + XtRImmediate, (XtPointer) False}, + { "firstHasOwnBookUCI", "firstHasOwnBookUCI", XtRBoolean, + sizeof(Boolean), XtOffset(AppDataPtr, firstHasOwnBookUCI), + XtRImmediate, (XtPointer) True}, + { "secondHasOwnBookUCI", "secondHasOwnBookUCI", XtRBoolean, + sizeof(Boolean), XtOffset(AppDataPtr, secondHasOwnBookUCI), + XtRImmediate, (XtPointer) True}, + { "usePolyglotBook", "usePolyglotBook", XtRBoolean, + sizeof(Boolean), XtOffset(AppDataPtr, usePolyglotBook), + XtRImmediate, (XtPointer) False}, + { "defaultHashSize", "defaultHashSize", XtRInt, + sizeof(int), XtOffset(AppDataPtr, defaultHashSize), + XtRImmediate, (XtPointer) 64}, + { "defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XtRInt, + sizeof(int), XtOffset(AppDataPtr, defaultCacheSizeEGTB), + XtRImmediate, (XtPointer) 4}, + { "polyglotDir", "polyglotDir", XtRString, + sizeof(String), XtOffset(AppDataPtr, polyglotDir), + XtRImmediate, (XtPointer) "." }, + { "polyglotBook", "polyglotBook", XtRString, + sizeof(String), XtOffset(AppDataPtr, polyglotBook), + XtRImmediate, (XtPointer) "" }, + { "defaultPathEGTB", "defaultPathEGTB", XtRString, + sizeof(String), XtOffset(AppDataPtr, defaultPathEGTB), + XtRImmediate, (XtPointer) "/usr/local/share/egtb"}, + { "delayBeforeQuit", "delayBeforeQuit", XtRInt, + sizeof(int), XtOffset(AppDataPtr, delayBeforeQuit), + XtRImmediate, (XtPointer) 0}, + { "delayAfterQuit", "delayAfterQuit", XtRInt, + sizeof(int), XtOffset(AppDataPtr, delayAfterQuit), + XtRImmediate, (XtPointer) 0}, + { "keepAlive", "keepAlive", XtRInt, + sizeof(int), XtOffset(AppDataPtr, keepAlive), + XtRImmediate, (XtPointer) 0}, }; XrmOptionDescRec shellOptions[] = { @@ -1366,6 +1626,7 @@ XrmOptionDescRec shellOptions[] = { { "-zippyVariants", "zippyVariants", XrmoptionSepArg, NULL }, { "-zippyMaxGames", "zippyMaxGames", XrmoptionSepArg, NULL }, { "-zippyReplayTimeout", "zippyReplayTimeout", XrmoptionSepArg, NULL }, + { "-zippyShortGame", "zippyShortGame", XrmoptionSepArg, NULL }, #endif { "-flashCount", "flashCount", XrmoptionSepArg, NULL }, { "-flash", "flashCount", XrmoptionNoArg, "3" }, @@ -1434,6 +1695,83 @@ XrmOptionDescRec shellOptions[] = { { "-showButtonBar", "showButtonBar", XrmoptionSepArg, NULL }, { "-buttons", "showButtonBar", XrmoptionNoArg, "True" }, { "-xbuttons", "showButtonBar", XrmoptionNoArg, "False" }, + { "-lowTimeWarningColor", "lowTimeWarningColor", XrmoptionSepArg, NULL }, + { "-lowTimeWarning", "lowTimeWarning", XrmoptionSepArg, NULL }, + /* [AS,HR] New features */ + { "-firstScoreAbs", "firstScoreAbs", XrmoptionSepArg, NULL }, + { "-secondScoreAbs", "secondScoreAbs", XrmoptionSepArg, NULL }, + { "-pgnExtendedInfo", "pgnExtendedInfo", XrmoptionSepArg, NULL }, + { "-hideThinkingFromHuman", "hideThinkingFromHuman", XrmoptionSepArg, NULL }, + { "-adjudicateLossThreshold", "adjudicateLossThreshold", XrmoptionSepArg, NULL }, + { "-adjudicateDrawMoves", "adjudicateDrawMoves", XrmoptionSepArg, NULL }, + { "-pgnEventHeader", "pgnEventHeader", XrmoptionSepArg, NULL }, + { "-firstIsUCI", "firstIsUCI", XrmoptionSepArg, NULL }, + { "-secondIsUCI", "secondIsUCI", XrmoptionSepArg, NULL }, + { "-fUCI", "firstIsUCI", XrmoptionNoArg, "True" }, + { "-sUCI", "secondIsUCI", XrmoptionNoArg, "True" }, + { "-firstHasOwnBookUCI", "firstHasOwnBookUCI", XrmoptionSepArg, NULL }, + { "-secondHasOwnBookUCI", "secondHasOwnBookUCI", XrmoptionSepArg, NULL }, + { "-fNoOwnBookUCI", "firstHasOwnBookUCI", XrmoptionNoArg, "False" }, + { "-sNoOwnBookUCI", "secondHasOwnBookUCI", XrmoptionNoArg, "False" }, + { "-firstXBook", "firstHasOwnBookUCI", XrmoptionNoArg, "False" }, + { "-secondXBook", "secondHasOwnBookUCI", XrmoptionNoArg, "False" }, + { "-polyglotDir", "polyglotDir", XrmoptionSepArg, NULL }, + { "-usePolyglotBook", "usePolyglotBook", XrmoptionSepArg, NULL }, + { "-polyglotBook", "polyglotBook", XrmoptionSepArg, NULL }, + { "-defaultHashSize", "defaultHashSize", XrmoptionSepArg, NULL }, + { "-defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XrmoptionSepArg, NULL }, + { "-defaultPathEGTB", "defaultPathEGTB", XrmoptionSepArg, NULL }, + { "-defaultFrcPosition", "defaultFrcPosition", XrmoptionSepArg, NULL }, + { "-gameListTags", "gameListTags", XrmoptionSepArg, NULL }, + // [HGM] I am sure AS added many more options, but we have to fish them out, from the list in winboard.c + + /* [HGM,HR] User-selectable board size */ + { "-boardWidth", "boardWidth", XrmoptionSepArg, NULL }, + { "-boardHeight", "boardHeight", XrmoptionSepArg, NULL }, + { "-matchPause", "matchPause", XrmoptionSepArg, NULL }, + + /* [HGM] new arguments of 4.3.xx. All except first three are back-end options, which should work immediately */ + { "-holdingsSize", "holdingsSize", XrmoptionSepArg, NULL }, // requires extensive front-end changes to work + { "-flipBlack", "flipBlack", XrmoptionSepArg, NULL }, // requires front-end changes to work + { "-allWhite", "allWhite", XrmoptionSepArg, NULL }, // requires front-end changes to work + { "-pieceToCharTable", "pieceToCharTable", XrmoptionSepArg, NULL }, + { "-alphaRank", "alphaRank", XrmoptionSepArg, NULL }, + { "-testClaims", "testClaims", XrmoptionSepArg, NULL }, + { "-checkMates", "checkMates", XrmoptionSepArg, NULL }, + { "-materialDraws", "materialDraws", XrmoptionSepArg, NULL }, + { "-trivialDraws", "trivialDraws", XrmoptionSepArg, NULL }, + { "-ruleMoves", "ruleMoves", XrmoptionSepArg, NULL }, + { "-repeatsToDraw", "repeatsToDraw", XrmoptionSepArg, NULL }, + { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL }, + { "-userName", "userName", XrmoptionSepArg, NULL }, + { "-autoKibitz", "autoKibitz", XrmoptionNoArg, "True" }, + { "-firstTimeOdds", "firstTimeOdds", XrmoptionSepArg, NULL }, + { "-secondTimeOdds", "secondTimeOdds", XrmoptionSepArg, NULL }, + { "-timeOddsMode", "timeOddsMode", XrmoptionSepArg, NULL }, + { "-firstAccumulateTC", "firstAccumulateTC", XrmoptionSepArg, NULL }, + { "-secondAccumulateTC", "secondAccumulateTC", XrmoptionSepArg, NULL }, + { "-firstNPS", "firstNPS", XrmoptionSepArg, NULL }, + { "-secondNPS", "secondNPS", XrmoptionSepArg, NULL }, + { "-serverMoves", "serverMoves", XrmoptionSepArg, NULL }, + { "-serverPause", "serverPause", XrmoptionSepArg, NULL }, + { "-suppressLoadMoves", "suppressLoadMoves", XrmoptionSepArg, NULL }, + { "-egtFormats", "egtFormats", XrmoptionSepArg, NULL }, + { "-userName", "userName", XrmoptionSepArg, NULL }, + { "-smpCores", "smpCores", XrmoptionSepArg, NULL }, + { "-sameColorGames", "sameColorGames", XrmoptionSepArg, NULL }, + { "-rewindIndex", "rewindIndex", XrmoptionSepArg, NULL }, + { "-niceEngines", "niceEngines", XrmoptionSepArg, NULL }, + { "-delayBeforeQuit", "delayBeforeQuit", XrmoptionSepArg, NULL }, + { "-delayAfterQuit", "delayAfterQuit", XrmoptionSepArg, NULL }, + { "-nameOfDebugFile", "nameOfDebugFile", XrmoptionSepArg, NULL }, + { "-debugFile", "nameOfDebugFile", XrmoptionSepArg, NULL }, + { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL }, + { "-noGUI", "noGUI", XrmoptionNoArg, "True" }, + { "-firstOptions", "firstOptions", XrmoptionSepArg, NULL }, + { "-secondOptions", "secondOptions", XrmoptionSepArg, NULL }, + { "-firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XrmoptionSepArg, NULL }, + { "-secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XrmoptionSepArg, NULL }, + { "-keepAlive", "keepAlive", XrmoptionSepArg, NULL }, }; @@ -1476,6 +1814,7 @@ XtActionsRec boardActions[] = { { "EditGameProc", EditGameProc }, { "EditPositionProc", EditPositionProc }, { "TrainingProc", EditPositionProc }, + { "EngineOutputProc", EngineOutputProc}, // [HGM] Winboard_x engine-output window { "ShowGameListProc", ShowGameListProc }, { "ShowMoveListProc", HistoryShowProc}, { "EditTagsProc", EditCommentProc }, @@ -1491,6 +1830,9 @@ XtActionsRec boardActions[] = { { "AdjournProc", AdjournProc }, { "AbortProc", AbortProc }, { "ResignProc", ResignProc }, + { "AdjuWhiteProc", AdjuWhiteProc }, + { "AdjuBlackProc", AdjuBlackProc }, + { "AdjuDrawProc", AdjuDrawProc }, { "EnterKeyProc", EnterKeyProc }, { "StopObservingProc", StopObservingProc }, { "StopExaminingProc", StopExaminingProc }, @@ -1521,14 +1863,15 @@ XtActionsRec boardActions[] = { { "IcsAlarmProc", IcsAlarmProc }, { "MoveSoundProc", MoveSoundProc }, { "OldSaveStyleProc", OldSaveStyleProc }, - { "PeriodicUpdatesProc", PeriodicUpdatesProc }, + { "PeriodicUpdatesProc", PeriodicUpdatesProc }, { "PonderNextMoveProc", PonderNextMoveProc }, - { "PopupExitMessageProc", PopupExitMessageProc }, - { "PopupMoveErrorsProc", PopupMoveErrorsProc }, + { "PopupExitMessageProc", PopupExitMessageProc }, + { "PopupMoveErrorsProc", PopupMoveErrorsProc }, { "PremoveProc", PremoveProc }, { "QuietPlayProc", QuietPlayProc }, { "ShowCoordsProc", ShowCoordsProc }, { "ShowThinkingProc", ShowThinkingProc }, + { "HideThinkingProc", HideThinkingProc }, { "TestLegalityProc", TestLegalityProc }, { "InfoProc", InfoProc }, { "ManProc", ManProc }, @@ -1549,8 +1892,15 @@ XtActionsRec boardActions[] = { { "GameListPopDown", (XtActionProc) GameListPopDown }, { "PromotionPopDown", (XtActionProc) PromotionPopDown }, { "HistoryPopDown", (XtActionProc) HistoryPopDown }, + { "EngineOutputPopDown", (XtActionProc) EngineOutputPopDown }, + { "ShufflePopDown", (XtActionProc) ShufflePopDown }, + { "EnginePopDown", (XtActionProc) EnginePopDown }, + { "UciPopDown", (XtActionProc) UciPopDown }, + { "TimeControlPopDown", (XtActionProc) TimeControlPopDown }, + { "NewVariantPopDown", (XtActionProc) NewVariantPopDown }, + { "SettingsPopDown", (XtActionProc) SettingsPopDown }, }; - + char globalTranslations[] = ":R: ResignProc() \n \ :r: ResetProc() \n \ @@ -1589,10 +1939,10 @@ char boardTranslations[] = PieceMenuPopup(menuW) \n \ Any: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD) \ PieceMenuPopup(menuB) \n"; - + char whiteTranslations[] = ": WhiteClock()\n"; char blackTranslations[] = ": BlackClock()\n"; - + char ICSInputTranslations[] = "Return: EnterKeyProc() \n"; @@ -1602,7 +1952,7 @@ String xboardResources[] = { "*errorpopup*translations: #override\\n Return: ErrorPopDown()", NULL }; - + /* Max possible square size */ #define MAXSQSIZE 256 @@ -1620,14 +1970,14 @@ xpm_getsize(name, len, ext) { char *p, *d; char buf[10]; - + if (len < 4) return 0; if ((p=strchr(name, '.')) == NULL || StrCaseCmp(p+1, ext) != 0) return 0; - + p = name + 3; d = buf; @@ -1653,15 +2003,15 @@ xpm_getavail(dirname, ext) if (appData.debugMode) fprintf(stderr, "XPM dir:%s:ext:%s:\n", dirname, ext); - + dir = opendir(dirname); if (!dir) { - fprintf(stderr, "%s: Can't access XPM directory %s\n", + fprintf(stderr, _("%s: Can't access XPM directory %s\n"), programName, dirname); exit(1); } - + while ((ent=readdir(dir)) != NULL) { i = xpm_getsize(ent->d_name, NAMLEN(ent), ext); if (i > 0 && i < MAXSQSIZE) @@ -1680,7 +2030,7 @@ xpm_print_avail(fp, ext) { int i; - fprintf(fp, "Available `%s' sizes:\n", ext); + fprintf(fp, _("Available `%s' sizes:\n"), ext); for (i=1; i 99) /* watch bounds on buf */ return -1; @@ -1777,10 +2128,10 @@ parse_color(str, which) if (*p == ',') { return -1; /* Use default for empty field */ } - + if (which == 2 || isdigit(*p)) return atoi(p); - + while (*p && isalpha(*p)) *(d++) = *(p++); @@ -1792,7 +2143,7 @@ parse_color(str, which) } if (!StrCaseCmp(buf, "default")) return -1; - fprintf(stderr, "%s: unrecognized color %s\n", programName, buf); + fprintf(stderr, _("%s: unrecognized color %s\n"), programName, buf); return -2; } @@ -1802,7 +2153,7 @@ parse_cpair(cc, str) char *str; { if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) { - fprintf(stderr, "%s: can't parse foreground color in `%s'\n", + fprintf(stderr, _("%s: can't parse foreground color in `%s'\n"), programName, str); return -1; } @@ -1823,7 +2174,7 @@ CatchDeleteWindow(Widget w, String procname) { char buf[MSG_SIZ]; XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1); - sprintf(buf, "WM_PROTOCOLS: %s() \n", procname); + snprintf(buf, sizeof(buf), "WM_PROTOCOLS: %s() \n", procname); XtAugmentTranslations(w, XtParseTranslationTable(buf)); } @@ -1837,6 +2188,155 @@ BoardToTop() XtPopup(shellWidget, XtGrabNone); /* Raise if lowered */ } +#ifdef IDSIZES + // eventually, all layout determining code should go into a subroutine, but until then IDSIZE remains undefined +#else +#define BoardSize int +void InitDrawingSizes(BoardSize boardSize, int flags) +{ // [HGM] resize is functional now, but for board format changes only (nr of ranks, files) + Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr; + Arg args[16]; + XtGeometryResult gres; + int i; + + if(!formWidget) return; + + /* + * Enable shell resizing. + */ + shellArgs[0].value = (XtArgVal) &w; + shellArgs[1].value = (XtArgVal) &h; + XtGetValues(shellWidget, shellArgs, 2); + + shellArgs[4].value = 2*w; shellArgs[2].value = 10; + shellArgs[5].value = 2*h; shellArgs[3].value = 10; + XtSetValues(shellWidget, &shellArgs[2], 4); + + XtSetArg(args[0], XtNdefaultDistance, &sep); + XtGetValues(formWidget, args, 1); + + boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap); + boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap); + CreateGrid(); + + XtSetArg(args[0], XtNwidth, boardWidth); + XtSetArg(args[1], XtNheight, boardHeight); + XtSetValues(boardWidget, args, 2); + + timerWidth = (boardWidth - sep) / 2; + XtSetArg(args[0], XtNwidth, timerWidth); + XtSetValues(whiteTimerWidget, args, 1); + XtSetValues(blackTimerWidget, args, 1); + + XawFormDoLayout(formWidget, False); + + if (appData.titleInWindow) { + i = 0; + XtSetArg(args[i], XtNborderWidth, &bor); i++; + XtSetArg(args[i], XtNheight, &h); i++; + XtGetValues(titleWidget, args, i); + if (smallLayout) { + w = boardWidth - 2*bor; + } else { + XtSetArg(args[0], XtNwidth, &w); + XtGetValues(menuBarWidget, args, 1); + w = boardWidth - w - sep - 2*bor - 2; // WIDTH_FUDGE + } + + gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr); + if (gres != XtGeometryYes && appData.debugMode) { + fprintf(stderr, + _("%s: titleWidget geometry error %d %d %d %d %d\n"), + programName, gres, w, h, wr, hr); + } + } + + XawFormDoLayout(formWidget, True); + + /* + * Inhibit shell resizing. + */ + shellArgs[0].value = w = (XtArgVal) boardWidth + marginW; + shellArgs[1].value = h = (XtArgVal) boardHeight + marginH; + shellArgs[4].value = shellArgs[2].value = w; + shellArgs[5].value = shellArgs[3].value = h; + XtSetValues(shellWidget, &shellArgs[0], 6); + + // [HGM] pieces: tailor piece bitmaps to needs of specific variant + // (only for xpm) + if(useImages) { + for(i=0; i<4; i++) { + int p; + for(p=0; p<=(int)WhiteKing; p++) + xpmPieceBitmap[i][p] = xpmPieceBitmap2[i][p]; // defaults + if(gameInfo.variant == VariantShogi) { + xpmPieceBitmap[i][(int)WhiteCannon] = xpmPieceBitmap2[i][(int)WhiteKing+1]; + xpmPieceBitmap[i][(int)WhiteNightrider] = xpmPieceBitmap2[i][(int)WhiteKing+2]; + xpmPieceBitmap[i][(int)WhiteSilver] = xpmPieceBitmap2[i][(int)WhiteKing+3]; + xpmPieceBitmap[i][(int)WhiteGrasshopper] = xpmPieceBitmap2[i][(int)WhiteKing+4]; + xpmPieceBitmap[i][(int)WhiteQueen] = xpmPieceBitmap2[i][(int)WhiteLance]; + } +#ifdef GOTHIC + if(gameInfo.variant == VariantGothic) { + xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteSilver]; + } +#endif +#if !HAVE_LIBXPM + // [HGM] why are thee ximMasks used at all? the ximPieceBitmaps seem to be never used! + for(p=0; p<=(int)WhiteKing; p++) + ximMaskPm[p] = ximMaskPm2[p]; // defaults + if(gameInfo.variant == VariantShogi) { + ximMaskPm[(int)WhiteCannon] = ximMaskPm2[(int)WhiteKing+1]; + ximMaskPm[(int)WhiteNightrider] = ximMaskPm2[(int)WhiteKing+2]; + ximMaskPm[(int)WhiteSilver] = ximMaskPm2[(int)WhiteKing+3]; + ximMaskPm[(int)WhiteGrasshopper] = ximMaskPm2[(int)WhiteKing+4]; + ximMaskPm[(int)WhiteQueen] = ximMaskPm2[(int)WhiteLance]; + } +#ifdef GOTHIC + if(gameInfo.variant == VariantGothic) { + ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[(int)WhiteSilver]; + } +#endif +#endif + } + } else { + for(i=0; i<2; i++) { + int p; + for(p=0; p<=(int)WhiteKing; p++) + pieceBitmap[i][p] = pieceBitmap2[i][p]; // defaults + if(gameInfo.variant == VariantShogi) { + pieceBitmap[i][(int)WhiteCannon] = pieceBitmap2[i][(int)WhiteKing+1]; + pieceBitmap[i][(int)WhiteNightrider] = pieceBitmap2[i][(int)WhiteKing+2]; + pieceBitmap[i][(int)WhiteSilver] = pieceBitmap2[i][(int)WhiteKing+3]; + pieceBitmap[i][(int)WhiteGrasshopper] = pieceBitmap2[i][(int)WhiteKing+4]; + pieceBitmap[i][(int)WhiteQueen] = pieceBitmap2[i][(int)WhiteLance]; + } +#ifdef GOTHIC + if(gameInfo.variant == VariantGothic) { + pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteSilver]; + } +#endif + } + } +#if HAVE_LIBXPM + CreateAnimVars(); +#endif +} +#endif + +void EscapeExpand(char *p, char *q) +{ // [HGM] initstring: routine to shape up string arguments + while(*p++ = *q++) if(p[-1] == '\\') + switch(*q++) { + case 'n': p[-1] = '\n'; break; + case 'r': p[-1] = '\r'; break; + case 't': p[-1] = '\t'; break; + case '\\': p[-1] = '\\'; break; + case 0: *p = 0; return; + default: p[-1] = q[-1]; break; + } +} + int main(argc, argv) int argc; @@ -1845,54 +2345,144 @@ main(argc, argv) int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize; XSetWindowAttributes window_attributes; Arg args[16]; - Dimension timerWidth, boardWidth, w, h, sep, bor, wr, hr; + Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr; XrmValue vFrom, vTo; XtGeometryResult gres; char *p; XrmDatabase xdb; int forceMono = False; +#define INDIRECTION +#ifdef INDIRECTION + // [HGM] before anything else, expand any indirection files amongst options + char *argvCopy[1000]; // 1000 seems enough + char newArgs[10000]; // holds actual characters + int k = 0; + + srandom(time(0)); // [HGM] book: make random truly random + + j = 0; + for(i=0; i= 1000-2) { printf(_("too many arguments\n")); exit(-1); } +//fprintf(stderr, "arg %s\n", argv[i]); + if(argv[i][0] != '@') argvCopy[j++] = argv[i]; else { + char c; + FILE *f = fopen(argv[i]+1, "rb"); + if(f == NULL) { fprintf(stderr, _("ignore %s\n"), argv[i]); continue; } // do not expand non-existing + argvCopy[j++] = newArgs + k; // get ready for first argument from file + while((c = fgetc(f)) != EOF) { // each line of file inserts 1 argument in the list + if(c == '\n') { + if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); } + newArgs[k++] = 0; // terminate current arg + if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); } + argvCopy[j++] = newArgs + k; // get ready for next + } else { + if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); } + newArgs[k++] = c; + } + } + newArgs[k] = 0; + j--; + fclose(f); + } + } + argvCopy[j] = NULL; + argv = argvCopy; + argc = j; +#if 0 + if(appData.debugMode,1) { // OK, appData is not initialized here yet... + for(i=0; i 1) { - fprintf(stderr, "%s: unrecognized argument %s\n", + fprintf(stderr, _("%s: unrecognized argument %s\n"), programName, argv[1]); - exit(2); - } - - if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) { - chessDir = "."; - } else { - if (chdir(chessDir) != 0) { - fprintf(stderr, "%s: can't cd to CHESSDIR: ", programName); - perror(chessDir); - exit(1); + fprintf(stderr, "Recognized options:\n"); + for(i = 0; i < XtNumber(shellOptions); i++) { + j = fprintf(stderr, " %s%s", shellOptions[i].option, + (shellOptions[i].argKind == XrmoptionSepArg + ? " ARG" : "")); + if (i++ < XtNumber(shellOptions)) { + fprintf(stderr, "%*c%s%s\n", 40 - j, ' ', + shellOptions[i].option, + (shellOptions[i].argKind == XrmoptionSepArg + ? " ARG" : "")); + } else { + fprintf(stderr, "\n"); + } } + exit(2); } - + p = getenv("HOME"); if (p == NULL) p = "/tmp"; i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1; gameCopyFilename = (char*) malloc(i); gamePasteFilename = (char*) malloc(i); - sprintf(gameCopyFilename, "%s/.xboard%05uc.pgn", p, getpid()); - sprintf(gamePasteFilename, "%s/.xboard%05up.pgn", p, getpid()); + snprintf(gameCopyFilename,i, "%s/.xboard%05uc.pgn", p, getpid()); + snprintf(gamePasteFilename,i, "%s/.xboard%05up.pgn", p, getpid()); XtGetApplicationResources(shellWidget, (XtPointer) &appData, clientResources, XtNumber(clientResources), NULL, 0); + + { // [HGM] initstring: kludge to fix bad bug. expand '\n' characters in init string and computer string. + static char buf[MSG_SIZ]; + EscapeExpand(buf, appData.initString); + appData.initString = strdup(buf); + EscapeExpand(buf, appData.secondInitString); + appData.secondInitString = strdup(buf); + EscapeExpand(buf, appData.firstComputerString); + appData.firstComputerString = strdup(buf); + EscapeExpand(buf, appData.secondComputerString); + appData.secondComputerString = strdup(buf); + } + + if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) { + chessDir = "."; + } else { + if (chdir(chessDir) != 0) { + fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName); + perror(chessDir); + exit(1); + } + } + + if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) { + /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */ + if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL) { + printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile); + exit(errno); + } + setbuf(debugFP, NULL); + } + + /* [HGM,HR] make sure board size is acceptable */ + if(appData.NrFiles > BOARD_SIZE || + appData.NrRanks > BOARD_SIZE ) + DisplayFatalError(_("Recompile with BOARD_SIZE > 12, to support this size"), 0, 2); + #if !HIGHDRAG /* This feature does not work; animation needs a rewrite */ appData.highlightDragging = FALSE; @@ -1903,15 +2493,31 @@ main(argc, argv) xScreen = DefaultScreen(xDisplay); wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True); + gameInfo.variant = StringToVariant(appData.variant); + InitPosition(FALSE); +#if 0 /* * Determine boardSize */ + gameInfo.boardWidth = gameInfo.boardHeight = 8; // [HGM] boardsize: make sure we start as 8x8 + +//#ifndef IDSIZE + // [HGM] as long as we have not created the possibility to change size while running, start with requested size + gameInfo.boardWidth = appData.NrFiles > 0 ? appData.NrFiles : 8; + gameInfo.boardHeight = appData.NrRanks > 0 ? appData.NrRanks : 8; + gameInfo.holdingsWidth = appData.holdingsSize > 0 ? 2 : 0; +#endif + + +#ifdef IDSIZE + InitDrawingSizes(-1, 0); // [HGM] initsize: make this into a subroutine +#else if (isdigit(appData.boardSize[0])) { i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize, &lineGap, &clockFontPxlSize, &coordFontPxlSize, &fontPxlSize, &smallLayout, &tinyLayout); if (i == 0) { - fprintf(stderr, "%s: bad boardSize syntax %s\n", + fprintf(stderr, _("%s: bad boardSize syntax %s\n"), programName, appData.boardSize); exit(2); } @@ -1947,7 +2553,7 @@ main(argc, argv) while (szd->name != NULL && StrCaseCmp(szd->name, appData.boardSize) != 0) szd++; if (szd->name == NULL) { - fprintf(stderr, "%s: unrecognized boardSize name %s\n", + fprintf(stderr, _("%s: unrecognized boardSize name %s\n"), programName, appData.boardSize); exit(2); } @@ -1965,35 +2571,38 @@ main(argc, argv) if (strlen(appData.pixmapDirectory) > 0) { p = ExpandPathName(appData.pixmapDirectory); if (!p) { - fprintf(stderr, "Error expanding path name \"%s\"\n", + fprintf(stderr, _("Error expanding path name \"%s\"\n"), appData.pixmapDirectory); exit(1); } if (appData.debugMode) { - fprintf(stderr, "XBoard square size (hint): %d\n", squareSize); - fprintf(stderr, "%s fulldir:%s:\n", IMAGE_EXT, p); + fprintf(stderr, _("\ +XBoard square size (hint): %d\n\ +%s fulldir:%s:\n"), squareSize, IMAGE_EXT, p); } squareSize = xpm_closest_to(p, squareSize, IMAGE_EXT); if (appData.debugMode) { - fprintf(stderr, "Closest %s size: %d\n", IMAGE_EXT, squareSize); + fprintf(stderr, _("Closest %s size: %d\n"), IMAGE_EXT, squareSize); } } - - boardWidth = lineGap + BOARD_SIZE * (squareSize + lineGap); + + /* [HR] height treated separately (hacked) */ + boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap); + boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap); if (appData.showJail == 1) { /* Jail on top and bottom */ XtSetArg(boardArgs[1], XtNwidth, boardWidth); XtSetArg(boardArgs[2], XtNheight, - boardWidth + 2*(lineGap + squareSize)); + boardHeight + 2*(lineGap + squareSize)); } else if (appData.showJail == 2) { /* Jail on sides */ XtSetArg(boardArgs[1], XtNwidth, boardWidth + 2*(lineGap + squareSize)); - XtSetArg(boardArgs[2], XtNheight, boardWidth); + XtSetArg(boardArgs[2], XtNheight, boardHeight); } else { /* No jail */ XtSetArg(boardArgs[1], XtNwidth, boardWidth); - XtSetArg(boardArgs[2], XtNheight, boardWidth); + XtSetArg(boardArgs[2], XtNheight, boardHeight); } /* @@ -2006,6 +2615,9 @@ main(argc, argv) coordFontID = XLoadFont(xDisplay, appData.coordFont); coordFontStruct = XQueryFont(xDisplay, coordFontID); appData.font = FindFont(appData.font, fontPxlSize); + countFontID = XLoadFont(xDisplay, appData.coordFont); // [HGM] holdings + countFontStruct = XQueryFont(xDisplay, countFontID); +// appData.font = FindFont(appData.font, fontPxlSize); xdb = XtDatabase(xDisplay); XrmPutStringResource(&xdb, "*font", appData.font); @@ -2087,16 +2699,30 @@ main(argc, argv) } if (forceMono) { - fprintf(stderr, "%s: too few colors available; trying monochrome mode\n", + fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"), programName); + + if (appData.bitmapDirectory == NULL || + appData.bitmapDirectory[0] == NULLCHAR) + appData.bitmapDirectory = DEF_BITMAP_DIR; + } + + if (appData.lowTimeWarning && !appData.monoMode) { + vFrom.addr = (caddr_t) appData.lowTimeWarningColor; + vFrom.size = strlen(appData.lowTimeWarningColor); + XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo); + if (vTo.addr == NULL) + appData.monoMode = True; + else + lowTimeWarningColor = *(Pixel *) vTo.addr; } if (appData.monoMode && appData.debugMode) { - fprintf(stderr, "white pixel = 0x%lx, black pixel = 0x%lx\n", + fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"), (unsigned long) XWhitePixel(xDisplay, xScreen), (unsigned long) XBlackPixel(xDisplay, xScreen)); } - + if (parse_cpair(ColorShout, appData.colorShout) < 0 || parse_cpair(ColorSShout, appData.colorSShout) < 0 || parse_cpair(ColorChannel1, appData.colorChannel1) < 0 || @@ -2110,16 +2736,16 @@ main(argc, argv) { if (appData.colorize) { fprintf(stderr, - "%s: can't parse color names; disabling colorization\n", + _("%s: can't parse color names; disabling colorization\n"), programName); } appData.colorize = FALSE; } textColors[ColorNone].fg = textColors[ColorNone].bg = -1; textColors[ColorNone].attr = 0; - + XtAppAddActions(appContext, boardActions, XtNumber(boardActions)); - + /* * widget hierarchy */ @@ -2140,51 +2766,69 @@ main(argc, argv) formArgs, XtNumber(formArgs)); XtSetArg(args[0], XtNdefaultDistance, &sep); XtGetValues(formWidget, args, 1); - + j = 0; widgetList[j++] = menuBarWidget = CreateMenuBar(menuBar); + XtSetArg(args[0], XtNtop, XtChainTop); + XtSetArg(args[1], XtNbottom, XtChainTop); + XtSetValues(menuBarWidget, args, 2); widgetList[j++] = whiteTimerWidget = XtCreateWidget("whiteTime", labelWidgetClass, formWidget, timerArgs, XtNumber(timerArgs)); XtSetArg(args[0], XtNfont, clockFontStruct); - XtSetValues(whiteTimerWidget, args, 1); - + XtSetArg(args[1], XtNtop, XtChainTop); + XtSetArg(args[2], XtNbottom, XtChainTop); + XtSetValues(whiteTimerWidget, args, 3); + widgetList[j++] = blackTimerWidget = XtCreateWidget("blackTime", labelWidgetClass, formWidget, timerArgs, XtNumber(timerArgs)); XtSetArg(args[0], XtNfont, clockFontStruct); - XtSetValues(blackTimerWidget, args, 1); - + XtSetArg(args[1], XtNtop, XtChainTop); + XtSetArg(args[2], XtNbottom, XtChainTop); + XtSetValues(blackTimerWidget, args, 3); + if (appData.titleInWindow) { - widgetList[j++] = titleWidget = + widgetList[j++] = titleWidget = XtCreateWidget("title", labelWidgetClass, formWidget, titleArgs, XtNumber(titleArgs)); + XtSetArg(args[0], XtNtop, XtChainTop); + XtSetArg(args[1], XtNbottom, XtChainTop); + XtSetValues(titleWidget, args, 2); } if (appData.showButtonBar) { widgetList[j++] = buttonBarWidget = CreateButtonBar(buttonBar); + XtSetArg(args[0], XtNleft, XtChainRight); // [HGM] glue to right window edge + XtSetArg(args[1], XtNright, XtChainRight); // for good run-time sizing + XtSetArg(args[2], XtNtop, XtChainTop); + XtSetArg(args[3], XtNbottom, XtChainTop); + XtSetValues(buttonBarWidget, args, 4); } widgetList[j++] = messageWidget = XtCreateWidget("message", labelWidgetClass, formWidget, messageArgs, XtNumber(messageArgs)); - + XtSetArg(args[0], XtNtop, XtChainTop); + XtSetArg(args[1], XtNbottom, XtChainTop); + XtSetValues(messageWidget, args, 2); + widgetList[j++] = boardWidget = XtCreateWidget("board", widgetClass, formWidget, boardArgs, XtNumber(boardArgs)); XtManageChildren(widgetList, j); - + timerWidth = (boardWidth - sep) / 2; XtSetArg(args[0], XtNwidth, timerWidth); XtSetValues(whiteTimerWidget, args, 1); XtSetValues(blackTimerWidget, args, 1); - + XtSetArg(args[0], XtNbackground, &timerBackgroundPixel); XtSetArg(args[1], XtNforeground, &timerForegroundPixel); XtGetValues(whiteTimerWidget, args, 2); - + if (appData.showButtonBar) { XtSetArg(args[0], XtNbackground, &buttonBackgroundPixel); XtSetArg(args[1], XtNforeground, &buttonForegroundPixel); @@ -2264,7 +2908,11 @@ main(argc, argv) } i = 0; XtSetArg(args[0], XtNfromVert, messageWidget); - XtSetValues(boardWidget, args, 1); + XtSetArg(args[1], XtNtop, XtChainTop); + XtSetArg(args[2], XtNbottom, XtChainBottom); + XtSetArg(args[3], XtNleft, XtChainLeft); + XtSetArg(args[4], XtNright, XtChainRight); + XtSetValues(boardWidget, args, 5); XtRealizeWidget(shellWidget); @@ -2274,6 +2922,7 @@ main(argc, argv) * The value "2" is probably larger than needed. */ XawFormDoLayout(formWidget, False); + #define WIDTH_FUDGE 2 i = 0; XtSetArg(args[i], XtNborderWidth, &bor); i++; @@ -2290,20 +2939,23 @@ main(argc, argv) gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr); if (gres != XtGeometryYes && appData.debugMode) { - fprintf(stderr, "%s: messageWidget geometry error %d %d %d %d %d\n", + fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"), programName, gres, w, h, wr, hr); } - + /* !! Horrible hack to work around bug in XFree86 4.0.1 (X11R6.4.3) */ /* The size used for the child widget in layout lags one resize behind its true size, so we resize a second time, 1 pixel smaller. Yeech! */ w--; gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr); if (gres != XtGeometryYes && appData.debugMode) { - fprintf(stderr, "%s: messageWidget geometry error %d %d %d %d %d\n", + fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"), programName, gres, w, h, wr, hr); } /* !! end hack */ + XtSetArg(args[0], XtNleft, XtChainLeft); // [HGM] glue ends for good run-time sizing + XtSetArg(args[1], XtNright, XtChainRight); + XtSetValues(messageWidget, args, 2); if (appData.titleInWindow) { i = 0; @@ -2321,15 +2973,19 @@ main(argc, argv) gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr); if (gres != XtGeometryYes && appData.debugMode) { fprintf(stderr, - "%s: titleWidget geometry error %d %d %d %d %d\n", + _("%s: titleWidget geometry error %d %d %d %d %d\n"), programName, gres, w, h, wr, hr); } } XawFormDoLayout(formWidget, True); xBoardWindow = XtWindow(boardWidget); - - /* + + // [HGM] it seems the layout code ends here, but perhaps the color stuff is size independent and would + // not need to go into InitDrawingSizes(). +#endif + + /* * Create X checkmark bitmap and initialize option menu checks. */ ReadBitmap(&xMarkPixmap, "checkmark.bm", @@ -2420,19 +3076,19 @@ main(argc, argv) if (appData.periodicUpdates) { XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Periodic Updates"), args, 1); - } + } if (appData.ponderNextMove) { XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Ponder Next Move"), args, 1); - } + } if (appData.popupExitMessage) { XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Popup Exit Message"), args, 1); - } + } if (appData.popupMoveErrors) { XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Popup Move Errors"), args, 1); - } + } if (appData.premove) { XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Premove"), args, 1); @@ -2445,8 +3101,8 @@ main(argc, argv) XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"), args, 1); } - if (appData.showThinking) { - XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Thinking"), + if (appData.hideThinkingFromHuman) { + XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"), args, 1); } if (appData.testLegality) { @@ -2465,14 +3121,14 @@ main(argc, argv) i = 0; XtSetArg(args[i], XtNiconPixmap, iconPixmap); i++; XtSetValues(shellWidget, args, i); - + /* * Create a cursor for the board widget. */ window_attributes.cursor = XCreateFontCursor(xDisplay, XC_hand2); XChangeWindowAttributes(xDisplay, xBoardWindow, CWCursor, &window_attributes); - + /* * Inhibit shell resizing. */ @@ -2482,7 +3138,9 @@ main(argc, argv) shellArgs[4].value = shellArgs[2].value = w; shellArgs[5].value = shellArgs[3].value = h; XtSetValues(shellWidget, &shellArgs[2], 4); - + marginW = w - boardWidth; // [HGM] needed to set new shellWidget size when we resize board + marginH = h - boardHeight; + CatchDeleteWindow(shellWidget, "QuitProc"); CreateGCs(); @@ -2497,13 +3155,13 @@ main(argc, argv) CreateXIMPieces(); /* Create regular pieces */ if (!useImages) CreatePieces(); -#endif +#endif CreatePieceMenus(); if (appData.animate || appData.animateDragging) CreateAnimVars(); - + XtAugmentTranslations(formWidget, XtParseTranslationTable(globalTranslations)); XtAugmentTranslations(boardWidget, @@ -2520,7 +3178,7 @@ main(argc, argv) /* end why */ InitBackEnd2(); - + if (errorExitStatus == -1) { if (appData.icsActive) { /* We now wait until we see "login:" from the ICS before @@ -2535,8 +3193,11 @@ main(argc, argv) signal(SIGUSR1, CmailSigHandler); } } + gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes() + InitPosition(TRUE); XtAppMainLoop(appContext); + if (appData.debugMode) fclose(debugFP); // [DM] debug return 0; } @@ -2650,14 +3311,14 @@ Enables icsEnables[] = { { "menuHelp.Hint", False }, { "menuHelp.Book", False }, { "menuStep.Move Now", False }, - { "menuOptions.Periodic Updates", False }, - { "menuOptions.Show Thinking", False }, + { "menuOptions.Periodic Updates", False }, + { "menuOptions.Hide Thinking", False }, { "menuOptions.Ponder Next Move", False }, #endif { NULL, False } }; -Enables ncpEnables[] = { +Enables ncpEnables[] = { { "menuFile.Mail Move", False }, { "menuFile.Reload CMail Message", False }, { "menuMode.Machine White", False }, @@ -2680,15 +3341,15 @@ Enables ncpEnables[] = { { "menuOptions.ICS Alarm", False }, { "menuOptions.Move Sound", False }, { "menuOptions.Quiet Play", False }, - { "menuOptions.Show Thinking", False }, - { "menuOptions.Periodic Updates", False }, + { "menuOptions.Hide Thinking", False }, + { "menuOptions.Periodic Updates", False }, { "menuOptions.Ponder Next Move", False }, { "menuHelp.Hint", False }, { "menuHelp.Book", False }, { NULL, False } }; -Enables gnuEnables[] = { +Enables gnuEnables[] = { { "menuMode.ICS Client", False }, { "menuMode.ICS Input Box", False }, { "menuAction.Accept", False }, @@ -2714,7 +3375,7 @@ Enables gnuEnables[] = { { NULL, False } }; -Enables cmailEnables[] = { +Enables cmailEnables[] = { { "Action", True }, { "menuAction.Call Flag", False }, { "menuAction.Draw", True }, @@ -2727,7 +3388,7 @@ Enables cmailEnables[] = { { NULL, False } }; -Enables trainingOnEnables[] = { +Enables trainingOnEnables[] = { { "menuMode.Edit Comment", False }, { "menuMode.Pause", False }, { "menuStep.Forward", False }, @@ -2739,7 +3400,7 @@ Enables trainingOnEnables[] = { { NULL, False } }; -Enables trainingOffEnables[] = { +Enables trainingOffEnables[] = { { "menuMode.Edit Comment", True }, { "menuMode.Pause", True }, { "menuStep.Forward", True }, @@ -2790,6 +3451,11 @@ Enables userThinkingEnables[] = { void SetICSMode() { SetMenuEnables(icsEnables); + +#ifdef ZIPPY + if (appData.zippyPlay && !appData.noChessProgram) /* [DM] icsEngineAnalyze */ + XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True); +#endif } void @@ -2859,7 +3525,7 @@ SetMachineThinkingEnables() * Find a font that matches "pattern" that is as close as * possible to the targetPxlSize. Prefer fonts that are k * pixels smaller to fonts that are k pixels larger. The - * pattern must be in the X Consortium standard format, + * pattern must be in the X Consortium standard format, * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*". * The return value should be freed with XtFree when no * longer needed. @@ -2871,12 +3537,40 @@ char *FindFont(pattern, targetPxlSize) char **fonts, *p, *best, *scalable, *scalableTail; int i, j, nfonts, minerr, err, pxlSize; +#ifdef ENABLE_NLS + char **missing_list; + int missing_count; + char *def_string, *base_fnt_lst, strInt[3]; + XFontSet fntSet; + XFontStruct **fnt_list; + + base_fnt_lst = calloc(1, strlen(pattern) + 3); + sprintf(strInt, "%d", targetPxlSize); + p = strstr(pattern, "--"); + strncpy(base_fnt_lst, pattern, p - pattern + 2); + strcat(base_fnt_lst, strInt); + strcat(base_fnt_lst, strchr(p + 2, '-')); + + if ((fntSet = XCreateFontSet(xDisplay, + base_fnt_lst, + &missing_list, + &missing_count, + &def_string)) == NULL) { + + fprintf(stderr, _("Unable to create font set.\n")); + exit (2); + } + + nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts); +#else fonts = XListFonts(xDisplay, pattern, 999999, &nfonts); if (nfonts < 1) { - fprintf(stderr, "%s: no fonts match pattern %s\n", + fprintf(stderr, _("%s: no fonts match pattern %s\n"), programName, pattern); exit(2); } +#endif + best = fonts[0]; scalable = NULL; minerr = 999999; @@ -2914,10 +3608,16 @@ char *FindFont(pattern, targetPxlSize) strcpy(p, best); } if (appData.debugMode) { - fprintf(debugFP, "resolved %s at pixel size %d\n to %s\n", + fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"), pattern, targetPxlSize, p); } - XFreeFontNames(fonts); +#ifdef ENABLE_NLS + if (missing_count > 0) + XFreeStringList(missing_list); + XFreeFontSet(xDisplay, fntSet); +#else + XFreeFontNames(fonts); +#endif return p; } @@ -2927,29 +3627,35 @@ void CreateGCs() | GCBackground | GCFunction | GCPlaneMask; XGCValues gc_values; GC copyInvertedGC; - + gc_values.plane_mask = AllPlanes; gc_values.line_width = lineGap; gc_values.line_style = LineSolid; gc_values.function = GXcopy; - + gc_values.foreground = XBlackPixel(xDisplay, xScreen); gc_values.background = XBlackPixel(xDisplay, xScreen); lineGC = XtGetGC(shellWidget, value_mask, &gc_values); - + gc_values.foreground = XBlackPixel(xDisplay, xScreen); gc_values.background = XWhitePixel(xDisplay, xScreen); coordGC = XtGetGC(shellWidget, value_mask, &gc_values); XSetFont(xDisplay, coordGC, coordFontID); - + + // [HGM] make font for holdings counts (white on black0 + gc_values.foreground = XWhitePixel(xDisplay, xScreen); + gc_values.background = XBlackPixel(xDisplay, xScreen); + countGC = XtGetGC(shellWidget, value_mask, &gc_values); + XSetFont(xDisplay, countGC, countFontID); + if (appData.monoMode) { gc_values.foreground = XWhitePixel(xDisplay, xScreen); gc_values.background = XWhitePixel(xDisplay, xScreen); - highlineGC = XtGetGC(shellWidget, value_mask, &gc_values); + highlineGC = XtGetGC(shellWidget, value_mask, &gc_values); gc_values.foreground = XWhitePixel(xDisplay, xScreen); gc_values.background = XBlackPixel(xDisplay, xScreen); - lightSquareGC = wbPieceGC + lightSquareGC = wbPieceGC = XtGetGC(shellWidget, value_mask, &gc_values); gc_values.foreground = XBlackPixel(xDisplay, xScreen); @@ -2973,16 +3679,16 @@ void CreateGCs() } else { gc_values.foreground = highlightSquareColor; gc_values.background = highlightSquareColor; - highlineGC = XtGetGC(shellWidget, value_mask, &gc_values); + highlineGC = XtGetGC(shellWidget, value_mask, &gc_values); gc_values.foreground = premoveHighlightColor; gc_values.background = premoveHighlightColor; - prelineGC = XtGetGC(shellWidget, value_mask, &gc_values); + prelineGC = XtGetGC(shellWidget, value_mask, &gc_values); gc_values.foreground = lightSquareColor; gc_values.background = darkSquareColor; lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values); - + gc_values.foreground = darkSquareColor; gc_values.background = lightSquareColor; darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values); @@ -2994,19 +3700,19 @@ void CreateGCs() gc_values.foreground = whitePieceColor; gc_values.background = darkSquareColor; wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values); - + gc_values.foreground = whitePieceColor; gc_values.background = lightSquareColor; wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values); - + gc_values.foreground = whitePieceColor; gc_values.background = jailSquareColor; wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values); - + gc_values.foreground = blackPieceColor; gc_values.background = darkSquareColor; bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values); - + gc_values.foreground = blackPieceColor; gc_values.background = lightSquareColor; blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values); @@ -3032,34 +3738,34 @@ void loadXIM(xim, xmask, filename, dest, mask) fp = fopen(filename, "rb"); if (!fp) { - fprintf(stderr, "%s: error loading XIM!\n", programName); + fprintf(stderr, _("%s: error loading XIM!\n"), programName); exit(1); } - + w = fgetc(fp); h = fgetc(fp); - + for (y=0; ydepth); XPutImage(xDisplay, *dest, lightSquareGC, xim, - 0, 0, 0, 0, w, h); + 0, 0, 0, 0, w, h); - /* create Pixmap of clipmask + /* create Pixmap of clipmask Note: We assume the white/black pieces have the same outline, so we make only 6 masks. This is okay since the XPM clipmask routines do the same. */ @@ -3082,7 +3788,7 @@ void loadXIM(xim, xmask, filename, dest, mask) temp = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay), w, h, xim->depth); XPutImage(xDisplay, temp, lightSquareGC, xmask, - 0, 0, 0, 0, w, h); + 0, 0, 0, 0, w, h); /* now create the 1-bit version */ *mask = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay), @@ -3092,14 +3798,17 @@ void loadXIM(xim, xmask, filename, dest, mask) values.background = 0; /* Don't use XtGetGC, not read only */ - maskGC = XCreateGC(xDisplay, *mask, + maskGC = XCreateGC(xDisplay, *mask, GCForeground | GCBackground, &values); - XCopyPlane(xDisplay, temp, *mask, maskGC, + XCopyPlane(xDisplay, temp, *mask, maskGC, 0, 0, squareSize, squareSize, 0, 0, 1); XFreePixmap(xDisplay, temp); } } + +char pieceBitmapNames[] = "pnbrqfeacwmohijgdvlsukpnsl"; + void CreateXIMPieces() { int piece, kind; @@ -3114,7 +3823,7 @@ void CreateXIMPieces() Not sure if needed, but can't hurt */ XSynchronize(xDisplay, True); /* Work-around for xlib/xt buffering bug */ - + /* temp needed by loadXIM() */ ximtemp = XGetImage(xDisplay, DefaultRootWindow(xDisplay), 0, 0, ss, ss, AllPlanes, XYPixmap); @@ -3124,60 +3833,63 @@ void CreateXIMPieces() } else { useImages = 1; if (appData.monoMode) { - DisplayFatalError("XIM pieces cannot be used in monochrome mode", + DisplayFatalError(_("XIM pieces cannot be used in monochrome mode"), 0, 2); ExitEvent(2); } - fprintf(stderr, "\nLoading XIMs...\n"); + fprintf(stderr, _("\nLoading XIMs...\n")); /* Load pieces */ - for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) { + for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) { fprintf(stderr, "%d", piece+1); for (kind=0; kind<4; kind++) { fprintf(stderr, "."); - sprintf(buf, "%s/%c%s%u.xim", + snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xim", ExpandPathName(appData.pixmapDirectory), - ToLower(PieceToChar((ChessSquare)piece)), + piece <= (int) WhiteKing ? "" : "w", + pieceBitmapNames[piece], ximkind[kind], ss); ximPieceBitmap[kind][piece] = XGetImage(xDisplay, DefaultRootWindow(xDisplay), 0, 0, ss, ss, AllPlanes, XYPixmap); if (appData.debugMode) - fprintf(stderr, "(File:%s:) ", buf); - loadXIM(ximPieceBitmap[kind][piece], + fprintf(stderr, _("(File:%s:) "), buf); + loadXIM(ximPieceBitmap[kind][piece], ximtemp, buf, - &(xpmPieceBitmap[kind][piece]), - &(ximMaskPm[piece%6])); + &(xpmPieceBitmap2[kind][piece]), + &(ximMaskPm2[piece])); + if(piece <= (int)WhiteKing) + xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece]; } fprintf(stderr," "); } /* Load light and dark squares */ - /* If the LSQ and DSQ pieces don't exist, we will + /* If the LSQ and DSQ pieces don't exist, we will draw them with solid squares. */ - sprintf(buf, "%s/lsq%u.xim", ExpandPathName(appData.pixmapDirectory), ss); + snprintf(buf,sizeof(buf), "%s/lsq%u.xim", ExpandPathName(appData.pixmapDirectory), ss); if (access(buf, 0) != 0) { useImageSqs = 0; } else { useImageSqs = 1; - fprintf(stderr, "light square "); - ximLightSquare= + fprintf(stderr, _("light square ")); + ximLightSquare= XGetImage(xDisplay, DefaultRootWindow(xDisplay), 0, 0, ss, ss, AllPlanes, XYPixmap); if (appData.debugMode) - fprintf(stderr, "(File:%s:) ", buf); + fprintf(stderr, _("(File:%s:) "), buf); loadXIM(ximLightSquare, NULL, buf, &xpmLightSquare, NULL); - fprintf(stderr, "dark square "); - sprintf(buf, "%s/dsq%u.xim", + fprintf(stderr, _("dark square ")); + snprintf(buf,sizeof(buf), "%s/dsq%u.xim", ExpandPathName(appData.pixmapDirectory), ss); if (appData.debugMode) - fprintf(stderr, "(File:%s:) ", buf); - ximDarkSquare= + fprintf(stderr, _("(File:%s:) "), buf); + ximDarkSquare= XGetImage(xDisplay, DefaultRootWindow(xDisplay), 0, 0, ss, ss, AllPlanes, XYPixmap); loadXIM(ximDarkSquare, NULL, buf, &xpmDarkSquare, NULL); xpmJailSquare = xpmLightSquare; } - fprintf(stderr, "Done.\n"); + fprintf(stderr, _("Done.\n")); } XSynchronize(xDisplay, False); /* Work-around for xlib/xt buffering bug */ } @@ -3195,15 +3907,15 @@ void CreateXPMPieces() #if 0 /* Apparently some versions of Xpm don't define XpmFormat at all --tpm */ if (appData.debugMode) { - fprintf(stderr, "XPM Library Version: %d.%d%c\n", + fprintf(stderr, "XPM Library Version: %d.%d%c\n", XpmFormat, XpmVersion, (char)('a' + XpmRevision - 1)); } #endif - + /* The XSynchronize calls were copied from CreatePieces. Not sure if needed, but can't hurt */ XSynchronize(xDisplay, True); /* Work-around for xlib/xt buffering bug */ - + /* Setup translations so piece colors match square colors */ symbols[0].name = "light_piece"; symbols[0].value = appData.whitePieceColor; @@ -3219,7 +3931,7 @@ void CreateXPMPieces() attr.numsymbols = 4; if (appData.monoMode) { - DisplayFatalError("XPM pieces cannot be used in monochrome mode", + DisplayFatalError(_("XPM pieces cannot be used in monochrome mode"), 0, 2); ExitEvent(2); } @@ -3229,83 +3941,102 @@ void CreateXPMPieces() /* Load pieces */ while (pieces->size != squareSize && pieces->size) pieces++; if (!pieces->size) { - fprintf(stderr, "No builtin XPM pieces of size %d\n", squareSize); + fprintf(stderr, _("No builtin XPM pieces of size %d\n"), squareSize); exit(1); } - for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) { + for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) { for (kind=0; kind<4; kind++) { if ((r=XpmCreatePixmapFromData(xDisplay, xBoardWindow, pieces->xpm[piece][kind], - &(xpmPieceBitmap[kind][piece]), + &(xpmPieceBitmap2[kind][piece]), NULL, &attr)) != 0) { - fprintf(stderr, "Error %d loading XPM image \"%s\"\n", + fprintf(stderr, _("Error %d loading XPM image \"%s\"\n"), r, buf); - exit(1); - } - } + exit(1); + } + if(piece <= (int) WhiteKing) + xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece]; + } } useImageSqs = 0; xpmJailSquare = xpmLightSquare; } else { useImages = 1; - - fprintf(stderr, "\nLoading XPMs...\n"); + + fprintf(stderr, _("\nLoading XPMs...\n")); /* Load pieces */ - for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) { + for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) { fprintf(stderr, "%d ", piece+1); for (kind=0; kind<4; kind++) { - sprintf(buf, "%s/%c%s%u.xpm", + snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xpm", ExpandPathName(appData.pixmapDirectory), - ToLower(PieceToChar((ChessSquare)piece)), + piece > (int) WhiteKing ? "w" : "", + pieceBitmapNames[piece], xpmkind[kind], ss); if (appData.debugMode) { - fprintf(stderr, "(File:%s:) ", buf); + fprintf(stderr, _("(File:%s:) "), buf); } if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf, - &(xpmPieceBitmap[kind][piece]), + &(xpmPieceBitmap2[kind][piece]), NULL, &attr)) != 0) { - fprintf(stderr, "Error %d loading XPM file \"%s\"\n", - r, buf); - exit(1); - } - } + if(piece != (int)WhiteKing && piece > (int)WhiteQueen) { + // [HGM] missing: read of unorthodox piece failed; substitute King. + snprintf(buf, sizeof(buf), "%s/k%s%u.xpm", + ExpandPathName(appData.pixmapDirectory), + xpmkind[kind], ss); + if (appData.debugMode) { + fprintf(stderr, _("(Replace by File:%s:) "), buf); + } + r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf, + &(xpmPieceBitmap2[kind][piece]), + NULL, &attr); + } + if (r != 0) { + fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), + r, buf); + exit(1); + } + } + if(piece <= (int) WhiteKing) + xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece]; + } } /* Load light and dark squares */ - /* If the LSQ and DSQ pieces don't exist, we will + /* If the LSQ and DSQ pieces don't exist, we will draw them with solid squares. */ - fprintf(stderr, "light square "); - sprintf(buf, "%s/lsq%u.xpm", ExpandPathName(appData.pixmapDirectory), ss); + fprintf(stderr, _("light square ")); + snprintf(buf, sizeof(buf), "%s/lsq%u.xpm", ExpandPathName(appData.pixmapDirectory), ss); if (access(buf, 0) != 0) { useImageSqs = 0; } else { useImageSqs = 1; if (appData.debugMode) - fprintf(stderr, "(File:%s:) ", buf); + fprintf(stderr, _("(File:%s:) "), buf); if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf, &xpmLightSquare, NULL, &attr)) != 0) { - fprintf(stderr, "Error %d loading XPM file \"%s\"\n", r, buf); + fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf); exit(1); } - fprintf(stderr, "dark square "); - sprintf(buf, "%s/dsq%u.xpm", + fprintf(stderr, _("dark square ")); + snprintf(buf, sizeof(buf), "%s/dsq%u.xpm", ExpandPathName(appData.pixmapDirectory), ss); if (appData.debugMode) { - fprintf(stderr, "(File:%s:) ", buf); + fprintf(stderr, _("(File:%s:) "), buf); } if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf, &xpmDarkSquare, NULL, &attr)) != 0) { - fprintf(stderr, "Error %d loading XPM file \"%s\"\n", r, buf); + fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf); exit(1); } } xpmJailSquare = xpmLightSquare; - fprintf(stderr, "Done.\n"); + fprintf(stderr, _("Done.\n")); } XSynchronize(xDisplay, False); /* Work-around for xlib/xt - buffering bug */ + buffering bug */ } #endif /* HAVE_LIBXPM */ @@ -3316,18 +4047,21 @@ void CreatePieces() int piece, kind; char buf[MSG_SIZ]; u_int ss = squareSize; - + XSynchronize(xDisplay, True); /* Work-around for xlib/xt buffering bug */ for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) { - for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) { - sprintf(buf, "%c%u%c.bm", ToLower(PieceToChar((ChessSquare)piece)), + for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) { + sprintf(buf, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "", + pieceBitmapNames[piece], ss, kind == SOLID ? 's' : 'o'); - ReadBitmap(&pieceBitmap[kind][piece], buf, NULL, ss, ss); + ReadBitmap(&pieceBitmap2[kind][piece], buf, NULL, ss, ss); + if(piece <= (int)WhiteKing) + pieceBitmap[kind][piece] = pieceBitmap2[kind][piece]; } } - + XSynchronize(xDisplay, False); /* Work-around for xlib/xt buffering bug */ } @@ -3339,21 +4073,24 @@ void CreatePieces() int piece, kind; char buf[MSG_SIZ]; u_int ss = squareSize; - + XSynchronize(xDisplay, True); /* Work-around for xlib/xt buffering bug */ while (bib->squareSize != ss && bib->squareSize != 0) bib++; for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) { - for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) { - sprintf(buf, "%c%u%c.bm", ToLower(PieceToChar((ChessSquare)piece)), + for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) { + sprintf(buf, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "", + pieceBitmapNames[piece], ss, kind == SOLID ? 's' : 'o'); - ReadBitmap(&pieceBitmap[kind][piece], buf, + ReadBitmap(&pieceBitmap2[kind][piece], buf, bib->bits[kind][piece], ss, ss); + if(piece <= (int)WhiteKing) + pieceBitmap[kind][piece] = pieceBitmap2[kind][piece]; } } - + XSynchronize(xDisplay, False); /* Work-around for xlib/xt buffering bug */ } @@ -3369,44 +4106,48 @@ void ReadBitmap(pm, name, bits, wreq, hreq) u_int w, h; int errcode; char msg[MSG_SIZ], fullname[MSG_SIZ]; - + if (*appData.bitmapDirectory != NULLCHAR) { strcpy(fullname, appData.bitmapDirectory); strcat(fullname, "/"); strcat(fullname, name); errcode = XReadBitmapFile(xDisplay, xBoardWindow, fullname, &w, &h, pm, &x_hot, &y_hot); + fprintf(stderr, "load %s\n", name); if (errcode != BitmapSuccess) { switch (errcode) { case BitmapOpenFailed: - sprintf(msg, "Can't open bitmap file %s", fullname); + snprintf(msg, sizeof(msg), _("Can't open bitmap file %s"), fullname); break; case BitmapFileInvalid: - sprintf(msg, "Invalid bitmap in file %s", fullname); + snprintf(msg, sizeof(msg), _("Invalid bitmap in file %s"), fullname); break; case BitmapNoMemory: - sprintf(msg, "Ran out of memory reading bitmap file %s", + snprintf(msg, sizeof(msg), _("Ran out of memory reading bitmap file %s"), fullname); break; default: - sprintf(msg, "Unknown XReadBitmapFile error %d on file %s", + snprintf(msg, sizeof(msg), _("Unknown XReadBitmapFile error %d on file %s"), errcode, fullname); break; } - fprintf(stderr, "%s: %s...using built-in\n", + fprintf(stderr, _("%s: %s...using built-in\n"), programName, msg); } else if (w != wreq || h != hreq) { fprintf(stderr, - "%s: Bitmap %s is %dx%d, not %dx%d...using built-in\n", + _("%s: Bitmap %s is %dx%d, not %dx%d...using built-in\n"), programName, fullname, w, h, wreq, hreq); } else { return; } } if (bits == NULL) { - fprintf(stderr, "%s: No built-in bitmap for %s; giving up\n", +#if 0 + fprintf(stderr, _("%s: No built-in bitmap for %s; giving up\n"), programName, name); exit(1); +#endif + ; // [HGM] bitmaps: make it non-fatal if we have no bitmap; } else { *pm = XCreateBitmapFromData(xDisplay, xBoardWindow, (char *) bits, wreq, hreq); @@ -3415,22 +4156,26 @@ void ReadBitmap(pm, name, bits, wreq, hreq) void CreateGrid() { - int i; - + int i, j; + if (lineGap == 0) return; - for (i = 0; i < BOARD_SIZE + 1; i++) { - gridSegments[i].x1 = 0; - gridSegments[i].x2 = - lineGap + BOARD_SIZE * (squareSize + lineGap); - gridSegments[i].y1 = gridSegments[i].y2 - = lineGap / 2 + (i * (squareSize + lineGap)); - gridSegments[i + BOARD_SIZE + 1].y1 = 0; - gridSegments[i + BOARD_SIZE + 1].y2 = - BOARD_SIZE * (squareSize + lineGap); - gridSegments[i + BOARD_SIZE + 1].x1 = - gridSegments[i + BOARD_SIZE + 1].x2 - = lineGap / 2 + (i * (squareSize + lineGap)); + /* [HR] Split this into 2 loops for non-square boards. */ + + for (i = 0; i < BOARD_HEIGHT + 1; i++) { + gridSegments[i].x1 = 0; + gridSegments[i].x2 = + lineGap + BOARD_WIDTH * (squareSize + lineGap); + gridSegments[i].y1 = gridSegments[i].y2 + = lineGap / 2 + (i * (squareSize + lineGap)); + } + + for (j = 0; j < BOARD_WIDTH + 1; j++) { + gridSegments[j + i].y1 = 0; + gridSegments[j + i].y2 = + lineGap + BOARD_HEIGHT * (squareSize + lineGap); + gridSegments[j + i].x1 = gridSegments[j + i].x2 + = lineGap / 2 + (j * (squareSize + lineGap)); } } @@ -3465,15 +4210,16 @@ void CreateMenuBarPopup(parent, name, mb) entry = XtCreateManagedWidget(mi->string, smeLineObjectClass, menu, args, j); } else { + XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string))); entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass, - menu, args, j); + menu, args, j+1); XtAddCallback(entry, XtNcallback, (XtCallbackProc) MenuBarSelect, (caddr_t) mi->proc); } mi++; } -} +} Widget CreateMenuBar(mb) Menu *mb; @@ -3497,10 +4243,14 @@ Widget CreateMenuBar(mb) XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++; if (tinyLayout) { char shortName[2]; - shortName[0] = mb->name[0]; + shortName[0] = _(mb->name)[0]; shortName[1] = NULLCHAR; XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++; } + else { + XtSetArg(args[j], XtNlabel, XtNewString(_(mb->name))); j++; + } + XtSetArg(args[j], XtNborderWidth, 0); j++; anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass, menuBar, args, j); @@ -3533,6 +4283,7 @@ Widget CreateButtonBar(mi) XtSetArg(args[j], XtNinternalWidth, 2); j++; XtSetArg(args[j], XtNborderWidth, 0); j++; } + XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string))); j++; button = XtCreateManagedWidget(mi->string, commandWidgetClass, buttonBar, args, j); XtAddCallback(button, XtNcallback, @@ -3541,7 +4292,7 @@ Widget CreateButtonBar(mi) mi++; } return buttonBar; -} +} Widget CreatePieceMenu(name, color) @@ -3555,16 +4306,17 @@ CreatePieceMenu(name, color) menu = XtCreatePopupShell(name, simpleMenuWidgetClass, boardWidget, args, 0); - + for (i = 0; i < PIECE_MENU_SIZE; i++) { String item = pieceMenuStrings[color][i]; - + if (strcmp(item, "----") == 0) { entry = XtCreateManagedWidget(item, smeLineObjectClass, menu, NULL, 0); } else { + XtSetArg(args[0], XtNlabel, XtNewString(_(item))); entry = XtCreateManagedWidget(item, smeBSBObjectClass, - menu, NULL, 0); + menu, args, 1); selection = pieceMenuTranslation[color][i]; XtAddCallback(entry, XtNcallback, (XtCallbackProc) PieceMenuSelect, @@ -3588,30 +4340,31 @@ CreatePieceMenus() whitePieceMenu = CreatePieceMenu("menuW", 0); blackPieceMenu = CreatePieceMenu("menuB", 1); - + XtRegisterGrabAction(PieceMenuPopup, True, (unsigned)(ButtonPressMask|ButtonReleaseMask), GrabModeAsync, GrabModeAsync); - XtSetArg(args[0], XtNlabel, "Drop"); + XtSetArg(args[0], XtNlabel, _("Drop")); dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass, boardWidget, args, 1); for (i = 0; i < DROP_MENU_SIZE; i++) { String item = dropMenuStrings[i]; - + if (strcmp(item, "----") == 0) { entry = XtCreateManagedWidget(item, smeLineObjectClass, dropMenu, NULL, 0); } else { + XtSetArg(args[0], XtNlabel, XtNewString(_(item))); entry = XtCreateManagedWidget(item, smeBSBObjectClass, - dropMenu, NULL, 0); + dropMenu, args, 1); selection = dropMenuTranslation[i]; XtAddCallback(entry, XtNcallback, (XtCallbackProc) DropMenuSelect, (caddr_t) selection); } } -} +} void SetupDropMenu() { @@ -3630,7 +4383,7 @@ void SetupDropMenu() && !appData.icsActive)); count = 0; while (p && *p++ == dmEnables[i].piece) count++; - sprintf(label, "%s %d", dmEnables[i].widget, count); + snprintf(label, sizeof(label), "%s %d", dmEnables[i].widget, count); j = 0; XtSetArg(args[j], XtNlabel, label); j++; XtSetValues(entry, args, j); @@ -3665,17 +4418,17 @@ void PieceMenuPopup(w, event, params, num_params) default: return; } - - if (((pmFromX = EventToSquare(event->xbutton.x, BOARD_SIZE)) < 0) || - ((pmFromY = EventToSquare(event->xbutton.y, BOARD_SIZE)) < 0)) { + + if (((pmFromX = EventToSquare(event->xbutton.x, BOARD_WIDTH)) < 0) || + ((pmFromY = EventToSquare(event->xbutton.y, BOARD_HEIGHT)) < 0)) { pmFromX = pmFromY = -1; return; } if (flipView) - pmFromX = BOARD_SIZE - 1 - pmFromX; + pmFromX = BOARD_WIDTH - 1 - pmFromX; else - pmFromY = BOARD_SIZE - 1 - pmFromY; - + pmFromY = BOARD_HEIGHT - 1 - pmFromY; + XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu)); } @@ -3731,7 +4484,7 @@ void BlackClock(w, event, prms, nprms) int EventToSquare(x, limit) int x; { - if (x <= 0) + if (x <= 0) return -2; if (x < lineGap) return -1; @@ -3757,17 +4510,17 @@ static void drawHighlight(file, rank, gc) int x, y; if (lineGap == 0 || appData.blindfold) return; - + if (flipView) { - x = lineGap/2 + ((BOARD_SIZE-1)-file) * + x = lineGap/2 + ((BOARD_WIDTH-1)-file) * (squareSize + lineGap); y = lineGap/2 + rank * (squareSize + lineGap); } else { x = lineGap/2 + file * (squareSize + lineGap); - y = lineGap/2 + ((BOARD_SIZE-1)-rank) * + y = lineGap/2 + ((BOARD_HEIGHT-1)-rank) * (squareSize + lineGap); } - + XDrawRectangle(xDisplay, xBoardWindow, gc, x, y, squareSize+lineGap, squareSize+lineGap); } @@ -3939,6 +4692,7 @@ static void colorDrawPiece(piece, square_color, x, y, dest) int square_color, x, y; Drawable dest; { + if(pieceToSolid(piece) == NULL) return; // [HGM] bitmaps: make it non-fatal if we have no bitmap; switch (square_color) { case 1: /* light */ XCopyPlane(xDisplay, *pieceToSolid(piece), @@ -3991,7 +4745,7 @@ static void colorDrawPieceImage(piece, square_color, x, y, dest) } XCopyArea(xDisplay, xpmPieceBitmap[kind][piece], dest, wlPieceGC, 0, 0, - squareSize, squareSize, x, y); + squareSize, squareSize, x, y); } typedef void (*DrawFunc)(); @@ -4012,6 +4766,32 @@ DrawFunc ChooseDrawFunc() } } +/* [HR] determine square color depending on chess variant. */ +static int SquareColor(row, column) + int row, column; +{ + int square_color; + + if (gameInfo.variant == VariantXiangqi) { + if (column >= 3 && column <= 5 && row >= 0 && row <= 2) { + square_color = 1; + } else if (column >= 3 && column <= 5 && row >= 7 && row <= 9) { + square_color = 0; + } else if (row <= 4) { + square_color = 0; + } else { + square_color = 1; + } + } else { + square_color = ((column + row) % 2) == 1; + } + + /* [hgm] holdings: next line makes all holdings squares light */ + if(column < BOARD_LEFT || column >= BOARD_RGHT) square_color = 1; + + return square_color; +} + void DrawSquare(row, column, piece, do_flash) int row, column, do_flash; ChessSquare piece; @@ -4025,56 +4805,93 @@ void DrawSquare(row, column, piece, do_flash) /* Calculate delay in milliseconds (2-delays per complete flash) */ flash_delay = 500 / appData.flashRate; - + if (flipView) { - x = lineGap + ((BOARD_SIZE-1)-column) * + x = lineGap + ((BOARD_WIDTH-1)-column) * (squareSize + lineGap); y = lineGap + row * (squareSize + lineGap); } else { x = lineGap + column * (squareSize + lineGap); - y = lineGap + ((BOARD_SIZE-1)-row) * + y = lineGap + ((BOARD_HEIGHT-1)-row) * (squareSize + lineGap); } - - square_color = ((column + row) % 2) == 1; - - if (piece == EmptySquare || appData.blindfold) { - BlankSquare(x, y, square_color, piece, xBoardWindow); - } else { - drawfunc = ChooseDrawFunc(); - if (do_flash && appData.flashCount > 0) { - for (i=0; i= gameInfo.holdingsSize) ) { + BlankSquare(x, y, 2, EmptySquare, xBoardWindow); + + // [HGM] print piece counts next to holdings + string[1] = NULLCHAR; + if (column == (flipView ? BOARD_LEFT-1 : BOARD_RGHT) && piece > 1 ) { + string[0] = '0' + piece; + XTextExtents(countFontStruct, string, 1, &direction, + &font_ascent, &font_descent, &overall); + if (appData.monoMode) { + XDrawImageString(xDisplay, xBoardWindow, countGC, + x + squareSize - overall.width - 2, + y + font_ascent + 1, string, 1); + } else { + XDrawString(xDisplay, xBoardWindow, countGC, + x + squareSize - overall.width - 2, + y + font_ascent + 1, string, 1); + } + } + if (column == (flipView ? BOARD_RGHT : BOARD_LEFT-1) && piece > 1) { + string[0] = '0' + piece; + XTextExtents(countFontStruct, string, 1, &direction, + &font_ascent, &font_descent, &overall); + if (appData.monoMode) { + XDrawImageString(xDisplay, xBoardWindow, countGC, + x + 2, y + font_ascent + 1, string, 1); + } else { + XDrawString(xDisplay, xBoardWindow, countGC, + x + 2, y + font_ascent + 1, string, 1); + } + } + } else { + if (piece == EmptySquare || appData.blindfold) { + BlankSquare(x, y, square_color, piece, xBoardWindow); + } else { + drawfunc = ChooseDrawFunc(); + if (do_flash && appData.flashCount > 0) { + for (i=0; i= BOARD_LEFT && column < BOARD_RGHT) { + string[0] = 'a' + column - BOARD_LEFT; + XTextExtents(coordFontStruct, string, 1, &direction, &font_ascent, &font_descent, &overall); if (appData.monoMode) { XDrawImageString(xDisplay, xBoardWindow, coordGC, - x + squareSize - overall.width - 2, + x + squareSize - overall.width - 2, y + squareSize - font_descent - 1, string, 1); } else { XDrawString(xDisplay, xBoardWindow, coordGC, - x + squareSize - overall.width - 2, + x + squareSize - overall.width - 2, y + squareSize - font_descent - 1, string, 1); } } - if (appData.showCoords && column == (flipView ? 7 : 0)) { - string[0] = '1' + row; - XTextExtents(coordFontStruct, string, 1, &direction, + if (appData.showCoords && column == (flipView ? BOARD_RGHT-1 : BOARD_LEFT)) { + string[0] = ONE + row; + XTextExtents(coordFontStruct, string, 1, &direction, &font_ascent, &font_descent, &overall); if (appData.monoMode) { XDrawImageString(xDisplay, xBoardWindow, coordGC, @@ -4082,8 +4899,8 @@ void DrawSquare(row, column, piece, do_flash) } else { XDrawString(xDisplay, xBoardWindow, coordGC, x + 2, y + font_ascent + 1, string, 1); - } - } + } + } } @@ -4121,9 +4938,9 @@ static int too_many_diffs(b1, b2) { int i, j; int c = 0; - - for (i=0; i 4) /* Castling causes 4 diffs */ return 1; @@ -4145,9 +4962,9 @@ static int castling_matrix[4][5] = { /* Checks whether castling occurred. If it did, *rrow and *rcol are set to the destination (row,col) of the rook that moved. - + Returns 1 if castling occurred, 0 if not. - + Note: Only handles a max of 1 castling move, so be sure to call too_many_diffs() first. */ @@ -4197,7 +5014,7 @@ void XDrawPosition(w, repaint, board) static Board lastBoard; Arg args[16]; int rrow, rcol; - + if (board == NULL) { if (!lastBoardValid) return; board = lastBoard; @@ -4212,7 +5029,7 @@ void XDrawPosition(w, repaint, board) * It would be simpler to clear the window with XClearWindow() * but this causes a very distracting flicker. */ - + if (!repaint && lastBoardValid && lastFlipView == flipView) { /* If too much changes (begin observing new game, etc.), don't @@ -4229,11 +5046,11 @@ void XDrawPosition(w, repaint, board) } } - /* First pass -- Draw (newly) empty squares and repair damage. - This prevents you from having a piece show up twice while it + /* First pass -- Draw (newly) empty squares and repair damage. + This prevents you from having a piece show up twice while it is flashing on its new square */ - for (i = 0; i < BOARD_SIZE; i++) - for (j = 0; j < BOARD_SIZE; j++) + for (i = 0; i < BOARD_HEIGHT; i++) + for (j = 0; j < BOARD_WIDTH; j++) if ((board[i][j] != lastBoard[i][j] && board[i][j] == EmptySquare) || damage[i][j]) { DrawSquare(i, j, board[i][j], 0); @@ -4241,18 +5058,18 @@ void XDrawPosition(w, repaint, board) } /* Second pass -- Draw piece(s) in new position and flash them */ - for (i = 0; i < BOARD_SIZE; i++) - for (j = 0; j < BOARD_SIZE; j++) + for (i = 0; i < BOARD_HEIGHT; i++) + for (j = 0; j < BOARD_WIDTH; j++) if (board[i][j] != lastBoard[i][j]) { - DrawSquare(i, j, board[i][j], do_flash); + DrawSquare(i, j, board[i][j], do_flash); } } else { if (lineGap > 0) XDrawSegments(xDisplay, xBoardWindow, lineGC, - gridSegments, (BOARD_SIZE + 1) * 2); - - for (i = 0; i < BOARD_SIZE; i++) - for (j = 0; j < BOARD_SIZE; j++) { + gridSegments, BOARD_HEIGHT + BOARD_WIDTH + 2); + + for (i = 0; i < BOARD_HEIGHT; i++) + for (j = 0; j < BOARD_WIDTH; j++) { DrawSquare(i, j, board[i][j], 0); damage[i][j] = False; } @@ -4299,6 +5116,13 @@ void DrawPositionProc(w, event, prms, nprms) /* * event handler for parsing user moves */ +// [HGM] This routine will need quite some reworking. Although the backend still supports the old +// way of doing things, by calling UserMoveEvent() to test the legality of the move and then perform +// it at the end, and doing all kind of preliminary tests here (e.g. to weed out self-captures), it +// should be made to use the new way, of calling UserMoveTest early to determine the legality of the +// move, (which will weed out the illegal selfcaptures and moves into the holdings, and flag promotions), +// and at the end FinishMove() to perform the move after optional promotion popups. +// For now I patched it to allow self-capture with King, and suppress clicks between board and holdings. void HandleUserMove(w, event, prms, nprms) Widget w; XEvent *event; @@ -4308,7 +5132,7 @@ void HandleUserMove(w, event, prms, nprms) int x, y; Boolean saveAnimate; static int second = 0; - + if (w != boardWidget || errorExitStatus != -1) return; if (event->type == ButtonPress) ErrorPopDown(); @@ -4324,19 +5148,26 @@ void HandleUserMove(w, event, prms, nprms) return; } } - - x = EventToSquare(event->xbutton.x, BOARD_SIZE); - y = EventToSquare(event->xbutton.y, BOARD_SIZE); + + x = EventToSquare(event->xbutton.x, BOARD_WIDTH); + y = EventToSquare(event->xbutton.y, BOARD_HEIGHT); if (!flipView && y >= 0) { - y = BOARD_SIZE - 1 - y; + y = BOARD_HEIGHT - 1 - y; } if (flipView && x >= 0) { - x = BOARD_SIZE - 1 - x; + x = BOARD_WIDTH - 1 - x; } + /* [HGM] holdings: next 5 lines: ignore all clicks between board and holdings */ + if(event->type == ButtonPress + && ( x == BOARD_LEFT-1 || x == BOARD_RGHT + || x == BOARD_LEFT-2 && y < BOARD_HEIGHT-gameInfo.holdingsSize + || x == BOARD_RGHT+1 && y >= gameInfo.holdingsSize) ) + return; + if (fromX == -1) { if (event->type == ButtonPress) { - /* First square */ + /* First square */ if (OKToStartUserMove(x, y)) { fromX = x; fromY = y; @@ -4345,7 +5176,7 @@ void HandleUserMove(w, event, prms, nprms) if (appData.highlightDragging) { SetHighlights(x, y, -1, -1); } - } + } } return; } @@ -4355,13 +5186,18 @@ void HandleUserMove(w, event, prms, nprms) x >= 0 && y >= 0) { ChessSquare fromP; ChessSquare toP; + int frc; + /* Check if clicking again on the same color piece */ fromP = boards[currentMove][fromY][fromX]; toP = boards[currentMove][y][x]; - if ((WhitePawn <= fromP && fromP <= WhiteKing && - WhitePawn <= toP && toP <= WhiteKing) || - (BlackPawn <= fromP && fromP <= BlackKing && - BlackPawn <= toP && toP <= BlackKing)) { + frc = gameInfo.variant == VariantFischeRandom || gameInfo.variant == VariantCapaRandom; + if ((WhitePawn <= fromP && fromP <= WhiteKing && // [HGM] this test should go, as UserMoveTest now does it. + WhitePawn <= toP && toP <= WhiteKing && + !(fromP == WhiteKing && toP == WhiteRook && frc)) || + (BlackPawn <= fromP && fromP <= BlackKing && + BlackPawn <= toP && toP <= BlackKing && + !(fromP == BlackKing && toP == BlackRook && frc))) { /* Clicked again on same color piece -- changed his mind */ second = (x == fromX && y == fromY); if (appData.highlightDragging) { @@ -4396,7 +5232,7 @@ void HandleUserMove(w, event, prms, nprms) SetHighlights(x, y, -1, -1); } return; - } + } /* Completed move */ toX = x; @@ -4513,7 +5349,7 @@ Widget CommentCreate(name, text, mutable, callback, lines) XtSetArg(args[j], XtNleft, XtChainLeft); j++; XtSetArg(args[j], XtNright, XtChainLeft); j++; b_ok = - XtCreateManagedWidget("ok", commandWidgetClass, form, args, j); + XtCreateManagedWidget(_("ok"), commandWidgetClass, form, args, j); XtAddCallback(b_ok, XtNcallback, callback, (XtPointer) 0); j = 0; @@ -4524,7 +5360,7 @@ Widget CommentCreate(name, text, mutable, callback, lines) XtSetArg(args[j], XtNleft, XtChainLeft); j++; XtSetArg(args[j], XtNright, XtChainLeft); j++; b_cancel = - XtCreateManagedWidget("cancel", commandWidgetClass, form, args, j); + XtCreateManagedWidget(_("cancel"), commandWidgetClass, form, args, j); XtAddCallback(b_cancel, XtNcallback, callback, (XtPointer) 0); j = 0; @@ -4535,7 +5371,7 @@ Widget CommentCreate(name, text, mutable, callback, lines) XtSetArg(args[j], XtNleft, XtChainLeft); j++; XtSetArg(args[j], XtNright, XtChainLeft); j++; b_clear = - XtCreateManagedWidget("clear", commandWidgetClass, form, args, j); + XtCreateManagedWidget(_("clear"), commandWidgetClass, form, args, j); XtAddCallback(b_clear, XtNcallback, callback, (XtPointer) 0); } else { j = 0; @@ -4545,7 +5381,7 @@ Widget CommentCreate(name, text, mutable, callback, lines) XtSetArg(args[j], XtNleft, XtChainLeft); j++; XtSetArg(args[j], XtNright, XtChainLeft); j++; b_close = - XtCreateManagedWidget("close", commandWidgetClass, form, args, j); + XtCreateManagedWidget(_("close"), commandWidgetClass, form, args, j); XtAddCallback(b_close, XtNcallback, callback, (XtPointer) 0); j = 0; @@ -4556,7 +5392,7 @@ Widget CommentCreate(name, text, mutable, callback, lines) XtSetArg(args[j], XtNleft, XtChainLeft); j++; XtSetArg(args[j], XtNright, XtChainLeft); j++; b_edit = - XtCreateManagedWidget("edit", commandWidgetClass, form, args, j); + XtCreateManagedWidget(_("edit"), commandWidgetClass, form, args, j); XtAddCallback(b_edit, XtNcallback, callback, (XtPointer) 0); } @@ -4721,7 +5557,7 @@ void EditCommentPopUp(index, title, text) if (editShell == NULL) { editShell = - CommentCreate(title, text, True, EditCommentCallback, 4); + CommentCreate(title, text, True, EditCommentCallback, 4); XtRealizeWidget(editShell); CatchDeleteWindow(editShell, "EditCommentPopDown"); } else { @@ -4757,16 +5593,16 @@ void EditCommentCallback(w, client_data, call_data) XtSetArg(args[j], XtNlabel, &name); j++; XtGetValues(w, args, j); - if (strcmp(name, "ok") == 0) { + if (strcmp(name, _("ok")) == 0) { edit = XtNameToWidget(editShell, "*form.text"); j = 0; XtSetArg(args[j], XtNstring, &val); j++; XtGetValues(edit, args, j); ReplaceComment(savedIndex, val); EditCommentPopDown(); - } else if (strcmp(name, "cancel") == 0) { + } else if (strcmp(name, _("cancel")) == 0) { EditCommentPopDown(); - } else if (strcmp(name, "clear") == 0) { + } else if (strcmp(name, _("clear")) == 0) { edit = XtNameToWidget(editShell, "*form.text"); XtCallActionProc(edit, "select-all", NULL, NULL, 0); XtCallActionProc(edit, "kill-selection", NULL, NULL, 0); @@ -4798,9 +5634,9 @@ void ICSInputBoxPopUp() Widget edit; Arg args[16]; int j; - char *title = "ICS Input"; + char *title = _("ICS Input"); XtTranslations tr; - + if (ICSInputShell == NULL) { ICSInputShell = MiscCreate(title, "", True, NULL, 1); tr = XtParseTranslationTable(ICSInputTranslations); @@ -4808,7 +5644,7 @@ void ICSInputBoxPopUp() XtOverrideTranslations(edit, tr); XtRealizeWidget(ICSInputShell); CatchDeleteWindow(ICSInputShell, "ICSInputBoxPopDown"); - + } else { edit = XtNameToWidget(ICSInputShell, "*form.text"); j = 0; @@ -4836,7 +5672,7 @@ void ICSInputSendText() int j; Arg args[16]; String val; - + edit = XtNameToWidget(ICSInputShell, "*form.text"); j = 0; XtSetArg(args[j], XtNstring, &val); j++; @@ -4933,9 +5769,9 @@ void CommentCallback(w, client_data, call_data) XtSetArg(args[j], XtNlabel, &name); j++; XtGetValues(w, args, j); - if (strcmp(name, "close") == 0) { + if (strcmp(name, _("close")) == 0) { CommentPopDown(); - } else if (strcmp(name, "edit") == 0) { + } else if (strcmp(name, _("edit")) == 0) { CommentPopDown(); EditCommentEvent(); } @@ -4965,6 +5801,7 @@ void AnalysisPopDown() XtPopdown(analysisShell); XSync(xDisplay, False); analysisUp = False; + if (appData.icsEngineAnalyze) ExitAnalyzeMode(); /* [DM] icsEngineAnalyze */ } @@ -4980,45 +5817,46 @@ void FileNamePopUp(label, def, proc, openMode) int x, y, i; int win_x, win_y; unsigned int mask; - + fileProc = proc; /* I can't see a way not */ fileOpenMode = openMode; /* to use globals here */ - + i = 0; XtSetArg(args[i], XtNresizable, True); i++; XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++; + XtSetArg(args[i], XtNtitle, XtNewString(_("File name prompt"))); i++; fileNameShell = popup = XtCreatePopupShell("File name prompt", transientShellWidgetClass, shellWidget, args, i); - + layout = XtCreateManagedWidget(layoutName, formWidgetClass, popup, layoutArgs, XtNumber(layoutArgs)); - + i = 0; XtSetArg(args[i], XtNlabel, label); i++; XtSetArg(args[i], XtNvalue, def); i++; XtSetArg(args[i], XtNborderWidth, 0); i++; dialog = XtCreateManagedWidget("fileName", dialogWidgetClass, layout, args, i); - - XawDialogAddButton(dialog, "ok", FileNameCallback, (XtPointer) dialog); - XawDialogAddButton(dialog, "cancel", FileNameCallback, + + XawDialogAddButton(dialog, _("ok"), FileNameCallback, (XtPointer) dialog); + XawDialogAddButton(dialog, _("cancel"), FileNameCallback, (XtPointer) dialog); - + XtRealizeWidget(popup); CatchDeleteWindow(popup, "FileNamePopDown"); - + XQueryPointer(xDisplay, xBoardWindow, &root, &child, &x, &y, &win_x, &win_y, &mask); - + XtSetArg(args[0], XtNx, x - 10); XtSetArg(args[1], XtNy, y - 30); XtSetValues(popup, args, 2); - + XtPopup(popup, XtGrabExclusive); filenameUp = True; - + edit = XtNameToWidget(dialog, "*value"); XtSetKeyboardFocus(popup, edit); } @@ -5038,15 +5876,15 @@ void FileNameCallback(w, client_data, call_data) { String name; Arg args[16]; - + XtSetArg(args[0], XtNlabel, &name); XtGetValues(w, args, 1); - - if (strcmp(name, "cancel") == 0) { + + if (strcmp(name, _("cancel")) == 0) { FileNamePopDown(); return; } - + FileNameAction(w, NULL, NULL, NULL); } @@ -5063,7 +5901,7 @@ void FileNameAction(w, event, prms, nprms) int index; name = XawDialogGetValueString(w = XtParent(w)); - + if ((name != NULL) && (*name != NULLCHAR)) { strcpy(buf, name); XtPopdown(w = XtParent(XtParent(w))); @@ -5079,12 +5917,12 @@ void FileNameAction(w, event, prms, nprms) } fullname = ExpandPathName(buf); if (!fullname) { - ErrorPopUp("Error", "Can't open file", FALSE); + ErrorPopUp(_("Error"), _("Can't open file"), FALSE); } else { f = fopen(fullname, fileOpenMode); if (f == NULL) { - DisplayError("Failed to open file", errno); + DisplayError(_("Failed to open file"), errno); } else { (void) (*fileProc)(f, index, buf); } @@ -5092,7 +5930,7 @@ void FileNameAction(w, event, prms, nprms) ModeHighlight(); return; } - + XtPopdown(w = XtParent(XtParent(w))); XtDestroyWidget(w); filenameUp = False; @@ -5110,56 +5948,74 @@ void PromotionPopUp() j = 0; XtSetArg(args[j], XtNwidth, &bw_width); j++; XtGetValues(boardWidget, args, j); - + j = 0; XtSetArg(args[j], XtNresizable, True); j++; + XtSetArg(args[j], XtNtitle, XtNewString(_("Promotion"))); j++; promotionShell = XtCreatePopupShell("Promotion", transientShellWidgetClass, shellWidget, args, j); layout = XtCreateManagedWidget(layoutName, formWidgetClass, promotionShell, layoutArgs, XtNumber(layoutArgs)); - + j = 0; - XtSetArg(args[j], XtNlabel, "Promote pawn to what?"); j++; + XtSetArg(args[j], XtNlabel, _("Promote to what?")); j++; XtSetArg(args[j], XtNborderWidth, 0); j++; dialog = XtCreateManagedWidget("promotion", dialogWidgetClass, layout, args, j); - - XawDialogAddButton(dialog, "Queen", PromotionCallback, + + if(gameInfo.variant != VariantShogi) { + XawDialogAddButton(dialog, _("Queen"), PromotionCallback, (XtPointer) dialog); - XawDialogAddButton(dialog, "Rook", PromotionCallback, + XawDialogAddButton(dialog, _("Rook"), PromotionCallback, (XtPointer) dialog); - XawDialogAddButton(dialog, "Bishop", PromotionCallback, + XawDialogAddButton(dialog, _("Bishop"), PromotionCallback, (XtPointer) dialog); - XawDialogAddButton(dialog, "Knight", PromotionCallback, + XawDialogAddButton(dialog, _("Knight"), PromotionCallback, (XtPointer) dialog); - if (!appData.testLegality || gameInfo.variant == VariantSuicide) { - XawDialogAddButton(dialog, "King", PromotionCallback, - (XtPointer) dialog); - } - XawDialogAddButton(dialog, "cancel", PromotionCallback, + if (!appData.testLegality || gameInfo.variant == VariantSuicide || + gameInfo.variant == VariantGiveaway) { + XawDialogAddButton(dialog, _("King"), PromotionCallback, + (XtPointer) dialog); + } + if(gameInfo.variant == VariantCapablanca || + gameInfo.variant == VariantGothic || + gameInfo.variant == VariantCapaRandom) { + XawDialogAddButton(dialog, _("Archbishop"), PromotionCallback, + (XtPointer) dialog); + XawDialogAddButton(dialog, _("Chancellor"), PromotionCallback, + (XtPointer) dialog); + } + } else // [HGM] shogi + { + XawDialogAddButton(dialog, _("Promote"), PromotionCallback, + (XtPointer) dialog); + XawDialogAddButton(dialog, _("Defer"), PromotionCallback, + (XtPointer) dialog); + } + XawDialogAddButton(dialog, _("cancel"), PromotionCallback, (XtPointer) dialog); - + XtRealizeWidget(promotionShell); CatchDeleteWindow(promotionShell, "PromotionPopDown"); - + j = 0; XtSetArg(args[j], XtNwidth, &pw_width); j++; XtGetValues(promotionShell, args, j); - + XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2, lineGap + squareSize/3 + - ((toY == 7) ^ (flipView) ? + ((toY == BOARD_HEIGHT-1) ^ (flipView) ? 0 : 6*(squareSize + lineGap)), &x, &y); - + j = 0; XtSetArg(args[j], XtNx, x); j++; XtSetArg(args[j], XtNy, y); j++; XtSetValues(promotionShell, args, j); - + XtPopup(promotionShell, XtGrabNone); - + promotionUp = True; } @@ -5178,20 +6034,24 @@ void PromotionCallback(w, client_data, call_data) String name; Arg args[16]; int promoChar; - + XtSetArg(args[0], XtNlabel, &name); XtGetValues(w, args, 1); - + PromotionPopDown(); - + if (fromX == -1) return; - - if (strcmp(name, "cancel") == 0) { + + if (strcmp(name, _("cancel")) == 0) { fromX = fromY = -1; ClearHighlights(); return; - } else if (strcmp(name, "Knight") == 0) { + } else if (strcmp(name, _("Knight")) == 0) { promoChar = 'n'; + } else if (strcmp(name, _("Promote")) == 0) { + promoChar = '+'; + } else if (strcmp(name, _("Defer")) == 0) { + promoChar = '='; } else { promoChar = ToLower(name[0]); } @@ -5236,28 +6096,28 @@ void ErrorPopUp(title, label, modal) Dimension bw_width, pw_width; Dimension pw_height; int i; - + i = 0; XtSetArg(args[i], XtNresizable, True); i++; XtSetArg(args[i], XtNtitle, title); i++; - errorShell = + errorShell = XtCreatePopupShell("errorpopup", transientShellWidgetClass, shellWidget, args, i); layout = XtCreateManagedWidget(layoutName, formWidgetClass, errorShell, layoutArgs, XtNumber(layoutArgs)); - + i = 0; XtSetArg(args[i], XtNlabel, label); i++; XtSetArg(args[i], XtNborderWidth, 0); i++; dialog = XtCreateManagedWidget("dialog", dialogWidgetClass, layout, args, i); - - XawDialogAddButton(dialog, "ok", ErrorCallback, (XtPointer) dialog); - + + XawDialogAddButton(dialog, _("ok"), ErrorCallback, (XtPointer) dialog); + XtRealizeWidget(errorShell); CatchDeleteWindow(errorShell, "ErrorPopDown"); - + i = 0; XtSetArg(args[i], XtNwidth, &bw_width); i++; XtGetValues(boardWidget, args, i); @@ -5350,7 +6210,7 @@ char *ModeToWidgetName(mode) case EndOfGame: return NULL; } -} +} void ModeHighlight() { @@ -5358,7 +6218,7 @@ void ModeHighlight() static int oldPausing = FALSE; static GameMode oldmode = (GameMode) -1; char *wname; - + if (!boardWidget || !XtIsRealized(boardWidget)) return; if (pausing != oldPausing) { @@ -5438,7 +6298,7 @@ int LoadGamePopUp(f, gameNumber, title) if (gameNumber == 0) { int error = GameListBuild(f); if (error) { - DisplayError("Cannot build game list", error); + DisplayError(_("Cannot build game list"), error); } else if (!ListEmpty(&gameList) && ((ListGame *) gameList.tailPred)->number > 1) { GameListPopUp(f, title); @@ -5459,7 +6319,7 @@ void LoadGameProc(w, event, prms, nprms) if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) { Reset(FALSE, TRUE); } - FileNamePopUp("Load game file name?", "", LoadGamePopUp, "r"); + FileNamePopUp(_("Load game file name?"), "", LoadGamePopUp, "rb"); } void LoadNextGameProc(w, event, prms, nprms) @@ -5525,7 +6385,7 @@ void LoadPositionProc(w, event, prms, nprms) if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) { Reset(FALSE, TRUE); } - FileNamePopUp("Load position file name?", "", LoadPosition, "r"); + FileNamePopUp(_("Load position file name?"), "", LoadPosition, "rb"); } void SaveGameProc(w, event, prms, nprms) @@ -5534,7 +6394,7 @@ void SaveGameProc(w, event, prms, nprms) String *prms; Cardinal *nprms; { - FileNamePopUp("Save game file name?", + FileNamePopUp(_("Save game file name?"), DefaultFileName(appData.oldSaveStyle ? "game" : "pgn"), SaveGame, "a"); } @@ -5545,7 +6405,7 @@ void SavePositionProc(w, event, prms, nprms) String *prms; Cardinal *nprms; { - FileNamePopUp("Save position file name?", + FileNamePopUp(_("Save position file name?"), DefaultFileName(appData.oldSaveStyle ? "pos" : "fen"), SavePosition, "a"); } @@ -5593,7 +6453,7 @@ SendPositionSelection(Widget w, Atom *selection, Atom *target, return True; } else { return False; - } + } } /* note: when called from menu all parameters are NULL, so no clue what the @@ -5608,7 +6468,7 @@ void CopyPositionProc(w, event, prms, nprms) int ret; if (selected_fen_position) free(selected_fen_position); - selected_fen_position = (char *)PositionToFEN(currentMove); + selected_fen_position = (char *)PositionToFEN(currentMove, NULL); if (!selected_fen_position) return; ret = XtOwnSelection(menuBarWidget, XA_PRIMARY, CurrentTime, @@ -5682,7 +6542,7 @@ SendGameSelection(Widget w, Atom *selection, Atom *target, return True; } else { return False; - } + } } /* note: when called from menu all parameters are NULL, so no clue what the @@ -5717,13 +6577,13 @@ PasteGameCB(Widget w, XtPointer client_data, Atom *selection, } f = fopen(gamePasteFilename, "w"); if (f == NULL) { - DisplayError("Can't open temp file", errno); + DisplayError(_("Can't open temp file"), errno); return; } fwrite(value, 1, *len, f); fclose(f); XtFree(value); - LoadGameFromFile(gamePasteFilename, 0, gamePasteFilename, FALSE); + LoadGameFromFile(gamePasteFilename, 0, gamePasteFilename, TRUE); } /* called when Paste Game button is pressed, @@ -5796,12 +6656,37 @@ void AnalyzeModeProc(w, event, prms, nprms) String *prms; Cardinal *nprms; { + char buf[MSG_SIZ]; + if (!first.analysisSupport) { - char buf[MSG_SIZ]; - sprintf(buf, "%s does not support analysis", first.tidy); + snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy); DisplayError(buf, 0); return; } + /* [DM] icsEngineAnalyze [HGM] This is horrible code; reverse the gameMode and isEngineAnalyze tests! */ + if (appData.icsActive) { + if (gameMode != IcsObserving) { + sprintf(buf,_("You are not observing a game")); + DisplayError(buf, 0); + /* secure check */ + if (appData.icsEngineAnalyze) { + if (appData.debugMode) + fprintf(debugFP, _("Found unexpected active ICS engine analyze \n")); + ExitAnalyzeMode(); + ModeHighlight(); + } + return; + } + /* if enable, use want disable icsEngineAnalyze */ + if (appData.icsEngineAnalyze) { + ExitAnalyzeMode(); + ModeHighlight(); + return; + } + appData.icsEngineAnalyze = TRUE; + if (appData.debugMode) + fprintf(debugFP, _("ICS engine analyze starting... \n")); + } if (!appData.showThinking) ShowThinkingProc(w,event,prms,nprms); @@ -5816,7 +6701,7 @@ void AnalyzeFileProc(w, event, prms, nprms) { if (!first.analysisSupport) { char buf[MSG_SIZ]; - sprintf(buf, "%s does not support analysis", first.tidy); + snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy); DisplayError(buf, 0); return; } @@ -5826,7 +6711,7 @@ void AnalyzeFileProc(w, event, prms, nprms) ShowThinkingProc(w,event,prms,nprms); AnalyzeFileEvent(); - FileNamePopUp("File to analyze", "", LoadGamePopUp, "r"); + FileNamePopUp(_("File to analyze"), "", LoadGamePopUp, "rb"); AnalysisPeriodicEvent(1); } @@ -5973,6 +6858,33 @@ void ResignProc(w, event, prms, nprms) ResignEvent(); } +void AdjuWhiteProc(w, event, prms, nprms) + Widget w; + XEvent *event; + String *prms; + Cardinal *nprms; +{ + UserAdjudicationEvent(+1); +} + +void AdjuBlackProc(w, event, prms, nprms) + Widget w; + XEvent *event; + String *prms; + Cardinal *nprms; +{ + UserAdjudicationEvent(-1); +} + +void AdjuDrawProc(w, event, prms, nprms) + Widget w; + XEvent *event; + String *prms; + Cardinal *nprms; +{ + UserAdjudicationEvent(0); +} + void EnterKeyProc(w, event, prms, nprms) Widget w; XEvent *event; @@ -6450,7 +7362,7 @@ void PeriodicUpdatesProc(w, event, prms, nprms) Arg args[16]; PeriodicUpdatesEvent(!appData.periodicUpdates); - + if (appData.periodicUpdates) { XtSetArg(args[0], XtNleftBitmap, xMarkPixmap); } else { @@ -6584,8 +7496,10 @@ void ShowThinkingProc(w, event, prms, nprms) { Arg args[16]; - ShowThinkingEvent(!appData.showThinking); - + appData.showThinking = !appData.showThinking; // [HGM] thinking: tken out of ShowThinkingEvent + ShowThinkingEvent(); +#if 0 + // [HGM] thinking: currently no suc menu item; replaced by Hide Thinking (From Human) if (appData.showThinking) { XtSetArg(args[0], XtNleftBitmap, xMarkPixmap); } else { @@ -6593,6 +7507,27 @@ void ShowThinkingProc(w, event, prms, nprms) } XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Thinking"), args, 1); +#endif +} + +void HideThinkingProc(w, event, prms, nprms) + Widget w; + XEvent *event; + String *prms; + Cardinal *nprms; +{ + Arg args[16]; + + appData.hideThinkingFromHuman = !appData.hideThinkingFromHuman; // [HGM] thinking: tken out of ShowThinkingEvent + ShowThinkingEvent(); + + if (appData.hideThinkingFromHuman) { + XtSetArg(args[0], XtNleftBitmap, xMarkPixmap); + } else { + XtSetArg(args[0], XtNleftBitmap, None); + } + XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"), + args, 1); } void InfoProc(w, event, prms, nprms) @@ -6602,7 +7537,7 @@ void InfoProc(w, event, prms, nprms) Cardinal *nprms; { char buf[MSG_SIZ]; - sprintf(buf, "xterm -e info --directory %s --directory . -f %s &", + snprintf(buf, sizeof(buf), "xterm -e info --directory %s --directory . -f %s &", INFODIR, INFOFILE); system(buf); } @@ -6619,7 +7554,7 @@ void ManProc(w, event, prms, nprms) name = prms[0]; else name = "xboard"; - sprintf(buf, "xterm -e man %s &", name); + snprintf(buf, sizeof(buf), "xterm -e man %s &", name); system(buf); } @@ -6653,13 +7588,14 @@ void AboutProc(w, event, prms, nprms) #else char *zippy = ""; #endif - sprintf(buf, "%s%s\n\n%s\n%s\n\n%s%s\n%s", + snprintf(buf, sizeof(buf), "%s%s\n\n%s\n%s\n%s\n\n%s%s\n%s", programVersion, zippy, "Copyright 1991 Digital Equipment Corporation", - "Enhancements Copyright 1992-2001 Free Software Foundation", - PRODUCT, " is free software and carries NO WARRANTY;", + "Enhancements Copyright 1992-2009 Free Software Foundation", + "Enhancements Copyright 2005 Alessandro Scotti", + PACKAGE, " is free software and carries NO WARRANTY;", "see the file COPYING for more information."); - ErrorPopUp("About XBoard", buf, FALSE); + ErrorPopUp(_("About XBoard"), buf, FALSE); } void DebugProc(w, event, prms, nprms) @@ -6696,7 +7632,7 @@ void Iconify(w, event, prms, nprms) Cardinal *nprms; { Arg args[16]; - + fromX = fromY = -1; XtSetArg(args[0], XtNiconic, True); XtSetValues(shellWidget, args, 1); @@ -6707,10 +7643,10 @@ void DisplayMessage(message, extMessage) { char buf[MSG_SIZ]; Arg arg; - + if (extMessage) { if (*message) { - sprintf(buf, "%s %s", message, extMessage); + snprintf(buf, sizeof(buf), "%s %s", message, extMessage); message = buf; } else { message = extMessage; @@ -6740,17 +7676,28 @@ void DisplayTitle(text) strcpy(icon, text); strcpy(title, text); } else if (appData.icsActive) { - sprintf(icon, "%s", appData.icsHost); - sprintf(title, "%s: %s", programName, appData.icsHost); + snprintf(icon, sizeof(icon), "%s", appData.icsHost); + snprintf(title, sizeof(title), "%s: %s", programName, appData.icsHost); } else if (appData.cmailGameName[0] != NULLCHAR) { - sprintf(icon, "%s", "CMail"); - sprintf(title, "%s: %s", programName, "CMail"); + snprintf(icon, sizeof(icon), "%s", "CMail"); + snprintf(title,sizeof(title), "%s: %s", programName, "CMail"); +#ifdef GOTHIC + // [HGM] license: This stuff should really be done in back-end, but WinBoard already had a pop-up for it + } else if (gameInfo.variant == VariantGothic) { + strcpy(icon, programName); + strcpy(title, GOTHIC); +#endif +#ifdef FALCON + } else if (gameInfo.variant == VariantFalcon) { + strcpy(icon, programName); + strcpy(title, FALCON); +#endif } else if (appData.noChessProgram) { strcpy(icon, programName); strcpy(title, programName); } else { strcpy(icon, first.tidy); - sprintf(title, "%s: %s", programName, first.tidy); + snprintf(title,sizeof(title), "%s: %s", programName, first.tidy); } i = 0; XtSetArg(args[i], XtNiconName, (XtArgVal) icon); i++; @@ -6772,12 +7719,12 @@ void DisplayError(message, error) } else { if (appData.debugMode || appData.matchMode) { fprintf(stderr, "%s: %s: %s\n", - programName, message, sys_errlist[error]); + programName, message, strerror(error)); } - sprintf(buf, "%s: %s", message, sys_errlist[error]); + snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error)); message = buf; - } - ErrorPopUp("Error", message, FALSE); + } + ErrorPopUp(_("Error"), message, FALSE); } @@ -6791,7 +7738,7 @@ void DisplayMoveError(message) fprintf(stderr, "%s: %s\n", programName, message); } if (appData.popupMoveErrors) { - ErrorPopUp("Error", message, FALSE); + ErrorPopUp(_("Error"), message, FALSE); } else { DisplayMessage(message, ""); } @@ -6809,12 +7756,12 @@ void DisplayFatalError(message, error, status) fprintf(stderr, "%s: %s\n", programName, message); } else { fprintf(stderr, "%s: %s: %s\n", - programName, message, sys_errlist[error]); - sprintf(buf, "%s: %s", message, sys_errlist[error]); + programName, message, strerror(error)); + snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error)); message = buf; } if (appData.popupExitMessage && boardWidget && XtIsRealized(boardWidget)) { - ErrorPopUp(status ? "Fatal Error" : "Exiting", message, TRUE); + ErrorPopUp(status ? _("Fatal Error") : _("Exiting"), message, TRUE); } else { ExitEvent(status); } @@ -6824,7 +7771,14 @@ void DisplayInformation(message) String message; { ErrorPopDown(); - ErrorPopUp("Information", message, TRUE); + ErrorPopUp(_("Information"), message, TRUE); +} + +void DisplayNote(message) + String message; +{ + ErrorPopDown(); + ErrorPopUp(_("Note"), message, FALSE); } static int @@ -6857,9 +7811,9 @@ void DisplayIcsInteractionTitle(message) XSetErrorHandler(oldHandler); } if (oldICSInteractionTitle == NULL) { - oldICSInteractionTitle = "xterm"; + oldICSInteractionTitle = "xterm"; } - } + } printf("\033]0;%s\007", message); fflush(stdout); } @@ -6874,7 +7828,7 @@ void AskQuestionProc(w, event, prms, nprms) Cardinal *nprms; { if (*nprms != 4) { - fprintf(stderr, "AskQuestionProc needed 4 parameters, got %d\n", + fprintf(stderr, _("AskQuestionProc needed 4 parameters, got %d\n"), *nprms); return; } @@ -6907,7 +7861,7 @@ void AskQuestionReplyAction(w, event, prms, nprms) OutputToProcess(pendingReplyPR, buf, strlen(buf), &err); AskQuestionPopDown(); - if (err) DisplayFatalError("Error writing to chess program", err, 0); + if (err) DisplayFatalError(_("Error writing to chess program"), err, 0); } void AskQuestionCallback(w, client_data, call_data) @@ -6919,8 +7873,8 @@ void AskQuestionCallback(w, client_data, call_data) XtSetArg(args[0], XtNlabel, &name); XtGetValues(w, args, 1); - - if (strcmp(name, "cancel") == 0) { + + if (strcmp(name, _("cancel")) == 0) { AskQuestionPopDown(); } else { AskQuestionReplyAction(w, NULL, NULL, NULL); @@ -6937,46 +7891,46 @@ void AskQuestion(title, question, replyPrefix, pr) int x, y, i; int win_x, win_y; unsigned int mask; - + strcpy(pendingReplyPrefix, replyPrefix); pendingReplyPR = pr; - + i = 0; XtSetArg(args[i], XtNresizable, True); i++; XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++; askQuestionShell = popup = XtCreatePopupShell(title, transientShellWidgetClass, shellWidget, args, i); - + layout = XtCreateManagedWidget(layoutName, formWidgetClass, popup, layoutArgs, XtNumber(layoutArgs)); - + i = 0; XtSetArg(args[i], XtNlabel, question); i++; XtSetArg(args[i], XtNvalue, ""); i++; XtSetArg(args[i], XtNborderWidth, 0); i++; dialog = XtCreateManagedWidget("question", dialogWidgetClass, layout, args, i); - - XawDialogAddButton(dialog, "enter", AskQuestionCallback, + + XawDialogAddButton(dialog, _("enter"), AskQuestionCallback, (XtPointer) dialog); - XawDialogAddButton(dialog, "cancel", AskQuestionCallback, + XawDialogAddButton(dialog, _("cancel"), AskQuestionCallback, (XtPointer) dialog); XtRealizeWidget(popup); CatchDeleteWindow(popup, "AskQuestionPopDown"); - + XQueryPointer(xDisplay, xBoardWindow, &root, &child, &x, &y, &win_x, &win_y, &mask); - + XtSetArg(args[0], XtNx, x - 10); XtSetArg(args[1], XtNy, y - 30); XtSetValues(popup, args, 2); - + XtPopup(popup, XtGrabExclusive); askQuestionUp = True; - + edit = XtNameToWidget(dialog, "*value"); XtSetKeyboardFocus(popup, edit); } @@ -6992,7 +7946,7 @@ PlaySound(name) putc(BELLCHAR, stderr); } else { char buf[2048]; - sprintf(buf, "%s '%s' &", appData.soundProgram, name); + snprintf(buf, sizeof(buf), "%s '%s' &", appData.soundProgram, name); system(buf); } } @@ -7072,7 +8026,7 @@ Colorize(cc, continuation) count = strlen(buf); outCount = OutputToProcess(NoProc, buf, count, &error); if (outCount < count) { - DisplayFatalError("Error writing to display", error, 1); + DisplayFatalError(_("Error writing to display"), error, 1); } if (continuation) return; @@ -7122,7 +8076,7 @@ static char *ExpandPathName(path) static char static_buf[2000]; char *d, *s, buf[2000]; struct passwd *pwd; - + s = path; d = static_buf; @@ -7145,7 +8099,7 @@ static char *ExpandPathName(path) pwd = getpwnam(buf); if (!pwd) { - fprintf(stderr, "ERROR: Unknown user %s (in path %s)\n", + fprintf(stderr, _("ERROR: Unknown user %s (in path %s)\n"), buf, path); return NULL; } @@ -7157,12 +8111,12 @@ static char *ExpandPathName(path) strcpy(d, s); return static_buf; -} +} char *HostName() { static char host_name[MSG_SIZ]; - + #if HAVE_GETHOSTNAME gethostname(host_name, MSG_SIZ); return host_name; @@ -7178,14 +8132,25 @@ char *HostName() XtIntervalId delayedEventTimerXID = 0; DelayedEventCallback delayedEventCallback = 0; + +void +FireDelayedEvent() +{ + delayedEventTimerXID = 0; + delayedEventCallback(); +} + void ScheduleDelayedEvent(cb, millisec) DelayedEventCallback cb; long millisec; { + if(delayedEventTimerXID && delayedEventCallback == cb) + // [HGM] alive: replace, rather than add or flush identical event + XtRemoveTimeOut(delayedEventTimerXID); delayedEventCallback = cb; delayedEventTimerXID = - XtAppAddTimeOut(appContext, millisec, (XtTimerCallbackProc) cb, - (XtPointer) 0); + XtAppAddTimeOut(appContext, millisec, + (XtTimerCallbackProc) FireDelayedEvent, (XtPointer) 0); } DelayedEventCallback @@ -7251,7 +8216,8 @@ AnalysisClockCallback(arg, id) XtPointer arg; XtIntervalId *id; { - if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) { + if (gameMode == AnalyzeMode || gameMode == AnalyzeFile + || appData.icsEngineAnalyze) { // [DM] AnalysisPeriodicEvent(0); StartAnalysisClock(); } @@ -7312,7 +8278,15 @@ DisplayTimerLabel(w, color, timer, highlight) { char buf[MSG_SIZ]; Arg args[16]; - + + /* check for low time warning */ + Pixel foregroundOrWarningColor = timerForegroundPixel; + + if (timer > 0 && + appData.lowTimeWarning && + (timer / 1000) < appData.icsAlarmTime) + foregroundOrWarningColor = lowTimeWarningColor; + if (appData.clockMode) { sprintf(buf, "%s: %s", color, TimeString(timer)); XtSetArg(args[0], XtNlabel, buf); @@ -7320,15 +8294,16 @@ DisplayTimerLabel(w, color, timer, highlight) sprintf(buf, "%s ", color); XtSetArg(args[0], XtNlabel, buf); } - + if (highlight) { - XtSetArg(args[1], XtNbackground, timerForegroundPixel); + + XtSetArg(args[1], XtNbackground, foregroundOrWarningColor); XtSetArg(args[2], XtNforeground, timerBackgroundPixel); } else { XtSetArg(args[1], XtNbackground, timerBackgroundPixel); - XtSetArg(args[2], XtNforeground, timerForegroundPixel); + XtSetArg(args[2], XtNforeground, foregroundOrWarningColor); } - + XtSetValues(w, args, 3); } @@ -7338,7 +8313,9 @@ DisplayWhiteClock(timeRemaining, highlight) int highlight; { Arg args[16]; - DisplayTimerLabel(whiteTimerWidget, "White", timeRemaining, highlight); + + if(appData.noGUI) return; + DisplayTimerLabel(whiteTimerWidget, _("White"), timeRemaining, highlight); if (highlight && iconPixmap == bIconPixmap) { iconPixmap = wIconPixmap; XtSetArg(args[0], XtNiconPixmap, iconPixmap); @@ -7352,7 +8329,9 @@ DisplayBlackClock(timeRemaining, highlight) int highlight; { Arg args[16]; - DisplayTimerLabel(blackTimerWidget, "Black", timeRemaining, highlight); + + if(appData.noGUI) return; + DisplayTimerLabel(blackTimerWidget, _("Black"), timeRemaining, highlight); if (highlight && iconPixmap == wIconPixmap) { iconPixmap = bIconPixmap; XtSetArg(args[0], XtNiconPixmap, iconPixmap); @@ -7370,12 +8349,12 @@ typedef int CPKind; typedef struct { CPKind kind; int pid; - int fdTo, fdFrom; + int fdTo, fdFrom; } ChildProc; int StartChildProcess(cmdLine, dir, pr) - char *cmdLine; + char *cmdLine; char *dir; ProcRef *pr; { @@ -7384,7 +8363,7 @@ int StartChildProcess(cmdLine, dir, pr) int to_prog[2], from_prog[2]; ChildProc *cp; char buf[MSG_SIZ]; - + if (appData.debugMode) { fprintf(stderr, "StartChildProcess (dir=\"%s\") %s\n",dir, cmdLine); } @@ -7408,30 +8387,34 @@ int StartChildProcess(cmdLine, dir, pr) if ((pid = fork()) == 0) { /* Child process */ - dup2(to_prog[0], 0); - dup2(from_prog[1], 1); - close(to_prog[0]); - close(to_prog[1]); + // [HGM] PSWBTM: made order resistant against case where fd of created pipe was 0 or 1 + close(to_prog[1]); // first close the unused pipe ends close(from_prog[0]); - close(from_prog[1]); - dup2(1, fileno(stderr)); /* force stderr to the pipe */ + dup2(to_prog[0], 0); // to_prog was created first, nd is the only one to use 0 or 1 + dup2(from_prog[1], 1); + if(to_prog[0] >= 2) close(to_prog[0]); // if 0 or 1, the dup2 already cosed the original + close(from_prog[1]); // and closing again loses one of the pipes! + if(fileno(stderr) >= 2) // better safe than sorry... + dup2(1, fileno(stderr)); /* force stderr to the pipe */ if (dir[0] != NULLCHAR && chdir(dir) != 0) { perror(dir); exit(1); } + nice(appData.niceEngines); // [HGM] nice: adjust priority of engine proc + execvp(argv[0], argv); - + /* If we get here, exec failed */ perror(argv[0]); exit(1); } - + /* Parent process */ close(to_prog[0]); close(from_prog[1]); - + cp = (ChildProc *) calloc(1, sizeof(ChildProc)); cp->kind = CPReal; cp->pid = pid; @@ -7441,22 +8424,37 @@ int StartChildProcess(cmdLine, dir, pr) return 0; } +// [HGM] kill: implement the 'hard killing' of AS's Winboard_x +static RETSIGTYPE AlarmCallBack(int n) +{ + return; +} + void -DestroyChildProcess(pr, signal) +DestroyChildProcess(pr, signalType) ProcRef pr; - int signal; + int signalType; { ChildProc *cp = (ChildProc *) pr; if (cp->kind != CPReal) return; cp->kind = CPNone; - if (signal) { - kill(cp->pid, SIGTERM); + if (signalType == 10) { // [HGM] kill: if it does not terminate in 3 sec, kill + signal(SIGALRM, AlarmCallBack); + alarm(3); + if(wait((int *) 0) == -1) { // process does not terminate on its own accord + kill(cp->pid, SIGKILL); // kill it forcefully + wait((int *) 0); // and wait again + } + } else { + if (signalType) { + kill(cp->pid, signalType == 9 ? SIGKILL : SIGTERM); // [HGM] kill: use hard kill if so requested + } + /* Process is exiting either because of the kill or because of + a quit command sent by the backend; either way, wait for it to die. + */ + wait((int *) 0); } - /* Process is exiting either because of the kill or because of - a quit command sent by the backend; either way, wait for it to die. - */ - wait((int *) 0); close(cp->fdFrom); close(cp->fdTo); } @@ -7479,9 +8477,9 @@ int OpenTelnet(host, port, pr) char cmdLine[MSG_SIZ]; if (port[0] == NULLCHAR) { - sprintf(cmdLine, "%s %s", appData.telnetProgram, host); + snprintf(cmdLine, sizeof(cmdLine), "%s %s", appData.telnetProgram, host); } else { - sprintf(cmdLine, "%s %s %s", appData.telnetProgram, host, port); + snprintf(cmdLine, sizeof(cmdLine), "%s %s %s", appData.telnetProgram, host, port); } return StartChildProcess(cmdLine, "", pr); } @@ -7492,7 +8490,7 @@ int OpenTCP(host, port, pr) ProcRef *pr; { #if OMIT_SOCKETS - DisplayFatalError("Socket support is not configured in", 0, 2); + DisplayFatalError(_("Socket support is not configured in"), 0, 2); #else /* !OMIT_SOCKETS */ int s; struct sockaddr_in sa; @@ -7535,7 +8533,7 @@ int OpenTCP(host, port, pr) sa.sin_port = htons(uport); memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length); - if (connect(s, (struct sockaddr *) &sa, + if (connect(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)) < 0) { return errno; } @@ -7594,9 +8592,9 @@ int OpenRcmd(host, user, cmd, pr) char *host, *user, *cmd; ProcRef *pr; { - DisplayFatalError("internal rcmd not implemented for Unix", 0, 1); + DisplayFatalError(_("internal rcmd not implemented for Unix"), 0, 1); return -1; -} +} #define INPUT_SOURCE_BUF_SIZE 8192 @@ -7612,7 +8610,7 @@ typedef struct { } InputSource; void -DoInputCallback(closure, source, xid) +DoInputCallback(closure, source, xid) caddr_t closure; int *source; XtInputId *xid; @@ -7650,7 +8648,7 @@ DoInputCallback(closure, source, xid) else error = 0; (is->func)(is, is->closure, is->buf, count, error); - } + } } InputSourceRef AddInputSource(pr, lineByLine, func, closure) @@ -7675,7 +8673,7 @@ InputSourceRef AddInputSource(pr, lineByLine, func, closure) if (lineByLine) { is->unused = is->buf; } - + is->xid = XtAppAddInput(appContext, is->fd, (XtPointer) (XtInputReadMask), (XtInputCallbackProc) DoInputCallback, @@ -7731,7 +8729,7 @@ int OutputToProcessDelayed(pr, message, count, outError, msdelay) ChildProc *cp = (ChildProc *) pr; int outCount = 0; int r; - + while (count--) { r = write(cp->fdTo, message++, 1); if (r == -1) { @@ -7765,6 +8763,8 @@ int OutputToProcessDelayed(pr, message, count, outError, msdelay) and dark squares, and all pieces must use the same background square colors/images. */ +static int xpmDone = 0; + static void CreateAnimMasks (pieceDepth) int pieceDepth; @@ -7787,7 +8787,7 @@ CreateAnimMasks (pieceDepth) XFreePixmap(xDisplay, buf); buf = XCreatePixmap(xDisplay, xBoardWindow, - squareSize, squareSize, pieceDepth); + squareSize, squareSize, pieceDepth); values.foreground = XBlackPixel(xDisplay, xScreen); values.background = XWhitePixel(xDisplay, xScreen); bufGC = XCreateGC(xDisplay, buf, @@ -7795,22 +8795,23 @@ CreateAnimMasks (pieceDepth) for (piece = WhitePawn; piece <= BlackKing; piece++) { /* Begin with empty mask */ + if(!xpmDone) // [HGM] pieces: keep using existing xpmMask[piece] = XCreatePixmap(xDisplay, xBoardWindow, squareSize, squareSize, 1); XSetFunction(xDisplay, maskGC, GXclear); XFillRectangle(xDisplay, xpmMask[piece], maskGC, 0, 0, squareSize, squareSize); - + /* Take a copy of the piece */ if (White(piece)) kind = 0; else kind = 2; XSetFunction(xDisplay, bufGC, GXcopy); - XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % 6], + XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn], buf, bufGC, 0, 0, squareSize, squareSize, 0, 0); - + /* XOR the background (light) over the piece */ XSetFunction(xDisplay, bufGC, GXxor); if (useImageSqs) @@ -7820,7 +8821,7 @@ CreateAnimMasks (pieceDepth) XSetForeground(xDisplay, bufGC, lightSquareColor); XFillRectangle(xDisplay, buf, bufGC, 0, 0, squareSize, squareSize); } - + /* We now have an inverted piece image with the background erased. Construct mask by just selecting all the non-zero pixels - no need to reconstruct the original image. */ @@ -7850,7 +8851,7 @@ InitAnimState (anim, info) { XtGCMask mask; XGCValues values; - + /* Each buffer is square size, same depth as window */ anim->saveBuf = XCreatePixmap(xDisplay, xBoardWindow, squareSize, squareSize, info->depth); @@ -7878,19 +8879,20 @@ InitAnimState (anim, info) static void CreateAnimVars () { - static int done = 0; + static VariantClass old = (VariantClass) -1; // [HGM] pieces: redo every time variant changes XWindowAttributes info; - if (done) return; - done = 1; + if (xpmDone && gameInfo.variant == old) return; + if(xpmDone) old = gameInfo.variant; // first time pieces might not be created yet XGetWindowAttributes(xDisplay, xBoardWindow, &info); - + InitAnimState(&game, &info); InitAnimState(&player, &info); - + /* For XPM pieces, we need bitmaps to use as masks. */ if (useImages) CreateAnimMasks(info.depth); + xpmDone = 1; } #ifndef HAVE_USLEEP @@ -7910,20 +8912,20 @@ FrameDelay (time) int time; { struct itimerval delay; - + XSync(xDisplay, False); if (time > 0) { frameWaiting = True; signal(SIGALRM, FrameAlarm); - delay.it_interval.tv_sec = + delay.it_interval.tv_sec = delay.it_value.tv_sec = time / 1000; - delay.it_interval.tv_usec = + delay.it_interval.tv_usec = delay.it_value.tv_usec = (time % 1000) * 1000; setitimer(ITIMER_REAL, &delay, NULL); #if 0 /* Ugh -- busy-wait! --tpm */ - while (frameWaiting); + while (frameWaiting); #else while (frameWaiting) pause(); #endif @@ -7953,13 +8955,13 @@ ScreenSquare(column, row, pt, color) int column; int row; XPoint * pt; int * color; { if (flipView) { - pt->x = lineGap + ((BOARD_SIZE-1)-column) * (squareSize + lineGap); + pt->x = lineGap + ((BOARD_WIDTH-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); + pt->y = lineGap + ((BOARD_HEIGHT-1)-row) * (squareSize + lineGap); } - *color = ((column + row) % 2) == 1; + *color = SquareColor(row, column); } /* Convert window coords to square */ @@ -7968,12 +8970,12 @@ static void BoardSquare(x, y, column, row) int x; int y; int * column; int * row; { - *column = EventToSquare(x, BOARD_SIZE); + *column = EventToSquare(x, BOARD_WIDTH); if (flipView && *column >= 0) - *column = BOARD_SIZE - 1 - *column; - *row = EventToSquare(y, BOARD_SIZE); + *column = BOARD_WIDTH - 1 - *column; + *row = EventToSquare(y, BOARD_HEIGHT); if (!flipView && *row >= 0) - *row = BOARD_SIZE - 1 - *row; + *row = BOARD_HEIGHT - 1 - *row; } /* Utilities */ @@ -7996,7 +8998,7 @@ SetRect(rect, x, y, width, height) /* Test if two frames overlap. If they do, return intersection rect within old and location of that rect within new. */ - + static Boolean Intersect(old, new, size, area, pt) XPoint * old; XPoint * new; @@ -8016,7 +9018,7 @@ Intersect(old, new, size, area, pt) /* For two overlapping frames, return the rect(s) in the old that do not intersect with the new. */ - + static void CalcUpdateRects(old, new, size, update, nUpdates) XPoint * old; XPoint * new; int size; @@ -8085,11 +9087,11 @@ Tween(start, mid, finish, factor, frames, nFrames) 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++) { @@ -8116,7 +9118,7 @@ SelectGCMask(piece, clip, outline, mask) #if HAVE_LIBXPM *mask = xpmMask[piece]; #else - *mask = ximMaskPm[piece%6]; + *mask = ximMaskPm[piece]; #endif } else { *mask = *pieceToSolid(piece); @@ -8136,7 +9138,7 @@ SelectGCMask(piece, clip, outline, mask) source = blPieceGC; } XCopyGC(xDisplay, source, 0xFFFFFFFF, *clip); - + /* Outline only used in mono mode and is not modified */ if (White(piece)) *outline = bwPieceGC; @@ -8149,7 +9151,7 @@ OverlayPiece(piece, clip, outline, dest) ChessSquare piece; GC clip; GC outline; Drawable dest; { int kind; - + if (!useImages) { /* Draw solid rectangle which will be clipped to shape of piece */ XFillRectangle(xDisplay, dest, clip, @@ -8165,16 +9167,16 @@ OverlayPiece(piece, clip, outline, dest) kind = 0; else kind = 2; - XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % 6], + XCopyArea(xDisplay, xpmPieceBitmap[kind][piece], dest, clip, 0, 0, squareSize, squareSize, - 0, 0); + 0, 0); } } /* Animate the movement of a single piece */ -static void +static void BeginAnimation(anim, piece, startColor, start) AnimState *anim; ChessSquare piece; @@ -8182,11 +9184,11 @@ BeginAnimation(anim, piece, startColor, start) XPoint * start; { Pixmap mask; - + /* The old buffer is initialised with the start square (empty) */ BlankSquare(0, 0, startColor, EmptySquare, anim->saveBuf); anim->prevFrame = *start; - + /* The piece will be drawn using its own bitmap as a matte */ SelectGCMask(piece, &anim->pieceGC, &anim->outlineGC, &mask); XSetClipMask(xDisplay, anim->pieceGC, mask); @@ -8202,12 +9204,12 @@ AnimationFrame(anim, frame, piece) XRectangle overlap; XPoint pt; int count, i; - + /* Save what we are about to draw into the new buffer */ XCopyArea(xDisplay, xBoardWindow, anim->newBuf, anim->blitGC, frame->x, frame->y, squareSize, squareSize, 0, 0); - + /* Erase bits of the previous frame */ if (Intersect(&anim->prevFrame, frame, squareSize, &overlap, &pt)) { /* Where the new frame overlapped the previous, @@ -8236,7 +9238,7 @@ AnimationFrame(anim, frame, piece) 0, 0, squareSize, squareSize, 0, 0); anim->prevFrame = *frame; - + /* Draw piece over original screen contents, not current, and copy entire rect. Wipes out overlapping piece images. */ OverlayPiece(piece, anim->pieceGC, anim->outlineGC, anim->newBuf); @@ -8309,6 +9311,10 @@ AnimateMove(board, fromX, fromY, toX, toY) if (!appData.animate || appData.blindfold) return; + if(board[toY][toX] == WhiteRook && board[fromY][fromX] == WhiteKing || + board[toY][toX] == BlackRook && board[fromY][fromX] == BlackKing) + return; // [HGM] FRC: no animtion of FRC castlings, as to-square is not true to-square + if (fromY < 0 || fromX < 0 || toX < 0 || toY < 0) return; piece = board[fromY][fromX]; if (piece >= EmptySquare) return; @@ -8320,9 +9326,9 @@ AnimateMove(board, fromX, fromY, toX, toY) #endif if (appData.debugMode) { - printf("AnimateMove: piece %d %s from %d,%d to %d,%d \n", - piece, hop ? "hops" : "slides", fromX, fromY, toX, toY); - } + fprintf(debugFP, hop ? _("AnimateMove: piece %d hops from %d,%d to %d,%d \n") : + _("AnimateMove: piece %d slides from %d,%d to %d,%d \n"), + piece, fromX, fromY, toX, toY); } ScreenSquare(fromX, fromY, &start, &startColor); ScreenSquare(toX, toY, &finish, &endColor); @@ -8340,14 +9346,14 @@ AnimateMove(board, fromX, fromY, toX, toY) mid.x = start.x + (finish.x - start.x) / 2; 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); FrameSequence(&game, piece, startColor, &start, &finish, frames, nFrames); - + /* Be sure end square is redrawn */ damage[toY][toX] = True; } @@ -8362,7 +9368,7 @@ DragPieceBegin(x, y) /* Are we animating? */ if (!appData.animateDragging || appData.blindfold) return; - + /* Figure out which square we start in and the mouse position relative to top left corner. */ BoardSquare(x, y, &boardX, &boardY); @@ -8393,6 +9399,11 @@ DragPieceBegin(x, y) /* Mark this square as needing to be redrawn. Note that we don't remove the piece though, since logically (ie as seen by opponent) the move hasn't been made yet. */ + if(boardX == BOARD_RGHT+1 && PieceForSquare(boardX-1, boardY) > 1 || + boardX == BOARD_LEFT-2 && PieceForSquare(boardX+1, boardY) > 1) + XCopyArea(xDisplay, xBoardWindow, player.saveBuf, player.blitGC, + corner.x, corner.y, squareSize, squareSize, + 0, 0); // [HGM] zh: unstack in stead of grab damage[boardY][boardX] = True; } else { player.dragActive = False; @@ -8408,7 +9419,7 @@ DragPieceMove(x, y) /* Are we animating? */ if (!appData.animateDragging || appData.blindfold) return; - + /* Sanity check */ if (! player.dragActive) return; @@ -8436,7 +9447,7 @@ DragPieceEnd(x, y) /* Are we animating? */ if (!appData.animateDragging || appData.blindfold) return; - + /* Sanity check */ if (! player.dragActive) return; @@ -8473,3 +9484,10 @@ DrawDragPiece () damage[player.startBoardY][player.startBoardX] = TRUE; } +void +SetProgramStats( FrontEndProgramStats * stats ) +{ + // [HR] TODO + // [HGM] done, but perhaps backend should call this directly? + EngineOutputUpdate( stats ); +}