X-Git-Url: http://winboard.nl/cgi-bin?a=blobdiff_plain;f=xboard.c;h=7a8a7ac7a0f360e1247c2261e7916939c1481e05;hb=b382d988c6f886f3a49483df9e3e36de0b6b0824;hp=36987280a8c0522ecda17115c1fcc42ca5ae680f;hpb=912ff451e7a648f6aa3ba7d2a10df2a1dc2cace5;p=xboard.git diff --git a/xboard.c b/xboard.c index 3698728..7a8a7ac 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, 2010, 2011 Free Software Foundation, Inc. * * The following terms apply to Digital Equipment Corporation's copyright * interest in XBoard: @@ -27,26 +29,27 @@ * 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. */ + +#define HIGHDRAG 1 #include "config.h" @@ -57,6 +60,7 @@ #include #include #include +#include #if !OMIT_SOCKETS # if HAVE_SYS_SOCKET_H @@ -143,6 +147,7 @@ extern char *getenv(); #include #include #include +#include #if USE_XAW3D #include #include @@ -169,6 +174,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,9 +190,9 @@ extern char *getenv(); #include "bitmaps/icon_black.bm" #include "bitmaps/checkmark.bm" -#include "common.h" #include "frontend.h" #include "backend.h" +#include "backendz.h" #include "moves.h" #include "xboard.h" #include "childio.h" @@ -193,6 +201,14 @@ extern char *getenv(); #include "xedittags.h" #include "gettext.h" +// must be moved to xengineoutput.h + +void EngineOutputProc P((Widget w, XEvent *event, + String *prms, Cardinal *nprms)); +void EvalGraphProc P((Widget w, XEvent *event, + String *prms, Cardinal *nprms)); + + #ifdef __EMX__ #ifndef HAVE_USLEEP #define HAVE_USLEEP @@ -210,20 +226,26 @@ extern char *getenv(); typedef struct { String string; + String ref; XtActionProc proc; } MenuItem; typedef struct { String name; + String ref; MenuItem *mi; } Menu; int main P((int argc, char **argv)); +FILE * XsraSelFile P((Widget w, char *prompt, char *ok, char *cancel, char *failed, + char *init_path, char *mode, int (*show_entry)(), char **name_return)); RETSIGTYPE CmailSigHandler P((int sig)); RETSIGTYPE IntSigHandler P((int sig)); +RETSIGTYPE TermSizeSigHandler P((int sig)); void CreateGCs P((void)); void CreateXIMPieces P((void)); void CreateXPMPieces P((void)); +void CreateXPMBoard P((char *s, int n)); void CreatePieces P((void)); void CreatePieceMenus P((void)); Widget CreateMenuBar P((Menu *mb)); @@ -243,14 +265,22 @@ void HandleUserMove P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); void AnimateUserMove P((Widget w, XEvent * event, String * params, Cardinal * nParams)); +void HandlePV P((Widget w, XEvent * event, + String * params, Cardinal * nParams)); +void SelectPV P((Widget w, XEvent * event, + String * params, Cardinal * nParams)); +void StopPV P((Widget w, XEvent * event, + String * params, Cardinal * nParams)); void WhiteClock P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); 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 CommentClick P((Widget w, XEvent * event, + String * params, Cardinal * nParams)); void CommentPopUp P((char *title, char *label)); void CommentPopDown P((void)); void CommentCallback P((Widget w, XtPointer client_data, @@ -269,7 +299,6 @@ void AskQuestionReplyAction P((Widget w, XEvent *event, void AskQuestionProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); void AskQuestionPopDown P((void)); -void PromotionPopUp P((void)); void PromotionPopDown P((void)); void PromotionCallback P((Widget w, XtPointer client_data, XtPointer call_data)); @@ -335,16 +364,23 @@ 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 UpKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); +void DownKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); void StopObservingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); void StopExaminingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); +void UploadProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); void BackwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); void ForwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); void ToStartProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); void ToEndProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); void RevertProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); +void AnnotateProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); void TruncateGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); void RetractMoveProc P((Widget w, XEvent *event, String *prms, @@ -374,10 +410,11 @@ void HighlightDraggingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); void HighlightLastMoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); +void HighlightArrowProc P((Widget w, XEvent *event, String *prms, + Cardinal *nprms)); void MoveSoundProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); void IcsAlarmProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); -void OldSaveStyleProc P((Widget w, XEvent *event, String *prms, - Cardinal *nprms)); +void OneClickProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); void PeriodicUpdatesProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); void PonderNextMoveProc P((Widget w, XEvent *event, String *prms, @@ -392,8 +429,12 @@ 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 SaveSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); +void SaveOnExitProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); void InfoProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); void ManProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); void HintProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); @@ -411,11 +452,29 @@ void ErrorPopUp P((char *title, char *text, int modal)); void ErrorPopDown P((void)); static char *ExpandPathName P((char *path)); static void CreateAnimVars P((void)); -static void DragPieceBegin P((int x, int y)); 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 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 GameListOptionsPopUp P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); +void GameListOptionsPopDown P(()); +void ShufflePopDown P(()); +void EnginePopDown P(()); +void UciPopDown P(()); +void TimeControlPopDown P(()); +void NewVariantPopDown P(()); +void SettingsPopDown P(()); +void update_ics_width P(()); +int get_term_width P(()); +int CopyMemoProc P(()); +void DrawArrowHighlight P((int fromX, int fromY, int toX,int toY)); +Boolean IsDrawArrowEnabled P(()); /* * XBoard depends on Xt R4 or higher @@ -427,30 +486,40 @@ 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; +Widget historyShell, evalGraphShell, gameListShell; +int hOffset; // [HGM] dual +XSegment secondSegments[BOARD_RANKS + BOARD_FILES + 2]; +XSegment gridSegments[BOARD_RANKS + BOARD_FILES + 2]; +XSegment jailGridSegments[BOARD_RANKS + BOARD_FILES + 6]; +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; +typedef unsigned int BoardSize; +BoardSize boardSize; +Boolean chessProgram; +int minX, minY; // [HGM] placement: volatile limits on upper-left corner 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, @@ -459,20 +528,40 @@ Pixel timerForegroundPixel, timerBackgroundPixel; Pixel buttonForegroundPixel, buttonBackgroundPixel; char *chessDir, *programName, *programVersion, *gameCopyFilename, *gamePasteFilename; +Boolean alwaysOnTop = False; +Boolean saveSettingsOnExit; +char *settingsFileName; +char *icsTextMenuString; +char *icsNames; +char *firstChessProgramNames; +char *secondChessProgramNames; + +WindowPlacement wpMain; +WindowPlacement wpConsole; +WindowPlacement wpComment; +WindowPlacement wpMoveHistory; +WindowPlacement wpEvalGraph; +WindowPlacement wpEngineOutput; +WindowPlacement wpGameList; +WindowPlacement wpTags; #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 */ +Pixmap xpmBoardBitmap[2]; +int useImages, useImageSqs, useTexture, textureW[2], textureH[2]; +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) @@ -508,163 +597,206 @@ static Pixmap xpmMask[BlackKing + 1]; SizeDefaults sizeDefaults[] = SIZE_DEFAULTS; MenuItem fileMenu[] = { - {N_("Reset Game"), ResetProc}, - {"----", NothingProc}, - {N_("Load Game"), LoadGameProc}, - {N_("Load Next Game"), LoadNextGameProc}, - {N_("Load Previous Game"), LoadPrevGameProc}, - {N_("Reload Same Game"), ReloadGameProc}, - {N_("Save Game"), SaveGameProc}, - {"----", NothingProc}, - {N_("Copy Game"), CopyGameProc}, - {N_("Paste Game"), PasteGameProc}, - {"----", NothingProc}, - {N_("Load Position"), LoadPositionProc}, - {N_("Load Next Position"), LoadNextPositionProc}, - {N_("Load Previous Position"), LoadPrevPositionProc}, - {N_("Reload Same Position"), ReloadPositionProc}, - {N_("Save Position"), SavePositionProc}, - {"----", NothingProc}, - {N_("Copy Position"), CopyPositionProc}, - {N_("Paste Position"), PastePositionProc}, - {"----", NothingProc}, - {N_("Mail Move"), MailMoveProc}, - {N_("Reload CMail Message"), ReloadCmailMsgProc}, - {"----", NothingProc}, - {N_("Exit"), QuitProc}, - {NULL, NULL} + {N_("New Game Ctrl+N"), "New Game", ResetProc}, + {N_("New Shuffle Game ..."), "New Shuffle Game", ShuffleMenuProc}, + {N_("New Variant ... Alt+Shift+V"), "New Variant", NewVariantProc}, // [HGM] variant: not functional yet + {"----", NULL, NothingProc}, + {N_("Load Game Ctrl+O"), "Load Game", LoadGameProc}, + {N_("Load Position Ctrl+Shift+O"), "Load Position", LoadPositionProc}, +// {N_("Load Next Game"), "Load Next Game", LoadNextGameProc}, +// {N_("Load Previous Game"), "Load Previous Game", LoadPrevGameProc}, +// {N_("Reload Same Game"), "Reload Same Game", ReloadGameProc}, + {N_("Next Position Shift+PgDn"), "Load Next Position", LoadNextPositionProc}, + {N_("Prev Position Shift+PgUp"), "Load Previous Position", LoadPrevPositionProc}, + {"----", NULL, NothingProc}, +// {N_("Reload Same Position"), "Reload Same Position", ReloadPositionProc}, + {N_("Save Game Ctrl+S"), "Save Game", SaveGameProc}, + {N_("Save Position Ctrl+Shift+S"), "Save Position", SavePositionProc}, + {"----", NULL, NothingProc}, + {N_("Mail Move"), "Mail Move", MailMoveProc}, + {N_("Reload CMail Message"), "Reload CMail Message", ReloadCmailMsgProc}, + {"----", NULL, NothingProc}, + {N_("Quit Ctr+Q"), "Exit", QuitProc}, + {NULL, NULL, NULL} +}; + +MenuItem editMenu[] = { + {N_("Copy Game Ctrl+C"), "Copy Game", CopyGameProc}, + {N_("Copy Position Ctrl+Shift+C"), "Copy Position", CopyPositionProc}, + {"----", NULL, NothingProc}, + {N_("Paste Game Ctrl+V"), "Paste Game", PasteGameProc}, + {N_("Paste Position Ctrl+Shift+V"), "Paste Position", PastePositionProc}, + {"----", NULL, NothingProc}, + {N_("Edit Game Ctrl+E"), "Edit Game", EditGameProc}, + {N_("Edit Position Ctrl+Shift+E"), "Edit Position", EditPositionProc}, + {N_("Edit Tags"), "Edit Tags", EditTagsProc}, + {N_("Edit Comment"), "Edit Comment", EditCommentProc}, + {"----", NULL, NothingProc}, + {N_("Revert Home"), "Revert", RevertProc}, + {N_("Annotate"), "Annotate", AnnotateProc}, + {N_("Truncate Game End"), "Truncate Game", TruncateGameProc}, + {"----", NULL, NothingProc}, + {N_("Backward Alt+Left"), "Backward", BackwardProc}, + {N_("Forward Alt+Right"), "Forward", ForwardProc}, + {N_("Back to Start Alt+Home"), "Back to Start", ToStartProc}, + {N_("Forward to End Alt+End"), "Forward to End", ToEndProc}, + {NULL, NULL, NULL} +}; + +MenuItem viewMenu[] = { + {N_("Flip View F2"), "Flip View", FlipViewProc}, + {"----", NULL, NothingProc}, + {N_("Engine Output Alt+Shift+O"), "Show Engine Output", EngineOutputProc}, + {N_("Move History Alt+Shift+H"), "Show Move History", HistoryShowProc}, // [HGM] hist: activate 4.2.7 code + {N_("Evaluation Graph Alt+Shift+E"), "Show Evaluation Graph", EvalGraphProc}, + {N_("Game List Alt+Shift+G"), "Show Game List", ShowGameListProc}, + {"----", NULL, NothingProc}, + {N_("Tags"), "Show Tags", EditTagsProc}, + {N_("Comments"), "Show Comments", EditCommentProc}, + {N_("ICS Input Box"), "ICS Input Box", IcsInputBoxProc}, + {NULL, NULL, NULL} }; MenuItem modeMenu[] = { - {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}, - {N_("Show Game List"), ShowGameListProc}, - {N_("Show Move List"), HistoryShowProc}, - {N_("Edit Tags"), EditTagsProc}, - {N_("Edit Comment"), EditCommentProc}, - {N_("ICS Input Box"), IcsInputBoxProc}, - {N_("Pause"), PauseProc}, - {NULL, NULL} + {N_("Machine White Ctrl+W"), "Machine White", MachineWhiteProc}, + {N_("Machine Black Ctrl+B"), "Machine Black", MachineBlackProc}, + {N_("Two Machines Ctrl+T"), "Two Machines", TwoMachinesProc}, + {N_("Analysis Mode Ctrl+A"), "Analysis Mode", AnalyzeModeProc}, + {N_("Analyze File Ctrl+F"), "Analyze File", AnalyzeFileProc }, + {N_("Edit Game Ctrl+E"), "Edit Game", EditGameProc}, + {N_("Edit Position Ctrl+Shift+E"), "Edit Position", EditPositionProc}, + {N_("Training"), "Training", TrainingProc}, + {N_("ICS Client"), "ICS Client", IcsClientProc}, + {"----", NULL, NothingProc}, + {N_("Pause Pause"), "Pause", PauseProc}, + {NULL, NULL, NULL} }; MenuItem actionMenu[] = { - {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}, - {NULL, NULL} + {N_("Accept F3"), "Accept", AcceptProc}, + {N_("Decline F4"), "Decline", DeclineProc}, + {N_("Rematch F12"), "Rematch", RematchProc}, + {"----", NULL, NothingProc}, + {N_("Call Flag F5"), "Call Flag", CallFlagProc}, + {N_("Draw F6"), "Draw", DrawProc}, + {N_("Adjourn F7"), "Adjourn", AdjournProc}, + {N_("Abort F8"),"Abort", AbortProc}, + {N_("Resign F9"), "Resign", ResignProc}, + {"----", NULL, NothingProc}, + {N_("Stop Observing F10"), "Stop Observing", StopObservingProc}, + {N_("Stop Examining F11"), "Stop Examining", StopExaminingProc}, + {N_("Upload to Examine"), "Upload to Examine", UploadProc}, + {"----", NULL, NothingProc}, + {N_("Adjudicate to White"), "Adjudicate to White", AdjuWhiteProc}, + {N_("Adjudicate to Black"), "Adjudicate to Black", AdjuBlackProc}, + {N_("Adjudicate Draw"), "Adjudicate Draw", AdjuDrawProc}, + {NULL, NULL, NULL} }; -MenuItem stepMenu[] = { - {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 engineMenu[] = { + {N_("Engine #1 Settings ..."), "Engine #1 Settings", FirstSettingsProc}, + {N_("Engine #2 Settings ..."), "Engine #2 Settings", SecondSettingsProc}, + {"----", NULL, NothingProc}, + {N_("Hint"), "Hint", HintProc}, + {N_("Book"), "Book", BookProc}, + {"----", NULL, NothingProc}, + {N_("Move Now Ctrl+M"), "Move Now", MoveNowProc}, + {N_("Retract Move Ctrl+X"), "Retract Move", RetractMoveProc}, + {NULL, NULL, NULL} +}; MenuItem optionsMenu[] = { - {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_("Flip View"), FlipViewProc}, - {N_("Get Move List"), GetMoveListProc}, + {N_("Time Control ... Alt+Shift+T"), "Time Control", TimeControlProc}, + {N_("Common Engine ... Alt+Shift+U"), "Common Engine", UciMenuProc}, + {N_("Adjudications ... Alt+Shift+J"), "Adjudications", EngineMenuProc}, + {N_("Game List ..."), "Game List", GameListOptionsPopUp}, + {"----", NULL, NothingProc}, + {N_("Always Queen Ctrl+Shift+Q"), "Always Queen", AlwaysQueenProc}, + {N_("Animate Dragging"), "Animate Dragging", AnimateDraggingProc}, + {N_("Animate Moving Ctrl+Shift+A"), "Animate Moving", AnimateMovingProc}, + {N_("Auto Comment"), "Auto Comment", AutocommProc}, + {N_("Auto Flag Ctrl+Shift+F"), "Auto Flag", AutoflagProc}, + {N_("Auto Flip View"), "Auto Flip View", AutoflipProc}, + {N_("Auto Observe"), "Auto Observe", AutobsProc}, + {N_("Auto Raise Board"), "Auto Raise Board", AutoraiseProc}, + {N_("Auto Save"), "Auto Save", AutosaveProc}, + {N_("Blindfold"), "Blindfold", BlindfoldProc}, + {N_("Flash Moves"), "Flash Moves", FlashMovesProc}, + {N_("Get Move List"), "Get Move List", GetMoveListProc}, #if HIGHDRAG - {N_("Highlight Dragging"), HighlightDraggingProc}, + {N_("Highlight Dragging"), "Highlight Dragging", HighlightDraggingProc}, #endif - {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_("Show Thinking"), ShowThinkingProc}, - {N_("Test Legality"), TestLegalityProc}, - {NULL, NULL} + {N_("Highlight Last Move"), "Highlight Last Move", HighlightLastMoveProc}, + {N_("Highlight With Arrow"), "Arrow", HighlightArrowProc}, + {N_("Move Sound"), "Move Sound", MoveSoundProc}, + {N_("ICS Alarm"), "ICS Alarm", IcsAlarmProc}, + {N_("One-Click Moving"), "OneClick", OneClickProc}, + {N_("Periodic Updates"), "Periodic Updates", PeriodicUpdatesProc}, + {N_("Ponder Next Move Ctrl+Shift+P"), "Ponder Next Move", PonderNextMoveProc}, + {N_("Popup Exit Message"), "Popup Exit Message", PopupExitMessageProc}, + {N_("Popup Move Errors"), "Popup Move Errors", PopupMoveErrorsProc}, + {N_("Premove"), "Premove", PremoveProc}, + {N_("Quiet Play"), "Quiet Play", QuietPlayProc}, + {N_("Show Coords"), "Show Coords", ShowCoordsProc}, + {N_("Hide Thinking Ctrl+Shift+H"), "Hide Thinking", HideThinkingProc}, + {N_("Test Legality Ctrl+Shift+L"), "Test Legality", TestLegalityProc}, + {"----", NULL, NothingProc}, + {N_("Save Settings Now"), "Save Settings Now", SaveSettingsProc}, + {N_("Save Settings on Exit"), "Save Settings on Exit", SaveOnExitProc}, + {NULL, NULL, NULL} }; MenuItem helpMenu[] = { - {N_("Info XBoard"), InfoProc}, - {N_("Man XBoard"), ManProc}, - {"----", NothingProc}, - {N_("Hint"), HintProc}, - {N_("Book"), BookProc}, - {"----", NothingProc}, - {N_("About XBoard"), AboutProc}, - {NULL, NULL} + {N_("Info XBoard"), "Info XBoard", InfoProc}, + {N_("Man XBoard F1"), "Man XBoard", ManProc}, + {"----", NULL, NothingProc}, + {N_("About XBoard"), "About XBoard", AboutProc}, + {NULL, NULL, NULL} }; Menu menuBar[] = { - {N_("File"), fileMenu}, - {N_("Mode"), modeMenu}, - {N_("Action"), actionMenu}, - {N_("Step"), stepMenu}, - {N_("Options"), optionsMenu}, - {N_("Help"), helpMenu}, - {NULL, NULL} + {N_("File"), "File", fileMenu}, + {N_("Edit"), "Edit", editMenu}, + {N_("View"), "View", viewMenu}, + {N_("Mode"), "Mode", modeMenu}, + {N_("Action"), "Action", actionMenu}, + {N_("Engine"), "Engine", engineMenu}, + {N_("Options"), "Options", optionsMenu}, + {N_("Help"), "Help", helpMenu}, + {NULL, NULL, NULL} }; - -/* Label on pause button */ -#define PAUSE_BUTTON N_("P") +#define PAUSE_BUTTON "P" MenuItem buttonBar[] = { - {"<<", ToStartProc}, - {"<", BackwardProc}, - {PAUSE_BUTTON, PauseProc}, - {">", ForwardProc}, - {">>", ToEndProc}, - {NULL, NULL} + {"<<", "<<", ToStartProc}, + {"<", "<", BackwardProc}, + {PAUSE_BUTTON, PAUSE_BUTTON, PauseProc}, + {">", ">", ForwardProc}, + {">>", ">>", ToEndProc}, + {NULL, NULL, NULL} }; -#define PIECE_MENU_SIZE 11 +#define PIECE_MENU_SIZE 18 String pieceMenuStrings[2][PIECE_MENU_SIZE] = { { N_("White"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"), - N_("Queen"), N_("King"), "----", N_("Empty square"), N_("Clear board") }, + 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_("Empty square"), N_("Clear board") }, - }; + 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 @@ -735,719 +867,24 @@ Arg timerArgs[] = { }; XtResource clientResources[] = { - { "whitePieceColor", "whitePieceColor", XtRString, sizeof(String), - XtOffset(AppDataPtr, whitePieceColor), XtRString, - WHITE_PIECE_COLOR }, - { "blackPieceColor", "blackPieceColor", XtRString, sizeof(String), - XtOffset(AppDataPtr, blackPieceColor), XtRString, - BLACK_PIECE_COLOR }, - { "lightSquareColor", "lightSquareColor", XtRString, - sizeof(String), XtOffset(AppDataPtr, lightSquareColor), - XtRString, LIGHT_SQUARE_COLOR }, - { "darkSquareColor", "darkSquareColor", XtRString, sizeof(String), - XtOffset(AppDataPtr, darkSquareColor), XtRString, - DARK_SQUARE_COLOR }, - { "highlightSquareColor", "highlightSquareColor", XtRString, - sizeof(String), XtOffset(AppDataPtr, highlightSquareColor), - XtRString, HIGHLIGHT_SQUARE_COLOR }, - { "premoveHighlightColor", "premoveHighlightColor", XtRString, - sizeof(String), XtOffset(AppDataPtr, premoveHighlightColor), - XtRString, PREMOVE_HIGHLIGHT_COLOR }, - { "movesPerSession", "movesPerSession", XtRInt, sizeof(int), - XtOffset(AppDataPtr, movesPerSession), XtRImmediate, - (XtPointer) MOVES_PER_SESSION }, - { "timeIncrement", "timeIncrement", XtRInt, sizeof(int), - XtOffset(AppDataPtr, timeIncrement), XtRImmediate, - (XtPointer) TIME_INCREMENT }, - { "initString", "initString", XtRString, sizeof(String), - XtOffset(AppDataPtr, initString), XtRString, INIT_STRING }, - { "secondInitString", "secondInitString", XtRString, sizeof(String), - XtOffset(AppDataPtr, secondInitString), XtRString, INIT_STRING }, - { "firstComputerString", "firstComputerString", XtRString, - sizeof(String), XtOffset(AppDataPtr, firstComputerString), XtRString, - COMPUTER_STRING }, - { "secondComputerString", "secondComputerString", XtRString, - sizeof(String), XtOffset(AppDataPtr, secondComputerString), XtRString, - COMPUTER_STRING }, - { "firstChessProgram", "firstChessProgram", XtRString, - sizeof(String), XtOffset(AppDataPtr, firstChessProgram), - XtRString, FIRST_CHESS_PROGRAM }, - { "secondChessProgram", "secondChessProgram", XtRString, - sizeof(String), XtOffset(AppDataPtr, secondChessProgram), - XtRString, SECOND_CHESS_PROGRAM }, - { "firstPlaysBlack", "firstPlaysBlack", XtRBoolean, - sizeof(Boolean), XtOffset(AppDataPtr, firstPlaysBlack), - XtRImmediate, (XtPointer) False }, - { "noChessProgram", "noChessProgram", XtRBoolean, - sizeof(Boolean), XtOffset(AppDataPtr, noChessProgram), - XtRImmediate, (XtPointer) False }, - { "firstHost", "firstHost", XtRString, sizeof(String), - XtOffset(AppDataPtr, firstHost), XtRString, FIRST_HOST }, - { "secondHost", "secondHost", XtRString, sizeof(String), - XtOffset(AppDataPtr, secondHost), XtRString, SECOND_HOST }, - { "firstDirectory", "firstDirectory", XtRString, sizeof(String), - XtOffset(AppDataPtr, firstDirectory), XtRString, "" }, - { "secondDirectory", "secondDirectory", XtRString, sizeof(String), - XtOffset(AppDataPtr, secondDirectory), XtRString, "" }, - { "bitmapDirectory", "bitmapDirectory", XtRString, - sizeof(String), XtOffset(AppDataPtr, bitmapDirectory), - XtRString, "" }, - { "remoteShell", "remoteShell", XtRString, sizeof(String), - XtOffset(AppDataPtr, remoteShell), XtRString, REMOTE_SHELL }, - { "remoteUser", "remoteUser", XtRString, sizeof(String), - XtOffset(AppDataPtr, remoteUser), XtRString, "" }, - { "timeDelay", "timeDelay", XtRFloat, sizeof(float), - XtOffset(AppDataPtr, timeDelay), XtRString, - (XtPointer) TIME_DELAY_QUOTE }, - { "timeControl", "timeControl", XtRString, sizeof(String), - XtOffset(AppDataPtr, timeControl), XtRString, - (XtPointer) TIME_CONTROL }, - { "internetChessServerMode", "internetChessServerMode", - XtRBoolean, sizeof(Boolean), - XtOffset(AppDataPtr, icsActive), XtRImmediate, - (XtPointer) False }, - { "internetChessServerHost", "internetChessServerHost", - XtRString, sizeof(String), - XtOffset(AppDataPtr, icsHost), - XtRString, (XtPointer) ICS_HOST }, - { "internetChessServerPort", "internetChessServerPort", - XtRString, sizeof(String), - XtOffset(AppDataPtr, icsPort), XtRString, - (XtPointer) ICS_PORT }, - { "internetChessServerCommPort", "internetChessServerCommPort", - XtRString, sizeof(String), - XtOffset(AppDataPtr, icsCommPort), XtRString, - ICS_COMM_PORT }, - { "internetChessServerLogonScript", "internetChessServerLogonScript", - XtRString, sizeof(String), - XtOffset(AppDataPtr, icsLogon), XtRString, - ICS_LOGON }, - { "internetChessServerHelper", "internetChessServerHelper", - XtRString, sizeof(String), - XtOffset(AppDataPtr, icsHelper), XtRString, "" }, - { "internetChessServerInputBox", "internetChessServerInputBox", - XtRBoolean, sizeof(Boolean), - XtOffset(AppDataPtr, icsInputBox), XtRImmediate, - (XtPointer) False }, - { "icsAlarm", "icsAlarm", - XtRBoolean, sizeof(Boolean), - XtOffset(AppDataPtr, icsAlarm), XtRImmediate, - (XtPointer) True }, - { "icsAlarmTime", "icsAlarmTime", - XtRInt, sizeof(int), - XtOffset(AppDataPtr, icsAlarmTime), XtRImmediate, - (XtPointer) 5000 }, - { "useTelnet", "useTelnet", XtRBoolean, sizeof(Boolean), - XtOffset(AppDataPtr, useTelnet), XtRImmediate, - (XtPointer) False }, - { "telnetProgram", "telnetProgram", XtRString, sizeof(String), - XtOffset(AppDataPtr, telnetProgram), XtRString, TELNET_PROGRAM }, - { "gateway", "gateway", XtRString, sizeof(String), - XtOffset(AppDataPtr, gateway), XtRString, "" }, - { "loadGameFile", "loadGameFile", XtRString, sizeof(String), - XtOffset(AppDataPtr, loadGameFile), XtRString, "" }, - { "loadGameIndex", "loadGameIndex", - XtRInt, sizeof(int), - XtOffset(AppDataPtr, loadGameIndex), XtRImmediate, - (XtPointer) 0 }, - { "saveGameFile", "saveGameFile", XtRString, sizeof(String), - XtOffset(AppDataPtr, saveGameFile), XtRString, "" }, - { "autoRaiseBoard", "autoRaiseBoard", XtRBoolean, - sizeof(Boolean), XtOffset(AppDataPtr, autoRaiseBoard), - XtRImmediate, (XtPointer) True }, - { "autoSaveGames", "autoSaveGames", XtRBoolean, - sizeof(Boolean), XtOffset(AppDataPtr, autoSaveGames), - XtRImmediate, (XtPointer) False }, - { "blindfold", "blindfold", XtRBoolean, - sizeof(Boolean), XtOffset(AppDataPtr, blindfold), - XtRImmediate, (XtPointer) False }, - { "loadPositionFile", "loadPositionFile", XtRString, - sizeof(String), XtOffset(AppDataPtr, loadPositionFile), - XtRString, "" }, - { "loadPositionIndex", "loadPositionIndex", - XtRInt, sizeof(int), - XtOffset(AppDataPtr, loadPositionIndex), XtRImmediate, - (XtPointer) 1 }, - { "savePositionFile", "savePositionFile", XtRString, - sizeof(String), XtOffset(AppDataPtr, savePositionFile), - XtRString, "" }, - { "matchMode", "matchMode", XtRBoolean, sizeof(Boolean), - XtOffset(AppDataPtr, matchMode), XtRImmediate, (XtPointer) False }, - { "matchGames", "matchGames", XtRInt, sizeof(int), - XtOffset(AppDataPtr, matchGames), XtRImmediate, - (XtPointer) 0 }, - { "monoMode", "monoMode", XtRBoolean, sizeof(Boolean), - XtOffset(AppDataPtr, monoMode), XtRImmediate, - (XtPointer) False }, - { "debugMode", "debugMode", XtRBoolean, sizeof(Boolean), - XtOffset(AppDataPtr, debugMode), XtRImmediate, - (XtPointer) False }, - { "clockMode", "clockMode", XtRBoolean, sizeof(Boolean), - XtOffset(AppDataPtr, clockMode), XtRImmediate, - (XtPointer) True }, - { "boardSize", "boardSize", XtRString, sizeof(String), - XtOffset(AppDataPtr, boardSize), XtRString, "" }, - { "searchTime", "searchTime", XtRString, sizeof(String), - XtOffset(AppDataPtr, searchTime), XtRString, - (XtPointer) "" }, - { "searchDepth", "searchDepth", XtRInt, sizeof(int), - XtOffset(AppDataPtr, searchDepth), XtRImmediate, - (XtPointer) 0 }, - { "showCoords", "showCoords", XtRBoolean, sizeof(Boolean), - XtOffset(AppDataPtr, showCoords), XtRImmediate, - (XtPointer) False }, - { "showJail", "showJail", XtRInt, sizeof(int), - XtOffset(AppDataPtr, showJail), XtRImmediate, - (XtPointer) 0 }, - { "showThinking", "showThinking", XtRBoolean, sizeof(Boolean), - XtOffset(AppDataPtr, showThinking), XtRImmediate, - (XtPointer) False }, - { "ponderNextMove", "ponderNextMove", XtRBoolean, sizeof(Boolean), - XtOffset(AppDataPtr, ponderNextMove), XtRImmediate, - (XtPointer) True }, - { "periodicUpdates", "periodicUpdates", XtRBoolean, sizeof(Boolean), - XtOffset(AppDataPtr, periodicUpdates), XtRImmediate, - (XtPointer) True }, - { "clockFont", "clockFont", XtRString, sizeof(String), - XtOffset(AppDataPtr, clockFont), XtRString, CLOCK_FONT }, - { "coordFont", "coordFont", XtRString, sizeof(String), - XtOffset(AppDataPtr, coordFont), XtRString, COORD_FONT }, - { "font", "font", XtRString, sizeof(String), - XtOffset(AppDataPtr, font), XtRString, DEFAULT_FONT }, - { "ringBellAfterMoves", "ringBellAfterMoves", - XtRBoolean, sizeof(Boolean), - XtOffset(AppDataPtr, ringBellAfterMoves), - XtRImmediate, (XtPointer) False }, - { "autoCallFlag", "autoCallFlag", XtRBoolean, - sizeof(Boolean), XtOffset(AppDataPtr, autoCallFlag), - XtRImmediate, (XtPointer) False }, - { "autoFlipView", "autoFlipView", XtRBoolean, - sizeof(Boolean), XtOffset(AppDataPtr, autoFlipView), - XtRImmediate, (XtPointer) True }, - { "autoObserve", "autoObserve", XtRBoolean, - sizeof(Boolean), XtOffset(AppDataPtr, autoObserve), - XtRImmediate, (XtPointer) False }, - { "autoComment", "autoComment", XtRBoolean, - sizeof(Boolean), XtOffset(AppDataPtr, autoComment), - XtRImmediate, (XtPointer) False }, - { "getMoveList", "getMoveList", XtRBoolean, - sizeof(Boolean), XtOffset(AppDataPtr, getMoveList), - XtRImmediate, (XtPointer) True }, -#if HIGHDRAG - { "highlightDragging", "highlightDragging", XtRBoolean, - sizeof(Boolean), XtOffset(AppDataPtr, highlightDragging), - XtRImmediate, (XtPointer) False }, -#endif - { "highlightLastMove", "highlightLastMove", XtRBoolean, - sizeof(Boolean), XtOffset(AppDataPtr, highlightLastMove), - XtRImmediate, (XtPointer) False }, - { "premove", "premove", XtRBoolean, - sizeof(Boolean), XtOffset(AppDataPtr, premove), - XtRImmediate, (XtPointer) True }, - { "testLegality", "testLegality", XtRBoolean, - sizeof(Boolean), XtOffset(AppDataPtr, testLegality), - XtRImmediate, (XtPointer) True }, - { "flipView", "flipView", XtRBoolean, - sizeof(Boolean), XtOffset(AppDataPtr, flipView), - XtRImmediate, (XtPointer) False }, - { "cmail", "cmailGameName", XtRString, sizeof(String), - XtOffset(AppDataPtr, cmailGameName), XtRString, "" }, - { "alwaysPromoteToQueen", "alwaysPromoteToQueen", XtRBoolean, - sizeof(Boolean), XtOffset(AppDataPtr, alwaysPromoteToQueen), - XtRImmediate, (XtPointer) False }, - { "oldSaveStyle", "oldSaveStyle", XtRBoolean, - sizeof(Boolean), XtOffset(AppDataPtr, oldSaveStyle), - XtRImmediate, (XtPointer) False }, - { "quietPlay", "quietPlay", XtRBoolean, - sizeof(Boolean), XtOffset(AppDataPtr, quietPlay), - XtRImmediate, (XtPointer) False }, - { "titleInWindow", "titleInWindow", XtRBoolean, - sizeof(Boolean), XtOffset(AppDataPtr, titleInWindow), - XtRImmediate, (XtPointer) False }, - { "localLineEditing", "localLineEditing", XtRBoolean, - sizeof(Boolean), XtOffset(AppDataPtr, localLineEditing), - XtRImmediate, (XtPointer) True }, /* not implemented, must be True */ -#ifdef ZIPPY - { "zippyTalk", "zippyTalk", XtRBoolean, - sizeof(Boolean), XtOffset(AppDataPtr, zippyTalk), - XtRImmediate, (XtPointer) ZIPPY_TALK }, - { "zippyPlay", "zippyPlay", XtRBoolean, - sizeof(Boolean), XtOffset(AppDataPtr, zippyPlay), - XtRImmediate, (XtPointer) ZIPPY_PLAY }, - { "zippyLines", "zippyLines", XtRString, sizeof(String), - XtOffset(AppDataPtr, zippyLines), XtRString, ZIPPY_LINES }, - { "zippyPinhead", "zippyPinhead", XtRString, sizeof(String), - XtOffset(AppDataPtr, zippyPinhead), XtRString, ZIPPY_PINHEAD }, - { "zippyPassword", "zippyPassword", XtRString, sizeof(String), - XtOffset(AppDataPtr, zippyPassword), XtRString, ZIPPY_PASSWORD }, - { "zippyPassword2", "zippyPassword2", XtRString, sizeof(String), - XtOffset(AppDataPtr, zippyPassword2), XtRString, ZIPPY_PASSWORD2 }, - { "zippyWrongPassword", "zippyWrongPassword", XtRString, sizeof(String), - XtOffset(AppDataPtr, zippyWrongPassword), XtRString, - ZIPPY_WRONG_PASSWORD }, - { "zippyAcceptOnly", "zippyAcceptOnly", XtRString, sizeof(String), - XtOffset(AppDataPtr, zippyAcceptOnly), XtRString, ZIPPY_ACCEPT_ONLY }, - { "zippyUseI", "zippyUseI", XtRBoolean, - sizeof(Boolean), XtOffset(AppDataPtr, zippyUseI), - XtRImmediate, (XtPointer) ZIPPY_USE_I }, - { "zippyBughouse", "zippyBughouse", XtRInt, - sizeof(int), XtOffset(AppDataPtr, zippyBughouse), - XtRImmediate, (XtPointer) ZIPPY_BUGHOUSE }, - { "zippyNoplayCrafty", "zippyNoplayCrafty", XtRBoolean, - sizeof(Boolean), XtOffset(AppDataPtr, zippyNoplayCrafty), - XtRImmediate, (XtPointer) ZIPPY_NOPLAY_CRAFTY }, - { "zippyGameEnd", "zippyGameEnd", XtRString, sizeof(String), - XtOffset(AppDataPtr, zippyGameEnd), XtRString, ZIPPY_GAME_END }, - { "zippyGameStart", "zippyGameStart", XtRString, sizeof(String), - XtOffset(AppDataPtr, zippyGameStart), XtRString, ZIPPY_GAME_START }, - { "zippyAdjourn", "zippyAdjourn", XtRBoolean, - sizeof(Boolean), XtOffset(AppDataPtr, zippyAdjourn), - XtRImmediate, (XtPointer) ZIPPY_ADJOURN }, - { "zippyAbort", "zippyAbort", XtRBoolean, - sizeof(Boolean), XtOffset(AppDataPtr, zippyAbort), - XtRImmediate, (XtPointer) ZIPPY_ABORT }, - { "zippyVariants", "zippyVariants", XtRString, sizeof(String), - XtOffset(AppDataPtr, zippyVariants), XtRString, ZIPPY_VARIANTS }, - { "zippyMaxGames", "zippyMaxGames", XtRInt, sizeof(int), - XtOffset(AppDataPtr, zippyMaxGames), XtRImmediate, - (XtPointer) ZIPPY_MAX_GAMES }, - { "zippyReplayTimeout", "zippyReplayTimeout", XtRInt, sizeof(int), - XtOffset(AppDataPtr, zippyReplayTimeout), XtRImmediate, - (XtPointer) ZIPPY_REPLAY_TIMEOUT }, -#endif { "flashCount", "flashCount", XtRInt, sizeof(int), XtOffset(AppDataPtr, flashCount), XtRImmediate, (XtPointer) FLASH_COUNT }, - { "flashRate", "flashRate", XtRInt, sizeof(int), - XtOffset(AppDataPtr, flashRate), XtRImmediate, - (XtPointer) FLASH_RATE }, - { "pixmapDirectory", "pixmapDirectory", XtRString, - sizeof(String), XtOffset(AppDataPtr, pixmapDirectory), - XtRString, "" }, - { "msLoginDelay", "msLoginDelay", XtRInt, sizeof(int), - XtOffset(AppDataPtr, msLoginDelay), XtRImmediate, - (XtPointer) MS_LOGIN_DELAY }, - { "colorizeMessages", "colorizeMessages", XtRBoolean, - sizeof(Boolean), XtOffset(AppDataPtr, colorize), - XtRImmediate, (XtPointer) False }, - { "colorShout", "colorShout", XtRString, - sizeof(String), XtOffset(AppDataPtr, colorShout), - XtRString, COLOR_SHOUT }, - { "colorSShout", "colorSShout", XtRString, - sizeof(String), XtOffset(AppDataPtr, colorSShout), - XtRString, COLOR_SSHOUT }, - { "colorChannel1", "colorChannel1", XtRString, - sizeof(String), XtOffset(AppDataPtr, colorChannel1), - XtRString, COLOR_CHANNEL1 }, - { "colorChannel", "colorChannel", XtRString, - sizeof(String), XtOffset(AppDataPtr, colorChannel), - XtRString, COLOR_CHANNEL }, - { "colorKibitz", "colorKibitz", XtRString, - sizeof(String), XtOffset(AppDataPtr, colorKibitz), - XtRString, COLOR_KIBITZ }, - { "colorTell", "colorTell", XtRString, - sizeof(String), XtOffset(AppDataPtr, colorTell), - XtRString, COLOR_TELL }, - { "colorChallenge", "colorChallenge", XtRString, - sizeof(String), XtOffset(AppDataPtr, colorChallenge), - XtRString, COLOR_CHALLENGE }, - { "colorRequest", "colorRequest", XtRString, - sizeof(String), XtOffset(AppDataPtr, colorRequest), - XtRString, COLOR_REQUEST }, - { "colorSeek", "colorSeek", XtRString, - sizeof(String), XtOffset(AppDataPtr, colorSeek), - XtRString, COLOR_SEEK }, - { "colorNormal", "colorNormal", XtRString, - sizeof(String), XtOffset(AppDataPtr, colorNormal), - XtRString, COLOR_NORMAL }, - { "soundProgram", "soundProgram", XtRString, - sizeof(String), XtOffset(AppDataPtr, soundProgram), - XtRString, "play" }, - { "soundShout", "soundShout", XtRString, - sizeof(String), XtOffset(AppDataPtr, soundShout), - XtRString, "" }, - { "soundSShout", "soundSShout", XtRString, - sizeof(String), XtOffset(AppDataPtr, soundSShout), - XtRString, "" }, - { "soundChannel1", "soundChannel1", XtRString, - sizeof(String), XtOffset(AppDataPtr, soundChannel1), - XtRString, "" }, - { "soundChannel", "soundChannel", XtRString, - sizeof(String), XtOffset(AppDataPtr, soundChannel), - XtRString, "" }, - { "soundKibitz", "soundKibitz", XtRString, - sizeof(String), XtOffset(AppDataPtr, soundKibitz), - XtRString, "" }, - { "soundTell", "soundTell", XtRString, - sizeof(String), XtOffset(AppDataPtr, soundTell), - XtRString, "" }, - { "soundChallenge", "soundChallenge", XtRString, - sizeof(String), XtOffset(AppDataPtr, soundChallenge), - XtRString, "" }, - { "soundRequest", "soundRequest", XtRString, - sizeof(String), XtOffset(AppDataPtr, soundRequest), - XtRString, "" }, - { "soundSeek", "soundSeek", XtRString, - sizeof(String), XtOffset(AppDataPtr, soundSeek), - XtRString, "" }, - { "soundMove", "soundMove", XtRString, - sizeof(String), XtOffset(AppDataPtr, soundMove), - XtRString, "$" }, - { "soundIcsWin", "soundIcsWin", XtRString, - sizeof(String), XtOffset(AppDataPtr, soundIcsWin), - XtRString, "" }, - { "soundIcsLoss", "soundIcsLoss", XtRString, - sizeof(String), XtOffset(AppDataPtr, soundIcsLoss), - XtRString, "" }, - { "soundIcsDraw", "soundIcsDraw", XtRString, - sizeof(String), XtOffset(AppDataPtr, soundIcsDraw), - XtRString, "" }, - { "soundIcsUnfinished", "soundIcsUnfinished", XtRString, - sizeof(String), XtOffset(AppDataPtr, soundIcsUnfinished), - XtRString, "" }, - { "soundIcsAlarm", "soundIcsAlarm", XtRString, - sizeof(String), XtOffset(AppDataPtr, soundIcsAlarm), - XtRString, "$" }, - { "reuseFirst", "reuseFirst", XtRBoolean, - sizeof(Boolean), XtOffset(AppDataPtr, reuseFirst), - XtRImmediate, (XtPointer) True }, - { "reuseSecond", "reuseSecond", XtRBoolean, - sizeof(Boolean), XtOffset(AppDataPtr, reuseSecond), - XtRImmediate, (XtPointer) True }, - { "animateDragging", "animateDragging", XtRBoolean, - sizeof(Boolean), XtOffset(AppDataPtr, animateDragging), - XtRImmediate, (XtPointer) True }, - { "animateMoving", "animateMoving", XtRBoolean, - sizeof(Boolean), XtOffset(AppDataPtr, animate), - XtRImmediate, (XtPointer) True }, - { "animateSpeed", "animateSpeed", XtRInt, - sizeof(int), XtOffset(AppDataPtr, animSpeed), - XtRImmediate, (XtPointer)10 }, - { "popupExitMessage", "popupExitMessage", XtRBoolean, - sizeof(Boolean), XtOffset(AppDataPtr, popupExitMessage), - XtRImmediate, (XtPointer) True }, - { "popupMoveErrors", "popupMoveErrors", XtRBoolean, - sizeof(Boolean), XtOffset(AppDataPtr, popupMoveErrors), - XtRImmediate, (XtPointer) False }, - { "fontSizeTolerance", "fontSizeTolerance", XtRInt, - sizeof(int), XtOffset(AppDataPtr, fontSizeTolerance), - XtRImmediate, (XtPointer)4 }, - { "initialMode", "initialMode", XtRString, - sizeof(String), XtOffset(AppDataPtr, initialMode), - XtRImmediate, (XtPointer) "" }, - { "variant", "variant", XtRString, - sizeof(String), XtOffset(AppDataPtr, variant), - XtRImmediate, (XtPointer) "normal" }, - { "firstProtocolVersion", "firstProtocolVersion", XtRInt, - sizeof(int), XtOffset(AppDataPtr, firstProtocolVersion), - XtRImmediate, (XtPointer)PROTOVER }, - { "secondProtocolVersion", "secondProtocolVersion", XtRInt, - sizeof(int), XtOffset(AppDataPtr, secondProtocolVersion), - XtRImmediate, (XtPointer)PROTOVER }, - { "showButtonBar", "showButtonBar", XtRBoolean, - sizeof(Boolean), XtOffset(AppDataPtr, showButtonBar), - XtRImmediate, (XtPointer) True }, - /* icsEngineAnalyze */ - {"icsEngineAnalyze", "icsEngineAnalyze", XtRBoolean, - sizeof(Boolean), XtOffset(AppDataPtr, icsEngineAnalyze), - XtRImmediate, (XtPointer) False }, }; XrmOptionDescRec shellOptions[] = { - { "-whitePieceColor", "whitePieceColor", XrmoptionSepArg, NULL }, - { "-blackPieceColor", "blackPieceColor", XrmoptionSepArg, NULL }, - { "-lightSquareColor", "lightSquareColor", XrmoptionSepArg, NULL }, - { "-darkSquareColor", "darkSquareColor", XrmoptionSepArg, NULL }, - { "-highlightSquareColor", "highlightSquareColor", XrmoptionSepArg, NULL }, - { "-premoveHighlightColor", "premoveHighlightColor", XrmoptionSepArg,NULL}, - { "-movesPerSession", "movesPerSession", XrmoptionSepArg, NULL }, - { "-mps", "movesPerSession", XrmoptionSepArg, NULL }, - { "-timeIncrement", "timeIncrement", XrmoptionSepArg, NULL }, - { "-inc", "timeIncrement", XrmoptionSepArg, NULL }, - { "-initString", "initString", XrmoptionSepArg, NULL }, - { "-firstInitString", "initString", XrmoptionSepArg, NULL }, - { "-secondInitString", "secondInitString", XrmoptionSepArg, NULL }, - { "-firstComputerString", "firstComputerString", XrmoptionSepArg, NULL }, - { "-secondComputerString", "secondComputerString", XrmoptionSepArg, NULL }, - { "-firstChessProgram", "firstChessProgram", XrmoptionSepArg, NULL }, - { "-fcp", "firstChessProgram", XrmoptionSepArg, NULL }, - { "-secondChessProgram", "secondChessProgram", XrmoptionSepArg, NULL }, - { "-scp", "secondChessProgram", XrmoptionSepArg, NULL }, - { "-firstPlaysBlack", "firstPlaysBlack", XrmoptionSepArg, NULL }, - { "-fb", "firstPlaysBlack", XrmoptionNoArg, "True" }, - { "-xfb", "firstPlaysBlack", XrmoptionNoArg, "False" }, - { "-noChessProgram", "noChessProgram", XrmoptionSepArg, NULL }, - { "-ncp", "noChessProgram", XrmoptionNoArg, "True" }, - { "-xncp", "noChessProgram", XrmoptionNoArg, "False" }, - { "-firstHost", "firstHost", XrmoptionSepArg, NULL }, - { "-fh", "firstHost", XrmoptionSepArg, NULL }, - { "-secondHost", "secondHost", XrmoptionSepArg, NULL }, - { "-sh", "secondHost", XrmoptionSepArg, NULL }, - { "-firstDirectory", "firstDirectory", XrmoptionSepArg, NULL }, - { "-fd", "firstDirectory", XrmoptionSepArg, NULL }, - { "-secondDirectory", "secondDirectory", XrmoptionSepArg, NULL }, - { "-sd", "secondDirectory", XrmoptionSepArg, NULL }, - { "-bitmapDirectory", "bitmapDirectory", XrmoptionSepArg, NULL }, - { "-bm", "bitmapDirectory", XrmoptionSepArg, NULL }, - { "-remoteShell", "remoteShell", XrmoptionSepArg, NULL }, - { "-rsh", "remoteShell", XrmoptionSepArg, NULL }, - { "-remoteUser", "remoteUser", XrmoptionSepArg, NULL }, - { "-ruser", "remoteUser", XrmoptionSepArg, NULL }, - { "-timeDelay", "timeDelay", XrmoptionSepArg, NULL }, - { "-td", "timeDelay", XrmoptionSepArg, NULL }, - { "-timeControl", "timeControl", XrmoptionSepArg, NULL }, - { "-tc", "timeControl", XrmoptionSepArg, NULL }, - { "-internetChessServerMode", "internetChessServerMode", - XrmoptionSepArg, NULL }, - { "-ics", "internetChessServerMode", XrmoptionNoArg, "True" }, - { "-xics", "internetChessServerMode", XrmoptionNoArg, "False" }, - { "-internetChessServerHost", "internetChessServerHost", - XrmoptionSepArg, NULL }, - { "-icshost", "internetChessServerHost", XrmoptionSepArg, NULL }, - { "-internetChessServerPort", "internetChessServerPort", - XrmoptionSepArg, NULL }, - { "-icsport", "internetChessServerPort", XrmoptionSepArg, NULL }, - { "-internetChessServerCommPort", "internetChessServerCommPort", - XrmoptionSepArg, NULL }, - { "-icscomm", "internetChessServerCommPort", XrmoptionSepArg, NULL }, - { "-internetChessServerLogonScript", "internetChessServerLogonScript", - XrmoptionSepArg, NULL }, - { "-icslogon", "internetChessServerLogonScript", XrmoptionSepArg, NULL }, - { "-internetChessServerHelper", "internetChessServerHelper", - XrmoptionSepArg, NULL }, - { "-icshelper", "internetChessServerHelper", XrmoptionSepArg, NULL }, - { "-internetChessServerInputBox", "internetChessServerInputBox", - XrmoptionSepArg, NULL }, - { "-icsinput", "internetChessServerInputBox", XrmoptionNoArg, "True" }, - { "-xicsinput", "internetChessServerInputBox", XrmoptionNoArg, "False" }, - { "-icsAlarm", "icsAlarm", XrmoptionSepArg, NULL }, - { "-alarm", "icsAlarm", XrmoptionNoArg, "True" }, - { "-xalarm", "icsAlarm", XrmoptionNoArg, "False" }, - { "-icsAlarmTime", "icsAlarmTime", XrmoptionSepArg, NULL }, - { "-useTelnet", "useTelnet", XrmoptionSepArg, NULL }, - { "-telnet", "useTelnet", XrmoptionNoArg, "True" }, - { "-xtelnet", "useTelnet", XrmoptionNoArg, "False" }, - { "-telnetProgram", "telnetProgram", XrmoptionSepArg, NULL }, - { "-gateway", "gateway", XrmoptionSepArg, NULL }, - { "-loadGameFile", "loadGameFile", XrmoptionSepArg, NULL }, - { "-lgf", "loadGameFile", XrmoptionSepArg, NULL }, - { "-loadGameIndex", "loadGameIndex", XrmoptionSepArg, NULL }, - { "-lgi", "loadGameIndex", XrmoptionSepArg, NULL }, - { "-saveGameFile", "saveGameFile", XrmoptionSepArg, NULL }, - { "-sgf", "saveGameFile", XrmoptionSepArg, NULL }, - { "-autoSaveGames", "autoSaveGames", XrmoptionSepArg, NULL }, - { "-autosave", "autoSaveGames", XrmoptionNoArg, "True" }, - { "-xautosave", "autoSaveGames", XrmoptionNoArg, "False" }, - { "-autoRaiseBoard", "autoRaiseBoard", XrmoptionSepArg, NULL }, - { "-autoraise", "autoRaiseBoard", XrmoptionNoArg, "True" }, - { "-xautoraise", "autoRaiseBoard", XrmoptionNoArg, "False" }, - { "-blindfold", "blindfold", XrmoptionSepArg, NULL }, - { "-blind", "blindfold", XrmoptionNoArg, "True" }, - { "-xblind", "blindfold", XrmoptionNoArg, "False" }, - { "-loadPositionFile", "loadPositionFile", XrmoptionSepArg, NULL }, - { "-lpf", "loadPositionFile", XrmoptionSepArg, NULL }, - { "-loadPositionIndex", "loadPositionIndex", XrmoptionSepArg, NULL }, - { "-lpi", "loadPositionIndex", XrmoptionSepArg, NULL }, - { "-savePositionFile", "savePositionFile", XrmoptionSepArg, NULL }, - { "-spf", "savePositionFile", XrmoptionSepArg, NULL }, - { "-matchMode", "matchMode", XrmoptionSepArg, NULL }, - { "-mm", "matchMode", XrmoptionNoArg, "True" }, - { "-xmm", "matchMode", XrmoptionNoArg, "False" }, - { "-matchGames", "matchGames", XrmoptionSepArg, NULL }, - { "-mg", "matchGames", XrmoptionSepArg, NULL }, - { "-monoMode", "monoMode", XrmoptionSepArg, NULL }, - { "-mono", "monoMode", XrmoptionNoArg, "True" }, - { "-xmono", "monoMode", XrmoptionNoArg, "False" }, - { "-debugMode", "debugMode", XrmoptionSepArg, NULL }, - { "-debug", "debugMode", XrmoptionNoArg, "True" }, - { "-xdebug", "debugMode", XrmoptionNoArg, "False" }, - { "-clockMode", "clockMode", XrmoptionSepArg, NULL }, - { "-clock", "clockMode", XrmoptionNoArg, "True" }, - { "-xclock", "clockMode", XrmoptionNoArg, "False" }, - { "-boardSize", "boardSize", XrmoptionSepArg, NULL }, - { "-size", "boardSize", XrmoptionSepArg, NULL }, - { "-searchTime", "searchTime", XrmoptionSepArg, NULL }, - { "-st", "searchTime", XrmoptionSepArg, NULL }, - { "-searchDepth", "searchDepth", XrmoptionSepArg, NULL }, - { "-depth", "searchDepth", XrmoptionSepArg, NULL }, - { "-showCoords", "showCoords", XrmoptionSepArg, NULL }, - { "-coords", "showCoords", XrmoptionNoArg, "True" }, - { "-xcoords", "showCoords", XrmoptionNoArg, "False" }, -#if JAIL - { "-showJail", "showJail", XrmoptionSepArg, NULL }, - { "-jail", "showJail", XrmoptionNoArg, "1" }, - { "-sidejail", "showJail", XrmoptionNoArg, "2" }, - { "-xjail", "showJail", XrmoptionNoArg, "0" }, -#endif - { "-showThinking", "showThinking", XrmoptionSepArg, NULL }, - { "-thinking", "showThinking", XrmoptionNoArg, "True" }, - { "-xthinking", "showThinking", XrmoptionNoArg, "False" }, - { "-ponderNextMove", "ponderNextMove", XrmoptionSepArg, NULL }, - { "-ponder", "ponderNextMove", XrmoptionNoArg, "True" }, - { "-xponder", "ponderNextMove", XrmoptionNoArg, "False" }, - { "-periodicUpdates", "periodicUpdates", XrmoptionSepArg, NULL }, - { "-periodic", "periodicUpdates", XrmoptionNoArg, "True" }, - { "-xperiodic", "periodicUpdates", XrmoptionNoArg, "False" }, - { "-clockFont", "clockFont", XrmoptionSepArg, NULL }, - { "-coordFont", "coordFont", XrmoptionSepArg, NULL }, - { "-font", "font", XrmoptionSepArg, NULL }, - { "-ringBellAfterMoves", "ringBellAfterMoves", XrmoptionSepArg, NULL }, - { "-bell", "ringBellAfterMoves", XrmoptionNoArg, "True" }, - { "-xbell", "ringBellAfterMoves", XrmoptionNoArg, "False" }, - { "-movesound", "ringBellAfterMoves", XrmoptionNoArg, "True" }, - { "-xmovesound", "ringBellAfterMoves", XrmoptionNoArg, "False" }, - { "-autoCallFlag", "autoCallFlag", XrmoptionSepArg, NULL }, - { "-autoflag", "autoCallFlag", XrmoptionNoArg, "True" }, - { "-xautoflag", "autoCallFlag", XrmoptionNoArg, "False" }, - { "-autoFlipView", "autoFlipView", XrmoptionSepArg, NULL }, - { "-autoflip", "autoFlipView", XrmoptionNoArg, "True" }, - { "-xautoflip", "autoFlipView", XrmoptionNoArg, "False" }, - { "-autoObserve", "autoObserve", XrmoptionSepArg, NULL }, - { "-autobs", "autoObserve", XrmoptionNoArg, "True" }, - { "-xautobs", "autoObserve", XrmoptionNoArg, "False" }, - { "-autoComment", "autoComment", XrmoptionSepArg, NULL }, - { "-autocomm", "autoComment", XrmoptionNoArg, "True" }, - { "-xautocomm", "autoComment", XrmoptionNoArg, "False" }, - { "-getMoveList", "getMoveList", XrmoptionSepArg, NULL }, - { "-moves", "getMoveList", XrmoptionNoArg, "True" }, - { "-xmoves", "getMoveList", XrmoptionNoArg, "False" }, -#if HIGHDRAG - { "-highlightDragging", "highlightDragging", XrmoptionSepArg, NULL }, - { "-highdrag", "highlightDragging", XrmoptionNoArg, "True" }, - { "-xhighdrag", "highlightDragging", XrmoptionNoArg, "False" }, -#endif - { "-highlightLastMove", "highlightLastMove", XrmoptionSepArg, NULL }, - { "-highlight", "highlightLastMove", XrmoptionNoArg, "True" }, - { "-xhighlight", "highlightLastMove", XrmoptionNoArg, "False" }, - { "-premove", "premove", XrmoptionSepArg, NULL }, - { "-pre", "premove", XrmoptionNoArg, "True" }, - { "-xpre", "premove", XrmoptionNoArg, "False" }, - { "-testLegality", "testLegality", XrmoptionSepArg, NULL }, - { "-legal", "testLegality", XrmoptionNoArg, "True" }, - { "-xlegal", "testLegality", XrmoptionNoArg, "False" }, - { "-flipView", "flipView", XrmoptionSepArg, NULL }, - { "-flip", "flipView", XrmoptionNoArg, "True" }, - { "-xflip", "flipView", XrmoptionNoArg, "False" }, - { "-cmail", "cmailGameName", XrmoptionSepArg, NULL }, - { "-alwaysPromoteToQueen", "alwaysPromoteToQueen", - XrmoptionSepArg, NULL }, - { "-queen", "alwaysPromoteToQueen", XrmoptionNoArg, "True" }, - { "-xqueen", "alwaysPromoteToQueen", XrmoptionNoArg, "False" }, - { "-oldSaveStyle", "oldSaveStyle", XrmoptionSepArg, NULL }, - { "-oldsave", "oldSaveStyle", XrmoptionNoArg, "True" }, - { "-xoldsave", "oldSaveStyle", XrmoptionNoArg, "False" }, - { "-quietPlay", "quietPlay", XrmoptionSepArg, NULL }, - { "-quiet", "quietPlay", XrmoptionNoArg, "True" }, - { "-xquiet", "quietPlay", XrmoptionNoArg, "False" }, - { "-titleInWindow", "titleInWindow", XrmoptionSepArg, NULL }, - { "-title", "titleInWindow", XrmoptionNoArg, "True" }, - { "-xtitle", "titleInWindow", XrmoptionNoArg, "False" }, -#ifdef ZIPPY - { "-zippyTalk", "zippyTalk", XrmoptionSepArg, NULL }, - { "-zt", "zippyTalk", XrmoptionNoArg, "True" }, - { "-xzt", "zippyTalk", XrmoptionNoArg, "False" }, - { "-zippyPlay", "zippyPlay", XrmoptionSepArg, NULL }, - { "-zp", "zippyPlay", XrmoptionNoArg, "True" }, - { "-xzp", "zippyPlay", XrmoptionNoArg, "False" }, - { "-zippyLines", "zippyLines", XrmoptionSepArg, NULL }, - { "-zippyPinhead", "zippyPinhead", XrmoptionSepArg, NULL }, - { "-zippyPassword", "zippyPassword", XrmoptionSepArg, NULL }, - { "-zippyPassword2", "zippyPassword2", XrmoptionSepArg, NULL }, - { "-zippyWrongPassword", "zippyWrongPassword", XrmoptionSepArg, NULL }, - { "-zippyAcceptOnly", "zippyAcceptOnly", XrmoptionSepArg, NULL }, - { "-zippyUseI", "zippyUseI", XrmoptionSepArg, NULL }, - { "-zui", "zippyUseI", XrmoptionNoArg, "True" }, - { "-xzui", "zippyUseI", XrmoptionNoArg, "False" }, - { "-zippyBughouse", "zippyBughouse", XrmoptionSepArg, NULL }, - { "-zippyNoplayCrafty", "zippyNoplayCrafty", XrmoptionSepArg, NULL }, - { "-znc", "zippyNoplayCrafty", XrmoptionNoArg, "True" }, - { "-xznc", "zippyNoplayCrafty", XrmoptionNoArg, "False" }, - { "-zippyGameEnd", "zippyGameEnd", XrmoptionSepArg, NULL }, - { "-zippyGameStart", "zippyGameStart", XrmoptionSepArg, NULL }, - { "-zippyAdjourn", "zippyAdjourn", XrmoptionSepArg, NULL }, - { "-zadj", "zippyAdjourn", XrmoptionNoArg, "True" }, - { "-xzadj", "zippyAdjourn", XrmoptionNoArg, "False" }, - { "-zippyAbort", "zippyAbort", XrmoptionSepArg, NULL }, - { "-zab", "zippyAbort", XrmoptionNoArg, "True" }, - { "-xzab", "zippyAbort", XrmoptionNoArg, "False" }, - { "-zippyVariants", "zippyVariants", XrmoptionSepArg, NULL }, - { "-zippyMaxGames", "zippyMaxGames", XrmoptionSepArg, NULL }, - { "-zippyReplayTimeout", "zippyReplayTimeout", XrmoptionSepArg, NULL }, -#endif { "-flashCount", "flashCount", XrmoptionSepArg, NULL }, { "-flash", "flashCount", XrmoptionNoArg, "3" }, { "-xflash", "flashCount", XrmoptionNoArg, "0" }, - { "-flashRate", "flashRate", XrmoptionSepArg, NULL }, - { "-pixmapDirectory", "pixmapDirectory", XrmoptionSepArg, NULL }, - { "-msLoginDelay", "msLoginDelay", XrmoptionSepArg, NULL }, - { "-pixmap", "pixmapDirectory", XrmoptionSepArg, NULL }, - { "-colorizeMessages", "colorizeMessages", XrmoptionSepArg, NULL }, - { "-colorize", "colorizeMessages", XrmoptionNoArg, "True" }, - { "-xcolorize", "colorizeMessages", XrmoptionNoArg, "False" }, - { "-colorShout", "colorShout", XrmoptionSepArg, NULL }, - { "-colorSShout", "colorSShout", XrmoptionSepArg, NULL }, - { "-colorCShout", "colorSShout", XrmoptionSepArg, NULL }, /*FICS name*/ - { "-colorChannel1", "colorChannel1", XrmoptionSepArg, NULL }, - { "-colorChannel", "colorChannel", XrmoptionSepArg, NULL }, - { "-colorKibitz", "colorKibitz", XrmoptionSepArg, NULL }, - { "-colorTell", "colorTell", XrmoptionSepArg, NULL }, - { "-colorChallenge", "colorChallenge", XrmoptionSepArg, NULL }, - { "-colorRequest", "colorRequest", XrmoptionSepArg, NULL }, - { "-colorSeek", "colorSeek", XrmoptionSepArg, NULL }, - { "-colorNormal", "colorNormal", XrmoptionSepArg, NULL }, - { "-soundProgram", "soundProgram", XrmoptionSepArg, NULL }, - { "-soundShout", "soundShout", XrmoptionSepArg, NULL }, - { "-soundSShout", "soundSShout", XrmoptionSepArg, NULL }, - { "-soundCShout", "soundSShout", XrmoptionSepArg, NULL }, /*FICS name*/ - { "-soundChannel1", "soundChannel1", XrmoptionSepArg, NULL }, - { "-soundChannel", "soundChannel", XrmoptionSepArg, NULL }, - { "-soundKibitz", "soundKibitz", XrmoptionSepArg, NULL }, - { "-soundTell", "soundTell", XrmoptionSepArg, NULL }, - { "-soundChallenge", "soundChallenge", XrmoptionSepArg, NULL }, - { "-soundRequest", "soundRequest", XrmoptionSepArg, NULL }, - { "-soundSeek", "soundSeek", XrmoptionSepArg, NULL }, - { "-soundMove", "soundMove", XrmoptionSepArg, NULL }, - { "-soundIcsWin", "soundIcsWin", XrmoptionSepArg, NULL }, - { "-soundIcsLoss", "soundIcsLoss", XrmoptionSepArg, NULL }, - { "-soundIcsDraw", "soundIcsDraw", XrmoptionSepArg, NULL }, - { "-soundIcsUnfinished", "soundIcsUnfinished", XrmoptionSepArg, NULL }, - { "-soundIcsAlarm", "soundIcsAlarm", XrmoptionSepArg, NULL }, - { "-reuseFirst", "reuseFirst", XrmoptionSepArg, NULL }, - { "-reuseChessPrograms", "reuseFirst", XrmoptionSepArg, NULL }, /*compat*/ - { "-reuse", "reuseFirst", XrmoptionNoArg, "True" }, - { "-xreuse", "reuseFirst", XrmoptionNoArg, "False" }, - { "-reuseSecond", "reuseSecond", XrmoptionSepArg, NULL }, - { "-reuse2", "reuseSecond", XrmoptionNoArg, "True" }, - { "-xreuse2", "reuseSecond", XrmoptionNoArg, "False" }, - { "-animateMoving", "animateMoving", XrmoptionSepArg, NULL }, - { "-animate", "animateMoving", XrmoptionNoArg, "True" }, - { "-xanimate", "animateMoving", XrmoptionNoArg, "False" }, - { "-animateDragging", "animateDragging", XrmoptionSepArg, NULL }, - { "-drag", "animateDragging", XrmoptionNoArg, "True" }, - { "-xdrag", "animateDragging", XrmoptionNoArg, "False" }, - { "-animateSpeed", "animateSpeed", XrmoptionSepArg, NULL }, - { "-popupExitMessage", "popupExitMessage", XrmoptionSepArg, NULL }, - { "-exit", "popupExitMessage", XrmoptionNoArg, "True" }, - { "-xexit", "popupExitMessage", XrmoptionNoArg, "False" }, - { "-popupMoveErrors", "popupMoveErrors", XrmoptionSepArg, NULL }, - { "-popup", "popupMoveErrors", XrmoptionNoArg, "True" }, - { "-xpopup", "popupMoveErrors", XrmoptionNoArg, "False" }, - { "-fontSizeTolerance", "fontSizeTolerance", XrmoptionSepArg, NULL }, - { "-initialMode", "initialMode", XrmoptionSepArg, NULL }, - { "-mode", "initialMode", XrmoptionSepArg, NULL }, - { "-variant", "variant", XrmoptionSepArg, NULL }, - { "-firstProtocolVersion", "firstProtocolVersion", XrmoptionSepArg, NULL }, - { "-secondProtocolVersion","secondProtocolVersion",XrmoptionSepArg, NULL }, - { "-showButtonBar", "showButtonBar", XrmoptionSepArg, NULL }, - { "-buttons", "showButtonBar", XrmoptionNoArg, "True" }, - { "-xbuttons", "showButtonBar", XrmoptionNoArg, "False" }, }; - XtActionsRec boardActions[] = { { "DrawPosition", DrawPositionProc }, { "HandleUserMove", HandleUserMove }, { "AnimateUserMove", AnimateUserMove }, + { "HandlePV", HandlePV }, + { "SelectPV", SelectPV }, + { "StopPV", StopPV }, { "FileNameAction", FileNameAction }, { "AskQuestionProc", AskQuestionProc }, { "AskQuestionReplyAction", AskQuestionReplyAction }, @@ -1456,10 +893,12 @@ XtActionsRec boardActions[] = { { "BlackClock", BlackClock }, { "Iconify", Iconify }, { "ResetProc", ResetProc }, + { "NewVariantProc", NewVariantProc }, { "LoadGameProc", LoadGameProc }, { "LoadNextGameProc", LoadNextGameProc }, { "LoadPrevGameProc", LoadPrevGameProc }, { "LoadSelectedProc", LoadSelectedProc }, + { "SetFilterProc", SetFilterProc }, { "ReloadGameProc", ReloadGameProc }, { "LoadPositionProc", LoadPositionProc }, { "LoadNextPositionProc", LoadNextPositionProc }, @@ -1483,6 +922,8 @@ XtActionsRec boardActions[] = { { "EditGameProc", EditGameProc }, { "EditPositionProc", EditPositionProc }, { "TrainingProc", EditPositionProc }, + { "EngineOutputProc", EngineOutputProc}, // [HGM] Winboard_x engine-output window + { "EvalGraphProc", EvalGraphProc}, // [HGM] Winboard_x avaluation graph window { "ShowGameListProc", ShowGameListProc }, { "ShowMoveListProc", HistoryShowProc}, { "EditTagsProc", EditCommentProc }, @@ -1498,17 +939,27 @@ XtActionsRec boardActions[] = { { "AdjournProc", AdjournProc }, { "AbortProc", AbortProc }, { "ResignProc", ResignProc }, + { "AdjuWhiteProc", AdjuWhiteProc }, + { "AdjuBlackProc", AdjuBlackProc }, + { "AdjuDrawProc", AdjuDrawProc }, { "EnterKeyProc", EnterKeyProc }, + { "UpKeyProc", UpKeyProc }, + { "DownKeyProc", DownKeyProc }, { "StopObservingProc", StopObservingProc }, { "StopExaminingProc", StopExaminingProc }, + { "UploadProc", UploadProc }, { "BackwardProc", BackwardProc }, { "ForwardProc", ForwardProc }, { "ToStartProc", ToStartProc }, { "ToEndProc", ToEndProc }, { "RevertProc", RevertProc }, + { "AnnotateProc", AnnotateProc }, { "TruncateGameProc", TruncateGameProc }, { "MoveNowProc", MoveNowProc }, { "RetractMoveProc", RetractMoveProc }, + { "EngineMenuProc", (XtActionProc) EngineMenuProc }, + { "UciMenuProc", (XtActionProc) UciMenuProc }, + { "TimeControlProc", (XtActionProc) TimeControlProc }, { "AlwaysQueenProc", AlwaysQueenProc }, { "AnimateDraggingProc", AnimateDraggingProc }, { "AnimateMovingProc", AnimateMovingProc }, @@ -1527,16 +978,18 @@ XtActionsRec boardActions[] = { { "HighlightLastMoveProc", HighlightLastMoveProc }, { "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 }, + { "SaveSettingsProc", SaveSettingsProc }, + { "SaveOnExitProc", SaveOnExitProc }, { "InfoProc", InfoProc }, { "ManProc", ManProc }, { "HintProc", HintProc }, @@ -1545,49 +998,102 @@ XtActionsRec boardActions[] = { { "AboutProc", AboutProc }, { "DebugProc", DebugProc }, { "NothingProc", NothingProc }, + { "CommentClick", (XtActionProc) CommentClick }, { "CommentPopDown", (XtActionProc) CommentPopDown }, { "EditCommentPopDown", (XtActionProc) EditCommentPopDown }, { "TagsPopDown", (XtActionProc) TagsPopDown }, { "ErrorPopDown", (XtActionProc) ErrorPopDown }, { "ICSInputBoxPopDown", (XtActionProc) ICSInputBoxPopDown }, - { "AnalysisPopDown", (XtActionProc) AnalysisPopDown }, { "FileNamePopDown", (XtActionProc) FileNamePopDown }, { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown }, { "GameListPopDown", (XtActionProc) GameListPopDown }, + { "GameListOptionsPopDown", (XtActionProc) GameListOptionsPopDown }, { "PromotionPopDown", (XtActionProc) PromotionPopDown }, { "HistoryPopDown", (XtActionProc) HistoryPopDown }, + { "EngineOutputPopDown", (XtActionProc) EngineOutputPopDown }, + { "EvalGraphPopDown", (XtActionProc) EvalGraphPopDown }, + { "ShufflePopDown", (XtActionProc) ShufflePopDown }, + { "EnginePopDown", (XtActionProc) EnginePopDown }, + { "UciPopDown", (XtActionProc) UciPopDown }, + { "TimeControlPopDown", (XtActionProc) TimeControlPopDown }, + { "NewVariantPopDown", (XtActionProc) NewVariantPopDown }, + { "SettingsPopDown", (XtActionProc) SettingsPopDown }, + { "CopyMemoProc", (XtActionProc) CopyMemoProc }, }; - + char globalTranslations[] = - ":R: ResignProc() \n \ - :r: ResetProc() \n \ - :g: LoadGameProc() \n \ - :N: LoadNextGameProc() \n \ - :P: LoadPrevGameProc() \n \ - :Q: QuitProc() \n \ - :F: ToEndProc() \n \ - :f: ForwardProc() \n \ - :B: ToStartProc() \n \ - :b: BackwardProc() \n \ - :p: PauseProc() \n \ - :d: DrawProc() \n \ - :t: CallFlagProc() \n \ - :i: Iconify() \n \ - :c: Iconify() \n \ - :v: FlipViewProc() \n \ - Control_L: BackwardProc() \n \ - Control_L: ForwardProc() \n \ - Control_R: BackwardProc() \n \ - Control_R: ForwardProc() \n \ + ":F9: ResignProc() \n \ + :Ctrln: ResetProc() \n \ + :MetaV: NewVariantProc() \n \ + :Ctrlo: LoadGameProc() \n \ + :MetaNext: LoadNextGameProc() \n \ + :MetaPrior: LoadPrevGameProc() \n \ + :Ctrls: SaveGameProc() \n \ + :Ctrlc: CopyGameProc() \n \ + :Ctrlv: PasteGameProc() \n \ + :CtrlO: LoadPositionProc() \n \ + :ShiftNext: LoadNextPositionProc() \n \ + :ShiftPrior: LoadPrevPositionProc() \n \ + :CtrlS: SavePositionProc() \n \ + :CtrlC: CopyPositionProc() \n \ + :CtrlV: PastePositionProc() \n \ + :Ctrlq: QuitProc() \n \ + :Ctrlw: MachineWhiteProc() \n \ + :Ctrlb: MachineBlackProc() \n \ + :Ctrlt: TwoMachinesProc() \n \ + :Ctrla: AnalysisModeProc() \n \ + :Ctrlf: AnalyzeFileProc() \n \ + :Ctrle: EditGameProc() \n \ + :CtrlE: EditPositionProc() \n \ + :MetaO: EngineOutputProc() \n \ + :MetaE: EvalGraphProc() \n \ + :MetaG: ShowGameListProc() \n \ + :MetaH: ShowMoveListProc() \n \ + :Pause: PauseProc() \n \ + :F3: AcceptProc() \n \ + :F4: DeclineProc() \n \ + :F12: RematchProc() \n \ + :F5: CallFlagProc() \n \ + :F6: DrawProc() \n \ + :F7: AdjournProc() \n \ + :F8: AbortProc() \n \ + :F10: StopObservingProc() \n \ + :F11: StopExaminingProc() \n \ + :Meta CtrlF12: DebugProc() \n \ + :MetaEnd: ToEndProc() \n \ + :MetaRight: ForwardProc() \n \ + :MetaHome: ToStartProc() \n \ + :MetaLeft: BackwardProc() \n \ + :Home: RevertProc() \n \ + :End: TruncateGameProc() \n \ + :Ctrlm: MoveNowProc() \n \ + :Ctrlx: RetractMoveProc() \n \ + :MetaJ: EngineMenuProc() \n \ + :MetaU: UciMenuProc() \n \ + :MetaT: TimeControlProc() \n \ + :CtrlQ: AlwaysQueenProc() \n \ + :CtrlF: AutoflagProc() \n \ + :CtrlA: AnimateMovingProc() \n \ + :CtrlP: PonderNextMoveProc() \n \ + :CtrlL: TestLegalityProc() \n \ + :CtrlH: HideThinkingProc() \n \ + :-: Iconify() \n \ + :F1: ManProc() \n \ + :F2: FlipViewProc() \n \ + .: BackwardProc() \n \ + .: ForwardProc() \n \ Shift1: AskQuestionProc(\"Direct command\",\ \"Send to chess program:\",,1) \n \ Shift2: AskQuestionProc(\"Direct command\",\ \"Send to second chess program:\",,2) \n"; char boardTranslations[] = - ": HandleUserMove() \n \ - : HandleUserMove() \n \ + ": HandleUserMove(0) \n \ + Shift: HandleUserMove(1) \n \ + : HandleUserMove(0) \n \ : AnimateUserMove() \n \ + : HandlePV() \n \ + : PieceMenuPopup(menuB) \n \ Shift: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD)\ PieceMenuPopup(menuB) \n \ Any: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD) \ @@ -1596,20 +1102,26 @@ char boardTranslations[] = PieceMenuPopup(menuW) \n \ Any: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD) \ PieceMenuPopup(menuB) \n"; - + char whiteTranslations[] = ": WhiteClock()\n"; char blackTranslations[] = ": BlackClock()\n"; - + char ICSInputTranslations[] = + "Up: UpKeyProc() \n " + "Down: DownKeyProc() \n " "Return: EnterKeyProc() \n"; +// [HGM] vari: another hideous kludge: call extend-end first so we can be sure select-start works, +// as the widget is destroyed before the up-click can call extend-end +char commentTranslations[] = ": extend-end() select-start() CommentClick() \n"; + String xboardResources[] = { "*fileName*value.translations: #override\\n Return: FileNameAction()", "*question*value.translations: #override\\n Return: AskQuestionReplyAction()", "*errorpopup*translations: #override\\n Return: ErrorPopDown()", NULL }; - + /* Max possible square size */ #define MAXSQSIZE 256 @@ -1627,14 +1139,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; @@ -1660,15 +1172,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) @@ -1705,12 +1217,12 @@ xpm_closest_to(dirname, size, ext) int sm_diff = MAXSQSIZE; int sm_index = 0; int diff; - + xpm_getavail(dirname, ext); if (appData.debugMode) xpm_print_avail(stderr, ext); - + for (i=1; i 99) /* watch bounds on buf */ return -1; @@ -1785,10 +1297,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++); @@ -1831,7 +1343,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)); } @@ -1845,6 +1357,442 @@ BoardToTop() XtPopup(shellWidget, XtGrabNone); /* Raise if lowered */ } +//--------------------------------------------------------------------------------------------------------- +// some symbol definitions to provide the proper (= XBoard) context for the code in args.h +#define XBOARD True +#define JAWS_ARGS +#define CW_USEDEFAULT (1<<31) +#define ICS_TEXT_MENU_SIZE 90 +#define DEBUG_FILE "xboard.debug" +#define SetCurrentDirectory chdir +#define GetCurrentDirectory(SIZE, NAME) getcwd(NAME, SIZE) +#define OPTCHAR "-" +#define SEPCHAR " " + +// these two must some day move to frontend.h, when they are implemented +Boolean GameListIsUp(); + +// The option definition and parsing code common to XBoard and WinBoard is collected in this file +#include "args.h" + +// front-end part of option handling + +// [HGM] This platform-dependent table provides the location for storing the color info +extern char *crWhite, * crBlack; + +void * +colorVariable[] = { + &appData.whitePieceColor, + &appData.blackPieceColor, + &appData.lightSquareColor, + &appData.darkSquareColor, + &appData.highlightSquareColor, + &appData.premoveHighlightColor, + &appData.lowTimeWarningColor, + NULL, + NULL, + NULL, + NULL, + NULL, + &crWhite, + &crBlack, + NULL +}; + +// [HGM] font: keep a font for each square size, even non-stndard ones +#define NUM_SIZES 18 +#define MAX_SIZE 130 +Boolean fontSet[NUM_FONTS], fontValid[NUM_FONTS][MAX_SIZE]; +char *fontTable[NUM_FONTS][MAX_SIZE]; + +void +ParseFont(char *name, int number) +{ // in XBoard, only 2 of the fonts are currently implemented, and we just copy their name + int size; + if(sscanf(name, "size%d:", &size)) { + // [HGM] font: font is meant for specific boardSize (likely from settings file); + // defer processing it until we know if it matches our board size + if(size >= 0 && sizeargLoc; + switch(n) { + case 0: // CLOCK_FONT + name = appData.clockFont; + break; + case 1: // MESSAGE_FONT + name = appData.font; + break; + case 2: // COORD_FONT + name = appData.coordFont; + break; + default: + return; + } + for(i=0; iargName, i, fontTable[n][i]); +} + +void +ExportSounds() +{ // nothing to do, as the sounds are at all times represented by their text-string names already +} + +void +SaveAttribsArg(FILE *f, ArgDescriptor *ad) +{ // here the "argLoc" defines a table index. It could have contained the 'ta' pointer itself, though + fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", ad->argName, (&appData.colorShout)[(int)ad->argLoc]); +} + +void +SaveColor(FILE *f, ArgDescriptor *ad) +{ // in WinBoard the color is an int and has to be converted to text. In X it would be a string already? + if(colorVariable[(int)ad->argLoc]) + fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", ad->argName, *(char**)colorVariable[(int)ad->argLoc]); +} + +void +SaveBoardSize(FILE *f, char *name, void *addr) +{ // wrapper to shield back-end from BoardSize & sizeInfo + fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", name, appData.boardSize); +} + +void +ParseCommPortSettings(char *s) +{ // no such option in XBoard (yet) +} + +extern Widget engineOutputShell; +extern Widget tagsShell, editTagsShell; +void +GetActualPlacement(Widget wg, WindowPlacement *wp) +{ + Arg args[16]; + Dimension w, h; + Position x, y; + int i; + + if(!wg) return; + + i = 0; + XtSetArg(args[i], XtNx, &x); i++; + XtSetArg(args[i], XtNy, &y); i++; + XtSetArg(args[i], XtNwidth, &w); i++; + XtSetArg(args[i], XtNheight, &h); i++; + XtGetValues(wg, args, i); + wp->x = x - 4; + wp->y = y - 23; + wp->height = h; + wp->width = w; +} + +void +GetWindowCoords() +{ // wrapper to shield use of window handles from back-end (make addressible by number?) + // In XBoard this will have to wait until awareness of window parameters is implemented + GetActualPlacement(shellWidget, &wpMain); + if(EngineOutputIsUp()) GetActualPlacement(engineOutputShell, &wpEngineOutput); else + if(MoveHistoryIsUp()) GetActualPlacement(historyShell, &wpMoveHistory); + if(EvalGraphIsUp()) GetActualPlacement(evalGraphShell, &wpEvalGraph); + if(GameListIsUp()) GetActualPlacement(gameListShell, &wpGameList); + if(commentShell) GetActualPlacement(commentShell, &wpComment); + else GetActualPlacement(editShell, &wpComment); + if(tagsShell) GetActualPlacement(tagsShell, &wpTags); + else GetActualPlacement(editTagsShell, &wpTags); +} + +void +PrintCommPortSettings(FILE *f, char *name) +{ // This option does not exist in XBoard +} + +int +MySearchPath(char *installDir, char *name, char *fullname) +{ // just append installDir and name. Perhaps ExpandPath should be used here? + name = ExpandPathName(name); + if(name && name[0] == '/') + safeStrCpy(fullname, name, MSG_SIZ ); + else { + sprintf(fullname, "%s%c%s", installDir, '/', name); + } + return 1; +} + +int +MyGetFullPathName(char *name, char *fullname) +{ // should use ExpandPath? + name = ExpandPathName(name); + safeStrCpy(fullname, name, MSG_SIZ ); + return 1; +} + +void +EnsureOnScreen(int *x, int *y, int minX, int minY) +{ + return; +} + +int +MainWindowUp() +{ // [HGM] args: allows testing if main window is realized from back-end + return xBoardWindow != 0; +} + +void +PopUpStartupDialog() +{ // start menu not implemented in XBoard +} + +char * +ConvertToLine(int argc, char **argv) +{ + static char line[128*1024], buf[1024]; + int i; + + line[0] = NULLCHAR; + for(i=1; i 1 && (!strcmp(argv[1], "-v" ) || !strcmp(argv[1], "--version" ))) { + printf("%s version %s\n", PACKAGE_NAME, PACKAGE_VERSION); + exit(0); + } + programName = strrchr(argv[0], '/'); if (programName == NULL) programName = argv[0]; @@ -1872,21 +1827,40 @@ main(argc, argv) #ifdef ENABLE_NLS XtSetLanguageProc(NULL, NULL, NULL); - bindtextdomain(PRODUCT, LOCALEDIR); - bind_textdomain_codeset(PRODUCT, "UTF-8"); - textdomain(PRODUCT); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); #endif shellWidget = XtAppInitialize(&appContext, "XBoard", shellOptions, XtNumber(shellOptions), &argc, argv, xboardResources, NULL, 0); - if (argc > 1) { - fprintf(stderr, _("%s: unrecognized argument %s\n"), - programName, argv[1]); - exit(2); + appData.boardSize = ""; + InitAppData(ConvertToLine(argc, argv)); + p = getenv("HOME"); + if (p == NULL) p = "/tmp"; + i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1; + gameCopyFilename = (char*) malloc(i); + gamePasteFilename = (char*) malloc(i); + 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 { @@ -1896,27 +1870,21 @@ main(argc, argv) exit(1); } } - - 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()); - XtGetApplicationResources(shellWidget, (XtPointer) &appData, - clientResources, XtNumber(clientResources), - NULL, 0); - - if (appData.debugMode) { - if ((debugFP = fopen("xboard.debug", "w")) == NULL) { - printf(_("Failed to open file xboard.debug \n")); - exit(errno); - } + 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_FILES || + appData.NrRanks > BOARD_RANKS ) + DisplayFatalError(_("Recompile with larger BOARD_RANKS or BOARD_FILES to support this size"), 0, 2); + #if !HIGHDRAG /* This feature does not work; animation needs a rewrite */ appData.highlightDragging = FALSE; @@ -1927,9 +1895,12 @@ main(argc, argv) xScreen = DefaultScreen(xDisplay); wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True); - /* - * Determine boardSize - */ + gameInfo.variant = StringToVariant(appData.variant); + InitPosition(FALSE); + +#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, @@ -1967,6 +1938,7 @@ main(argc, argv) szd++; } if (szd->name == NULL) szd--; + appData.boardSize = strdup(szd->name); // [HGM] settings: remember name for saving settings } else { while (szd->name != NULL && StrCaseCmp(szd->name, appData.boardSize) != 0) szd++; @@ -1983,7 +1955,14 @@ main(argc, argv) fontPxlSize = szd->fontPxlSize; smallLayout = szd->smallLayout; tinyLayout = szd->tinyLayout; + // [HGM] font: use defaults from settings file if available and not overruled } + if(!fontSet[CLOCK_FONT] && fontValid[CLOCK_FONT][squareSize]) + appData.clockFont = fontTable[CLOCK_FONT][squareSize]; + if(!fontSet[MESSAGE_FONT] && fontValid[MESSAGE_FONT][squareSize]) + appData.font = fontTable[MESSAGE_FONT][squareSize]; + if(!fontSet[COORD_FONT] && fontValid[COORD_FONT][squareSize]) + appData.coordFont = fontTable[COORD_FONT][squareSize]; /* Now, using squareSize as a hint, find a good XPM/XIM set size */ if (strlen(appData.pixmapDirectory) > 0) { @@ -1994,7 +1973,7 @@ main(argc, argv) exit(1); } if (appData.debugMode) { - fprintf(stderr, _("\ + fprintf(stderr, _("\ XBoard square size (hint): %d\n\ %s fulldir:%s:\n"), squareSize, IMAGE_EXT, p); } @@ -2003,22 +1982,25 @@ XBoard square size (hint): %d\n\ fprintf(stderr, _("Closest %s size: %d\n"), IMAGE_EXT, squareSize); } } - - boardWidth = lineGap + BOARD_SIZE * (squareSize + lineGap); + if(appData.overrideLineGap >= 0) lineGap = appData.overrideLineGap; + + /* [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); } /* @@ -2031,6 +2013,9 @@ XBoard square size (hint): %d\n\ 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); @@ -2114,6 +2099,20 @@ XBoard square size (hint): %d\n\ if (forceMono) { 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) { @@ -2121,7 +2120,7 @@ XBoard square size (hint): %d\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 || @@ -2142,9 +2141,9 @@ XBoard square size (hint): %d\n\ } textColors[ColorNone].fg = textColors[ColorNone].bg = -1; textColors[ColorNone].attr = 0; - + XtAppAddActions(appContext, boardActions, XtNumber(boardActions)); - + /* * widget hierarchy */ @@ -2165,51 +2164,70 @@ XBoard square size (hint): %d\n\ 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); + XtSetArg(args[2], XtNright, XtChainLeft); + XtSetValues(menuBarWidget, args, 3); 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); @@ -2289,16 +2307,27 @@ XBoard square size (hint): %d\n\ } 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); + if(wpMain.x > 0) { + XtSetArg(args[0], XtNx, wpMain.x); + XtSetArg(args[1], XtNy, wpMain.y); + XtSetValues(shellWidget, args, 2); + } + /* * Correct the width of the message and title widgets. * It is not known why some systems need the extra fudge term. * The value "2" is probably larger than needed. */ XawFormDoLayout(formWidget, False); + #define WIDTH_FUDGE 2 i = 0; XtSetArg(args[i], XtNborderWidth, &bor); i++; @@ -2318,7 +2347,7 @@ XBoard square size (hint): %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! */ @@ -2329,6 +2358,9 @@ XBoard square size (hint): %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; @@ -2353,8 +2385,12 @@ XBoard square size (hint): %d\n\ 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", @@ -2430,6 +2466,11 @@ XBoard square size (hint): %d\n\ "menuOptions.Highlight Last Move"), args, 1); } + if (appData.highlightMoveWithArrow) { + XtSetValues(XtNameToWidget(menuBarWidget, + "menuOptions.Arrow"), + args, 1); + } if (appData.icsAlarm) { XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.ICS Alarm"), args, 1); @@ -2438,26 +2479,26 @@ XBoard square size (hint): %d\n\ XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"), args, 1); } - if (appData.oldSaveStyle) { + if (appData.oneClick) { XtSetValues(XtNameToWidget(menuBarWidget, - "menuOptions.Old Save Style"), args, 1); + "menuOptions.OneClick"), args, 1); } 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); @@ -2470,14 +2511,18 @@ XBoard square size (hint): %d\n\ 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) { XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Test Legality"), args, 1); } + if (saveSettingsOnExit) { + XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Save Settings on Exit"), + args, 1); + } /* * Create an icon. @@ -2490,14 +2535,14 @@ XBoard square size (hint): %d\n\ 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. */ @@ -2507,7 +2552,9 @@ XBoard square size (hint): %d\n\ 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(); @@ -2517,18 +2564,20 @@ XBoard square size (hint): %d\n\ CreatePieces(); } else { CreateXPMPieces(); + CreateXPMBoard(appData.liteBackTextureFile, 1); + CreateXPMBoard(appData.darkBackTextureFile, 0); } #else CreateXIMPieces(); /* Create regular pieces */ if (!useImages) CreatePieces(); -#endif +#endif CreatePieceMenus(); if (appData.animate || appData.animateDragging) CreateAnimVars(); - + XtAugmentTranslations(formWidget, XtParseTranslationTable(globalTranslations)); XtAugmentTranslations(boardWidget, @@ -2540,12 +2589,26 @@ XBoard square size (hint): %d\n\ /* Why is the following needed on some versions of X instead * of a translation? */ - XtAddEventHandler(boardWidget, ExposureMask, False, + XtAddEventHandler(boardWidget, ExposureMask|PointerMotionMask, False, (XtEventHandler) EventProc, NULL); /* end why */ + /* [AS] Restore layout */ + if( wpMoveHistory.visible ) { + HistoryPopUp(); + } + + if( wpEvalGraph.visible ) + { + EvalGraphPopUp(); + }; + + if( wpEngineOutput.visible ) { + EngineOutputPopUp(); + } + InitBackEnd2(); - + if (errorExitStatus == -1) { if (appData.icsActive) { /* We now wait until we see "login:" from the ICS before @@ -2554,16 +2617,21 @@ XBoard square size (hint): %d\n\ if (appData.icsInputBox) ICSInputBoxPopUp(); } + #ifdef SIGWINCH + signal(SIGWINCH, TermSizeSigHandler); + #endif signal(SIGINT, IntSigHandler); signal(SIGTERM, IntSigHandler); if (*appData.cmailGameName != NULLCHAR) { signal(SIGUSR1, CmailSigHandler); } } + gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes() + InitPosition(TRUE); + XtSetKeyboardFocus(shellWidget, formWidget); XtAppMainLoop(appContext); - if (appData.debugMode) fclose(debugFP); - + if (appData.debugMode) fclose(debugFP); // [DM] debug return 0; } @@ -2573,10 +2641,16 @@ ShutDownFrontEnd() if (appData.icsActive && oldICSInteractionTitle != NULL) { DisplayIcsInteractionTitle(oldICSInteractionTitle); } + if (saveSettingsOnExit) SaveSettings(settingsFileName); unlink(gameCopyFilename); unlink(gamePasteFilename); } +RETSIGTYPE TermSizeSigHandler(int sig) +{ + update_ics_width(); +} + RETSIGTYPE IntSigHandler(sig) int sig; @@ -2616,22 +2690,33 @@ CmailSigHandlerCallBack(isr, closure, message, count, error) void ICSInitScript() { - FILE *f; - char buf[MSG_SIZ]; - char *p; + /* try to open the icsLogon script, either in the location given + * or in the users HOME directory + */ - f = fopen(appData.icsLogon, "r"); - if (f == NULL) { - p = getenv("HOME"); - if (p != NULL) { - strcpy(buf, p); - strcat(buf, "/"); - strcat(buf, appData.icsLogon); - f = fopen(buf, "r"); + FILE *f; + char buf[MSG_SIZ]; + char *homedir; + + f = fopen(appData.icsLogon, "r"); + if (f == NULL) + { + homedir = getenv("HOME"); + if (homedir != NULL) + { + safeStrCpy(buf, homedir, sizeof(buf)/sizeof(buf[0]) ); + strncat(buf, "/", MSG_SIZ - strlen(buf) - 1); + strncat(buf, appData.icsLogon, MSG_SIZ - strlen(buf) - 1); + f = fopen(buf, "r"); } } - if (f != NULL) - ProcessICSInitScript(f); + + if (f != NULL) + ProcessICSInitScript(f); + else + printf("Warning: Couldn't open icsLogon file (checked %s and %s).\n", appData.icsLogon, buf); + + return; } void @@ -2649,6 +2734,26 @@ typedef struct { } Enables; void +GreyRevert(grey) + Boolean grey; +{ + Widget w; + if (!menuBarWidget) return; + w = XtNameToWidget(menuBarWidget, "menuEdit.Revert"); + if (w == NULL) { + DisplayError("menuEdit.Revert", 0); + } else { + XtSetSensitive(w, !grey); + } + w = XtNameToWidget(menuBarWidget, "menuEdit.Annotate"); + if (w == NULL) { + DisplayError("menuEdit.Annotate", 0); + } else { + XtSetSensitive(w, !grey); + } +} + +void SetMenuEnables(enab) Enables *enab; { @@ -2674,17 +2779,20 @@ Enables icsEnables[] = { { "menuMode.Analyze File", False }, { "menuMode.Two Machines", False }, #ifndef ZIPPY - { "menuHelp.Hint", False }, - { "menuHelp.Book", False }, - { "menuStep.Move Now", False }, - { "menuOptions.Periodic Updates", False }, - { "menuOptions.Show Thinking", False }, + { "menuEngine.Hint", False }, + { "menuEngine.Book", False }, + { "menuEngine.Move Now", False }, + { "menuOptions.Periodic Updates", False }, + { "menuOptions.Hide Thinking", False }, { "menuOptions.Ponder Next Move", False }, + { "menuEngine.Engine #1 Settings", False }, #endif + { "menuEngine.Engine #2 Settings", False }, + { "menuEdit.Annotate", False }, { NULL, False } }; -Enables ncpEnables[] = { +Enables ncpEnables[] = { { "menuFile.Mail Move", False }, { "menuFile.Reload CMail Message", False }, { "menuMode.Machine White", False }, @@ -2693,11 +2801,14 @@ Enables ncpEnables[] = { { "menuMode.Analyze File", False }, { "menuMode.Two Machines", False }, { "menuMode.ICS Client", False }, - { "menuMode.ICS Input Box", False }, + { "menuView.ICS Input Box", False }, { "Action", False }, - { "menuStep.Revert", False }, - { "menuStep.Move Now", False }, - { "menuStep.Retract Move", False }, + { "menuEdit.Revert", False }, + { "menuEdit.Annotate", False }, + { "menuEngine.Engine #1 Settings", False }, + { "menuEngine.Engine #2 Settings", False }, + { "menuEngine.Move Now", False }, + { "menuEngine.Retract Move", False }, { "menuOptions.Auto Comment", False }, { "menuOptions.Auto Flag", False }, { "menuOptions.Auto Flip View", False }, @@ -2707,24 +2818,26 @@ 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 }, + { "menuEngine.Hint", False }, + { "menuEngine.Book", False }, { NULL, False } }; -Enables gnuEnables[] = { +Enables gnuEnables[] = { { "menuMode.ICS Client", False }, - { "menuMode.ICS Input Box", False }, + { "menuView.ICS Input Box", False }, { "menuAction.Accept", False }, { "menuAction.Decline", False }, { "menuAction.Rematch", False }, { "menuAction.Adjourn", False }, { "menuAction.Stop Examining", False }, { "menuAction.Stop Observing", False }, - { "menuStep.Revert", False }, + { "menuAction.Upload to Examine", False }, + { "menuEdit.Revert", False }, + { "menuEdit.Annotate", False }, { "menuOptions.Auto Comment", False }, { "menuOptions.Auto Observe", False }, { "menuOptions.Auto Raise Board", False }, @@ -2741,7 +2854,7 @@ Enables gnuEnables[] = { { NULL, False } }; -Enables cmailEnables[] = { +Enables cmailEnables[] = { { "Action", True }, { "menuAction.Call Flag", False }, { "menuAction.Draw", True }, @@ -2754,63 +2867,63 @@ Enables cmailEnables[] = { { NULL, False } }; -Enables trainingOnEnables[] = { +Enables trainingOnEnables[] = { { "menuMode.Edit Comment", False }, { "menuMode.Pause", False }, - { "menuStep.Forward", False }, - { "menuStep.Backward", False }, - { "menuStep.Forward to End", False }, - { "menuStep.Back to Start", False }, - { "menuStep.Move Now", False }, - { "menuStep.Truncate Game", False }, + { "menuEdit.Forward", False }, + { "menuEdit.Backward", False }, + { "menuEdit.Forward to End", False }, + { "menuEdit.Back to Start", False }, + { "menuEngine.Move Now", False }, + { "menuEdit.Truncate Game", False }, { NULL, False } }; -Enables trainingOffEnables[] = { +Enables trainingOffEnables[] = { { "menuMode.Edit Comment", True }, { "menuMode.Pause", True }, - { "menuStep.Forward", True }, - { "menuStep.Backward", True }, - { "menuStep.Forward to End", True }, - { "menuStep.Back to Start", True }, - { "menuStep.Move Now", True }, - { "menuStep.Truncate Game", True }, + { "menuEdit.Forward", True }, + { "menuEdit.Backward", True }, + { "menuEdit.Forward to End", True }, + { "menuEdit.Back to Start", True }, + { "menuEngine.Move Now", True }, + { "menuEdit.Truncate Game", True }, { NULL, False } }; Enables machineThinkingEnables[] = { { "menuFile.Load Game", False }, - { "menuFile.Load Next Game", False }, - { "menuFile.Load Previous Game", False }, - { "menuFile.Reload Same Game", False }, - { "menuFile.Paste Game", False }, +// { "menuFile.Load Next Game", False }, +// { "menuFile.Load Previous Game", False }, +// { "menuFile.Reload Same Game", False }, + { "menuEdit.Paste Game", False }, { "menuFile.Load Position", False }, - { "menuFile.Load Next Position", False }, - { "menuFile.Load Previous Position", False }, - { "menuFile.Reload Same Position", False }, - { "menuFile.Paste Position", False }, +// { "menuFile.Load Next Position", False }, +// { "menuFile.Load Previous Position", False }, +// { "menuFile.Reload Same Position", False }, + { "menuEdit.Paste Position", False }, { "menuMode.Machine White", False }, { "menuMode.Machine Black", False }, { "menuMode.Two Machines", False }, - { "menuStep.Retract Move", False }, + { "menuEngine.Retract Move", False }, { NULL, False } }; Enables userThinkingEnables[] = { { "menuFile.Load Game", True }, - { "menuFile.Load Next Game", True }, - { "menuFile.Load Previous Game", True }, - { "menuFile.Reload Same Game", True }, - { "menuFile.Paste Game", True }, +// { "menuFile.Load Next Game", True }, +// { "menuFile.Load Previous Game", True }, +// { "menuFile.Reload Same Game", True }, + { "menuEdit.Paste Game", True }, { "menuFile.Load Position", True }, - { "menuFile.Load Next Position", True }, - { "menuFile.Load Previous Position", True }, - { "menuFile.Reload Same Position", True }, - { "menuFile.Paste Position", True }, +// { "menuFile.Load Next Position", True }, +// { "menuFile.Load Previous Position", True }, +// { "menuFile.Reload Same Position", True }, + { "menuEdit.Paste Position", True }, { "menuMode.Machine White", True }, { "menuMode.Machine Black", True }, { "menuMode.Two Machines", True }, - { "menuStep.Retract Move", True }, + { "menuEngine.Retract Move", True }, { NULL, False } }; @@ -2818,11 +2931,10 @@ void SetICSMode() { SetMenuEnables(icsEnables); - #ifdef ZIPPY - /* icsEngineAnalyze */ - if (appData.zippyPlay && !appData.noChessProgram) +#if ZIPPY + if (appData.zippyPlay && !appData.noChessProgram) /* [DM] icsEngineAnalyze */ XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True); - #endif +#endif } void @@ -2886,18 +2998,64 @@ SetMachineThinkingEnables() } } +// [HGM] code borrowed from winboard.c (which should thus go to backend.c!) +#define HISTORY_SIZE 64 +static char *history[HISTORY_SIZE]; +int histIn = 0, histP = 0; + +void +SaveInHistory(char *cmd) +{ + if (history[histIn] != NULL) { + free(history[histIn]); + history[histIn] = NULL; + } + if (*cmd == NULLCHAR) return; + history[histIn] = StrSave(cmd); + histIn = (histIn + 1) % HISTORY_SIZE; + if (history[histIn] != NULL) { + free(history[histIn]); + history[histIn] = NULL; + } + histP = histIn; +} + +char * +PrevInHistory(char *cmd) +{ + int newhp; + if (histP == histIn) { + if (history[histIn] != NULL) free(history[histIn]); + history[histIn] = StrSave(cmd); + } + newhp = (histP - 1 + HISTORY_SIZE) % HISTORY_SIZE; + if (newhp == histIn || history[newhp] == NULL) return NULL; + histP = newhp; + return history[histP]; +} + +char * +NextInHistory() +{ + if (histP == histIn) return NULL; + histP = (histP + 1) % HISTORY_SIZE; + return history[histP]; +} +// end of borrowed code + #define Abs(n) ((n)<0 ? -(n) : (n)) /* * 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. */ -char *FindFont(pattern, targetPxlSize) +char * +FindFont(pattern, targetPxlSize) char *pattern; int targetPxlSize; { @@ -2912,20 +3070,20 @@ char *FindFont(pattern, targetPxlSize) XFontStruct **fnt_list; base_fnt_lst = calloc(1, strlen(pattern) + 3); - sprintf(strInt, "%d", targetPxlSize); + snprintf(strInt, sizeof(strInt)/sizeof(strInt[0]), "%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, + if ((fntSet = XCreateFontSet(xDisplay, + base_fnt_lst, + &missing_list, + &missing_count, &def_string)) == NULL) { - fprintf(stderr, _("Unable to create font set.\n")); - exit (2); + fprintf(stderr, _("Unable to create font set.\n")); + exit (2); } nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts); @@ -2971,8 +3129,8 @@ char *FindFont(pattern, targetPxlSize) while (isdigit(*scalableTail)) scalableTail++; sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail); } else { - p = (char *) XtMalloc(strlen(best) + 1); - strcpy(p, best); + p = (char *) XtMalloc(strlen(best) + 2); + safeStrCpy(p, best, strlen(best)+1 ); } if (appData.debugMode) { fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"), @@ -2980,10 +3138,10 @@ char *FindFont(pattern, targetPxlSize) } #ifdef ENABLE_NLS if (missing_count > 0) - XFreeStringList(missing_list); + XFreeStringList(missing_list); XFreeFontSet(xDisplay, fntSet); #else - XFreeFontNames(fonts); + XFreeFontNames(fonts); #endif return p; } @@ -2994,29 +3152,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); @@ -3040,16 +3204,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); @@ -3061,19 +3225,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); @@ -3102,31 +3266,31 @@ void loadXIM(xim, xmask, filename, dest, mask) 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. */ @@ -3149,7 +3313,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), @@ -3159,14 +3323,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; @@ -3181,7 +3348,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); @@ -3197,36 +3364,39 @@ void CreateXIMPieces() } 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], + 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= + ximLightSquare= XGetImage(xDisplay, DefaultRootWindow(xDisplay), 0, 0, ss, ss, AllPlanes, XYPixmap); if (appData.debugMode) @@ -3234,11 +3404,11 @@ void CreateXIMPieces() loadXIM(ximLightSquare, NULL, buf, &xpmLightSquare, NULL); fprintf(stderr, _("dark square ")); - sprintf(buf, "%s/dsq%u.xim", + snprintf(buf,sizeof(buf), "%s/dsq%u.xim", ExpandPathName(appData.pixmapDirectory), ss); if (appData.debugMode) fprintf(stderr, _("(File:%s:) "), buf); - ximDarkSquare= + ximDarkSquare= XGetImage(xDisplay, DefaultRootWindow(xDisplay), 0, 0, ss, ss, AllPlanes, XYPixmap); loadXIM(ximDarkSquare, NULL, buf, &xpmDarkSquare, NULL); @@ -3250,6 +3420,16 @@ void CreateXIMPieces() } #if HAVE_LIBXPM +void CreateXPMBoard(char *s, int kind) +{ + XpmAttributes attr; + attr.valuemask = 0; + if(s == NULL || *s == 0 || *s == '*') return; + if (XpmReadFileToPixmap(xDisplay, xBoardWindow, s, &(xpmBoardBitmap[kind]), NULL, &attr) == 0) { + useTexture |= kind + 1; textureW[kind] = attr.width; textureH[kind] = attr.height; + } +} + void CreateXPMPieces() { int piece, kind, r; @@ -3259,18 +3439,10 @@ void CreateXPMPieces() static char *xpmkind[] = { "ll", "ld", "dl", "dd" }; XpmColorSymbol symbols[4]; -#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", - 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; @@ -3299,51 +3471,70 @@ void CreateXPMPieces() 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"), 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")); /* 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); } 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); + snprintf(buf, sizeof(buf), "%s/lsq%u.xpm", ExpandPathName(appData.pixmapDirectory), ss); if (access(buf, 0) != 0) { useImageSqs = 0; } else { @@ -3357,7 +3548,7 @@ void CreateXPMPieces() exit(1); } fprintf(stderr, _("dark square ")); - sprintf(buf, "%s/dsq%u.xpm", + snprintf(buf, sizeof(buf), "%s/dsq%u.xpm", ExpandPathName(appData.pixmapDirectory), ss); if (appData.debugMode) { fprintf(stderr, _("(File:%s:) "), buf); @@ -3372,7 +3563,7 @@ void CreateXPMPieces() fprintf(stderr, _("Done.\n")); } XSynchronize(xDisplay, False); /* Work-around for xlib/xt - buffering bug */ + buffering bug */ } #endif /* HAVE_LIBXPM */ @@ -3383,18 +3574,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)), - ss, kind == SOLID ? 's' : 'o'); - ReadBitmap(&pieceBitmap[kind][piece], buf, NULL, ss, ss); + for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) { + snprintf(buf, MSG_SIZ, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "", + pieceBitmapNames[piece], + ss, kind == SOLID ? 's' : 'o'); + 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 */ } @@ -3406,21 +3600,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)), - ss, kind == SOLID ? 's' : 'o'); - ReadBitmap(&pieceBitmap[kind][piece], buf, - bib->bits[kind][piece], ss, ss); + for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) { + snprintf(buf, MSG_SIZ, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "", + pieceBitmapNames[piece], + ss, kind == SOLID ? 's' : 'o'); + 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 */ } @@ -3436,27 +3633,28 @@ 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); + safeStrCpy(fullname, appData.bitmapDirectory, sizeof(fullname)/sizeof(fullname[0]) ); + strncat(fullname, "/", MSG_SIZ - strlen(fullname) - 1); + strncat(fullname, name, MSG_SIZ - strlen(fullname) - 1); + 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; } @@ -3470,11 +3668,7 @@ void ReadBitmap(pm, name, bits, wreq, hreq) return; } } - if (bits == NULL) { - fprintf(stderr, _("%s: No built-in bitmap for %s; giving up\n"), - programName, name); - exit(1); - } else { + if (bits != NULL) { *pm = XCreateBitmapFromData(xDisplay, xBoardWindow, (char *) bits, wreq, hreq); } @@ -3482,22 +3676,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)); } } @@ -3532,8 +3730,8 @@ 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, + XtSetArg(args[j], XtNlabel, XtNewString(mi->string)); + entry = XtCreateManagedWidget(mi->ref, smeBSBObjectClass, menu, args, j+1); XtAddCallback(entry, XtNcallback, (XtCallbackProc) MenuBarSelect, @@ -3541,7 +3739,7 @@ void CreateMenuBarPopup(parent, name, mb) } mi++; } -} +} Widget CreateMenuBar(mb) Menu *mb; @@ -3559,19 +3757,19 @@ Widget CreateMenuBar(mb) formWidget, args, j); while (mb->name != NULL) { - strcpy(menuName, "menu"); - strcat(menuName, mb->name); + safeStrCpy(menuName, "menu", sizeof(menuName)/sizeof(menuName[0]) ); + strncat(menuName, mb->ref, MSG_SIZ - strlen(menuName) - 1); j = 0; 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++; - } + else { + XtSetArg(args[j], XtNlabel, XtNewString(mb->name)); j++; + } XtSetArg(args[j], XtNborderWidth, 0); j++; anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass, @@ -3605,7 +3803,7 @@ Widget CreateButtonBar(mi) XtSetArg(args[j], XtNinternalWidth, 2); j++; XtSetArg(args[j], XtNborderWidth, 0); j++; } - XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string))); j++; + XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string))); j++; button = XtCreateManagedWidget(mi->string, commandWidgetClass, buttonBar, args, j); XtAddCallback(button, XtNcallback, @@ -3614,7 +3812,7 @@ Widget CreateButtonBar(mi) mi++; } return buttonBar; -} +} Widget CreatePieceMenu(name, color) @@ -3628,17 +3826,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))); + XtSetArg(args[0], XtNlabel, XtNewString(_(item))); entry = XtCreateManagedWidget(item, smeBSBObjectClass, - menu, args, 1); + menu, args, 1); selection = pieceMenuTranslation[color][i]; XtAddCallback(entry, XtNcallback, (XtCallbackProc) PieceMenuSelect, @@ -3662,7 +3860,7 @@ CreatePieceMenus() whitePieceMenu = CreatePieceMenu("menuW", 0); blackPieceMenu = CreatePieceMenu("menuB", 1); - + XtRegisterGrabAction(PieceMenuPopup, True, (unsigned)(ButtonPressMask|ButtonReleaseMask), GrabModeAsync, GrabModeAsync); @@ -3672,21 +3870,21 @@ CreatePieceMenus() 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))); + XtSetArg(args[0], XtNlabel, XtNewString(_(item))); entry = XtCreateManagedWidget(item, smeBSBObjectClass, - dropMenu, args, 1); + dropMenu, args, 1); selection = dropMenuTranslation[i]; XtAddCallback(entry, XtNcallback, (XtCallbackProc) DropMenuSelect, (caddr_t) selection); } } -} +} void SetupDropMenu() { @@ -3705,7 +3903,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); @@ -3718,39 +3916,18 @@ void PieceMenuPopup(w, event, params, num_params) String *params; Cardinal *num_params; { - String whichMenu; - if (event->type != ButtonPress) return; - if (errorUp) ErrorPopDown(); - switch (gameMode) { - case EditPosition: - case IcsExamining: - whichMenu = params[0]; - break; - case IcsPlayingWhite: - case IcsPlayingBlack: - case EditGame: - case MachinePlaysWhite: - case MachinePlaysBlack: - if (appData.testLegality && - gameInfo.variant != VariantBughouse && - gameInfo.variant != VariantCrazyhouse) return; - SetupDropMenu(); - whichMenu = "menuD"; - break; - default: - return; + String whichMenu; int menuNr; + if (event->type == ButtonRelease) + menuNr = RightClick(Release, event->xbutton.x, event->xbutton.y, &pmFromX, &pmFromY); + else if (event->type == ButtonPress) + menuNr = RightClick(Press, event->xbutton.x, event->xbutton.y, &pmFromX, &pmFromY); + switch(menuNr) { + case 0: whichMenu = params[0]; break; + case 1: SetupDropMenu(); whichMenu = "menuD"; break; + case 2: + case -1: if (errorUp) ErrorPopDown(); + default: return; } - - if (((pmFromX = EventToSquare(event->xbutton.x, BOARD_SIZE)) < 0) || - ((pmFromY = EventToSquare(event->xbutton.y, BOARD_SIZE)) < 0)) { - pmFromX = pmFromY = -1; - return; - } - if (flipView) - pmFromX = BOARD_SIZE - 1 - pmFromX; - else - pmFromY = BOARD_SIZE - 1 - pmFromY; - XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu)); } @@ -3778,11 +3955,7 @@ void WhiteClock(w, event, prms, nprms) String *prms; Cardinal *nprms; { - if (gameMode == EditPosition || gameMode == IcsExamining) { - SetWhiteToPlayEvent(); - } else if (gameMode == IcsPlayingBlack || gameMode == MachinePlaysWhite) { - CallFlagEvent(); - } + ClockClick(0); } void BlackClock(w, event, prms, nprms) @@ -3791,11 +3964,7 @@ void BlackClock(w, event, prms, nprms) String *prms; Cardinal *nprms; { - if (gameMode == EditPosition || gameMode == IcsExamining) { - SetBlackToPlayEvent(); - } else if (gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) { - CallFlagEvent(); - } + ClockClick(1); } @@ -3806,7 +3975,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; @@ -3831,18 +4000,18 @@ static void drawHighlight(file, rank, gc) { int x, y; - if (lineGap == 0 || appData.blindfold) return; - + if (lineGap == 0) 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); } @@ -3858,14 +4027,18 @@ SetHighlights(fromX, fromY, toX, toY) if (hi1X >= 0 && hi1Y >= 0) { drawHighlight(hi1X, hi1Y, lineGC); } + } // [HGM] first erase both, then draw new! + if (hi2X != toX || hi2Y != toY) { + if (hi2X >= 0 && hi2Y >= 0) { + drawHighlight(hi2X, hi2Y, lineGC); + } + } + if (hi1X != fromX || hi1Y != fromY) { if (fromX >= 0 && fromY >= 0) { drawHighlight(fromX, fromY, highlineGC); } } if (hi2X != toX || hi2Y != toY) { - if (hi2X >= 0 && hi2Y >= 0) { - drawHighlight(hi2X, hi2Y, lineGC); - } if (toX >= 0 && toY >= 0) { drawHighlight(toX, toY, highlineGC); } @@ -3915,11 +4088,34 @@ ClearPremoveHighlights() SetPremoveHighlights(-1, -1, -1, -1); } -static void BlankSquare(x, y, color, piece, dest) - int x, y, color; +static int CutOutSquare(x, y, x0, y0, kind) + int x, y, *x0, *y0, kind; +{ + int W = BOARD_WIDTH, H = BOARD_HEIGHT; + int nx = x/(squareSize + lineGap), ny = y/(squareSize + lineGap); + *x0 = 0; *y0 = 0; + if(textureW[kind] < squareSize || textureH[kind] < squareSize) return 0; + if(textureW[kind] < W*squareSize) + *x0 = (textureW[kind] - squareSize) * nx/(W-1); + else + *x0 = textureW[kind]*nx / W + (textureW[kind] - W*squareSize) / (2*W); + if(textureH[kind] < H*squareSize) + *y0 = (textureH[kind] - squareSize) * ny/(H-1); + else + *y0 = textureH[kind]*ny / H + (textureH[kind] - H*squareSize) / (2*H); + return 1; +} + +static void BlankSquare(x, y, color, piece, dest, fac) + int x, y, color, fac; ChessSquare piece; Drawable dest; -{ +{ // [HGM] extra param 'fac' for forcing destination to (0,0) for copying to animation buffer + int x0, y0; + if (useImages && color != 2 && (useTexture & color+1) && CutOutSquare(x, y, &x0, &y0, color)) { + XCopyArea(xDisplay, xpmBoardBitmap[color], dest, wlPieceGC, x0, y0, + squareSize, squareSize, x*fac, y*fac); + } else if (useImages && useImageSqs) { Pixmap pm; switch (color) { @@ -3935,7 +4131,7 @@ static void BlankSquare(x, y, color, piece, dest) break; } XCopyArea(xDisplay, pm, dest, wlPieceGC, 0, 0, - squareSize, squareSize, x, y); + squareSize, squareSize, x*fac, y*fac); } else { GC gc; switch (color) { @@ -3950,7 +4146,7 @@ static void BlankSquare(x, y, color, piece, dest) gc = jailSquareGC; break; } - XFillRectangle(xDisplay, dest, gc, x, y, squareSize, squareSize); + XFillRectangle(xDisplay, dest, gc, x*fac, y*fac, squareSize, squareSize); } } @@ -4014,6 +4210,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), @@ -4042,7 +4239,7 @@ static void colorDrawPieceImage(piece, square_color, x, y, dest) int square_color, x, y; Drawable dest; { - int kind; + int kind, p = piece; switch (square_color) { case 1: /* light */ @@ -4064,9 +4261,18 @@ static void colorDrawPieceImage(piece, square_color, x, y, dest) } break; } + if(appData.upsideDown && flipView) kind ^= 2; // swap white and black pieces + if(useTexture & square_color+1) { + BlankSquare(x, y, square_color, piece, dest, 1); // erase previous contents with background + XSetClipMask(xDisplay, wlPieceGC, xpmMask[p]); + XSetClipOrigin(xDisplay, wlPieceGC, x, y); + XCopyArea(xDisplay, xpmPieceBitmap[kind][piece], dest, wlPieceGC, 0, 0, squareSize, squareSize, x, y); + XSetClipMask(xDisplay, wlPieceGC, None); + XSetClipOrigin(xDisplay, wlPieceGC, 0, 0); + } else XCopyArea(xDisplay, xpmPieceBitmap[kind][piece], dest, wlPieceGC, 0, 0, - squareSize, squareSize, x, y); + squareSize, squareSize, x, y); } typedef void (*DrawFunc)(); @@ -4087,6 +4293,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; @@ -4100,56 +4332,95 @@ 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, 1); + + // [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, 1); + } 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, @@ -4157,8 +4428,12 @@ void DrawSquare(row, column, piece, do_flash) } else { XDrawString(xDisplay, xBoardWindow, coordGC, x + 2, y + font_ascent + 1, string, 1); - } - } + } + } + if(!partnerUp && marker[row][column]) { + XFillArc(xDisplay, xBoardWindow, marker[row][column] == 2 ? prelineGC : highlineGC, + x + squareSize/4, y+squareSize/4, squareSize/2, squareSize/2, 0, 64*360); + } } @@ -4175,7 +4450,14 @@ void EventProc(widget, unused, event) case Expose: if (event->xexpose.count > 0) return; /* no clipping is done */ XDrawPosition(widget, True, NULL); + if(twoBoards) { // [HGM] dual: draw other board in other orientation + flipView = !flipView; partnerUp = !partnerUp; + XDrawPosition(widget, True, NULL); + flipView = !flipView; partnerUp = !partnerUp; + } break; + case MotionNotify: + if(SeekGraphClick(Press, event->xbutton.x, event->xbutton.y, 1)) break; default: return; } @@ -4196,9 +4478,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; @@ -4220,9 +4502,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. */ @@ -4256,7 +4538,37 @@ static int check_castle_draw(newb, oldb, rrow, rcol) return 0; } -static int damage[BOARD_SIZE][BOARD_SIZE]; +// [HGM] seekgraph: some low-level drawing routines cloned from xevalgraph +void DrawSeekAxis( int x, int y, int xTo, int yTo ) +{ + XDrawLine(xDisplay, xBoardWindow, lineGC, x, y, xTo, yTo); +} + +void DrawSeekBackground( int left, int top, int right, int bottom ) +{ + XFillRectangle(xDisplay, xBoardWindow, lightSquareGC, left, top, right-left, bottom-top); +} + +void DrawSeekText(char *buf, int x, int y) +{ + XDrawString(xDisplay, xBoardWindow, coordGC, x, y+4, buf, strlen(buf)); +} + +void DrawSeekDot(int x, int y, int colorNr) +{ + int square = colorNr & 0x80; + GC color; + colorNr &= 0x7F; + color = colorNr == 0 ? prelineGC : colorNr == 1 ? darkSquareGC : highlineGC; + if(square) + XFillRectangle(xDisplay, xBoardWindow, color, + x-squareSize/9, y-squareSize/9, 2*squareSize/9, 2*squareSize/9); + else + XFillArc(xDisplay, xBoardWindow, color, + x-squareSize/8, y-squareSize/8, squareSize/4, squareSize/4, 0, 64*360); +} + +static int damage[2][BOARD_RANKS][BOARD_FILES]; /* * event handler for redrawing the board @@ -4268,18 +4580,21 @@ void XDrawPosition(w, repaint, board) { int i, j, do_flash; static int lastFlipView = 0; - static int lastBoardValid = 0; - static Board lastBoard; + static int lastBoardValid[2] = {0, 0}; + static Board lastBoard[2]; Arg args[16]; int rrow, rcol; - + int nr = twoBoards*partnerUp; + + if(DrawSeekGraph()) return; // [HGM] seekgraph: suppress any drawing if seek graph up + if (board == NULL) { - if (!lastBoardValid) return; - board = lastBoard; + if (!lastBoardValid[nr]) return; + board = lastBoard[nr]; } - if (!lastBoardValid || lastFlipView != flipView) { + if (!lastBoardValid[nr] || (nr == 0 && lastFlipView != flipView)) { XtSetArg(args[0], XtNleftBitmap, (flipView ? xMarkPixmap : None)); - XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flip View"), + XtSetValues(XtNameToWidget(menuBarWidget, "menuView.Flip View"), args, 1); } @@ -4287,54 +4602,57 @@ 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 ( lineGap && IsDrawArrowEnabled()) repaint = True; + if (!repaint && lastBoardValid[nr] && (nr == 1 || lastFlipView == flipView)) { /* If too much changes (begin observing new game, etc.), don't do flashing */ - do_flash = too_many_diffs(board, lastBoard) ? 0 : 1; + do_flash = too_many_diffs(board, lastBoard[nr]) ? 0 : 1; /* Special check for castling so we don't flash both the king and the rook (just flash the king). */ if (do_flash) { - if (check_castle_draw(board, lastBoard, &rrow, &rcol)) { + if (check_castle_draw(board, lastBoard[nr], &rrow, &rcol)) { /* Draw rook with NO flashing. King will be drawn flashing later */ DrawSquare(rrow, rcol, board[rrow][rcol], 0); - lastBoard[rrow][rcol] = board[rrow][rcol]; + lastBoard[nr][rrow][rcol] = board[rrow][rcol]; } } - /* 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++) - if ((board[i][j] != lastBoard[i][j] && board[i][j] == EmptySquare) - || damage[i][j]) { + for (i = 0; i < BOARD_HEIGHT; i++) + for (j = 0; j < BOARD_WIDTH; j++) + if ((board[i][j] != lastBoard[nr][i][j] && board[i][j] == EmptySquare) + || damage[nr][i][j]) { DrawSquare(i, j, board[i][j], 0); - damage[i][j] = False; + damage[nr][i][j] = False; } /* 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++) - if (board[i][j] != lastBoard[i][j]) { - DrawSquare(i, j, board[i][j], do_flash); + for (i = 0; i < BOARD_HEIGHT; i++) + for (j = 0; j < BOARD_WIDTH; j++) + if (board[i][j] != lastBoard[nr][i][j]) { + 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++) { + twoBoards & partnerUp ? secondSegments : // [HGM] dual + 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; + damage[nr][i][j] = False; } } - CopyBoard(lastBoard, board); - lastBoardValid = 1; + CopyBoard(lastBoard[nr], board); + lastBoardValid[nr] = 1; + if(nr == 0) { // [HGM] dual: no highlights on second board yet lastFlipView = flipView; /* Draw highlights */ @@ -4350,7 +4668,8 @@ void XDrawPosition(w, repaint, board) if (hi2X >= 0 && hi2Y >= 0) { drawHighlight(hi2X, hi2Y, highlineGC); } - + DrawArrowHighlight(hi1X, hi1Y, hi2X, hi2Y); + } /* If piece being dragged around board, must redraw that too */ DrawDragPiece(); @@ -4374,19 +4693,21 @@ 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; String *prms; Cardinal *nprms; { - int x, y; - Boolean saveAnimate; - static int second = 0; - if (w != boardWidget || errorExitStatus != -1) return; - - if (event->type == ButtonPress) ErrorPopDown(); + if(nprms) shiftKey = !strcmp(prms[0], "1"); if (promotionUp) { if (event->type == ButtonPress) { @@ -4399,123 +4720,10 @@ void HandleUserMove(w, event, prms, nprms) return; } } - - x = EventToSquare(event->xbutton.x, BOARD_SIZE); - y = EventToSquare(event->xbutton.y, BOARD_SIZE); - if (!flipView && y >= 0) { - y = BOARD_SIZE - 1 - y; - } - if (flipView && x >= 0) { - x = BOARD_SIZE - 1 - x; - } - - if (fromX == -1) { - if (event->type == ButtonPress) { - /* First square */ - if (OKToStartUserMove(x, y)) { - fromX = x; - fromY = y; - second = 0; - DragPieceBegin(event->xbutton.x, event->xbutton.y); - if (appData.highlightDragging) { - SetHighlights(x, y, -1, -1); - } - } - } - return; - } - - /* fromX != -1 */ - if (event->type == ButtonPress && gameMode != EditPosition && - x >= 0 && y >= 0) { - ChessSquare fromP; - ChessSquare toP; - /* 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)) { - /* Clicked again on same color piece -- changed his mind */ - second = (x == fromX && y == fromY); - if (appData.highlightDragging) { - SetHighlights(x, y, -1, -1); - } else { - ClearHighlights(); - } - if (OKToStartUserMove(x, y)) { - fromX = x; - fromY = y; - DragPieceBegin(event->xbutton.x, event->xbutton.y); - } - return; - } - } - if (event->type == ButtonRelease && x == fromX && y == fromY) { - DragPieceEnd(event->xbutton.x, event->xbutton.y); - if (appData.animateDragging) { - /* Undo animation damage if any */ - DrawPosition(FALSE, NULL); - } - if (second) { - /* Second up/down in same square; just abort move */ - second = 0; - fromX = fromY = -1; - ClearHighlights(); - gotPremove = 0; - ClearPremoveHighlights(); - } else { - /* First upclick in same square; start click-click mode */ - SetHighlights(x, y, -1, -1); - } - return; - } - - /* Completed move */ - toX = x; - toY = y; - saveAnimate = appData.animate; - if (event->type == ButtonPress) { - /* Finish clickclick move */ - if (appData.animate || appData.highlightLastMove) { - SetHighlights(fromX, fromY, toX, toY); - } else { - ClearHighlights(); - } - } else { - /* Finish drag move */ - if (appData.highlightLastMove) { - SetHighlights(fromX, fromY, toX, toY); - } else { - ClearHighlights(); - } - DragPieceEnd(event->xbutton.x, event->xbutton.y); - /* Don't animate move and drag both */ - appData.animate = FALSE; - } - if (IsPromotion(fromX, fromY, toX, toY)) { - if (appData.alwaysPromoteToQueen) { - UserMoveEvent(fromX, fromY, toX, toY, 'q'); - if (!appData.highlightLastMove || gotPremove) ClearHighlights(); - if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY); - fromX = fromY = -1; - } else { - SetHighlights(fromX, fromY, toX, toY); - PromotionPopUp(); - } - } else { - UserMoveEvent(fromX, fromY, toX, toY, NULLCHAR); - if (!appData.highlightLastMove || gotPremove) ClearHighlights(); - if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY); - fromX = fromY = -1; - } - appData.animate = saveAnimate; - if (appData.animate || appData.animateDragging) { - /* Undo animation damage if needed */ - DrawPosition(FALSE, NULL); - } + // [HGM] mouse: the rest of the mouse handler is moved to the backend, and called here + if(event->type == ButtonPress) LeftClick(Press, event->xbutton.x, event->xbutton.y); + if(event->type == ButtonRelease) LeftClick(Release, event->xbutton.x, event->xbutton.y); } void AnimateUserMove (Widget w, XEvent * event, @@ -4524,6 +4732,12 @@ void AnimateUserMove (Widget w, XEvent * event, DragPieceMove(event->xmotion.x, event->xmotion.y); } +void HandlePV (Widget w, XEvent * event, + String * params, Cardinal * nParams) +{ // [HGM] pv: walk PV + MovePV(event->xmotion.x, event->xmotion.y, lineGap + BOARD_HEIGHT * (squareSize + lineGap)); +} + Widget CommentCreate(name, text, mutable, callback, lines) char *name, *text; int /*Boolean*/ mutable; @@ -4569,16 +4783,13 @@ Widget CommentCreate(name, text, mutable, callback, lines) XtSetArg(args[j], XtNright, XtChainRight); j++; XtSetArg(args[j], XtNresizable, True); j++; XtSetArg(args[j], XtNwidth, bw_width); j++; /*force wider than buttons*/ -#if 0 - XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++; -#else /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */ XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++; -#endif XtSetArg(args[j], XtNautoFill, True); j++; XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++; edit = XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j); + XtOverrideTranslations(edit, XtParseTranslationTable(commentTranslations)); if (mutable) { j = 0; @@ -4672,6 +4883,14 @@ Widget CommentCreate(name, text, mutable, callback, lines) #endif /*!NOTDEF*/ if (commentY < 0) commentY = 0; /*avoid positioning top offscreen*/ } + + if(wpComment.width > 0) { + commentX = wpComment.x; + commentY = wpComment.y; + commentW = wpComment.width; + commentH = wpComment.height; + } + j = 0; XtSetArg(args[j], XtNheight, commentH); j++; XtSetArg(args[j], XtNwidth, commentW); j++; @@ -4727,12 +4946,8 @@ Widget MiscCreate(name, text, mutable, callback, lines) XtSetArg(args[j], XtNleft, XtChainLeft); j++; XtSetArg(args[j], XtNright, XtChainRight); j++; XtSetArg(args[j], XtNresizable, True); j++; -#if 0 - XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++; -#else /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */ XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++; -#endif XtSetArg(args[j], XtNautoFill, True); j++; XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++; edit = @@ -4783,6 +4998,20 @@ Widget MiscCreate(name, text, mutable, callback, lines) static int savedIndex; /* gross that this is global */ +void CommentClick (Widget w, XEvent * event, String * params, Cardinal * nParams) +{ + String val; + XawTextPosition index, dummy; + Arg arg; + + XawTextGetSelectionPos(w, &index, &dummy); + XtSetArg(arg, XtNstring, &val); + XtGetValues(w, &arg, 1); + ReplaceComment(savedIndex, val); + if(savedIndex != currentMove) ToNrEvent(savedIndex); + LoadVariation( index, val ); // [HGM] also does the actual moving to it, now +} + void EditCommentPopUp(index, title, text) int index; char *title, *text; @@ -4796,7 +5025,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 { @@ -4815,7 +5044,9 @@ void EditCommentPopUp(index, title, text) editUp = True; j = 0; XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++; - XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"), + XtSetValues(XtNameToWidget(menuBarWidget, "menuEdit.Edit Comment"), + args, j); + XtSetValues(XtNameToWidget(menuBarWidget, "menuView.Show Comments"), args, j); } @@ -4864,7 +5095,9 @@ void EditCommentPopDown() editUp = False; j = 0; XtSetArg(args[j], XtNleftBitmap, None); j++; - XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"), + XtSetValues(XtNameToWidget(menuBarWidget, "menuEdit.Edit Comment"), + args, j); + XtSetValues(XtNameToWidget(menuBarWidget, "menuView.Show Comments"), args, j); } @@ -4875,7 +5108,7 @@ void ICSInputBoxPopUp() int j; char *title = _("ICS Input"); XtTranslations tr; - + if (ICSInputShell == NULL) { ICSInputShell = MiscCreate(title, "", True, NULL, 1); tr = XtParseTranslationTable(ICSInputTranslations); @@ -4883,7 +5116,7 @@ void ICSInputBoxPopUp() XtOverrideTranslations(edit, tr); XtRealizeWidget(ICSInputShell); CatchDeleteWindow(ICSInputShell, "ICSInputBoxPopDown"); - + } else { edit = XtNameToWidget(ICSInputShell, "*form.text"); j = 0; @@ -4901,7 +5134,7 @@ void ICSInputBoxPopUp() ICSInputBoxUp = True; j = 0; XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++; - XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"), + XtSetValues(XtNameToWidget(menuBarWidget, "menuView.ICS Input Box"), args, j); } @@ -4911,11 +5144,12 @@ void ICSInputSendText() int j; Arg args[16]; String val; - + edit = XtNameToWidget(ICSInputShell, "*form.text"); j = 0; XtSetArg(args[j], XtNstring, &val); j++; XtGetValues(edit, args, j); + SaveInHistory(val); SendMultiLineToICS(val); XtCallActionProc(edit, "select-all", NULL, NULL, 0); XtCallActionProc(edit, "kill-selection", NULL, NULL, 0); @@ -4932,7 +5166,7 @@ void ICSInputBoxPopDown() ICSInputBoxUp = False; j = 0; XtSetArg(args[j], XtNleftBitmap, None); j++; - XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"), + XtSetValues(XtNameToWidget(menuBarWidget, "menuView.ICS Input Box"), args, j); } @@ -4943,6 +5177,7 @@ void CommentPopUp(title, text) int j; Widget edit; + savedIndex = currentMove; // [HGM] vari if (commentShell == NULL) { commentShell = CommentCreate(title, text, False, CommentCallback, 4); @@ -4965,37 +5200,6 @@ void CommentPopUp(title, text) commentUp = True; } -void AnalysisPopUp(title, text) - char *title, *text; -{ - Arg args[16]; - int j; - Widget edit; - - if (analysisShell == NULL) { - analysisShell = MiscCreate(title, text, False, NULL, 4); - XtRealizeWidget(analysisShell); - CatchDeleteWindow(analysisShell, "AnalysisPopDown"); - - } else { - edit = XtNameToWidget(analysisShell, "*form.text"); - j = 0; - XtSetArg(args[j], XtNstring, text); j++; - XtSetValues(edit, args, j); - j = 0; - XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++; - XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++; - XtSetValues(analysisShell, args, j); - } - - if (!analysisUp) { - XtPopup(analysisShell, XtGrabNone); - } - XSync(xDisplay, False); - - analysisUp = True; -} - void CommentCallback(w, client_data, call_data) Widget w; XtPointer client_data, call_data; @@ -5034,71 +5238,22 @@ void CommentPopDown() commentUp = False; } -void AnalysisPopDown() -{ - if (!analysisUp) return; - XtPopdown(analysisShell); - XSync(xDisplay, False); - analysisUp = False; - /* icsEngineAnalyze */ - if (appData.icsEngineAnalyze) ExitAnalyzeMode(); -} - - void FileNamePopUp(label, def, proc, openMode) char *label; char *def; FileProc proc; char *openMode; { - Arg args[16]; - Widget popup, layout, dialog, edit; - Window root, child; - 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, - (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); + { // [HGM] use file-selector dialog stolen from Ghostview + char *name; + int index; // this is not supported yet + FILE *f; + if(f = XsraSelFile(shellWidget, label, NULL, NULL, "could not open: ", + def, openMode, NULL, &name)) + (void) (*fileProc)(f, index=0, name); + } } void FileNamePopDown() @@ -5116,15 +5271,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) { FileNamePopDown(); return; } - + FileNameAction(w, NULL, NULL, NULL); } @@ -5141,9 +5296,9 @@ void FileNameAction(w, event, prms, nprms) int index; name = XawDialogGetValueString(w = XtParent(w)); - + if ((name != NULL) && (*name != NULLCHAR)) { - strcpy(buf, name); + safeStrCpy(buf, name, sizeof(buf)/sizeof(buf[0]) ); XtPopdown(w = XtParent(XtParent(w))); XtDestroyWidget(w); filenameUp = False; @@ -5170,7 +5325,7 @@ void FileNameAction(w, event, prms, nprms) ModeHighlight(); return; } - + XtPopdown(w = XtParent(XtParent(w))); XtDestroyWidget(w); filenameUp = False; @@ -5188,7 +5343,7 @@ 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++; @@ -5198,48 +5353,76 @@ void PromotionPopUp() 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) { + if(gameInfo.variant == VariantSpartan && !WhiteOnMove(currentMove)) { + XawDialogAddButton(dialog, _("Warlord"), PromotionCallback, + (XtPointer) dialog); + XawDialogAddButton(dialog, _("General"), PromotionCallback, + (XtPointer) dialog); + XawDialogAddButton(dialog, _("Lieutenant"), PromotionCallback, + (XtPointer) dialog); + XawDialogAddButton(dialog, _("Captain"), PromotionCallback, + (XtPointer) dialog); + } else { + 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 || + gameInfo.variant == VariantSpartan && !WhiteOnMove(currentMove) || gameInfo.variant == VariantGiveaway) { - XawDialogAddButton(dialog, _("King"), PromotionCallback, + 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); } - XawDialogAddButton(dialog, _("cancel"), PromotionCallback, + } 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; } @@ -5258,20 +5441,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) { fromX = fromY = -1; ClearHighlights(); return; } 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]); } @@ -5316,28 +5503,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); - + XtRealizeWidget(errorShell); CatchDeleteWindow(errorShell, "ErrorPopDown"); - + i = 0; XtSetArg(args[i], XtNwidth, &bw_width); i++; XtGetValues(boardWidget, args, i); @@ -5430,7 +5617,7 @@ char *ModeToWidgetName(mode) case EndOfGame: return NULL; } -} +} void ModeHighlight() { @@ -5438,7 +5625,7 @@ void ModeHighlight() static int oldPausing = FALSE; static GameMode oldmode = (GameMode) -1; char *wname; - + if (!boardWidget || !XtIsRealized(boardWidget)) return; if (pausing != oldPausing) { @@ -5452,15 +5639,6 @@ void ModeHighlight() args, 1); if (appData.showButtonBar) { -#if 0 - if (pausing) { - XtSetArg(args[0], XtNbackground, buttonForegroundPixel); - XtSetArg(args[1], XtNforeground, buttonBackgroundPixel); - } else { - XtSetArg(args[0], XtNbackground, buttonBackgroundPixel); - XtSetArg(args[1], XtNforeground, buttonForegroundPixel); - } -#else /* Always toggle, don't set. Previous code messes up when invoked while the button is pressed, as releasing it toggles the state again. */ @@ -5473,7 +5651,6 @@ void ModeHighlight() XtSetArg(args[0], XtNbackground, oldfg); XtSetArg(args[1], XtNforeground, oldbg); } -#endif XtSetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2); } } @@ -5495,6 +5672,7 @@ void ModeHighlight() gameMode == Training || gameMode == PlayFromGameFile); } + /* * Button/menu procedures */ @@ -5505,7 +5683,6 @@ void ResetProc(w, event, prms, nprms) Cardinal *nprms; { ResetGameEvent(); - AnalysisPopDown(); } int LoadGamePopUp(f, gameNumber, title) @@ -5648,9 +5825,9 @@ void MailMoveProc(w, event, prms, nprms) } /* this variable is shared between CopyPositionProc and SendPositionSelection */ -static char *selected_fen_position=NULL; +char *selected_fen_position=NULL; -static Boolean +Boolean SendPositionSelection(Widget w, Atom *selection, Atom *target, Atom *type_return, XtPointer *value_return, unsigned long *length_return, int *format_return) @@ -5658,21 +5835,34 @@ SendPositionSelection(Widget w, Atom *selection, Atom *target, char *selection_tmp; if (!selected_fen_position) return False; /* should never happen */ - if (*target == XA_STRING){ + if (*target == XA_STRING || *target == XA_UTF8_STRING(xDisplay)){ /* note: since no XtSelectionDoneProc was registered, Xt will * automatically call XtFree on the value returned. So have to * make a copy of it allocated with XtMalloc */ selection_tmp= XtMalloc(strlen(selected_fen_position)+16); - strcpy(selection_tmp, selected_fen_position); + safeStrCpy(selection_tmp, selected_fen_position, strlen(selected_fen_position)+16 ); *value_return=selection_tmp; *length_return=strlen(selection_tmp); - *type_return=XA_STRING; + *type_return=*target; *format_return = 8; /* bits per byte */ return True; + } else if (*target == XA_TARGETS(xDisplay)) { + Atom *targets_tmp = (Atom *) XtMalloc(2 * sizeof(Atom)); + targets_tmp[0] = XA_UTF8_STRING(xDisplay); + targets_tmp[1] = XA_STRING; + *value_return = targets_tmp; + *type_return = XA_ATOM; + *length_return = 2; + *format_return = 8 * sizeof(Atom); + if (*format_return > 32) { + *length_return *= *format_return / 32; + *format_return = 32; + } + return True; } else { return False; - } + } } /* note: when called from menu all parameters are NULL, so no clue what the @@ -5684,20 +5874,25 @@ void CopyPositionProc(w, event, prms, nprms) String *prms; Cardinal *nprms; { - int ret; - + /* + * Set both PRIMARY (the selection) and CLIPBOARD, since we don't + * have a notion of a position that is selected but not copied. + * See http://www.freedesktop.org/wiki/Specifications/ClipboardsWiki + */ + if(gameMode == EditPosition) EditPositionDone(TRUE); 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, - SendPositionSelection, - NULL/* lose_ownership_proc */ , - NULL/* transfer_done_proc */); - if (!ret) { - free(selected_fen_position); - selected_fen_position=NULL; - } + XtOwnSelection(menuBarWidget, XA_PRIMARY, + CurrentTime, + SendPositionSelection, + NULL/* lose_ownership_proc */ , + NULL/* transfer_done_proc */); + XtOwnSelection(menuBarWidget, XA_CLIPBOARD(xDisplay), + CurrentTime, + SendPositionSelection, + NULL/* lose_ownership_proc */ , + NULL/* transfer_done_proc */); } /* function called when the data to Paste is ready */ @@ -5720,7 +5915,8 @@ void PastePositionProc(w, event, prms, nprms) String *prms; Cardinal *nprms; { - XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING, + XtGetSelectionValue(menuBarWidget, + appData.pasteSelection ? XA_PRIMARY: XA_CLIPBOARD(xDisplay), XA_STRING, /* (XtSelectionCallbackProc) */ PastePositionCB, NULL, /* client_data passed to PastePositionCB */ @@ -5739,7 +5935,7 @@ SendGameSelection(Widget w, Atom *selection, Atom *target, { char *selection_tmp; - if (*target == XA_STRING){ + if (*target == XA_STRING || *target == XA_UTF8_STRING(xDisplay)){ FILE* f = fopen(gameCopyFilename, "r"); long len; size_t count; @@ -5756,12 +5952,25 @@ SendGameSelection(Widget w, Atom *selection, Atom *target, selection_tmp[len] = NULLCHAR; *value_return = selection_tmp; *length_return = len; - *type_return = XA_STRING; + *type_return = *target; *format_return = 8; /* bits per byte */ return True; + } else if (*target == XA_TARGETS(xDisplay)) { + Atom *targets_tmp = (Atom *) XtMalloc(2 * sizeof(Atom)); + targets_tmp[0] = XA_UTF8_STRING(xDisplay); + targets_tmp[1] = XA_STRING; + *value_return = targets_tmp; + *type_return = XA_ATOM; + *length_return = 2; + *format_return = 8 * sizeof(Atom); + if (*format_return > 32) { + *length_return *= *format_return / 32; + *format_return = 32; + } + return True; } else { return False; - } + } } /* note: when called from menu all parameters are NULL, so no clue what the @@ -5778,11 +5987,21 @@ void CopyGameProc(w, event, prms, nprms) ret = SaveGameToFile(gameCopyFilename, FALSE); if (!ret) return; - ret = XtOwnSelection(menuBarWidget, XA_PRIMARY, - CurrentTime, - SendGameSelection, - NULL/* lose_ownership_proc */ , - NULL/* transfer_done_proc */); + /* + * Set both PRIMARY (the selection) and CLIPBOARD, since we don't + * have a notion of a game that is selected but not copied. + * See http://www.freedesktop.org/wiki/Specifications/ClipboardsWiki + */ + XtOwnSelection(menuBarWidget, XA_PRIMARY, + CurrentTime, + SendGameSelection, + NULL/* lose_ownership_proc */ , + NULL/* transfer_done_proc */); + XtOwnSelection(menuBarWidget, XA_CLIPBOARD(xDisplay), + CurrentTime, + SendGameSelection, + NULL/* lose_ownership_proc */ , + NULL/* transfer_done_proc */); } /* function called when the data to Paste is ready */ @@ -5813,7 +6032,8 @@ void PasteGameProc(w, event, prms, nprms) String *prms; Cardinal *nprms; { - XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING, + XtGetSelectionValue(menuBarWidget, + appData.pasteSelection ? XA_PRIMARY: XA_CLIPBOARD(xDisplay), XA_STRING, /* (XtSelectionCallbackProc) */ PasteGameCB, NULL, /* client_data passed to PasteGameCB */ @@ -5876,40 +6096,39 @@ void AnalyzeModeProc(w, event, prms, nprms) Cardinal *nprms; { char buf[MSG_SIZ]; - + if (!first.analysisSupport) { - sprintf(buf, _("%s does not support analysis"), first.tidy); + snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy); DisplayError(buf, 0); return; } - /* icsEngineAnalyze */ + /* [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; - } - return; - } else { - /* if enable, use want disable icsEngineAnalyze */ - if (appData.icsEngineAnalyze) { - ExitAnalyzeMode(); - ModeHighlight(); - return; + if (gameMode != IcsObserving) { + snprintf(buf, MSG_SIZ, _("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"); - } - } + fprintf(debugFP, _("ICS engine analyze starting... \n")); + } if (!appData.showThinking) ShowThinkingProc(w,event,prms,nprms); + AnalyzeModeEvent(); } @@ -5921,7 +6140,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; } @@ -6078,6 +6297,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; @@ -6088,6 +6334,55 @@ void EnterKeyProc(w, event, prms, nprms) ICSInputSendText(); } +void UpKeyProc(w, event, prms, nprms) + Widget w; + XEvent *event; + String *prms; + Cardinal *nprms; +{ // [HGM] input: let up-arrow recall previous line from history + Widget edit; + int j; + Arg args[16]; + String val; + XawTextBlock t; + + if (!ICSInputBoxUp) return; + edit = XtNameToWidget(ICSInputShell, "*form.text"); + j = 0; + XtSetArg(args[j], XtNstring, &val); j++; + XtGetValues(edit, args, j); + val = PrevInHistory(val); + XtCallActionProc(edit, "select-all", NULL, NULL, 0); + XtCallActionProc(edit, "kill-selection", NULL, NULL, 0); + if(val) { + t.ptr = val; t.firstPos = 0; t.length = strlen(val); t.format = XawFmt8Bit; + XawTextReplace(edit, 0, 0, &t); + XawTextSetInsertionPoint(edit, 9999); + } +} + +void DownKeyProc(w, event, prms, nprms) + Widget w; + XEvent *event; + String *prms; + Cardinal *nprms; +{ // [HGM] input: let down-arrow recall next line from history + Widget edit; + String val; + XawTextBlock t; + + if (!ICSInputBoxUp) return; + edit = XtNameToWidget(ICSInputShell, "*form.text"); + val = NextInHistory(); + XtCallActionProc(edit, "select-all", NULL, NULL, 0); + XtCallActionProc(edit, "kill-selection", NULL, NULL, 0); + if(val) { + t.ptr = val; t.firstPos = 0; t.length = strlen(val); t.format = XawFmt8Bit; + XawTextReplace(edit, 0, 0, &t); + XawTextSetInsertionPoint(edit, 9999); + } +} + void StopObservingProc(w, event, prms, nprms) Widget w; XEvent *event; @@ -6106,6 +6401,15 @@ void StopExaminingProc(w, event, prms, nprms) StopExaminingEvent(); } +void UploadProc(w, event, prms, nprms) + Widget w; + XEvent *event; + String *prms; + Cardinal *nprms; +{ + UploadGameEvent(); +} + void ForwardProc(w, event, prms, nprms) Widget w; @@ -6150,7 +6454,16 @@ void RevertProc(w, event, prms, nprms) String *prms; Cardinal *nprms; { - RevertEvent(); + RevertEvent(False); +} + +void AnnotateProc(w, event, prms, nprms) + Widget w; + XEvent *event; + String *prms; + Cardinal *nprms; +{ + RevertEvent(True); } void TruncateGameProc(w, event, prms, nprms) @@ -6488,6 +6801,25 @@ void HighlightLastMoveProc(w, event, prms, nprms) "menuOptions.Highlight Last Move"), args, 1); } +void HighlightArrowProc(w, event, prms, nprms) + Widget w; + XEvent *event; + String *prms; + Cardinal *nprms; +{ + Arg args[16]; + + appData.highlightMoveWithArrow = !appData.highlightMoveWithArrow; + + if (appData.highlightMoveWithArrow) { + XtSetArg(args[0], XtNleftBitmap, xMarkPixmap); + } else { + XtSetArg(args[0], XtNleftBitmap, None); + } + XtSetValues(XtNameToWidget(menuBarWidget, + "menuOptions.Arrow"), args, 1); +} + void IcsAlarmProc(w, event, prms, nprms) Widget w; XEvent *event; @@ -6526,8 +6858,7 @@ void MoveSoundProc(w, event, prms, nprms) args, 1); } - -void OldSaveStyleProc(w, event, prms, nprms) +void OneClickProc(w, event, prms, nprms) Widget w; XEvent *event; String *prms; @@ -6535,14 +6866,14 @@ void OldSaveStyleProc(w, event, prms, nprms) { Arg args[16]; - appData.oldSaveStyle = !appData.oldSaveStyle; + appData.oneClick = !appData.oneClick; - if (appData.oldSaveStyle) { + if (appData.oneClick) { XtSetArg(args[0], XtNleftBitmap, xMarkPixmap); } else { XtSetArg(args[0], XtNleftBitmap, None); } - XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Old Save Style"), + XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.OneClick"), args, 1); } @@ -6555,7 +6886,7 @@ void PeriodicUpdatesProc(w, event, prms, nprms) Arg args[16]; PeriodicUpdatesEvent(!appData.periodicUpdates); - + if (appData.periodicUpdates) { XtSetArg(args[0], XtNleftBitmap, xMarkPixmap); } else { @@ -6687,19 +7018,58 @@ void ShowThinkingProc(w, event, prms, nprms) String *prms; Cardinal *nprms; { + appData.showThinking = !appData.showThinking; // [HGM] thinking: tken out of ShowThinkingEvent + ShowThinkingEvent(); +} + +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 SaveOnExitProc(w, event, prms, nprms) + Widget w; + XEvent *event; + String *prms; + Cardinal *nprms; +{ Arg args[16]; - ShowThinkingEvent(!appData.showThinking); + saveSettingsOnExit = !saveSettingsOnExit; - if (appData.showThinking) { + if (saveSettingsOnExit) { XtSetArg(args[0], XtNleftBitmap, xMarkPixmap); } else { XtSetArg(args[0], XtNleftBitmap, None); } - XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Thinking"), + XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Save Settings on Exit"), args, 1); } +void SaveSettingsProc(w, event, prms, nprms) + Widget w; + XEvent *event; + String *prms; + Cardinal *nprms; +{ + SaveSettings(settingsFileName); +} + void InfoProc(w, event, prms, nprms) Widget w; XEvent *event; @@ -6707,7 +7077,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); } @@ -6724,7 +7094,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); } @@ -6758,11 +7128,12 @@ 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); } @@ -6801,7 +7172,7 @@ void Iconify(w, event, prms, nprms) Cardinal *nprms; { Arg args[16]; - + fromX = fromY = -1; XtSetArg(args[0], XtNiconic, True); XtSetValues(shellWidget, args, 1); @@ -6810,19 +7181,34 @@ void Iconify(w, event, prms, nprms) void DisplayMessage(message, extMessage) char *message, *extMessage; { - char buf[MSG_SIZ]; - Arg arg; - - if (extMessage) { - if (*message) { - sprintf(buf, "%s %s", message, extMessage); - message = buf; - } else { - message = extMessage; + /* display a message in the message widget */ + + char buf[MSG_SIZ]; + Arg arg; + + if (extMessage) + { + if (*message) + { + snprintf(buf, sizeof(buf), "%s %s", message, extMessage); + message = buf; } - } - XtSetArg(arg, XtNlabel, message); - XtSetValues(messageWidget, &arg, 1); + else + { + message = extMessage; + }; + }; + + /* need to test if messageWidget already exists, since this function + can also be called during the startup, if for example a Xresource + is not set up correctly */ + if(messageWidget) + { + XtSetArg(arg, XtNlabel, message); + XtSetValues(messageWidget, &arg, 1); + }; + + return; } void DisplayTitle(text) @@ -6842,20 +7228,31 @@ void DisplayTitle(text) } if (*text != NULLCHAR) { - strcpy(icon, text); - strcpy(title, text); + safeStrCpy(icon, text, sizeof(icon)/sizeof(icon[0]) ); + safeStrCpy(title, text, sizeof(title)/sizeof(title[0]) ); } 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) { + safeStrCpy(icon, programName, sizeof(icon)/sizeof(icon[0]) ); + safeStrCpy(title, GOTHIC, sizeof(title)/sizeof(title[0]) ); +#endif +#ifdef FALCON + } else if (gameInfo.variant == VariantFalcon) { + safeStrCpy(icon, programName, sizeof(icon)/sizeof(icon[0]) ); + safeStrCpy(title, FALCON, sizeof(title)/sizeof(title[0]) ); +#endif } else if (appData.noChessProgram) { - strcpy(icon, programName); - strcpy(title, programName); + safeStrCpy(icon, programName, sizeof(icon)/sizeof(icon[0]) ); + safeStrCpy(title, programName, sizeof(title)/sizeof(title[0]) ); } else { - strcpy(icon, first.tidy); - sprintf(title, "%s: %s", programName, first.tidy); + safeStrCpy(icon, first.tidy, sizeof(icon)/sizeof(icon[0]) ); + snprintf(title,sizeof(title), "%s: %s", programName, first.tidy); } i = 0; XtSetArg(args[i], XtNiconName, (XtArgVal) icon); i++; @@ -6864,7 +7261,8 @@ void DisplayTitle(text) } -void DisplayError(message, error) +void +DisplayError(message, error) String message; int error; { @@ -6879,9 +7277,9 @@ void DisplayError(message, error) fprintf(stderr, "%s: %s: %s\n", programName, message, strerror(error)); } - sprintf(buf, "%s: %s", message, strerror(error)); + snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error)); message = buf; - } + } ErrorPopUp(_("Error"), message, FALSE); } @@ -6915,7 +7313,7 @@ void DisplayFatalError(message, error, status) } else { fprintf(stderr, "%s: %s: %s\n", programName, message, strerror(error)); - sprintf(buf, "%s: %s", message, strerror(error)); + snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error)); message = buf; } if (appData.popupExitMessage && boardWidget && XtIsRealized(boardWidget)) { @@ -6969,9 +7367,9 @@ void DisplayIcsInteractionTitle(message) XSetErrorHandler(oldHandler); } if (oldICSInteractionTitle == NULL) { - oldICSInteractionTitle = "xterm"; + oldICSInteractionTitle = "xterm"; } - } + } printf("\033]0;%s\007", message); fflush(stdout); } @@ -7012,10 +7410,10 @@ void AskQuestionReplyAction(w, event, prms, nprms) String reply; reply = XawDialogGetValueString(w = XtParent(w)); - strcpy(buf, pendingReplyPrefix); - if (*buf) strcat(buf, " "); - strcat(buf, reply); - strcat(buf, "\n"); + safeStrCpy(buf, pendingReplyPrefix, sizeof(buf)/sizeof(buf[0]) ); + if (*buf) strncat(buf, " ", MSG_SIZ - strlen(buf) - 1); + strncat(buf, reply, MSG_SIZ - strlen(buf) - 1); + strncat(buf, "\n", MSG_SIZ - strlen(buf) - 1); OutputToProcess(pendingReplyPR, buf, strlen(buf), &err); AskQuestionPopDown(); @@ -7031,7 +7429,7 @@ void AskQuestionCallback(w, client_data, call_data) XtSetArg(args[0], XtNlabel, &name); XtGetValues(w, args, 1); - + if (strcmp(name, _("cancel")) == 0) { AskQuestionPopDown(); } else { @@ -7049,28 +7447,28 @@ void AskQuestion(title, question, replyPrefix, pr) int x, y, i; int win_x, win_y; unsigned int mask; - - strcpy(pendingReplyPrefix, replyPrefix); + + safeStrCpy(pendingReplyPrefix, replyPrefix, sizeof(pendingReplyPrefix)/sizeof(pendingReplyPrefix[0]) ); 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, (XtPointer) dialog); XawDialogAddButton(dialog, _("cancel"), AskQuestionCallback, @@ -7078,17 +7476,17 @@ void AskQuestion(title, question, replyPrefix, pr) 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); } @@ -7104,7 +7502,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); } } @@ -7167,18 +7565,18 @@ Colorize(cc, continuation) if (textColors[(int)cc].bg > 0) { if (textColors[(int)cc].fg > 0) { - sprintf(buf, "\033[0;%d;%d;%dm", textColors[(int)cc].attr, - textColors[(int)cc].fg, textColors[(int)cc].bg); + snprintf(buf, MSG_SIZ, "\033[0;%d;%d;%dm", textColors[(int)cc].attr, + textColors[(int)cc].fg, textColors[(int)cc].bg); } else { - sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr, - textColors[(int)cc].bg); + snprintf(buf, MSG_SIZ, "\033[0;%d;%dm", textColors[(int)cc].attr, + textColors[(int)cc].bg); } } else { if (textColors[(int)cc].fg > 0) { - sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr, + snprintf(buf, MSG_SIZ, "\033[0;%d;%dm", textColors[(int)cc].attr, textColors[(int)cc].fg); } else { - sprintf(buf, "\033[0;%dm", textColors[(int)cc].attr); + snprintf(buf, MSG_SIZ, "\033[0;%dm", textColors[(int)cc].attr); } } count = strlen(buf); @@ -7228,13 +7626,14 @@ char *UserName() return getpwuid(getuid())->pw_name; } -static char *ExpandPathName(path) +static char * +ExpandPathName(path) char *path; { - static char static_buf[2000]; - char *d, *s, buf[2000]; + static char static_buf[4*MSG_SIZ]; + char *d, *s, buf[4*MSG_SIZ]; struct passwd *pwd; - + s = path; d = static_buf; @@ -7248,33 +7647,33 @@ static char *ExpandPathName(path) if (*s == '~') { if (*(s+1) == '/') { - strcpy(d, getpwuid(getuid())->pw_dir); - strcat(d, s+1); + safeStrCpy(d, getpwuid(getuid())->pw_dir, 4*MSG_SIZ ); + strcat(d, s+1); } else { - strcpy(buf, s+1); - *strchr(buf, '/') = 0; - pwd = getpwnam(buf); - if (!pwd) - { - fprintf(stderr, _("ERROR: Unknown user %s (in path %s)\n"), - buf, path); - return NULL; - } - strcpy(d, pwd->pw_dir); - strcat(d, strchr(s+1, '/')); + safeStrCpy(buf, s+1, sizeof(buf)/sizeof(buf[0]) ); + { char *p; if(p = strchr(buf, '/')) *p = 0; } + pwd = getpwnam(buf); + if (!pwd) + { + fprintf(stderr, _("ERROR: Unknown user %s (in path %s)\n"), + buf, path); + return NULL; + } + safeStrCpy(d, pwd->pw_dir, 4*MSG_SIZ ); + strcat(d, strchr(s+1, '/')); } } else - strcpy(d, s); + safeStrCpy(d, s, 4*MSG_SIZ ); return static_buf; -} +} char *HostName() { static char host_name[MSG_SIZ]; - + #if HAVE_GETHOSTNAME gethostname(host_name, MSG_SIZ); return host_name; @@ -7302,6 +7701,9 @@ 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, @@ -7371,8 +7773,8 @@ AnalysisClockCallback(arg, id) XtPointer arg; XtIntervalId *id; { - if (gameMode == AnalyzeMode || gameMode == AnalyzeFile - || appData.icsEngineAnalyze) { + if (gameMode == AnalyzeMode || gameMode == AnalyzeFile + || appData.icsEngineAnalyze) { // [DM] AnalysisPeriodicEvent(0); StartAnalysisClock(); } @@ -7433,23 +7835,32 @@ 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); + snprintf(buf, MSG_SIZ, "%s: %s", color, TimeString(timer)); + XtSetArg(args[0], XtNlabel, buf); } else { - sprintf(buf, "%s ", color); - XtSetArg(args[0], XtNlabel, buf); + snprintf(buf, MSG_SIZ, "%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); } @@ -7459,6 +7870,8 @@ DisplayWhiteClock(timeRemaining, highlight) int highlight; { Arg args[16]; + + if(appData.noGUI) return; DisplayTimerLabel(whiteTimerWidget, _("White"), timeRemaining, highlight); if (highlight && iconPixmap == bIconPixmap) { iconPixmap = wIconPixmap; @@ -7473,6 +7886,8 @@ DisplayBlackClock(timeRemaining, highlight) int highlight; { Arg args[16]; + + if(appData.noGUI) return; DisplayTimerLabel(blackTimerWidget, _("Black"), timeRemaining, highlight); if (highlight && iconPixmap == wIconPixmap) { iconPixmap = bIconPixmap; @@ -7491,12 +7906,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; { @@ -7505,7 +7920,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); } @@ -7515,11 +7930,14 @@ int StartChildProcess(cmdLine, dir, pr) most simple-minded way possible. */ i = 0; - strcpy(buf, cmdLine); + safeStrCpy(buf, cmdLine, sizeof(buf)/sizeof(buf[0]) ); p = buf; for (;;) { + while(*p == ' ') p++; argv[i++] = p; - p = strchr(p, ' '); + if(*p == '"' || *p == '\'') + p = strchr(++argv[i-1], *p); + else p = strchr(p, ' '); if (p == NULL) break; *p++ = NULLCHAR; } @@ -7529,30 +7947,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; @@ -7562,22 +7984,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); } @@ -7600,9 +8037,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); } @@ -7656,7 +8093,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; } @@ -7717,7 +8154,7 @@ int OpenRcmd(host, user, cmd, pr) { DisplayFatalError(_("internal rcmd not implemented for Unix"), 0, 1); return -1; -} +} #define INPUT_SOURCE_BUF_SIZE 8192 @@ -7733,7 +8170,7 @@ typedef struct { } InputSource; void -DoInputCallback(closure, source, xid) +DoInputCallback(closure, source, xid) caddr_t closure; int *source; XtInputId *xid; @@ -7771,7 +8208,7 @@ DoInputCallback(closure, source, xid) else error = 0; (is->func)(is, is->closure, is->buf, count, error); - } + } } InputSourceRef AddInputSource(pr, lineByLine, func, closure) @@ -7796,7 +8233,7 @@ InputSourceRef AddInputSource(pr, lineByLine, func, closure) if (lineByLine) { is->unused = is->buf; } - + is->xid = XtAppAddInput(appContext, is->fd, (XtPointer) (XtInputReadMask), (XtInputCallbackProc) DoInputCallback, @@ -7822,11 +8259,33 @@ int OutputToProcess(pr, message, count, outError) int count; int *outError; { + static int line = 0; ChildProc *cp = (ChildProc *) pr; int outCount; if (pr == NoProc) - outCount = fwrite(message, 1, count, stdout); + { + if (appData.noJoin || !appData.useInternalWrap) + outCount = fwrite(message, 1, count, stdout); + else + { + int width = get_term_width(); + int len = wrap(NULL, message, count, width, &line); + char *msg = malloc(len); + int dbgchk; + + if (!msg) + outCount = fwrite(message, 1, count, stdout); + else + { + dbgchk = wrap(msg, message, count, width, &line); + if (dbgchk != len && appData.debugMode) + fprintf(debugFP, "wrap(): dbgchk(%d) != len(%d)\n", dbgchk, len); + outCount = fwrite(msg, 1, dbgchk, stdout); + free(msg); + } + } + } else outCount = write(cp->fdTo, message, count); @@ -7852,7 +8311,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) { @@ -7886,6 +8345,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; @@ -7908,7 +8369,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, @@ -7916,22 +8377,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) @@ -7941,7 +8403,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. */ @@ -7971,7 +8433,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); @@ -7999,19 +8461,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 @@ -8031,23 +8494,18 @@ 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); -#else while (frameWaiting) pause(); -#endif delay.it_interval.tv_sec = delay.it_value.tv_sec = 0; delay.it_interval.tv_usec = delay.it_value.tv_usec = 0; setitimer(ITIMER_REAL, &delay, NULL); @@ -8074,13 +8532,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 */ @@ -8089,12 +8547,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 */ @@ -8117,7 +8575,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; @@ -8137,7 +8595,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; @@ -8206,11 +8664,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++) { @@ -8237,7 +8695,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); @@ -8257,7 +8715,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; @@ -8270,7 +8728,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, @@ -8286,16 +8744,17 @@ OverlayPiece(piece, clip, outline, dest) kind = 0; else kind = 2; - XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % 6], + if(appData.upsideDown && flipView) kind ^= 2; + 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; @@ -8303,11 +8762,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); + BlankSquare(start->x, start->y, startColor, EmptySquare, anim->saveBuf, 0); 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); @@ -8323,12 +8782,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, @@ -8357,7 +8816,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); @@ -8410,6 +8869,29 @@ FrameSequence(anim, piece, startColor, start, finish, frames, nFrames) EndAnimation(anim, finish); } +void +AnimateAtomicCapture(Board board, int fromX, int fromY, int toX, int toY) +{ + int i, x, y; + ChessSquare piece = board[fromY][toY]; + board[fromY][toY] = EmptySquare; + DrawPosition(FALSE, board); + if (flipView) { + x = lineGap + ((BOARD_WIDTH-1)-toX) * (squareSize + lineGap); + y = lineGap + toY * (squareSize + lineGap); + } else { + x = lineGap + toX * (squareSize + lineGap); + y = lineGap + ((BOARD_HEIGHT-1)-toY) * (squareSize + lineGap); + } + for(i=1; i<4*kFactor; i++) { + int r = squareSize * 9 * i/(20*kFactor - 5); + XFillArc(xDisplay, xBoardWindow, highlineGC, + x + squareSize/2 - r, y+squareSize/2 - r, 2*r, 2*r, 0, 64*360); + FrameDelay(appData.animSpeed); + } + board[fromY][toY] = piece; +} + /* Main control logic for deciding what to animate and how */ void @@ -8430,6 +8912,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; @@ -8437,44 +8923,48 @@ AnimateMove(board, fromX, fromY, toX, toY) #if DONT_HOP hop = FALSE; #else - hop = (piece == WhiteKnight || piece == BlackKnight); + hop = abs(fromX-toX) == 1 && abs(fromY-toY) == 2 || abs(fromX-toX) == 2 && abs(fromY-toY) == 1; #endif if (appData.debugMode) { - printf(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); - } + 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); if (hop) { - /* Knight: make diagonal movement then straight */ + /* Knight: make straight movement then diagonal */ if (abs(toY - fromY) < abs(toX - fromX)) { mid.x = start.x + (finish.x - start.x) / 2; - mid.y = finish.y; + mid.y = start.y; } else { - mid.x = finish.x; + mid.x = start.x; mid.y = start.y + (finish.y - start.y) / 2; } } else { 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); - + if(Explode(board, fromX, fromY, toX, toY)) { // mark as damaged + int i,j; + for(i=0; i 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 + if(gatingPiece != EmptySquare) { + /* Kludge alert: When gating we want the introduced + piece to appear on the from square. To generate an + image of it, we draw it on the board, copy the image, + and draw the original piece again. */ + ChessSquare piece = boards[currentMove][boardY][boardX]; + DrawSquare(boardY, boardX, gatingPiece, 0); + XCopyArea(xDisplay, xBoardWindow, player.saveBuf, player.blitGC, + corner.x, corner.y, squareSize, squareSize, 0, 0); + DrawSquare(boardY, boardX, piece, 0); + } + damage[0][boardY][boardX] = True; } else { player.dragActive = False; } @@ -8530,7 +9027,7 @@ DragPieceMove(x, y) /* Are we animating? */ if (!appData.animateDragging || appData.blindfold) return; - + /* Sanity check */ if (! player.dragActive) return; @@ -8539,7 +9036,7 @@ DragPieceMove(x, y) corner.x = x - player.mouseDelta.x; corner.y = y - player.mouseDelta.y; AnimationFrame(&player, &corner, player.dragPiece); -#if HIGHDRAG +#if HIGHDRAG*0 if (appData.highlightDragging) { int boardX, boardY; BoardSquare(x, y, &boardX, &boardY); @@ -8548,7 +9045,7 @@ DragPieceMove(x, y) #endif } -static void +void DragPieceEnd(x, y) int x; int y; { @@ -8558,7 +9055,7 @@ DragPieceEnd(x, y) /* Are we animating? */ if (!appData.animateDragging || appData.blindfold) return; - + /* Sanity check */ if (! player.dragActive) return; @@ -8569,7 +9066,7 @@ DragPieceEnd(x, y) EndAnimation(&player, &corner); /* Be sure end square is redrawn */ - damage[boardY][boardX] = True; + damage[0][boardY][boardX] = True; /* This prevents weird things happening with fast successive clicks which on my Sun at least can cause motion events @@ -8590,8 +9087,239 @@ DrawDragPiece () it's being dragged around the board. So we erase the square that the piece is on and draw it at the last known drag point. */ BlankSquare(player.startSquare.x, player.startSquare.y, - player.startColor, EmptySquare, xBoardWindow); + player.startColor, EmptySquare, xBoardWindow, 1); AnimationFrame(&player, &player.prevFrame, player.dragPiece); - damage[player.startBoardY][player.startBoardX] = TRUE; + damage[0][player.startBoardY][player.startBoardX] = TRUE; +} + +#include +int get_term_width() +{ + int fd, default_width; + + fd = STDIN_FILENO; + default_width = 79; // this is FICS default anyway... + +#if !defined(TIOCGWINSZ) && defined(TIOCGSIZE) + struct ttysize win; + if (!ioctl(fd, TIOCGSIZE, &win)) + default_width = win.ts_cols; +#elif defined(TIOCGWINSZ) + struct winsize win; + if (!ioctl(fd, TIOCGWINSZ, &win)) + default_width = win.ws_col; +#endif + return default_width; +} + +void +update_ics_width() +{ + static int old_width = 0; + int new_width = get_term_width(); + + if (old_width != new_width) + ics_printf("set width %d\n", new_width); + old_width = new_width; +} + +void NotifyFrontendLogin() +{ + update_ics_width(); +} + +/* [AS] Arrow highlighting support */ + +static double A_WIDTH = 5; /* Width of arrow body */ + +#define A_HEIGHT_FACTOR 6 /* Length of arrow "point", relative to body width */ +#define A_WIDTH_FACTOR 3 /* Width of arrow "point", relative to body width */ + +static double Sqr( double x ) +{ + return x*x; +} + +static int Round( double x ) +{ + return (int) (x + 0.5); +} + +void SquareToPos(int rank, int file, int *x, int *y) +{ + if (flipView) { + *x = lineGap + ((BOARD_WIDTH-1)-file) * (squareSize + lineGap); + *y = lineGap + rank * (squareSize + lineGap); + } else { + *x = lineGap + file * (squareSize + lineGap); + *y = lineGap + ((BOARD_HEIGHT-1)-rank) * (squareSize + lineGap); + } +} + +/* Draw an arrow between two points using current settings */ +void DrawArrowBetweenPoints( int s_x, int s_y, int d_x, int d_y ) +{ + XPoint arrow[7]; + double dx, dy, j, k, x, y; + + if( d_x == s_x ) { + int h = (d_y > s_y) ? +A_WIDTH*A_HEIGHT_FACTOR : -A_WIDTH*A_HEIGHT_FACTOR; + + arrow[0].x = s_x + A_WIDTH + 0.5; + arrow[0].y = s_y; + + arrow[1].x = s_x + A_WIDTH + 0.5; + arrow[1].y = d_y - h; + + arrow[2].x = arrow[1].x + A_WIDTH*(A_WIDTH_FACTOR-1) + 0.5; + arrow[2].y = d_y - h; + + arrow[3].x = d_x; + arrow[3].y = d_y; + + arrow[5].x = arrow[1].x - 2*A_WIDTH + 0.5; + arrow[5].y = d_y - h; + + arrow[4].x = arrow[5].x - A_WIDTH*(A_WIDTH_FACTOR-1) + 0.5; + arrow[4].y = d_y - h; + + arrow[6].x = arrow[1].x - 2*A_WIDTH + 0.5; + arrow[6].y = s_y; + } + else if( d_y == s_y ) { + int w = (d_x > s_x) ? +A_WIDTH*A_HEIGHT_FACTOR : -A_WIDTH*A_HEIGHT_FACTOR; + + arrow[0].x = s_x; + arrow[0].y = s_y + A_WIDTH + 0.5; + + arrow[1].x = d_x - w; + arrow[1].y = s_y + A_WIDTH + 0.5; + + arrow[2].x = d_x - w; + arrow[2].y = arrow[1].y + A_WIDTH*(A_WIDTH_FACTOR-1) + 0.5; + + arrow[3].x = d_x; + arrow[3].y = d_y; + + arrow[5].x = d_x - w; + arrow[5].y = arrow[1].y - 2*A_WIDTH + 0.5; + + arrow[4].x = d_x - w; + arrow[4].y = arrow[5].y - A_WIDTH*(A_WIDTH_FACTOR-1) + 0.5; + + arrow[6].x = s_x; + arrow[6].y = arrow[1].y - 2*A_WIDTH + 0.5; + } + else { + /* [AS] Needed a lot of paper for this! :-) */ + dy = (double) (d_y - s_y) / (double) (d_x - s_x); + dx = (double) (s_x - d_x) / (double) (s_y - d_y); + + j = sqrt( Sqr(A_WIDTH) / (1.0 + Sqr(dx)) ); + + k = sqrt( Sqr(A_WIDTH*A_HEIGHT_FACTOR) / (1.0 + Sqr(dy)) ); + + x = s_x; + y = s_y; + + arrow[0].x = Round(x - j); + arrow[0].y = Round(y + j*dx); + + arrow[1].x = Round(arrow[0].x + 2*j); // [HGM] prevent width to be affected by rounding twice + arrow[1].y = Round(arrow[0].y - 2*j*dx); + + if( d_x > s_x ) { + x = (double) d_x - k; + y = (double) d_y - k*dy; + } + else { + x = (double) d_x + k; + y = (double) d_y + k*dy; + } + + x = Round(x); y = Round(y); // [HGM] make sure width of shaft is rounded the same way on both ends + + arrow[6].x = Round(x - j); + arrow[6].y = Round(y + j*dx); + + arrow[2].x = Round(arrow[6].x + 2*j); + arrow[2].y = Round(arrow[6].y - 2*j*dx); + + arrow[3].x = Round(arrow[2].x + j*(A_WIDTH_FACTOR-1)); + arrow[3].y = Round(arrow[2].y - j*(A_WIDTH_FACTOR-1)*dx); + + arrow[4].x = d_x; + arrow[4].y = d_y; + + arrow[5].x = Round(arrow[6].x - j*(A_WIDTH_FACTOR-1)); + arrow[5].y = Round(arrow[6].y + j*(A_WIDTH_FACTOR-1)*dx); + } + + XFillPolygon(xDisplay, xBoardWindow, highlineGC, arrow, 7, Nonconvex, CoordModeOrigin); +// Polygon( hdc, arrow, 7 ); +} + +/* [AS] Draw an arrow between two squares */ +void DrawArrowBetweenSquares( int s_col, int s_row, int d_col, int d_row ) +{ + int s_x, s_y, d_x, d_y, hor, vert, i; + + if( s_col == d_col && s_row == d_row ) { + return; + } + + /* Get source and destination points */ + SquareToPos( s_row, s_col, &s_x, &s_y); + SquareToPos( d_row, d_col, &d_x, &d_y); + + if( d_y > s_y ) { + d_y += squareSize / 2 - squareSize / 4; // [HGM] round towards same centers on all sides! + } + else if( d_y < s_y ) { + d_y += squareSize / 2 + squareSize / 4; + } + else { + d_y += squareSize / 2; + } + + if( d_x > s_x ) { + d_x += squareSize / 2 - squareSize / 4; + } + else if( d_x < s_x ) { + d_x += squareSize / 2 + squareSize / 4; + } + else { + d_x += squareSize / 2; + } + + s_x += squareSize / 2; + s_y += squareSize / 2; + + /* Adjust width */ + A_WIDTH = squareSize / 14.; //[HGM] make float + + DrawArrowBetweenPoints( s_x, s_y, d_x, d_y ); + + if(lineGap == 0) { + // this is a good idea, but it only works when lineGap == 0, because 'damage' on grid lines is not repaired + hor = 64*s_col + 32; vert = 64*s_row + 32; + for(i=0; i<= 64; i++) { + damage[0][vert+6>>6][hor+6>>6] = True; + damage[0][vert-6>>6][hor+6>>6] = True; + damage[0][vert+6>>6][hor-6>>6] = True; + damage[0][vert-6>>6][hor-6>>6] = True; + hor += d_col - s_col; vert += d_row - s_row; + } + } } +Boolean IsDrawArrowEnabled() +{ + return appData.highlightMoveWithArrow && squareSize >= 32; +} + +void DrawArrowHighlight(int fromX, int fromY, int toX,int toY) +{ + if( IsDrawArrowEnabled() && fromX >= 0 && fromY >= 0 && toX >= 0 && toY >= 0) + DrawArrowBetweenSquares(fromX, fromY, toX, toY); +}