-/*\r
- * xboard.c -- X front end for XBoard\r
- * $Id: xboard.c,v 2.2 2003/11/06 07:22:14 mann Exp $\r
- *\r
- * Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts.\r
- * Enhancements Copyright 1992-2001 Free Software Foundation, Inc.\r
- *\r
- * The following terms apply to Digital Equipment Corporation's copyright\r
- * interest in XBoard:\r
- * ------------------------------------------------------------------------\r
- * All Rights Reserved\r
- *\r
- * Permission to use, copy, modify, and distribute this software and its\r
- * documentation for any purpose and without fee is hereby granted,\r
- * provided that the above copyright notice appear in all copies and that\r
- * both that copyright notice and this permission notice appear in\r
- * supporting documentation, and that the name of Digital not be\r
- * used in advertising or publicity pertaining to distribution of the\r
- * software without specific, written prior permission.\r
- *\r
- * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING\r
- * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL\r
- * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR\r
- * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,\r
- * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,\r
- * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS\r
- * SOFTWARE.\r
- * ------------------------------------------------------------------------\r
- *\r
- * The following terms apply to the enhanced version of XBoard distributed\r
- * by the Free Software Foundation:\r
- * ------------------------------------------------------------------------\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License\r
- * along with this program; if not, write to the Free Software\r
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\r
- * ------------------------------------------------------------------------\r
- *\r
- * See the file ChangeLog for a revision history.\r
- */\r
-\r
-#include "config.h"\r
-\r
-#include <stdio.h>\r
-#include <ctype.h>\r
-#include <signal.h>\r
-#include <errno.h>\r
-#include <sys/types.h>\r
-#include <sys/stat.h>\r
-#include <pwd.h>\r
-\r
-#if !OMIT_SOCKETS\r
-# if HAVE_SYS_SOCKET_H\r
-# include <sys/socket.h>\r
-# include <netinet/in.h>\r
-# include <netdb.h>\r
-# else /* not HAVE_SYS_SOCKET_H */\r
-# if HAVE_LAN_SOCKET_H\r
-# include <lan/socket.h>\r
-# include <lan/in.h>\r
-# include <lan/netdb.h>\r
-# else /* not HAVE_LAN_SOCKET_H */\r
-# define OMIT_SOCKETS 1\r
-# endif /* not HAVE_LAN_SOCKET_H */\r
-# endif /* not HAVE_SYS_SOCKET_H */\r
-#endif /* !OMIT_SOCKETS */\r
-\r
-#if STDC_HEADERS\r
-# include <stdlib.h>\r
-# include <string.h>\r
-#else /* not STDC_HEADERS */\r
-extern char *getenv();\r
-# if HAVE_STRING_H\r
-# include <string.h>\r
-# else /* not HAVE_STRING_H */\r
-# include <strings.h>\r
-# endif /* not HAVE_STRING_H */\r
-#endif /* not STDC_HEADERS */\r
-\r
-#if HAVE_SYS_FCNTL_H\r
-# include <sys/fcntl.h>\r
-#else /* not HAVE_SYS_FCNTL_H */\r
-# if HAVE_FCNTL_H\r
-# include <fcntl.h>\r
-# endif /* HAVE_FCNTL_H */\r
-#endif /* not HAVE_SYS_FCNTL_H */\r
-\r
-#if HAVE_SYS_SYSTEMINFO_H\r
-# include <sys/systeminfo.h>\r
-#endif /* HAVE_SYS_SYSTEMINFO_H */\r
-\r
-#if TIME_WITH_SYS_TIME\r
-# include <sys/time.h>\r
-# include <time.h>\r
-#else\r
-# if HAVE_SYS_TIME_H\r
-# include <sys/time.h>\r
-# else\r
-# include <time.h>\r
-# endif\r
-#endif\r
-\r
-#if HAVE_UNISTD_H\r
-# include <unistd.h>\r
-#endif\r
-\r
-#if HAVE_SYS_WAIT_H\r
-# include <sys/wait.h>\r
-#endif\r
-\r
-#if HAVE_DIRENT_H\r
-# include <dirent.h>\r
-# define NAMLEN(dirent) strlen((dirent)->d_name)\r
-# define HAVE_DIR_STRUCT\r
-#else\r
-# define dirent direct\r
-# define NAMLEN(dirent) (dirent)->d_namlen\r
-# if HAVE_SYS_NDIR_H\r
-# include <sys/ndir.h>\r
-# define HAVE_DIR_STRUCT\r
-# endif\r
-# if HAVE_SYS_DIR_H\r
-# include <sys/dir.h>\r
-# define HAVE_DIR_STRUCT\r
-# endif\r
-# if HAVE_NDIR_H\r
-# include <ndir.h>\r
-# define HAVE_DIR_STRUCT\r
-# endif\r
-#endif\r
-\r
-#include <X11/Intrinsic.h>\r
-#include <X11/StringDefs.h>\r
-#include <X11/Shell.h>\r
-#include <X11/cursorfont.h>\r
-#include <X11/Xatom.h>\r
-#if USE_XAW3D\r
-#include <X11/Xaw3d/Dialog.h>\r
-#include <X11/Xaw3d/Form.h>\r
-#include <X11/Xaw3d/List.h>\r
-#include <X11/Xaw3d/Label.h>\r
-#include <X11/Xaw3d/SimpleMenu.h>\r
-#include <X11/Xaw3d/SmeBSB.h>\r
-#include <X11/Xaw3d/SmeLine.h>\r
-#include <X11/Xaw3d/Box.h>\r
-#include <X11/Xaw3d/MenuButton.h>\r
-#include <X11/Xaw3d/Text.h>\r
-#include <X11/Xaw3d/AsciiText.h>\r
-#else\r
-#include <X11/Xaw/Dialog.h>\r
-#include <X11/Xaw/Form.h>\r
-#include <X11/Xaw/List.h>\r
-#include <X11/Xaw/Label.h>\r
-#include <X11/Xaw/SimpleMenu.h>\r
-#include <X11/Xaw/SmeBSB.h>\r
-#include <X11/Xaw/SmeLine.h>\r
-#include <X11/Xaw/Box.h>\r
-#include <X11/Xaw/MenuButton.h>\r
-#include <X11/Xaw/Text.h>\r
-#include <X11/Xaw/AsciiText.h>\r
-#endif\r
-\r
-// [HGM] bitmaps: put before incuding the bitmaps / pixmaps, to know how many piece types there are.\r
-#include "common.h"\r
-\r
-#if HAVE_LIBXPM\r
-#include <X11/xpm.h>\r
-#include "pixmaps/pixmaps.h"\r
-#define IMAGE_EXT "xpm"\r
-#else\r
-#define IMAGE_EXT "xim"\r
-#include "bitmaps/bitmaps.h"\r
-#endif\r
-\r
-#include "bitmaps/icon_white.bm"\r
-#include "bitmaps/icon_black.bm"\r
-#include "bitmaps/checkmark.bm"\r
-\r
-#include "frontend.h"\r
-#include "backend.h"\r
-#include "moves.h"\r
-#include "xboard.h"\r
-#include "childio.h"\r
-#include "xgamelist.h"\r
-#include "xhistory.h"\r
-#include "xedittags.h"\r
-#include "gettext.h"\r
-\r
-// must be moved to xengineoutput.h\r
-\r
-void EngineOutputProc P((Widget w, XEvent *event,\r
- String *prms, Cardinal *nprms));\r
-\r
-void EngineOutputPopDown();\r
-\r
-\r
-#ifdef __EMX__\r
-#ifndef HAVE_USLEEP\r
-#define HAVE_USLEEP\r
-#endif\r
-#define usleep(t) _sleep2(((t)+500)/1000)\r
-#endif\r
-\r
-#ifdef ENABLE_NLS\r
-# define _(s) gettext (s)\r
-# define N_(s) gettext_noop (s)\r
-#else\r
-# define _(s) (s)\r
-# define N_(s) s\r
-#endif\r
-\r
-typedef struct {\r
- String string;\r
- XtActionProc proc;\r
-} MenuItem;\r
-\r
-typedef struct {\r
- String name;\r
- MenuItem *mi;\r
-} Menu;\r
-\r
-int main P((int argc, char **argv));\r
-RETSIGTYPE CmailSigHandler P((int sig));\r
-RETSIGTYPE IntSigHandler P((int sig));\r
-void CreateGCs P((void));\r
-void CreateXIMPieces P((void));\r
-void CreateXPMPieces P((void));\r
-void CreatePieces P((void));\r
-void CreatePieceMenus P((void));\r
-Widget CreateMenuBar P((Menu *mb));\r
-Widget CreateButtonBar P ((MenuItem *mi));\r
-char *FindFont P((char *pattern, int targetPxlSize));\r
-void PieceMenuPopup P((Widget w, XEvent *event,\r
- String *params, Cardinal *num_params));\r
-static void PieceMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));\r
-static void DropMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));\r
-void ReadBitmap P((Pixmap *pm, String name, unsigned char bits[],\r
- u_int wreq, u_int hreq));\r
-void CreateGrid P((void));\r
-int EventToSquare P((int x, int limit));\r
-void DrawSquare P((int row, int column, ChessSquare piece, int do_flash));\r
-void EventProc P((Widget widget, caddr_t unused, XEvent *event));\r
-void HandleUserMove P((Widget w, XEvent *event,\r
- String *prms, Cardinal *nprms));\r
-void AnimateUserMove P((Widget w, XEvent * event,\r
- String * params, Cardinal * nParams));\r
-void WhiteClock P((Widget w, XEvent *event,\r
- String *prms, Cardinal *nprms));\r
-void BlackClock P((Widget w, XEvent *event,\r
- String *prms, Cardinal *nprms));\r
-void DrawPositionProc P((Widget w, XEvent *event,\r
- String *prms, Cardinal *nprms));\r
-void XDrawPosition P((Widget w, /*Boolean*/int repaint, \r
- Board board));\r
-void CommentPopUp P((char *title, char *label));\r
-void CommentPopDown P((void));\r
-void CommentCallback P((Widget w, XtPointer client_data,\r
- XtPointer call_data));\r
-void ICSInputBoxPopUp P((void));\r
-void ICSInputBoxPopDown P((void));\r
-void FileNamePopUp P((char *label, char *def,\r
- FileProc proc, char *openMode));\r
-void FileNamePopDown P((void));\r
-void FileNameCallback P((Widget w, XtPointer client_data,\r
- XtPointer call_data));\r
-void FileNameAction P((Widget w, XEvent *event,\r
- String *prms, Cardinal *nprms));\r
-void AskQuestionReplyAction P((Widget w, XEvent *event,\r
- String *prms, Cardinal *nprms));\r
-void AskQuestionProc P((Widget w, XEvent *event,\r
- String *prms, Cardinal *nprms));\r
-void AskQuestionPopDown P((void));\r
-void PromotionPopUp P((void));\r
-void PromotionPopDown P((void));\r
-void PromotionCallback P((Widget w, XtPointer client_data,\r
- XtPointer call_data));\r
-void EditCommentPopDown P((void));\r
-void EditCommentCallback P((Widget w, XtPointer client_data,\r
- XtPointer call_data));\r
-void SelectCommand P((Widget w, XtPointer client_data, XtPointer call_data));\r
-void ResetProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));\r
-void LoadGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));\r
-void LoadNextGameProc P((Widget w, XEvent *event, String *prms,\r
- Cardinal *nprms));\r
-void LoadPrevGameProc P((Widget w, XEvent *event, String *prms,\r
- Cardinal *nprms));\r
-void ReloadGameProc P((Widget w, XEvent *event, String *prms,\r
- Cardinal *nprms));\r
-void LoadPositionProc P((Widget w, XEvent *event,\r
- String *prms, Cardinal *nprms));\r
-void LoadNextPositionProc P((Widget w, XEvent *event, String *prms,\r
- Cardinal *nprms));\r
-void LoadPrevPositionProc P((Widget w, XEvent *event, String *prms,\r
- Cardinal *nprms));\r
-void ReloadPositionProc P((Widget w, XEvent *event, String *prms,\r
- Cardinal *nprms));\r
-void CopyPositionProc P((Widget w, XEvent *event, String *prms,\r
- Cardinal *nprms));\r
-void PastePositionProc P((Widget w, XEvent *event, String *prms,\r
- Cardinal *nprms));\r
-void CopyGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));\r
-void PasteGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));\r
-void SaveGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));\r
-void SavePositionProc P((Widget w, XEvent *event,\r
- String *prms, Cardinal *nprms));\r
-void MailMoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));\r
-void ReloadCmailMsgProc P((Widget w, XEvent *event, String *prms,\r
- Cardinal *nprms));\r
-void QuitProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));\r
-void PauseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));\r
-void MachineBlackProc P((Widget w, XEvent *event, String *prms,\r
- Cardinal *nprms));\r
-void MachineWhiteProc P((Widget w, XEvent *event,\r
- String *prms, Cardinal *nprms));\r
-void AnalyzeModeProc P((Widget w, XEvent *event,\r
- String *prms, Cardinal *nprms));\r
-void AnalyzeFileProc P((Widget w, XEvent *event,\r
- String *prms, Cardinal *nprms));\r
-void TwoMachinesProc P((Widget w, XEvent *event, String *prms,\r
- Cardinal *nprms));\r
-void IcsClientProc P((Widget w, XEvent *event, String *prms,\r
- Cardinal *nprms));\r
-void EditGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));\r
-void EditPositionProc P((Widget w, XEvent *event,\r
- String *prms, Cardinal *nprms));\r
-void TrainingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));\r
-void EditCommentProc P((Widget w, XEvent *event,\r
- String *prms, Cardinal *nprms));\r
-void IcsInputBoxProc P((Widget w, XEvent *event,\r
- String *prms, Cardinal *nprms));\r
-void AcceptProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));\r
-void DeclineProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));\r
-void RematchProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));\r
-void CallFlagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));\r
-void DrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));\r
-void AbortProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));\r
-void AdjournProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));\r
-void ResignProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));\r
-void EnterKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));\r
-void StopObservingProc P((Widget w, XEvent *event, String *prms,\r
- Cardinal *nprms));\r
-void StopExaminingProc P((Widget w, XEvent *event, String *prms,\r
- Cardinal *nprms));\r
-void BackwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));\r
-void ForwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));\r
-void ToStartProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));\r
-void ToEndProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));\r
-void RevertProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));\r
-void TruncateGameProc P((Widget w, XEvent *event, String *prms,\r
- Cardinal *nprms));\r
-void RetractMoveProc P((Widget w, XEvent *event, String *prms,\r
- Cardinal *nprms));\r
-void MoveNowProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));\r
-void AlwaysQueenProc P((Widget w, XEvent *event, String *prms,\r
- Cardinal *nprms));\r
-void AnimateDraggingProc P((Widget w, XEvent *event, String *prms,\r
- Cardinal *nprms));\r
-void AnimateMovingProc P((Widget w, XEvent *event, String *prms,\r
- Cardinal *nprms));\r
-void AutocommProc P((Widget w, XEvent *event, String *prms,\r
- Cardinal *nprms));\r
-void AutoflagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));\r
-void AutoflipProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));\r
-void AutobsProc P((Widget w, XEvent *event, String *prms,\r
- Cardinal *nprms));\r
-void AutoraiseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));\r
-void AutosaveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));\r
-void BlindfoldProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));\r
-void FlashMovesProc P((Widget w, XEvent *event, String *prms,\r
- Cardinal *nprms));\r
-void FlipViewProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));\r
-void GetMoveListProc P((Widget w, XEvent *event, String *prms,\r
- Cardinal *nprms));\r
-void HighlightDraggingProc P((Widget w, XEvent *event, String *prms,\r
- Cardinal *nprms));\r
-void HighlightLastMoveProc P((Widget w, XEvent *event, String *prms,\r
- Cardinal *nprms));\r
-void MoveSoundProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));\r
-void IcsAlarmProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));\r
-void OldSaveStyleProc P((Widget w, XEvent *event, String *prms,\r
- Cardinal *nprms));\r
-void PeriodicUpdatesProc P((Widget w, XEvent *event, String *prms,\r
- Cardinal *nprms));\r
-void PonderNextMoveProc P((Widget w, XEvent *event, String *prms,\r
- Cardinal *nprms));\r
-void PopupMoveErrorsProc P((Widget w, XEvent *event, String *prms,\r
- Cardinal *nprms));\r
-void PopupExitMessageProc P((Widget w, XEvent *event, String *prms,\r
- Cardinal *nprms));\r
-void PremoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));\r
-void QuietPlayProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));\r
-void ShowCoordsProc P((Widget w, XEvent *event, String *prms,\r
- Cardinal *nprms));\r
-void ShowThinkingProc P((Widget w, XEvent *event, String *prms,\r
- Cardinal *nprms));\r
-void HideThinkingProc P((Widget w, XEvent *event, String *prms,\r
- Cardinal *nprms));\r
-void TestLegalityProc P((Widget w, XEvent *event, String *prms,\r
- Cardinal *nprms));\r
-void InfoProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));\r
-void ManProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));\r
-void HintProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));\r
-void BookProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));\r
-void AboutGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));\r
-void AboutProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));\r
-void DebugProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));\r
-void NothingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));\r
-void Iconify P((Widget w, XEvent *event, String *prms, Cardinal *nprms));\r
-void DisplayMove P((int moveNumber));\r
-void DisplayTitle P((char *title));\r
-void ICSInitScript P((void));\r
-int LoadGamePopUp P((FILE *f, int gameNumber, char *title));\r
-void ErrorPopUp P((char *title, char *text, int modal));\r
-void ErrorPopDown P((void));\r
-static char *ExpandPathName P((char *path));\r
-static void CreateAnimVars P((void));\r
-static void DragPieceBegin P((int x, int y));\r
-static void DragPieceMove P((int x, int y));\r
-static void DragPieceEnd P((int x, int y));\r
-static void DrawDragPiece P((void));\r
-char *ModeToWidgetName P((GameMode mode));\r
-void EngineOutputUpdate( FrontEndProgramStats * stats );\r
-void ShuffleMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));\r
-void EngineMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));\r
-void UciMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));\r
-void TimeControlProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));\r
-void NewVariantProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));\r
-void FirstSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));\r
-void SecondSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));\r
-void ShufflePopDown P(());\r
-void EnginePopDown P(());\r
-void UciPopDown P(());\r
-void TimeControlPopDown P(());\r
-void NewVariantPopDown P(());\r
-void SettingsPopDown P(());\r
-/*\r
-* XBoard depends on Xt R4 or higher\r
-*/\r
-int xtVersion = XtSpecificationRelease;\r
-\r
-int xScreen;\r
-Display *xDisplay;\r
-Window xBoardWindow;\r
-Pixel lightSquareColor, darkSquareColor, whitePieceColor, blackPieceColor,\r
- jailSquareColor, highlightSquareColor, premoveHighlightColor;\r
-GC lightSquareGC, darkSquareGC, jailSquareGC, lineGC, wdPieceGC, wlPieceGC,\r
- bdPieceGC, blPieceGC, wbPieceGC, bwPieceGC, coordGC, highlineGC,\r
- wjPieceGC, bjPieceGC, prelineGC, countGC;\r
-Pixmap iconPixmap, wIconPixmap, bIconPixmap, xMarkPixmap;\r
-Widget shellWidget, layoutWidget, formWidget, boardWidget, messageWidget, \r
- whiteTimerWidget, blackTimerWidget, titleWidget, widgetList[16], \r
- commentShell, promotionShell, whitePieceMenu, blackPieceMenu, dropMenu,\r
- menuBarWidget, buttonBarWidget, editShell, errorShell, analysisShell,\r
- ICSInputShell, fileNameShell, askQuestionShell;\r
-XSegment gridSegments[(BOARD_SIZE + 1) * 2];\r
-XSegment jailGridSegments[(BOARD_SIZE + 3) * 2];\r
-Font clockFontID, coordFontID, countFontID;\r
-XFontStruct *clockFontStruct, *coordFontStruct, *countFontStruct;\r
-XtAppContext appContext;\r
-char *layoutName;\r
-char *oldICSInteractionTitle;\r
-\r
-FileProc fileProc;\r
-char *fileOpenMode;\r
-char installDir[] = "."; // [HGM] UCI: needed for UCI; probably needs run-time initializtion\r
-\r
-Position commentX = -1, commentY = -1;\r
-Dimension commentW, commentH;\r
-\r
-int squareSize, smallLayout = 0, tinyLayout = 0,\r
- marginW, marginH, // [HGM] for run-time resizing\r
- fromX = -1, fromY = -1, toX, toY, commentUp = False, analysisUp = False,\r
- ICSInputBoxUp = False, askQuestionUp = False,\r
- filenameUp = False, promotionUp = False, pmFromX = -1, pmFromY = -1,\r
- editUp = False, errorUp = False, errorExitStatus = -1, lineGap;\r
-Pixel timerForegroundPixel, timerBackgroundPixel;\r
-Pixel buttonForegroundPixel, buttonBackgroundPixel;\r
-char *chessDir, *programName, *programVersion,\r
- *gameCopyFilename, *gamePasteFilename;\r
-\r
-#define SOLID 0\r
-#define OUTLINE 1\r
-Pixmap pieceBitmap[2][(int)BlackPawn];\r
-Pixmap xpmPieceBitmap[4][(int)BlackPawn]; /* LL, LD, DL, DD */\r
-Pixmap xpmLightSquare, xpmDarkSquare, xpmJailSquare;\r
-int useImages, useImageSqs;\r
-XImage *ximPieceBitmap[4][(int)BlackPawn]; /* LL, LD, DL, DD */\r
-Pixmap ximMaskPm[(int)BlackPawn]; /* clipmasks, used for XIM pieces */\r
-XImage *ximLightSquare, *ximDarkSquare;\r
-XImage *xim_Cross;\r
-\r
-#define pieceToSolid(piece) &pieceBitmap[SOLID][((int)(piece)) % (int)BlackPawn]\r
-#define pieceToOutline(piece) &pieceBitmap[OUTLINE][((int)(piece)) % (int)BlackPawn]\r
-\r
-#define White(piece) ((int)(piece) < (int)BlackPawn)\r
-\r
-/* Variables for doing smooth animation. This whole thing\r
- would be much easier if the board was double-buffered,\r
- but that would require a fairly major rewrite. */\r
-\r
-typedef struct {\r
- Pixmap saveBuf;\r
- Pixmap newBuf;\r
- GC blitGC, pieceGC, outlineGC;\r
- XPoint startSquare, prevFrame, mouseDelta;\r
- int startColor;\r
- int dragPiece;\r
- Boolean dragActive;\r
- int startBoardX, startBoardY;\r
- } AnimState;\r
-\r
-/* There can be two pieces being animated at once: a player\r
- can begin dragging a piece before the remote opponent has moved. */\r
-\r
-static AnimState game, player;\r
-\r
-/* Bitmaps for use as masks when drawing XPM pieces.\r
- Need one for each black and white piece. */\r
-static Pixmap xpmMask[BlackKing + 1];\r
-\r
-/* This magic number is the number of intermediate frames used\r
- in each half of the animation. For short moves it's reduced\r
- by 1. The total number of frames will be factor * 2 + 1. */\r
-#define kFactor 4\r
-\r
-SizeDefaults sizeDefaults[] = SIZE_DEFAULTS;\r
-\r
-MenuItem fileMenu[] = {\r
- {N_("New Game"), ResetProc},\r
- {N_("New Shuffle Game ..."), ShuffleMenuProc},\r
- {N_("New Variant ..."), NewVariantProc}, // [HGM] variant: not functional yet\r
- {"----", NothingProc},\r
- {N_("Load Game"), LoadGameProc},\r
- {N_("Load Next Game"), LoadNextGameProc},\r
- {N_("Load Previous Game"), LoadPrevGameProc},\r
- {N_("Reload Same Game"), ReloadGameProc},\r
- {N_("Save Game"), SaveGameProc},\r
- {"----", NothingProc},\r
- {N_("Copy Game"), CopyGameProc},\r
- {N_("Paste Game"), PasteGameProc},\r
- {"----", NothingProc},\r
- {N_("Load Position"), LoadPositionProc},\r
- {N_("Load Next Position"), LoadNextPositionProc},\r
- {N_("Load Previous Position"), LoadPrevPositionProc},\r
- {N_("Reload Same Position"), ReloadPositionProc},\r
- {N_("Save Position"), SavePositionProc},\r
- {"----", NothingProc},\r
- {N_("Copy Position"), CopyPositionProc},\r
- {N_("Paste Position"), PastePositionProc},\r
- {"----", NothingProc},\r
- {N_("Mail Move"), MailMoveProc},\r
- {N_("Reload CMail Message"), ReloadCmailMsgProc},\r
- {"----", NothingProc},\r
- {N_("Exit"), QuitProc},\r
- {NULL, NULL}\r
-};\r
-\r
-MenuItem modeMenu[] = {\r
- {N_("Machine White"), MachineWhiteProc},\r
- {N_("Machine Black"), MachineBlackProc},\r
- {N_("Two Machines"), TwoMachinesProc},\r
- {N_("Analysis Mode"), AnalyzeModeProc},\r
- {N_("Analyze File"), AnalyzeFileProc },\r
- {N_("ICS Client"), IcsClientProc},\r
- {N_("Edit Game"), EditGameProc},\r
- {N_("Edit Position"), EditPositionProc},\r
- {N_("Training"), TrainingProc},\r
- {"----", NothingProc},\r
- {N_("Show Engine Output"), EngineOutputProc},\r
- {N_("Show Evaluation Graph"), NothingProc}, // [HGM] evalgr: not functional yet\r
- {N_("Show Game List"), ShowGameListProc},\r
- {"Show Move History", HistoryShowProc}, // [HGM] hist: activate 4.2.7 code\r
- {"----", NothingProc},\r
- {N_("Edit Tags"), EditTagsProc},\r
- {N_("Edit Comment"), EditCommentProc},\r
- {N_("ICS Input Box"), IcsInputBoxProc},\r
- {N_("Pause"), PauseProc},\r
- {NULL, NULL}\r
-};\r
-\r
-MenuItem actionMenu[] = {\r
- {N_("Accept"), AcceptProc},\r
- {N_("Decline"), DeclineProc},\r
- {N_("Rematch"), RematchProc},\r
- {"----", NothingProc}, \r
- {N_("Call Flag"), CallFlagProc},\r
- {N_("Draw"), DrawProc},\r
- {N_("Adjourn"), AdjournProc},\r
- {N_("Abort"), AbortProc},\r
- {N_("Resign"), ResignProc},\r
- {"----", NothingProc}, \r
- {N_("Stop Observing"), StopObservingProc},\r
- {N_("Stop Examining"), StopExaminingProc},\r
- {NULL, NULL}\r
-};\r
-\r
-MenuItem stepMenu[] = {\r
- {N_("Backward"), BackwardProc},\r
- {N_("Forward"), ForwardProc},\r
- {N_("Back to Start"), ToStartProc},\r
- {N_("Forward to End"), ToEndProc},\r
- {N_("Revert"), RevertProc},\r
- {N_("Truncate Game"), TruncateGameProc},\r
- {"----", NothingProc}, \r
- {N_("Move Now"), MoveNowProc},\r
- {N_("Retract Move"), RetractMoveProc},\r
- {NULL, NULL}\r
-}; \r
-\r
-MenuItem optionsMenu[] = {\r
- {N_("Flip View"), FlipViewProc},\r
- {"----", NothingProc}, \r
- {N_("Adjudications ..."), EngineMenuProc}, \r
- {N_("General Settings ..."), UciMenuProc}, \r
- {N_("Engine #1 Settings ..."), FirstSettingsProc}, \r
- {N_("Engine #2 Settings ..."), SecondSettingsProc}, \r
- {N_("Time Control ..."), TimeControlProc}, \r
- {"----", NothingProc}, \r
- {N_("Always Queen"), AlwaysQueenProc},\r
- {N_("Animate Dragging"), AnimateDraggingProc},\r
- {N_("Animate Moving"), AnimateMovingProc},\r
- {N_("Auto Comment"), AutocommProc},\r
- {N_("Auto Flag"), AutoflagProc},\r
- {N_("Auto Flip View"), AutoflipProc},\r
- {N_("Auto Observe"), AutobsProc},\r
- {N_("Auto Raise Board"), AutoraiseProc},\r
- {N_("Auto Save"), AutosaveProc},\r
- {N_("Blindfold"), BlindfoldProc},\r
- {N_("Flash Moves"), FlashMovesProc},\r
- {N_("Get Move List"), GetMoveListProc},\r
-#if HIGHDRAG\r
- {N_("Highlight Dragging"), HighlightDraggingProc},\r
-#endif\r
- {N_("Highlight Last Move"), HighlightLastMoveProc},\r
- {N_("Move Sound"), MoveSoundProc},\r
- {N_("ICS Alarm"), IcsAlarmProc},\r
- {N_("Old Save Style"), OldSaveStyleProc},\r
- {N_("Periodic Updates"), PeriodicUpdatesProc}, \r
- {N_("Ponder Next Move"), PonderNextMoveProc},\r
- {N_("Popup Exit Message"), PopupExitMessageProc}, \r
- {N_("Popup Move Errors"), PopupMoveErrorsProc}, \r
- {N_("Premove"), PremoveProc},\r
- {N_("Quiet Play"), QuietPlayProc},\r
- {N_("Show Coords"), ShowCoordsProc},\r
- {N_("Hide Thinking"), HideThinkingProc},\r
- {N_("Test Legality"), TestLegalityProc},\r
- {NULL, NULL}\r
-};\r
-\r
-MenuItem helpMenu[] = {\r
- {N_("Info XBoard"), InfoProc},\r
- {N_("Man XBoard"), ManProc},\r
- {"----", NothingProc},\r
- {N_("Hint"), HintProc},\r
- {N_("Book"), BookProc},\r
- {"----", NothingProc},\r
- {N_("About XBoard"), AboutProc},\r
- {NULL, NULL}\r
-};\r
-\r
-Menu menuBar[] = {\r
- {N_("File"), fileMenu},\r
- {N_("Mode"), modeMenu},\r
- {N_("Action"), actionMenu},\r
- {N_("Step"), stepMenu},\r
- {N_("Options"), optionsMenu},\r
- {N_("Help"), helpMenu},\r
- {NULL, NULL}\r
-};\r
-\r
-#define PAUSE_BUTTON N_("P")\r
-MenuItem buttonBar[] = {\r
- {"<<", ToStartProc},\r
- {"<", BackwardProc},\r
- {PAUSE_BUTTON, PauseProc},\r
- {">", ForwardProc},\r
- {">>", ToEndProc},\r
- {NULL, NULL}\r
-};\r
-\r
-#define PIECE_MENU_SIZE 11\r
-String pieceMenuStrings[2][PIECE_MENU_SIZE] = {\r
- { N_("White"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),\r
- N_("Queen"), N_("King"), "----", N_("Empty square"), N_("Clear board") },\r
- { N_("Black"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),\r
- N_("Queen"), N_("King"), "----", N_("Empty square"), N_("Clear board") }, \r
-};\r
-/* must be in same order as PieceMenuStrings! */\r
-ChessSquare pieceMenuTranslation[2][PIECE_MENU_SIZE] = {\r
- { WhitePlay, (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,\r
- WhiteRook, WhiteQueen, WhiteKing,\r
- (ChessSquare) 0, EmptySquare, ClearBoard },\r
- { BlackPlay, (ChessSquare) 0, BlackPawn, BlackKnight, BlackBishop,\r
- BlackRook, BlackQueen, BlackKing,\r
- (ChessSquare) 0, EmptySquare, ClearBoard },\r
-};\r
-\r
-#define DROP_MENU_SIZE 6\r
-String dropMenuStrings[DROP_MENU_SIZE] = {\r
- "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"), N_("Queen")\r
- };\r
-/* must be in same order as PieceMenuStrings! */\r
-ChessSquare dropMenuTranslation[DROP_MENU_SIZE] = {\r
- (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,\r
- WhiteRook, WhiteQueen\r
-};\r
-\r
-typedef struct {\r
- char piece;\r
- char* widget;\r
-} DropMenuEnables;\r
-\r
-DropMenuEnables dmEnables[] = {\r
- { 'P', "Pawn" },\r
- { 'N', "Knight" },\r
- { 'B', "Bishop" },\r
- { 'R', "Rook" },\r
- { 'Q', "Queen" }\r
-};\r
-\r
-Arg shellArgs[] = {\r
- { XtNwidth, 0 },\r
- { XtNheight, 0 },\r
- { XtNminWidth, 0 },\r
- { XtNminHeight, 0 },\r
- { XtNmaxWidth, 0 },\r
- { XtNmaxHeight, 0 }\r
-};\r
-\r
-Arg layoutArgs[] = {\r
- { XtNborderWidth, 0 },\r
- { XtNdefaultDistance, 0 },\r
-};\r
-\r
-Arg formArgs[] = {\r
- { XtNborderWidth, 0 },\r
- { XtNresizable, (XtArgVal) True },\r
-};\r
-\r
-Arg boardArgs[] = {\r
- { XtNborderWidth, 0 },\r
- { XtNwidth, 0 },\r
- { XtNheight, 0 }\r
-};\r
-\r
-Arg titleArgs[] = {\r
- { XtNjustify, (XtArgVal) XtJustifyRight },\r
- { XtNlabel, (XtArgVal) "..." },\r
- { XtNresizable, (XtArgVal) True },\r
- { XtNresize, (XtArgVal) False }\r
-};\r
-\r
-Arg messageArgs[] = {\r
- { XtNjustify, (XtArgVal) XtJustifyLeft },\r
- { XtNlabel, (XtArgVal) "..." },\r
- { XtNresizable, (XtArgVal) True },\r
- { XtNresize, (XtArgVal) False }\r
-};\r
-\r
-Arg timerArgs[] = {\r
- { XtNborderWidth, 0 },\r
- { XtNjustify, (XtArgVal) XtJustifyLeft }\r
-};\r
-\r
-XtResource clientResources[] = {\r
- { "whitePieceColor", "whitePieceColor", XtRString, sizeof(String),\r
- XtOffset(AppDataPtr, whitePieceColor), XtRString,\r
- WHITE_PIECE_COLOR },\r
- { "blackPieceColor", "blackPieceColor", XtRString, sizeof(String),\r
- XtOffset(AppDataPtr, blackPieceColor), XtRString,\r
- BLACK_PIECE_COLOR },\r
- { "lightSquareColor", "lightSquareColor", XtRString,\r
- sizeof(String), XtOffset(AppDataPtr, lightSquareColor),\r
- XtRString, LIGHT_SQUARE_COLOR }, \r
- { "darkSquareColor", "darkSquareColor", XtRString, sizeof(String),\r
- XtOffset(AppDataPtr, darkSquareColor), XtRString,\r
- DARK_SQUARE_COLOR },\r
- { "highlightSquareColor", "highlightSquareColor", XtRString,\r
- sizeof(String), XtOffset(AppDataPtr, highlightSquareColor),\r
- XtRString, HIGHLIGHT_SQUARE_COLOR },\r
- { "premoveHighlightColor", "premoveHighlightColor", XtRString,\r
- sizeof(String), XtOffset(AppDataPtr, premoveHighlightColor),\r
- XtRString, PREMOVE_HIGHLIGHT_COLOR },\r
- { "movesPerSession", "movesPerSession", XtRInt, sizeof(int),\r
- XtOffset(AppDataPtr, movesPerSession), XtRImmediate,\r
- (XtPointer) MOVES_PER_SESSION },\r
- { "timeIncrement", "timeIncrement", XtRInt, sizeof(int),\r
- XtOffset(AppDataPtr, timeIncrement), XtRImmediate,\r
- (XtPointer) TIME_INCREMENT },\r
- { "initString", "initString", XtRString, sizeof(String),\r
- XtOffset(AppDataPtr, initString), XtRString, INIT_STRING },\r
- { "secondInitString", "secondInitString", XtRString, sizeof(String),\r
- XtOffset(AppDataPtr, secondInitString), XtRString, INIT_STRING },\r
- { "firstComputerString", "firstComputerString", XtRString,\r
- sizeof(String), XtOffset(AppDataPtr, firstComputerString), XtRString,\r
- COMPUTER_STRING },\r
- { "secondComputerString", "secondComputerString", XtRString,\r
- sizeof(String), XtOffset(AppDataPtr, secondComputerString), XtRString,\r
- COMPUTER_STRING },\r
- { "firstChessProgram", "firstChessProgram", XtRString,\r
- sizeof(String), XtOffset(AppDataPtr, firstChessProgram),\r
- XtRString, FIRST_CHESS_PROGRAM },\r
- { "secondChessProgram", "secondChessProgram", XtRString,\r
- sizeof(String), XtOffset(AppDataPtr, secondChessProgram),\r
- XtRString, SECOND_CHESS_PROGRAM },\r
- { "firstPlaysBlack", "firstPlaysBlack", XtRBoolean,\r
- sizeof(Boolean), XtOffset(AppDataPtr, firstPlaysBlack),\r
- XtRImmediate, (XtPointer) False },\r
- { "noChessProgram", "noChessProgram", XtRBoolean,\r
- sizeof(Boolean), XtOffset(AppDataPtr, noChessProgram),\r
- XtRImmediate, (XtPointer) False },\r
- { "firstHost", "firstHost", XtRString, sizeof(String),\r
- XtOffset(AppDataPtr, firstHost), XtRString, FIRST_HOST },\r
- { "secondHost", "secondHost", XtRString, sizeof(String),\r
- XtOffset(AppDataPtr, secondHost), XtRString, SECOND_HOST },\r
- { "firstDirectory", "firstDirectory", XtRString, sizeof(String),\r
- XtOffset(AppDataPtr, firstDirectory), XtRString, "." },\r
- { "secondDirectory", "secondDirectory", XtRString, sizeof(String),\r
- XtOffset(AppDataPtr, secondDirectory), XtRString, "." },\r
- { "bitmapDirectory", "bitmapDirectory", XtRString,\r
- sizeof(String), XtOffset(AppDataPtr, bitmapDirectory),\r
- XtRString, "" },\r
- { "remoteShell", "remoteShell", XtRString, sizeof(String),\r
- XtOffset(AppDataPtr, remoteShell), XtRString, REMOTE_SHELL },\r
- { "remoteUser", "remoteUser", XtRString, sizeof(String),\r
- XtOffset(AppDataPtr, remoteUser), XtRString, "" },\r
- { "timeDelay", "timeDelay", XtRFloat, sizeof(float),\r
- XtOffset(AppDataPtr, timeDelay), XtRString,\r
- (XtPointer) TIME_DELAY_QUOTE },\r
- { "timeControl", "timeControl", XtRString, sizeof(String),\r
- XtOffset(AppDataPtr, timeControl), XtRString,\r
- (XtPointer) TIME_CONTROL },\r
- { "internetChessServerMode", "internetChessServerMode",\r
- XtRBoolean, sizeof(Boolean),\r
- XtOffset(AppDataPtr, icsActive), XtRImmediate,\r
- (XtPointer) False },\r
- { "internetChessServerHost", "internetChessServerHost",\r
- XtRString, sizeof(String),\r
- XtOffset(AppDataPtr, icsHost),\r
- XtRString, (XtPointer) ICS_HOST },\r
- { "internetChessServerPort", "internetChessServerPort",\r
- XtRString, sizeof(String),\r
- XtOffset(AppDataPtr, icsPort), XtRString,\r
- (XtPointer) ICS_PORT },\r
- { "internetChessServerCommPort", "internetChessServerCommPort",\r
- XtRString, sizeof(String),\r
- XtOffset(AppDataPtr, icsCommPort), XtRString,\r
- ICS_COMM_PORT },\r
- { "internetChessServerLogonScript", "internetChessServerLogonScript",\r
- XtRString, sizeof(String),\r
- XtOffset(AppDataPtr, icsLogon), XtRString,\r
- ICS_LOGON },\r
- { "internetChessServerHelper", "internetChessServerHelper",\r
- XtRString, sizeof(String),\r
- XtOffset(AppDataPtr, icsHelper), XtRString, "" },\r
- { "internetChessServerInputBox", "internetChessServerInputBox",\r
- XtRBoolean, sizeof(Boolean),\r
- XtOffset(AppDataPtr, icsInputBox), XtRImmediate,\r
- (XtPointer) False },\r
- { "icsAlarm", "icsAlarm",\r
- XtRBoolean, sizeof(Boolean),\r
- XtOffset(AppDataPtr, icsAlarm), XtRImmediate,\r
- (XtPointer) True },\r
- { "icsAlarmTime", "icsAlarmTime",\r
- XtRInt, sizeof(int),\r
- XtOffset(AppDataPtr, icsAlarmTime), XtRImmediate,\r
- (XtPointer) 5000 },\r
- { "useTelnet", "useTelnet", XtRBoolean, sizeof(Boolean),\r
- XtOffset(AppDataPtr, useTelnet), XtRImmediate,\r
- (XtPointer) False },\r
- { "telnetProgram", "telnetProgram", XtRString, sizeof(String),\r
- XtOffset(AppDataPtr, telnetProgram), XtRString, TELNET_PROGRAM },\r
- { "gateway", "gateway", XtRString, sizeof(String),\r
- XtOffset(AppDataPtr, gateway), XtRString, "" },\r
- { "loadGameFile", "loadGameFile", XtRString, sizeof(String),\r
- XtOffset(AppDataPtr, loadGameFile), XtRString, "" },\r
- { "loadGameIndex", "loadGameIndex",\r
- XtRInt, sizeof(int),\r
- XtOffset(AppDataPtr, loadGameIndex), XtRImmediate,\r
- (XtPointer) 0 },\r
- { "saveGameFile", "saveGameFile", XtRString, sizeof(String),\r
- XtOffset(AppDataPtr, saveGameFile), XtRString, "" },\r
- { "autoRaiseBoard", "autoRaiseBoard", XtRBoolean,\r
- sizeof(Boolean), XtOffset(AppDataPtr, autoRaiseBoard),\r
- XtRImmediate, (XtPointer) True },\r
- { "autoSaveGames", "autoSaveGames", XtRBoolean,\r
- sizeof(Boolean), XtOffset(AppDataPtr, autoSaveGames),\r
- XtRImmediate, (XtPointer) False },\r
- { "blindfold", "blindfold", XtRBoolean,\r
- sizeof(Boolean), XtOffset(AppDataPtr, blindfold),\r
- XtRImmediate, (XtPointer) False },\r
- { "loadPositionFile", "loadPositionFile", XtRString,\r
- sizeof(String), XtOffset(AppDataPtr, loadPositionFile),\r
- XtRString, "" },\r
- { "loadPositionIndex", "loadPositionIndex",\r
- XtRInt, sizeof(int),\r
- XtOffset(AppDataPtr, loadPositionIndex), XtRImmediate,\r
- (XtPointer) 1 },\r
- { "savePositionFile", "savePositionFile", XtRString,\r
- sizeof(String), XtOffset(AppDataPtr, savePositionFile),\r
- XtRString, "" },\r
- { "matchMode", "matchMode", XtRBoolean, sizeof(Boolean),\r
- XtOffset(AppDataPtr, matchMode), XtRImmediate, (XtPointer) False },\r
- { "matchGames", "matchGames", XtRInt, sizeof(int),\r
- XtOffset(AppDataPtr, matchGames), XtRImmediate,\r
- (XtPointer) 0 },\r
- { "monoMode", "monoMode", XtRBoolean, sizeof(Boolean),\r
- XtOffset(AppDataPtr, monoMode), XtRImmediate,\r
- (XtPointer) False },\r
- { "debugMode", "debugMode", XtRBoolean, sizeof(Boolean),\r
- XtOffset(AppDataPtr, debugMode), XtRImmediate,\r
- (XtPointer) False },\r
- { "clockMode", "clockMode", XtRBoolean, sizeof(Boolean),\r
- XtOffset(AppDataPtr, clockMode), XtRImmediate,\r
- (XtPointer) True },\r
- { "boardSize", "boardSize", XtRString, sizeof(String),\r
- XtOffset(AppDataPtr, boardSize), XtRString, "" },\r
- { "searchTime", "searchTime", XtRString, sizeof(String),\r
- XtOffset(AppDataPtr, searchTime), XtRString,\r
- (XtPointer) "" },\r
- { "searchDepth", "searchDepth", XtRInt, sizeof(int),\r
- XtOffset(AppDataPtr, searchDepth), XtRImmediate, \r
- (XtPointer) 0 },\r
- { "showCoords", "showCoords", XtRBoolean, sizeof(Boolean),\r
- XtOffset(AppDataPtr, showCoords), XtRImmediate,\r
- (XtPointer) False },\r
- { "showJail", "showJail", XtRInt, sizeof(int),\r
- XtOffset(AppDataPtr, showJail), XtRImmediate,\r
- (XtPointer) 0 },\r
- { "showThinking", "showThinking", XtRBoolean, sizeof(Boolean),\r
- XtOffset(AppDataPtr, showThinking), XtRImmediate,\r
- (XtPointer) True },\r
- { "ponderNextMove", "ponderNextMove", XtRBoolean, sizeof(Boolean),\r
- XtOffset(AppDataPtr, ponderNextMove), XtRImmediate,\r
- (XtPointer) True },\r
- { "periodicUpdates", "periodicUpdates", XtRBoolean, sizeof(Boolean),\r
- XtOffset(AppDataPtr, periodicUpdates), XtRImmediate,\r
- (XtPointer) True },\r
- { "clockFont", "clockFont", XtRString, sizeof(String),\r
- XtOffset(AppDataPtr, clockFont), XtRString, CLOCK_FONT },\r
- { "coordFont", "coordFont", XtRString, sizeof(String),\r
- XtOffset(AppDataPtr, coordFont), XtRString, COORD_FONT },\r
- { "font", "font", XtRString, sizeof(String),\r
- XtOffset(AppDataPtr, font), XtRString, DEFAULT_FONT },\r
- { "ringBellAfterMoves", "ringBellAfterMoves",\r
- XtRBoolean, sizeof(Boolean),\r
- XtOffset(AppDataPtr, ringBellAfterMoves),\r
- XtRImmediate, (XtPointer) False },\r
- { "autoCallFlag", "autoCallFlag", XtRBoolean,\r
- sizeof(Boolean), XtOffset(AppDataPtr, autoCallFlag),\r
- XtRImmediate, (XtPointer) False },\r
- { "autoFlipView", "autoFlipView", XtRBoolean,\r
- sizeof(Boolean), XtOffset(AppDataPtr, autoFlipView),\r
- XtRImmediate, (XtPointer) True },\r
- { "autoObserve", "autoObserve", XtRBoolean,\r
- sizeof(Boolean), XtOffset(AppDataPtr, autoObserve),\r
- XtRImmediate, (XtPointer) False },\r
- { "autoComment", "autoComment", XtRBoolean,\r
- sizeof(Boolean), XtOffset(AppDataPtr, autoComment),\r
- XtRImmediate, (XtPointer) False },\r
- { "getMoveList", "getMoveList", XtRBoolean,\r
- sizeof(Boolean), XtOffset(AppDataPtr, getMoveList),\r
- XtRImmediate, (XtPointer) True },\r
-#if HIGHDRAG\r
- { "highlightDragging", "highlightDragging", XtRBoolean,\r
- sizeof(Boolean), XtOffset(AppDataPtr, highlightDragging),\r
- XtRImmediate, (XtPointer) False },\r
-#endif\r
- { "highlightLastMove", "highlightLastMove", XtRBoolean,\r
- sizeof(Boolean), XtOffset(AppDataPtr, highlightLastMove),\r
- XtRImmediate, (XtPointer) False },\r
- { "premove", "premove", XtRBoolean,\r
- sizeof(Boolean), XtOffset(AppDataPtr, premove),\r
- XtRImmediate, (XtPointer) True },\r
- { "testLegality", "testLegality", XtRBoolean,\r
- sizeof(Boolean), XtOffset(AppDataPtr, testLegality),\r
- XtRImmediate, (XtPointer) True },\r
- { "flipView", "flipView", XtRBoolean,\r
- sizeof(Boolean), XtOffset(AppDataPtr, flipView),\r
- XtRImmediate, (XtPointer) False },\r
- { "cmail", "cmailGameName", XtRString, sizeof(String),\r
- XtOffset(AppDataPtr, cmailGameName), XtRString, "" },\r
- { "alwaysPromoteToQueen", "alwaysPromoteToQueen", XtRBoolean,\r
- sizeof(Boolean), XtOffset(AppDataPtr, alwaysPromoteToQueen),\r
- XtRImmediate, (XtPointer) False },\r
- { "oldSaveStyle", "oldSaveStyle", XtRBoolean,\r
- sizeof(Boolean), XtOffset(AppDataPtr, oldSaveStyle),\r
- XtRImmediate, (XtPointer) False },\r
- { "quietPlay", "quietPlay", XtRBoolean,\r
- sizeof(Boolean), XtOffset(AppDataPtr, quietPlay),\r
- XtRImmediate, (XtPointer) False },\r
- { "titleInWindow", "titleInWindow", XtRBoolean,\r
- sizeof(Boolean), XtOffset(AppDataPtr, titleInWindow),\r
- XtRImmediate, (XtPointer) False },\r
- { "localLineEditing", "localLineEditing", XtRBoolean,\r
- sizeof(Boolean), XtOffset(AppDataPtr, localLineEditing),\r
- XtRImmediate, (XtPointer) True }, /* not implemented, must be True */\r
-#ifdef ZIPPY\r
- { "zippyTalk", "zippyTalk", XtRBoolean,\r
- sizeof(Boolean), XtOffset(AppDataPtr, zippyTalk),\r
- XtRImmediate, (XtPointer) ZIPPY_TALK },\r
- { "zippyPlay", "zippyPlay", XtRBoolean,\r
- sizeof(Boolean), XtOffset(AppDataPtr, zippyPlay),\r
- XtRImmediate, (XtPointer) ZIPPY_PLAY },\r
- { "zippyLines", "zippyLines", XtRString, sizeof(String),\r
- XtOffset(AppDataPtr, zippyLines), XtRString, ZIPPY_LINES },\r
- { "zippyPinhead", "zippyPinhead", XtRString, sizeof(String),\r
- XtOffset(AppDataPtr, zippyPinhead), XtRString, ZIPPY_PINHEAD },\r
- { "zippyPassword", "zippyPassword", XtRString, sizeof(String),\r
- XtOffset(AppDataPtr, zippyPassword), XtRString, ZIPPY_PASSWORD },\r
- { "zippyPassword2", "zippyPassword2", XtRString, sizeof(String),\r
- XtOffset(AppDataPtr, zippyPassword2), XtRString, ZIPPY_PASSWORD2 },\r
- { "zippyWrongPassword", "zippyWrongPassword", XtRString, sizeof(String),\r
- XtOffset(AppDataPtr, zippyWrongPassword), XtRString,\r
- ZIPPY_WRONG_PASSWORD },\r
- { "zippyAcceptOnly", "zippyAcceptOnly", XtRString, sizeof(String),\r
- XtOffset(AppDataPtr, zippyAcceptOnly), XtRString, ZIPPY_ACCEPT_ONLY },\r
- { "zippyUseI", "zippyUseI", XtRBoolean,\r
- sizeof(Boolean), XtOffset(AppDataPtr, zippyUseI),\r
- XtRImmediate, (XtPointer) ZIPPY_USE_I },\r
- { "zippyBughouse", "zippyBughouse", XtRInt,\r
- sizeof(int), XtOffset(AppDataPtr, zippyBughouse),\r
- XtRImmediate, (XtPointer) ZIPPY_BUGHOUSE },\r
- { "zippyNoplayCrafty", "zippyNoplayCrafty", XtRBoolean,\r
- sizeof(Boolean), XtOffset(AppDataPtr, zippyNoplayCrafty),\r
- XtRImmediate, (XtPointer) ZIPPY_NOPLAY_CRAFTY },\r
- { "zippyGameEnd", "zippyGameEnd", XtRString, sizeof(String),\r
- XtOffset(AppDataPtr, zippyGameEnd), XtRString, ZIPPY_GAME_END },\r
- { "zippyGameStart", "zippyGameStart", XtRString, sizeof(String),\r
- XtOffset(AppDataPtr, zippyGameStart), XtRString, ZIPPY_GAME_START },\r
- { "zippyAdjourn", "zippyAdjourn", XtRBoolean,\r
- sizeof(Boolean), XtOffset(AppDataPtr, zippyAdjourn),\r
- XtRImmediate, (XtPointer) ZIPPY_ADJOURN },\r
- { "zippyAbort", "zippyAbort", XtRBoolean,\r
- sizeof(Boolean), XtOffset(AppDataPtr, zippyAbort),\r
- XtRImmediate, (XtPointer) ZIPPY_ABORT },\r
- { "zippyVariants", "zippyVariants", XtRString, sizeof(String),\r
- XtOffset(AppDataPtr, zippyVariants), XtRString, ZIPPY_VARIANTS },\r
- { "zippyMaxGames", "zippyMaxGames", XtRInt, sizeof(int),\r
- XtOffset(AppDataPtr, zippyMaxGames), XtRImmediate,\r
- (XtPointer) ZIPPY_MAX_GAMES },\r
- { "zippyReplayTimeout", "zippyReplayTimeout", XtRInt, sizeof(int),\r
- XtOffset(AppDataPtr, zippyReplayTimeout), XtRImmediate,\r
- (XtPointer) ZIPPY_REPLAY_TIMEOUT },\r
-#endif\r
- { "flashCount", "flashCount", XtRInt, sizeof(int),\r
- XtOffset(AppDataPtr, flashCount), XtRImmediate,\r
- (XtPointer) FLASH_COUNT },\r
- { "flashRate", "flashRate", XtRInt, sizeof(int),\r
- XtOffset(AppDataPtr, flashRate), XtRImmediate,\r
- (XtPointer) FLASH_RATE },\r
- { "pixmapDirectory", "pixmapDirectory", XtRString,\r
- sizeof(String), XtOffset(AppDataPtr, pixmapDirectory),\r
- XtRString, "" },\r
- { "msLoginDelay", "msLoginDelay", XtRInt, sizeof(int),\r
- XtOffset(AppDataPtr, msLoginDelay), XtRImmediate,\r
- (XtPointer) MS_LOGIN_DELAY },\r
- { "colorizeMessages", "colorizeMessages", XtRBoolean,\r
- sizeof(Boolean), XtOffset(AppDataPtr, colorize),\r
- XtRImmediate, (XtPointer) False }, \r
- { "colorShout", "colorShout", XtRString,\r
- sizeof(String), XtOffset(AppDataPtr, colorShout),\r
- XtRString, COLOR_SHOUT },\r
- { "colorSShout", "colorSShout", XtRString,\r
- sizeof(String), XtOffset(AppDataPtr, colorSShout),\r
- XtRString, COLOR_SSHOUT },\r
- { "colorChannel1", "colorChannel1", XtRString,\r
- sizeof(String), XtOffset(AppDataPtr, colorChannel1),\r
- XtRString, COLOR_CHANNEL1 },\r
- { "colorChannel", "colorChannel", XtRString,\r
- sizeof(String), XtOffset(AppDataPtr, colorChannel),\r
- XtRString, COLOR_CHANNEL },\r
- { "colorKibitz", "colorKibitz", XtRString,\r
- sizeof(String), XtOffset(AppDataPtr, colorKibitz),\r
- XtRString, COLOR_KIBITZ },\r
- { "colorTell", "colorTell", XtRString,\r
- sizeof(String), XtOffset(AppDataPtr, colorTell),\r
- XtRString, COLOR_TELL },\r
- { "colorChallenge", "colorChallenge", XtRString,\r
- sizeof(String), XtOffset(AppDataPtr, colorChallenge),\r
- XtRString, COLOR_CHALLENGE },\r
- { "colorRequest", "colorRequest", XtRString,\r
- sizeof(String), XtOffset(AppDataPtr, colorRequest),\r
- XtRString, COLOR_REQUEST },\r
- { "colorSeek", "colorSeek", XtRString,\r
- sizeof(String), XtOffset(AppDataPtr, colorSeek),\r
- XtRString, COLOR_SEEK },\r
- { "colorNormal", "colorNormal", XtRString,\r
- sizeof(String), XtOffset(AppDataPtr, colorNormal),\r
- XtRString, COLOR_NORMAL }, \r
- { "soundProgram", "soundProgram", XtRString,\r
- sizeof(String), XtOffset(AppDataPtr, soundProgram),\r
- XtRString, "play" },\r
- { "soundShout", "soundShout", XtRString,\r
- sizeof(String), XtOffset(AppDataPtr, soundShout),\r
- XtRString, "" },\r
- { "soundSShout", "soundSShout", XtRString,\r
- sizeof(String), XtOffset(AppDataPtr, soundSShout),\r
- XtRString, "" },\r
- { "soundChannel1", "soundChannel1", XtRString,\r
- sizeof(String), XtOffset(AppDataPtr, soundChannel1),\r
- XtRString, "" },\r
- { "soundChannel", "soundChannel", XtRString,\r
- sizeof(String), XtOffset(AppDataPtr, soundChannel),\r
- XtRString, "" },\r
- { "soundKibitz", "soundKibitz", XtRString,\r
- sizeof(String), XtOffset(AppDataPtr, soundKibitz),\r
- XtRString, "" },\r
- { "soundTell", "soundTell", XtRString,\r
- sizeof(String), XtOffset(AppDataPtr, soundTell),\r
- XtRString, "" },\r
- { "soundChallenge", "soundChallenge", XtRString,\r
- sizeof(String), XtOffset(AppDataPtr, soundChallenge),\r
- XtRString, "" },\r
- { "soundRequest", "soundRequest", XtRString,\r
- sizeof(String), XtOffset(AppDataPtr, soundRequest),\r
- XtRString, "" },\r
- { "soundSeek", "soundSeek", XtRString,\r
- sizeof(String), XtOffset(AppDataPtr, soundSeek),\r
- XtRString, "" },\r
- { "soundMove", "soundMove", XtRString,\r
- sizeof(String), XtOffset(AppDataPtr, soundMove),\r
- XtRString, "$" },\r
- { "soundIcsWin", "soundIcsWin", XtRString,\r
- sizeof(String), XtOffset(AppDataPtr, soundIcsWin),\r
- XtRString, "" },\r
- { "soundIcsLoss", "soundIcsLoss", XtRString,\r
- sizeof(String), XtOffset(AppDataPtr, soundIcsLoss),\r
- XtRString, "" },\r
- { "soundIcsDraw", "soundIcsDraw", XtRString,\r
- sizeof(String), XtOffset(AppDataPtr, soundIcsDraw),\r
- XtRString, "" },\r
- { "soundIcsUnfinished", "soundIcsUnfinished", XtRString,\r
- sizeof(String), XtOffset(AppDataPtr, soundIcsUnfinished),\r
- XtRString, "" },\r
- { "soundIcsAlarm", "soundIcsAlarm", XtRString,\r
- sizeof(String), XtOffset(AppDataPtr, soundIcsAlarm),\r
- XtRString, "$" },\r
- { "reuseFirst", "reuseFirst", XtRBoolean,\r
- sizeof(Boolean), XtOffset(AppDataPtr, reuseFirst),\r
- XtRImmediate, (XtPointer) True },\r
- { "reuseSecond", "reuseSecond", XtRBoolean,\r
- sizeof(Boolean), XtOffset(AppDataPtr, reuseSecond),\r
- XtRImmediate, (XtPointer) True },\r
- { "animateDragging", "animateDragging", XtRBoolean,\r
- sizeof(Boolean), XtOffset(AppDataPtr, animateDragging),\r
- XtRImmediate, (XtPointer) True },\r
- { "animateMoving", "animateMoving", XtRBoolean,\r
- sizeof(Boolean), XtOffset(AppDataPtr, animate),\r
- XtRImmediate, (XtPointer) True },\r
- { "animateSpeed", "animateSpeed", XtRInt,\r
- sizeof(int), XtOffset(AppDataPtr, animSpeed),\r
- XtRImmediate, (XtPointer)10 },\r
- { "popupExitMessage", "popupExitMessage", XtRBoolean,\r
- sizeof(Boolean), XtOffset(AppDataPtr, popupExitMessage),\r
- XtRImmediate, (XtPointer) True },\r
- { "popupMoveErrors", "popupMoveErrors", XtRBoolean,\r
- sizeof(Boolean), XtOffset(AppDataPtr, popupMoveErrors),\r
- XtRImmediate, (XtPointer) False },\r
- { "fontSizeTolerance", "fontSizeTolerance", XtRInt,\r
- sizeof(int), XtOffset(AppDataPtr, fontSizeTolerance),\r
- XtRImmediate, (XtPointer)4 },\r
- { "initialMode", "initialMode", XtRString,\r
- sizeof(String), XtOffset(AppDataPtr, initialMode),\r
- XtRImmediate, (XtPointer) "" },\r
- { "variant", "variant", XtRString,\r
- sizeof(String), XtOffset(AppDataPtr, variant),\r
- XtRImmediate, (XtPointer) "normal" },\r
- { "firstProtocolVersion", "firstProtocolVersion", XtRInt,\r
- sizeof(int), XtOffset(AppDataPtr, firstProtocolVersion),\r
- XtRImmediate, (XtPointer)PROTOVER },\r
- { "secondProtocolVersion", "secondProtocolVersion", XtRInt,\r
- sizeof(int), XtOffset(AppDataPtr, secondProtocolVersion),\r
- XtRImmediate, (XtPointer)PROTOVER },\r
- { "showButtonBar", "showButtonBar", XtRBoolean,\r
- sizeof(Boolean), XtOffset(AppDataPtr, showButtonBar),\r
- XtRImmediate, (XtPointer) True },\r
- {"icsEngineAnalyze", "icsEngineAnalyze", XtRBoolean, /* [DM] icsEngineAnalyze */\r
- sizeof(Boolean), XtOffset(AppDataPtr, icsEngineAnalyze),\r
- XtRImmediate, (XtPointer) False },\r
- { "firstScoreAbs", "firstScoreAbs", XtRBoolean,\r
- sizeof(Boolean), XtOffset(AppDataPtr, firstScoreIsAbsolute),\r
- XtRImmediate, (XtPointer) False },\r
- { "secondScoreAbs", "secondScoreAbs", XtRBoolean,\r
- sizeof(Boolean), XtOffset(AppDataPtr, secondScoreIsAbsolute),\r
- XtRImmediate, (XtPointer) False },\r
- { "pgnExtendedInfo", "pgnExtendedInfo", XtRBoolean,\r
- sizeof(Boolean), XtOffset(AppDataPtr, saveExtendedInfoInPGN),\r
- XtRImmediate, (XtPointer) False },\r
- { "hideThinkingFromHuman", "hideThinkingFromHuman", XtRBoolean,\r
- sizeof(Boolean), XtOffset(AppDataPtr, hideThinkingFromHuman),\r
- XtRImmediate, (XtPointer) True },\r
- { "adjudicateLossThreshold", "adjudicateLossThreshold", XtRInt,\r
- sizeof(int), XtOffset(AppDataPtr, adjudicateLossThreshold),\r
- XtRImmediate, (XtPointer) 0},\r
- { "pgnEventHeader", "pgnEventHeader", XtRString,\r
- sizeof(String), XtOffset(AppDataPtr, pgnEventHeader),\r
- XtRImmediate, (XtPointer) "Computer Chess Game" }, \r
- { "defaultFrcPosition", "defaultFrcPositon", XtRInt,\r
- sizeof(int), XtOffset(AppDataPtr, defaultFrcPosition),\r
- XtRImmediate, (XtPointer) -1},\r
-\r
- // [HGM] 4.3.xx options\r
- { "boardWidth", "boardWidth", XtRInt,\r
- sizeof(int), XtOffset(AppDataPtr, NrFiles),\r
- XtRImmediate, (XtPointer) -1},\r
- { "boardHeight", "boardHeight", XtRInt,\r
- sizeof(int), XtOffset(AppDataPtr, NrRanks),\r
- XtRImmediate, (XtPointer) -1},\r
- { "matchPause", "matchPause", XtRInt,\r
- sizeof(int), XtOffset(AppDataPtr, matchPause),\r
- XtRImmediate, (XtPointer) 10000},\r
- { "holdingsSize", "holdingsSize", XtRInt,\r
- sizeof(int), XtOffset(AppDataPtr, holdingsSize),\r
- XtRImmediate, (XtPointer) -1},\r
- { "flipBlack", "flipBlack", XtRBoolean,\r
- sizeof(Boolean), XtOffset(AppDataPtr, upsideDown),\r
- XtRImmediate, (XtPointer) False},\r
- { "allWhite", "allWhite", XtRBoolean,\r
- sizeof(Boolean), XtOffset(AppDataPtr, allWhite),\r
- XtRImmediate, (XtPointer) False},\r
- { "pieceToCharTable", "pieceToCharTable", XtRString,\r
- sizeof(String), XtOffset(AppDataPtr, pieceToCharTable),\r
- XtRImmediate, (XtPointer) 0},\r
- { "alphaRank", "alphaRank", XtRBoolean,\r
- sizeof(Boolean), XtOffset(AppDataPtr, alphaRank),\r
- XtRImmediate, (XtPointer) False},\r
- { "testClaims", "testClaims", XtRBoolean,\r
- sizeof(Boolean), XtOffset(AppDataPtr, testClaims),\r
- XtRImmediate, (XtPointer) True},\r
- { "checkMates", "checkMates", XtRBoolean,\r
- sizeof(Boolean), XtOffset(AppDataPtr, checkMates),\r
- XtRImmediate, (XtPointer) True},\r
- { "materialDraws", "materialDraws", XtRBoolean,\r
- sizeof(Boolean), XtOffset(AppDataPtr, materialDraws),\r
- XtRImmediate, (XtPointer) True},\r
- { "trivialDraws", "trivialDraws", XtRBoolean,\r
- sizeof(Boolean), XtOffset(AppDataPtr, trivialDraws),\r
- XtRImmediate, (XtPointer) False},\r
- { "ruleMoves", "ruleMoves", XtRInt,\r
- sizeof(int), XtOffset(AppDataPtr, ruleMoves),\r
- XtRImmediate, (XtPointer) 51},\r
- { "repeatsToDraw", "repeatsToDraw", XtRInt,\r
- sizeof(int), XtOffset(AppDataPtr, drawRepeats),\r
- XtRImmediate, (XtPointer) 6},\r
- { "engineDebugOutput", "engineDebugOutput", XtRInt,\r
- sizeof(int), XtOffset(AppDataPtr, engineComments),\r
- XtRImmediate, (XtPointer) 1},\r
- { "userName", "userName", XtRString,\r
- sizeof(int), XtOffset(AppDataPtr, userName),\r
- XtRImmediate, (XtPointer) 0},\r
- { "autoKibitz", "autoKibitz", XtRBoolean,\r
- sizeof(Boolean), XtOffset(AppDataPtr, autoKibitz),\r
- XtRImmediate, (XtPointer) False},\r
- { "firstTimeOdds", "firstTimeOdds", XtRInt,\r
- sizeof(int), XtOffset(AppDataPtr, firstTimeOdds),\r
- XtRImmediate, (XtPointer) 1},\r
- { "secondTimeOdds", "secondTimeOdds", XtRInt,\r
- sizeof(int), XtOffset(AppDataPtr, secondTimeOdds),\r
- XtRImmediate, (XtPointer) 1},\r
- { "timeOddsMode", "timeOddsMode", XtRInt,\r
- sizeof(int), XtOffset(AppDataPtr, timeOddsMode),\r
- XtRImmediate, (XtPointer) 0},\r
- { "firstAccumulateTC", "firstAccumulateTC", XtRInt,\r
- sizeof(int), XtOffset(AppDataPtr, firstAccumulateTC),\r
- XtRImmediate, (XtPointer) 1},\r
- { "secondAccumulateTC", "secondAccumulateTC", XtRInt,\r
- sizeof(int), XtOffset(AppDataPtr, secondAccumulateTC),\r
- XtRImmediate, (XtPointer) 1},\r
- { "firstNPS", "firstNPS", XtRInt,\r
- sizeof(int), XtOffset(AppDataPtr, firstNPS),\r
- XtRImmediate, (XtPointer) -1},\r
- { "secondNPS", "secondNPS", XtRInt,\r
- sizeof(int), XtOffset(AppDataPtr, secondNPS),\r
- XtRImmediate, (XtPointer) -1},\r
- { "serverMoves", "serverMoves", XtRString,\r
- sizeof(String), XtOffset(AppDataPtr, serverMovesName),\r
- XtRImmediate, (XtPointer) 0},\r
- { "serverPause", "serverPause", XtRInt,\r
- sizeof(int), XtOffset(AppDataPtr, serverPause),\r
- XtRImmediate, (XtPointer) 0},\r
- { "suppressLoadMoves", "suppressLoadMoves", XtRBoolean,\r
- sizeof(Boolean), XtOffset(AppDataPtr, suppressLoadMoves),\r
- XtRImmediate, (XtPointer) False},\r
- { "userName", "userName", XtRString,\r
- sizeof(String), XtOffset(AppDataPtr, userName),\r
- XtRImmediate, (XtPointer) 0},\r
- { "egtFormats", "egtFormats", XtRString,\r
- sizeof(String), XtOffset(AppDataPtr, egtFormats),\r
- XtRImmediate, (XtPointer) 0},\r
- { "rewindIndex", "rewindIndex", XtRInt,\r
- sizeof(int), XtOffset(AppDataPtr, rewindIndex),\r
- XtRImmediate, (XtPointer) 0},\r
- { "sameColorGames", "sameColorGames", XtRInt,\r
- sizeof(int), XtOffset(AppDataPtr, sameColorGames),\r
- XtRImmediate, (XtPointer) 0},\r
- { "smpCores", "smpCores", XtRInt,\r
- sizeof(int), XtOffset(AppDataPtr, smpCores),\r
- XtRImmediate, (XtPointer) 1},\r
- { "niceEngines", "niceEngines", XtRInt,\r
- sizeof(int), XtOffset(AppDataPtr, niceEngines),\r
- XtRImmediate, (XtPointer) 0},\r
-\r
- // [HGM] Winboard_x UCI options\r
- { "firstIsUCI", "firstIsUCI", XtRBoolean,\r
- sizeof(Boolean), XtOffset(AppDataPtr, firstIsUCI),\r
- XtRImmediate, (XtPointer) False},\r
- { "secondIsUCI", "secondIsUCI", XtRBoolean,\r
- sizeof(Boolean), XtOffset(AppDataPtr, secondIsUCI),\r
- XtRImmediate, (XtPointer) False},\r
- { "firstHasOwnBookUCI", "firstHasOwnBookUCI", XtRBoolean,\r
- sizeof(Boolean), XtOffset(AppDataPtr, firstHasOwnBookUCI),\r
- XtRImmediate, (XtPointer) True},\r
- { "secondHasOwnBookUCI", "secondHasOwnBookUCI", XtRBoolean,\r
- sizeof(Boolean), XtOffset(AppDataPtr, secondHasOwnBookUCI),\r
- XtRImmediate, (XtPointer) True},\r
- { "usePolyglotBook", "usePolyglotBook", XtRBoolean,\r
- sizeof(Boolean), XtOffset(AppDataPtr, usePolyglotBook),\r
- XtRImmediate, (XtPointer) False},\r
- { "defaultHashSize", "defaultHashSize", XtRInt,\r
- sizeof(int), XtOffset(AppDataPtr, defaultHashSize),\r
- XtRImmediate, (XtPointer) 64},\r
- { "defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XtRInt,\r
- sizeof(int), XtOffset(AppDataPtr, defaultCacheSizeEGTB),\r
- XtRImmediate, (XtPointer) 4},\r
- { "polyglotDir", "polyglotDir", XtRString,\r
- sizeof(String), XtOffset(AppDataPtr, polyglotDir),\r
- XtRImmediate, (XtPointer) "." },\r
- { "polyglotBook", "polyglotBook", XtRString,\r
- sizeof(String), XtOffset(AppDataPtr, polyglotBook),\r
- XtRImmediate, (XtPointer) "" }, \r
- { "defaultPathEGTB", "defaultPathEGTB", XtRString,\r
- sizeof(String), XtOffset(AppDataPtr, defaultPathEGTB),\r
- XtRImmediate, (XtPointer) "/usr/local/share/egtb"},\r
- { "delayBeforeQuit", "delayBeforeQuit", XtRInt,\r
- sizeof(int), XtOffset(AppDataPtr, delayBeforeQuit),\r
- XtRImmediate, (XtPointer) 0},\r
- { "delayAfterQuit", "delayAfterQuit", XtRInt,\r
- sizeof(int), XtOffset(AppDataPtr, delayAfterQuit),\r
- XtRImmediate, (XtPointer) 0},\r
- { "nameOfDebugFile", "nameOfDebugFile", XtRString,\r
- sizeof(String), XtOffset(AppDataPtr, nameOfDebugFile),\r
- XtRImmediate, (XtPointer) "xboard.debug"},\r
- { "noGUI", "noGUI", XtRBoolean,\r
- sizeof(Boolean), XtOffset(AppDataPtr, noGUI),\r
- XtRImmediate, (XtPointer) 0},\r
-};\r
-\r
-XrmOptionDescRec shellOptions[] = {\r
- { "-whitePieceColor", "whitePieceColor", XrmoptionSepArg, NULL },\r
- { "-blackPieceColor", "blackPieceColor", XrmoptionSepArg, NULL },\r
- { "-lightSquareColor", "lightSquareColor", XrmoptionSepArg, NULL },\r
- { "-darkSquareColor", "darkSquareColor", XrmoptionSepArg, NULL },\r
- { "-highlightSquareColor", "highlightSquareColor", XrmoptionSepArg, NULL },\r
- { "-premoveHighlightColor", "premoveHighlightColor", XrmoptionSepArg,NULL},\r
- { "-movesPerSession", "movesPerSession", XrmoptionSepArg, NULL },\r
- { "-mps", "movesPerSession", XrmoptionSepArg, NULL },\r
- { "-timeIncrement", "timeIncrement", XrmoptionSepArg, NULL },\r
- { "-inc", "timeIncrement", XrmoptionSepArg, NULL },\r
- { "-initString", "initString", XrmoptionSepArg, NULL },\r
- { "-firstInitString", "initString", XrmoptionSepArg, NULL },\r
- { "-secondInitString", "secondInitString", XrmoptionSepArg, NULL },\r
- { "-firstComputerString", "firstComputerString", XrmoptionSepArg, NULL },\r
- { "-secondComputerString", "secondComputerString", XrmoptionSepArg, NULL },\r
- { "-firstChessProgram", "firstChessProgram", XrmoptionSepArg, NULL },\r
- { "-fcp", "firstChessProgram", XrmoptionSepArg, NULL },\r
- { "-secondChessProgram", "secondChessProgram", XrmoptionSepArg, NULL },\r
- { "-scp", "secondChessProgram", XrmoptionSepArg, NULL },\r
- { "-firstPlaysBlack", "firstPlaysBlack", XrmoptionSepArg, NULL },\r
- { "-fb", "firstPlaysBlack", XrmoptionNoArg, "True" },\r
- { "-xfb", "firstPlaysBlack", XrmoptionNoArg, "False" },\r
- { "-noChessProgram", "noChessProgram", XrmoptionSepArg, NULL },\r
- { "-ncp", "noChessProgram", XrmoptionNoArg, "True" },\r
- { "-xncp", "noChessProgram", XrmoptionNoArg, "False" },\r
- { "-firstHost", "firstHost", XrmoptionSepArg, NULL },\r
- { "-fh", "firstHost", XrmoptionSepArg, NULL },\r
- { "-secondHost", "secondHost", XrmoptionSepArg, NULL },\r
- { "-sh", "secondHost", XrmoptionSepArg, NULL },\r
- { "-firstDirectory", "firstDirectory", XrmoptionSepArg, NULL },\r
- { "-fd", "firstDirectory", XrmoptionSepArg, NULL },\r
- { "-secondDirectory", "secondDirectory", XrmoptionSepArg, NULL },\r
- { "-sd", "secondDirectory", XrmoptionSepArg, NULL },\r
- { "-bitmapDirectory", "bitmapDirectory", XrmoptionSepArg, NULL },\r
- { "-bm", "bitmapDirectory", XrmoptionSepArg, NULL },\r
- { "-remoteShell", "remoteShell", XrmoptionSepArg, NULL },\r
- { "-rsh", "remoteShell", XrmoptionSepArg, NULL },\r
- { "-remoteUser", "remoteUser", XrmoptionSepArg, NULL },\r
- { "-ruser", "remoteUser", XrmoptionSepArg, NULL },\r
- { "-timeDelay", "timeDelay", XrmoptionSepArg, NULL },\r
- { "-td", "timeDelay", XrmoptionSepArg, NULL },\r
- { "-timeControl", "timeControl", XrmoptionSepArg, NULL },\r
- { "-tc", "timeControl", XrmoptionSepArg, NULL },\r
- { "-internetChessServerMode", "internetChessServerMode",\r
- XrmoptionSepArg, NULL },\r
- { "-ics", "internetChessServerMode", XrmoptionNoArg, "True" },\r
- { "-xics", "internetChessServerMode", XrmoptionNoArg, "False" },\r
- { "-internetChessServerHost", "internetChessServerHost",\r
- XrmoptionSepArg, NULL },\r
- { "-icshost", "internetChessServerHost", XrmoptionSepArg, NULL },\r
- { "-internetChessServerPort", "internetChessServerPort",\r
- XrmoptionSepArg, NULL },\r
- { "-icsport", "internetChessServerPort", XrmoptionSepArg, NULL },\r
- { "-internetChessServerCommPort", "internetChessServerCommPort",\r
- XrmoptionSepArg, NULL },\r
- { "-icscomm", "internetChessServerCommPort", XrmoptionSepArg, NULL },\r
- { "-internetChessServerLogonScript", "internetChessServerLogonScript",\r
- XrmoptionSepArg, NULL },\r
- { "-icslogon", "internetChessServerLogonScript", XrmoptionSepArg, NULL },\r
- { "-internetChessServerHelper", "internetChessServerHelper",\r
- XrmoptionSepArg, NULL },\r
- { "-icshelper", "internetChessServerHelper", XrmoptionSepArg, NULL },\r
- { "-internetChessServerInputBox", "internetChessServerInputBox",\r
- XrmoptionSepArg, NULL },\r
- { "-icsinput", "internetChessServerInputBox", XrmoptionNoArg, "True" },\r
- { "-xicsinput", "internetChessServerInputBox", XrmoptionNoArg, "False" },\r
- { "-icsAlarm", "icsAlarm", XrmoptionSepArg, NULL },\r
- { "-alarm", "icsAlarm", XrmoptionNoArg, "True" },\r
- { "-xalarm", "icsAlarm", XrmoptionNoArg, "False" },\r
- { "-icsAlarmTime", "icsAlarmTime", XrmoptionSepArg, NULL },\r
- { "-useTelnet", "useTelnet", XrmoptionSepArg, NULL },\r
- { "-telnet", "useTelnet", XrmoptionNoArg, "True" },\r
- { "-xtelnet", "useTelnet", XrmoptionNoArg, "False" },\r
- { "-telnetProgram", "telnetProgram", XrmoptionSepArg, NULL },\r
- { "-gateway", "gateway", XrmoptionSepArg, NULL },\r
- { "-loadGameFile", "loadGameFile", XrmoptionSepArg, NULL },\r
- { "-lgf", "loadGameFile", XrmoptionSepArg, NULL },\r
- { "-loadGameIndex", "loadGameIndex", XrmoptionSepArg, NULL },\r
- { "-lgi", "loadGameIndex", XrmoptionSepArg, NULL },\r
- { "-saveGameFile", "saveGameFile", XrmoptionSepArg, NULL },\r
- { "-sgf", "saveGameFile", XrmoptionSepArg, NULL },\r
- { "-autoSaveGames", "autoSaveGames", XrmoptionSepArg, NULL },\r
- { "-autosave", "autoSaveGames", XrmoptionNoArg, "True" },\r
- { "-xautosave", "autoSaveGames", XrmoptionNoArg, "False" },\r
- { "-autoRaiseBoard", "autoRaiseBoard", XrmoptionSepArg, NULL },\r
- { "-autoraise", "autoRaiseBoard", XrmoptionNoArg, "True" },\r
- { "-xautoraise", "autoRaiseBoard", XrmoptionNoArg, "False" },\r
- { "-blindfold", "blindfold", XrmoptionSepArg, NULL },\r
- { "-blind", "blindfold", XrmoptionNoArg, "True" },\r
- { "-xblind", "blindfold", XrmoptionNoArg, "False" },\r
- { "-loadPositionFile", "loadPositionFile", XrmoptionSepArg, NULL },\r
- { "-lpf", "loadPositionFile", XrmoptionSepArg, NULL },\r
- { "-loadPositionIndex", "loadPositionIndex", XrmoptionSepArg, NULL },\r
- { "-lpi", "loadPositionIndex", XrmoptionSepArg, NULL },\r
- { "-savePositionFile", "savePositionFile", XrmoptionSepArg, NULL },\r
- { "-spf", "savePositionFile", XrmoptionSepArg, NULL },\r
- { "-matchMode", "matchMode", XrmoptionSepArg, NULL },\r
- { "-mm", "matchMode", XrmoptionNoArg, "True" },\r
- { "-xmm", "matchMode", XrmoptionNoArg, "False" },\r
- { "-matchGames", "matchGames", XrmoptionSepArg, NULL },\r
- { "-mg", "matchGames", XrmoptionSepArg, NULL },\r
- { "-monoMode", "monoMode", XrmoptionSepArg, NULL },\r
- { "-mono", "monoMode", XrmoptionNoArg, "True" },\r
- { "-xmono", "monoMode", XrmoptionNoArg, "False" },\r
- { "-debugMode", "debugMode", XrmoptionSepArg, NULL },\r
- { "-debug", "debugMode", XrmoptionNoArg, "True" },\r
- { "-xdebug", "debugMode", XrmoptionNoArg, "False" },\r
- { "-clockMode", "clockMode", XrmoptionSepArg, NULL },\r
- { "-clock", "clockMode", XrmoptionNoArg, "True" },\r
- { "-xclock", "clockMode", XrmoptionNoArg, "False" },\r
- { "-boardSize", "boardSize", XrmoptionSepArg, NULL },\r
- { "-size", "boardSize", XrmoptionSepArg, NULL },\r
- { "-searchTime", "searchTime", XrmoptionSepArg, NULL },\r
- { "-st", "searchTime", XrmoptionSepArg, NULL },\r
- { "-searchDepth", "searchDepth", XrmoptionSepArg, NULL },\r
- { "-depth", "searchDepth", XrmoptionSepArg, NULL },\r
- { "-showCoords", "showCoords", XrmoptionSepArg, NULL },\r
- { "-coords", "showCoords", XrmoptionNoArg, "True" },\r
- { "-xcoords", "showCoords", XrmoptionNoArg, "False" },\r
-#if JAIL\r
- { "-showJail", "showJail", XrmoptionSepArg, NULL },\r
- { "-jail", "showJail", XrmoptionNoArg, "1" },\r
- { "-sidejail", "showJail", XrmoptionNoArg, "2" },\r
- { "-xjail", "showJail", XrmoptionNoArg, "0" },\r
-#endif\r
- { "-showThinking", "showThinking", XrmoptionSepArg, NULL },\r
- { "-thinking", "showThinking", XrmoptionNoArg, "True" },\r
- { "-xthinking", "showThinking", XrmoptionNoArg, "False" },\r
- { "-ponderNextMove", "ponderNextMove", XrmoptionSepArg, NULL },\r
- { "-ponder", "ponderNextMove", XrmoptionNoArg, "True" },\r
- { "-xponder", "ponderNextMove", XrmoptionNoArg, "False" },\r
- { "-periodicUpdates", "periodicUpdates", XrmoptionSepArg, NULL },\r
- { "-periodic", "periodicUpdates", XrmoptionNoArg, "True" },\r
- { "-xperiodic", "periodicUpdates", XrmoptionNoArg, "False" },\r
- { "-clockFont", "clockFont", XrmoptionSepArg, NULL },\r
- { "-coordFont", "coordFont", XrmoptionSepArg, NULL },\r
- { "-font", "font", XrmoptionSepArg, NULL },\r
- { "-ringBellAfterMoves", "ringBellAfterMoves", XrmoptionSepArg, NULL },\r
- { "-bell", "ringBellAfterMoves", XrmoptionNoArg, "True" },\r
- { "-xbell", "ringBellAfterMoves", XrmoptionNoArg, "False" },\r
- { "-movesound", "ringBellAfterMoves", XrmoptionNoArg, "True" },\r
- { "-xmovesound", "ringBellAfterMoves", XrmoptionNoArg, "False" },\r
- { "-autoCallFlag", "autoCallFlag", XrmoptionSepArg, NULL },\r
- { "-autoflag", "autoCallFlag", XrmoptionNoArg, "True" },\r
- { "-xautoflag", "autoCallFlag", XrmoptionNoArg, "False" },\r
- { "-autoFlipView", "autoFlipView", XrmoptionSepArg, NULL },\r
- { "-autoflip", "autoFlipView", XrmoptionNoArg, "True" },\r
- { "-xautoflip", "autoFlipView", XrmoptionNoArg, "False" },\r
- { "-autoObserve", "autoObserve", XrmoptionSepArg, NULL },\r
- { "-autobs", "autoObserve", XrmoptionNoArg, "True" },\r
- { "-xautobs", "autoObserve", XrmoptionNoArg, "False" },\r
- { "-autoComment", "autoComment", XrmoptionSepArg, NULL },\r
- { "-autocomm", "autoComment", XrmoptionNoArg, "True" },\r
- { "-xautocomm", "autoComment", XrmoptionNoArg, "False" },\r
- { "-getMoveList", "getMoveList", XrmoptionSepArg, NULL },\r
- { "-moves", "getMoveList", XrmoptionNoArg, "True" },\r
- { "-xmoves", "getMoveList", XrmoptionNoArg, "False" },\r
-#if HIGHDRAG\r
- { "-highlightDragging", "highlightDragging", XrmoptionSepArg, NULL },\r
- { "-highdrag", "highlightDragging", XrmoptionNoArg, "True" },\r
- { "-xhighdrag", "highlightDragging", XrmoptionNoArg, "False" },\r
-#endif\r
- { "-highlightLastMove", "highlightLastMove", XrmoptionSepArg, NULL },\r
- { "-highlight", "highlightLastMove", XrmoptionNoArg, "True" },\r
- { "-xhighlight", "highlightLastMove", XrmoptionNoArg, "False" },\r
- { "-premove", "premove", XrmoptionSepArg, NULL },\r
- { "-pre", "premove", XrmoptionNoArg, "True" },\r
- { "-xpre", "premove", XrmoptionNoArg, "False" },\r
- { "-testLegality", "testLegality", XrmoptionSepArg, NULL },\r
- { "-legal", "testLegality", XrmoptionNoArg, "True" },\r
- { "-xlegal", "testLegality", XrmoptionNoArg, "False" },\r
- { "-flipView", "flipView", XrmoptionSepArg, NULL },\r
- { "-flip", "flipView", XrmoptionNoArg, "True" },\r
- { "-xflip", "flipView", XrmoptionNoArg, "False" },\r
- { "-cmail", "cmailGameName", XrmoptionSepArg, NULL },\r
- { "-alwaysPromoteToQueen", "alwaysPromoteToQueen",\r
- XrmoptionSepArg, NULL },\r
- { "-queen", "alwaysPromoteToQueen", XrmoptionNoArg, "True" },\r
- { "-xqueen", "alwaysPromoteToQueen", XrmoptionNoArg, "False" },\r
- { "-oldSaveStyle", "oldSaveStyle", XrmoptionSepArg, NULL },\r
- { "-oldsave", "oldSaveStyle", XrmoptionNoArg, "True" },\r
- { "-xoldsave", "oldSaveStyle", XrmoptionNoArg, "False" },\r
- { "-quietPlay", "quietPlay", XrmoptionSepArg, NULL },\r
- { "-quiet", "quietPlay", XrmoptionNoArg, "True" },\r
- { "-xquiet", "quietPlay", XrmoptionNoArg, "False" },\r
- { "-titleInWindow", "titleInWindow", XrmoptionSepArg, NULL },\r
- { "-title", "titleInWindow", XrmoptionNoArg, "True" },\r
- { "-xtitle", "titleInWindow", XrmoptionNoArg, "False" },\r
-#ifdef ZIPPY\r
- { "-zippyTalk", "zippyTalk", XrmoptionSepArg, NULL },\r
- { "-zt", "zippyTalk", XrmoptionNoArg, "True" },\r
- { "-xzt", "zippyTalk", XrmoptionNoArg, "False" },\r
- { "-zippyPlay", "zippyPlay", XrmoptionSepArg, NULL },\r
- { "-zp", "zippyPlay", XrmoptionNoArg, "True" },\r
- { "-xzp", "zippyPlay", XrmoptionNoArg, "False" },\r
- { "-zippyLines", "zippyLines", XrmoptionSepArg, NULL },\r
- { "-zippyPinhead", "zippyPinhead", XrmoptionSepArg, NULL },\r
- { "-zippyPassword", "zippyPassword", XrmoptionSepArg, NULL },\r
- { "-zippyPassword2", "zippyPassword2", XrmoptionSepArg, NULL },\r
- { "-zippyWrongPassword", "zippyWrongPassword", XrmoptionSepArg, NULL },\r
- { "-zippyAcceptOnly", "zippyAcceptOnly", XrmoptionSepArg, NULL },\r
- { "-zippyUseI", "zippyUseI", XrmoptionSepArg, NULL },\r
- { "-zui", "zippyUseI", XrmoptionNoArg, "True" },\r
- { "-xzui", "zippyUseI", XrmoptionNoArg, "False" },\r
- { "-zippyBughouse", "zippyBughouse", XrmoptionSepArg, NULL },\r
- { "-zippyNoplayCrafty", "zippyNoplayCrafty", XrmoptionSepArg, NULL },\r
- { "-znc", "zippyNoplayCrafty", XrmoptionNoArg, "True" },\r
- { "-xznc", "zippyNoplayCrafty", XrmoptionNoArg, "False" },\r
- { "-zippyGameEnd", "zippyGameEnd", XrmoptionSepArg, NULL },\r
- { "-zippyGameStart", "zippyGameStart", XrmoptionSepArg, NULL },\r
- { "-zippyAdjourn", "zippyAdjourn", XrmoptionSepArg, NULL },\r
- { "-zadj", "zippyAdjourn", XrmoptionNoArg, "True" },\r
- { "-xzadj", "zippyAdjourn", XrmoptionNoArg, "False" },\r
- { "-zippyAbort", "zippyAbort", XrmoptionSepArg, NULL },\r
- { "-zab", "zippyAbort", XrmoptionNoArg, "True" },\r
- { "-xzab", "zippyAbort", XrmoptionNoArg, "False" },\r
- { "-zippyVariants", "zippyVariants", XrmoptionSepArg, NULL },\r
- { "-zippyMaxGames", "zippyMaxGames", XrmoptionSepArg, NULL },\r
- { "-zippyReplayTimeout", "zippyReplayTimeout", XrmoptionSepArg, NULL },\r
-#endif\r
- { "-flashCount", "flashCount", XrmoptionSepArg, NULL },\r
- { "-flash", "flashCount", XrmoptionNoArg, "3" },\r
- { "-xflash", "flashCount", XrmoptionNoArg, "0" },\r
- { "-flashRate", "flashRate", XrmoptionSepArg, NULL },\r
- { "-pixmapDirectory", "pixmapDirectory", XrmoptionSepArg, NULL },\r
- { "-msLoginDelay", "msLoginDelay", XrmoptionSepArg, NULL },\r
- { "-pixmap", "pixmapDirectory", XrmoptionSepArg, NULL },\r
- { "-colorizeMessages", "colorizeMessages", XrmoptionSepArg, NULL },\r
- { "-colorize", "colorizeMessages", XrmoptionNoArg, "True" },\r
- { "-xcolorize", "colorizeMessages", XrmoptionNoArg, "False" },\r
- { "-colorShout", "colorShout", XrmoptionSepArg, NULL },\r
- { "-colorSShout", "colorSShout", XrmoptionSepArg, NULL },\r
- { "-colorCShout", "colorSShout", XrmoptionSepArg, NULL }, /*FICS name*/\r
- { "-colorChannel1", "colorChannel1", XrmoptionSepArg, NULL },\r
- { "-colorChannel", "colorChannel", XrmoptionSepArg, NULL },\r
- { "-colorKibitz", "colorKibitz", XrmoptionSepArg, NULL },\r
- { "-colorTell", "colorTell", XrmoptionSepArg, NULL },\r
- { "-colorChallenge", "colorChallenge", XrmoptionSepArg, NULL },\r
- { "-colorRequest", "colorRequest", XrmoptionSepArg, NULL },\r
- { "-colorSeek", "colorSeek", XrmoptionSepArg, NULL },\r
- { "-colorNormal", "colorNormal", XrmoptionSepArg, NULL },\r
- { "-soundProgram", "soundProgram", XrmoptionSepArg, NULL },\r
- { "-soundShout", "soundShout", XrmoptionSepArg, NULL },\r
- { "-soundSShout", "soundSShout", XrmoptionSepArg, NULL },\r
- { "-soundCShout", "soundSShout", XrmoptionSepArg, NULL }, /*FICS name*/\r
- { "-soundChannel1", "soundChannel1", XrmoptionSepArg, NULL },\r
- { "-soundChannel", "soundChannel", XrmoptionSepArg, NULL },\r
- { "-soundKibitz", "soundKibitz", XrmoptionSepArg, NULL },\r
- { "-soundTell", "soundTell", XrmoptionSepArg, NULL },\r
- { "-soundChallenge", "soundChallenge", XrmoptionSepArg, NULL },\r
- { "-soundRequest", "soundRequest", XrmoptionSepArg, NULL },\r
- { "-soundSeek", "soundSeek", XrmoptionSepArg, NULL },\r
- { "-soundMove", "soundMove", XrmoptionSepArg, NULL },\r
- { "-soundIcsWin", "soundIcsWin", XrmoptionSepArg, NULL },\r
- { "-soundIcsLoss", "soundIcsLoss", XrmoptionSepArg, NULL },\r
- { "-soundIcsDraw", "soundIcsDraw", XrmoptionSepArg, NULL },\r
- { "-soundIcsUnfinished", "soundIcsUnfinished", XrmoptionSepArg, NULL },\r
- { "-soundIcsAlarm", "soundIcsAlarm", XrmoptionSepArg, NULL },\r
- { "-reuseFirst", "reuseFirst", XrmoptionSepArg, NULL },\r
- { "-reuseChessPrograms", "reuseFirst", XrmoptionSepArg, NULL }, /*compat*/\r
- { "-reuse", "reuseFirst", XrmoptionNoArg, "True" },\r
- { "-xreuse", "reuseFirst", XrmoptionNoArg, "False" },\r
- { "-reuseSecond", "reuseSecond", XrmoptionSepArg, NULL },\r
- { "-reuse2", "reuseSecond", XrmoptionNoArg, "True" },\r
- { "-xreuse2", "reuseSecond", XrmoptionNoArg, "False" },\r
- { "-animateMoving", "animateMoving", XrmoptionSepArg, NULL },\r
- { "-animate", "animateMoving", XrmoptionNoArg, "True" },\r
- { "-xanimate", "animateMoving", XrmoptionNoArg, "False" },\r
- { "-animateDragging", "animateDragging", XrmoptionSepArg, NULL },\r
- { "-drag", "animateDragging", XrmoptionNoArg, "True" },\r
- { "-xdrag", "animateDragging", XrmoptionNoArg, "False" },\r
- { "-animateSpeed", "animateSpeed", XrmoptionSepArg, NULL },\r
- { "-popupExitMessage", "popupExitMessage", XrmoptionSepArg, NULL },\r
- { "-exit", "popupExitMessage", XrmoptionNoArg, "True" },\r
- { "-xexit", "popupExitMessage", XrmoptionNoArg, "False" },\r
- { "-popupMoveErrors", "popupMoveErrors", XrmoptionSepArg, NULL },\r
- { "-popup", "popupMoveErrors", XrmoptionNoArg, "True" },\r
- { "-xpopup", "popupMoveErrors", XrmoptionNoArg, "False" },\r
- { "-fontSizeTolerance", "fontSizeTolerance", XrmoptionSepArg, NULL },\r
- { "-initialMode", "initialMode", XrmoptionSepArg, NULL },\r
- { "-mode", "initialMode", XrmoptionSepArg, NULL },\r
- { "-variant", "variant", XrmoptionSepArg, NULL },\r
- { "-firstProtocolVersion", "firstProtocolVersion", XrmoptionSepArg, NULL },\r
- { "-secondProtocolVersion","secondProtocolVersion",XrmoptionSepArg, NULL },\r
- { "-showButtonBar", "showButtonBar", XrmoptionSepArg, NULL },\r
- { "-buttons", "showButtonBar", XrmoptionNoArg, "True" },\r
- { "-xbuttons", "showButtonBar", XrmoptionNoArg, "False" },\r
- /* [AS,HR] New features */\r
- { "-firstScoreAbs", "firstScoreAbs", XrmoptionSepArg, NULL },\r
- { "-secondScoreAbs", "secondScoreAbs", XrmoptionSepArg, NULL },\r
- { "-pgnExtendedInfo", "pgnExtendedInfo", XrmoptionSepArg, NULL },\r
- { "-hideThinkingFromHuman", "hideThinkingFromHuman", XrmoptionSepArg, NULL },\r
- { "-adjudicateLossThreshold", "adjudicateLossThreshold", XrmoptionSepArg, NULL },\r
- { "-pgnEventHeader", "pgnEventHeader", XrmoptionSepArg, NULL },\r
- { "-firstIsUCI", "firstIsUCI", XrmoptionSepArg, NULL },\r
- { "-secondIsUCI", "secondIsUCI", XrmoptionSepArg, NULL },\r
- { "-fUCI", "firstIsUCI", XrmoptionNoArg, "True" },\r
- { "-sUCI", "secondIsUCI", XrmoptionNoArg, "True" },\r
- { "-firstHasOwnBookUCI", "firstHasOwnBookUCI", XrmoptionSepArg, NULL },\r
- { "-secondHasOwnBookUCI", "secondHasOwnBookUCI", XrmoptionSepArg, NULL },\r
- { "-fNoOwnBookUCI", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },\r
- { "-sNoOwnBookUCI", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },\r
- { "-polyglotDir", "polyglotDir", XrmoptionSepArg, NULL },\r
- { "-usePolyglotBook", "usePolyglotBook", XrmoptionSepArg, NULL },\r
- { "-polyglotBook", "polyglotBook", XrmoptionSepArg, NULL },\r
- { "-defaultHashSize", "defaultHashSize", XrmoptionSepArg, NULL },\r
- { "-defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XrmoptionSepArg, NULL },\r
- { "-defaultPathEGTB", "defaultPathEGTB", XrmoptionSepArg, NULL },\r
- { "-defaultFrcPosition", "defaultFrcPosition", XrmoptionSepArg, NULL },\r
- // [HGM] I am sure AS added many more options, but we have to fish them out, from the list in winboard.c\r
-\r
- /* [HGM,HR] User-selectable board size */\r
- { "-boardWidth", "boardWidth", XrmoptionSepArg, NULL }, \r
- { "-boardHeight", "boardHeight", XrmoptionSepArg, NULL }, \r
- { "-matchPause", "matchPause", XrmoptionSepArg, NULL }, \r
-\r
- /* [HGM] new arguments of 4.3.xx. All except first three are back-end options, which should work immediately */\r
- { "-holdingsSize", "holdingsSize", XrmoptionSepArg, NULL }, // requires extensive front-end changes to work\r
- { "-flipBlack", "flipBlack", XrmoptionSepArg, NULL }, // requires front-end changes to work\r
- { "-allWhite", "allWhite", XrmoptionSepArg, NULL }, // requires front-end changes to work\r
- { "-pieceToCharTable", "pieceToCharTable", XrmoptionSepArg, NULL }, \r
- { "-alphaRank", "alphaRank", XrmoptionSepArg, NULL }, \r
- { "-testClaims", "testClaims", XrmoptionSepArg, NULL }, \r
- { "-checkMates", "checkMates", XrmoptionSepArg, NULL }, \r
- { "-materialDraws", "materialDraws", XrmoptionSepArg, NULL }, \r
- { "-trivialDraws", "trivialDraws", XrmoptionSepArg, NULL }, \r
- { "-ruleMoves", "ruleMoves", XrmoptionSepArg, NULL }, \r
- { "-repeatsToDraw", "repeatsToDraw", XrmoptionSepArg, NULL },\r
- { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL }, \r
- { "-userName", "userName", XrmoptionSepArg, NULL }, \r
- { "-autoKibitz", "autoKibitz", XrmoptionNoArg, "True" }, \r
- { "-firstTimeOdds", "firstTimeOdds", XrmoptionSepArg, NULL }, \r
- { "-secondTimeOdds", "secondTimeOdds", XrmoptionSepArg, NULL }, \r
- { "-timeOddsMode", "timeOddsMode", XrmoptionSepArg, NULL }, \r
- { "-firstAccumulateTC", "firstAccumulateTC", XrmoptionSepArg, NULL }, \r
- { "-secondAccumulateTC", "secondAccumulateTC", XrmoptionSepArg, NULL }, \r
- { "-firstNPS", "firstNPS", XrmoptionSepArg, NULL }, \r
- { "-secondNPS", "secondNPS", XrmoptionSepArg, NULL }, \r
- { "-serverMoves", "serverMoves", XrmoptionSepArg, NULL }, \r
- { "-serverPause", "serverPause", XrmoptionSepArg, NULL }, \r
- { "-suppressLoadMoves", "suppressLoadMoves", XrmoptionSepArg, NULL }, \r
- { "-egtFormats", "egtFormats", XrmoptionSepArg, NULL }, \r
- { "-userName", "userName", XrmoptionSepArg, NULL }, \r
- { "-smpCores", "smpCores", XrmoptionSepArg, NULL }, \r
- { "-sameColorGames", "sameColorGames", XrmoptionSepArg, NULL }, \r
- { "-rewindIndex", "rewindIndex", XrmoptionSepArg, NULL }, \r
- { "-niceEngines", "niceEngines", XrmoptionSepArg, NULL }, \r
- { "-delayBeforeQuit", "delayBeforeQuit", XrmoptionSepArg, NULL }, \r
- { "-delayAfterQuit", "delayAfterQuit", XrmoptionSepArg, NULL }, \r
- { "-nameOfDebugFile", "nameOfDebugFile", XrmoptionSepArg, NULL }, \r
- { "-noGUI", "noGUI", XrmoptionNoArg, "True" }, \r
-};\r
-\r
-\r
-XtActionsRec boardActions[] = {\r
- { "DrawPosition", DrawPositionProc },\r
- { "HandleUserMove", HandleUserMove },\r
- { "AnimateUserMove", AnimateUserMove },\r
- { "FileNameAction", FileNameAction },\r
- { "AskQuestionProc", AskQuestionProc },\r
- { "AskQuestionReplyAction", AskQuestionReplyAction },\r
- { "PieceMenuPopup", PieceMenuPopup },\r
- { "WhiteClock", WhiteClock },\r
- { "BlackClock", BlackClock },\r
- { "Iconify", Iconify },\r
- { "ResetProc", ResetProc },\r
- { "LoadGameProc", LoadGameProc },\r
- { "LoadNextGameProc", LoadNextGameProc },\r
- { "LoadPrevGameProc", LoadPrevGameProc },\r
- { "LoadSelectedProc", LoadSelectedProc },\r
- { "ReloadGameProc", ReloadGameProc },\r
- { "LoadPositionProc", LoadPositionProc },\r
- { "LoadNextPositionProc", LoadNextPositionProc },\r
- { "LoadPrevPositionProc", LoadPrevPositionProc },\r
- { "ReloadPositionProc", ReloadPositionProc },\r
- { "CopyPositionProc", CopyPositionProc },\r
- { "PastePositionProc", PastePositionProc },\r
- { "CopyGameProc", CopyGameProc },\r
- { "PasteGameProc", PasteGameProc },\r
- { "SaveGameProc", SaveGameProc },\r
- { "SavePositionProc", SavePositionProc },\r
- { "MailMoveProc", MailMoveProc },\r
- { "ReloadCmailMsgProc", ReloadCmailMsgProc },\r
- { "QuitProc", QuitProc },\r
- { "MachineWhiteProc", MachineWhiteProc },\r
- { "MachineBlackProc", MachineBlackProc },\r
- { "AnalysisModeProc", AnalyzeModeProc },\r
- { "AnalyzeFileProc", AnalyzeFileProc },\r
- { "TwoMachinesProc", TwoMachinesProc },\r
- { "IcsClientProc", IcsClientProc },\r
- { "EditGameProc", EditGameProc },\r
- { "EditPositionProc", EditPositionProc },\r
- { "TrainingProc", EditPositionProc },\r
- { "EngineOutputProc", EngineOutputProc}, // [HGM] Winboard_x engine-output window\r
- { "ShowGameListProc", ShowGameListProc },\r
- { "ShowMoveListProc", HistoryShowProc},\r
- { "EditTagsProc", EditCommentProc },\r
- { "EditCommentProc", EditCommentProc },\r
- { "IcsAlarmProc", IcsAlarmProc },\r
- { "IcsInputBoxProc", IcsInputBoxProc },\r
- { "PauseProc", PauseProc },\r
- { "AcceptProc", AcceptProc },\r
- { "DeclineProc", DeclineProc },\r
- { "RematchProc", RematchProc },\r
- { "CallFlagProc", CallFlagProc },\r
- { "DrawProc", DrawProc },\r
- { "AdjournProc", AdjournProc },\r
- { "AbortProc", AbortProc },\r
- { "ResignProc", ResignProc },\r
- { "EnterKeyProc", EnterKeyProc },\r
- { "StopObservingProc", StopObservingProc },\r
- { "StopExaminingProc", StopExaminingProc },\r
- { "BackwardProc", BackwardProc },\r
- { "ForwardProc", ForwardProc },\r
- { "ToStartProc", ToStartProc },\r
- { "ToEndProc", ToEndProc },\r
- { "RevertProc", RevertProc },\r
- { "TruncateGameProc", TruncateGameProc },\r
- { "MoveNowProc", MoveNowProc },\r
- { "RetractMoveProc", RetractMoveProc },\r
- { "AlwaysQueenProc", AlwaysQueenProc },\r
- { "AnimateDraggingProc", AnimateDraggingProc },\r
- { "AnimateMovingProc", AnimateMovingProc },\r
- { "AutoflagProc", AutoflagProc },\r
- { "AutoflipProc", AutoflipProc },\r
- { "AutobsProc", AutobsProc },\r
- { "AutoraiseProc", AutoraiseProc },\r
- { "AutosaveProc", AutosaveProc },\r
- { "BlindfoldProc", BlindfoldProc },\r
- { "FlashMovesProc", FlashMovesProc },\r
- { "FlipViewProc", FlipViewProc },\r
- { "GetMoveListProc", GetMoveListProc },\r
-#if HIGHDRAG\r
- { "HighlightDraggingProc", HighlightDraggingProc },\r
-#endif\r
- { "HighlightLastMoveProc", HighlightLastMoveProc },\r
- { "IcsAlarmProc", IcsAlarmProc },\r
- { "MoveSoundProc", MoveSoundProc },\r
- { "OldSaveStyleProc", OldSaveStyleProc },\r
- { "PeriodicUpdatesProc", PeriodicUpdatesProc }, \r
- { "PonderNextMoveProc", PonderNextMoveProc },\r
- { "PopupExitMessageProc", PopupExitMessageProc }, \r
- { "PopupMoveErrorsProc", PopupMoveErrorsProc }, \r
- { "PremoveProc", PremoveProc },\r
- { "QuietPlayProc", QuietPlayProc },\r
- { "ShowCoordsProc", ShowCoordsProc },\r
- { "ShowThinkingProc", ShowThinkingProc },\r
- { "HideThinkingProc", HideThinkingProc },\r
- { "TestLegalityProc", TestLegalityProc },\r
- { "InfoProc", InfoProc },\r
- { "ManProc", ManProc },\r
- { "HintProc", HintProc },\r
- { "BookProc", BookProc },\r
- { "AboutGameProc", AboutGameProc },\r
- { "AboutProc", AboutProc },\r
- { "DebugProc", DebugProc },\r
- { "NothingProc", NothingProc },\r
- { "CommentPopDown", (XtActionProc) CommentPopDown },\r
- { "EditCommentPopDown", (XtActionProc) EditCommentPopDown },\r
- { "TagsPopDown", (XtActionProc) TagsPopDown },\r
- { "ErrorPopDown", (XtActionProc) ErrorPopDown },\r
- { "ICSInputBoxPopDown", (XtActionProc) ICSInputBoxPopDown },\r
- { "AnalysisPopDown", (XtActionProc) AnalysisPopDown },\r
- { "FileNamePopDown", (XtActionProc) FileNamePopDown },\r
- { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown },\r
- { "GameListPopDown", (XtActionProc) GameListPopDown },\r
- { "PromotionPopDown", (XtActionProc) PromotionPopDown },\r
- { "HistoryPopDown", (XtActionProc) HistoryPopDown },\r
- { "EngineOutputPopDown", (XtActionProc) EngineOutputPopDown },\r
- { "ShufflePopDown", (XtActionProc) ShufflePopDown },\r
- { "EnginePopDown", (XtActionProc) EnginePopDown },\r
- { "UciPopDown", (XtActionProc) UciPopDown },\r
- { "TimeControlPopDown", (XtActionProc) TimeControlPopDown },\r
- { "NewVariantPopDown", (XtActionProc) NewVariantPopDown },\r
- { "SettingsPopDown", (XtActionProc) SettingsPopDown },\r
-};\r
- \r
-char globalTranslations[] =\r
- ":<Key>R: ResignProc() \n \\r
- :<Key>r: ResetProc() \n \\r
- :<Key>g: LoadGameProc() \n \\r
- :<Key>N: LoadNextGameProc() \n \\r
- :<Key>P: LoadPrevGameProc() \n \\r
- :<Key>Q: QuitProc() \n \\r
- :<Key>F: ToEndProc() \n \\r
- :<Key>f: ForwardProc() \n \\r
- :<Key>B: ToStartProc() \n \\r
- :<Key>b: BackwardProc() \n \\r
- :<Key>p: PauseProc() \n \\r
- :<Key>d: DrawProc() \n \\r
- :<Key>t: CallFlagProc() \n \\r
- :<Key>i: Iconify() \n \\r
- :<Key>c: Iconify() \n \\r
- :<Key>v: FlipViewProc() \n \\r
- <KeyDown>Control_L: BackwardProc() \n \\r
- <KeyUp>Control_L: ForwardProc() \n \\r
- <KeyDown>Control_R: BackwardProc() \n \\r
- <KeyUp>Control_R: ForwardProc() \n \\r
- Shift<Key>1: AskQuestionProc(\"Direct command\",\\r
- \"Send to chess program:\",,1) \n \\r
- Shift<Key>2: AskQuestionProc(\"Direct command\",\\r
- \"Send to second chess program:\",,2) \n";\r
-\r
-char boardTranslations[] =\r
- "<Btn1Down>: HandleUserMove() \n \\r
- <Btn1Up>: HandleUserMove() \n \\r
- <Btn1Motion>: AnimateUserMove() \n \\r
- Shift<Btn2Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD)\\r
- PieceMenuPopup(menuB) \n \\r
- Any<Btn2Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD) \\r
- PieceMenuPopup(menuW) \n \\r
- Shift<Btn3Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD)\\r
- PieceMenuPopup(menuW) \n \\r
- Any<Btn3Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD) \\r
- PieceMenuPopup(menuB) \n";\r
- \r
-char whiteTranslations[] = "<BtnDown>: WhiteClock()\n";\r
-char blackTranslations[] = "<BtnDown>: BlackClock()\n";\r
- \r
-char ICSInputTranslations[] =\r
- "<Key>Return: EnterKeyProc() \n";\r
-\r
-String xboardResources[] = {\r
- "*fileName*value.translations: #override\\n <Key>Return: FileNameAction()",\r
- "*question*value.translations: #override\\n <Key>Return: AskQuestionReplyAction()",\r
- "*errorpopup*translations: #override\\n <Key>Return: ErrorPopDown()",\r
- NULL\r
- };\r
- \r
-\r
-/* Max possible square size */\r
-#define MAXSQSIZE 256\r
-\r
-static int xpm_avail[MAXSQSIZE];\r
-\r
-#ifdef HAVE_DIR_STRUCT\r
-\r
-/* Extract piece size from filename */\r
-static int\r
-xpm_getsize(name, len, ext)\r
- char *name;\r
- int len;\r
- char *ext;\r
-{\r
- char *p, *d;\r
- char buf[10];\r
- \r
- if (len < 4)\r
- return 0;\r
-\r
- if ((p=strchr(name, '.')) == NULL ||\r
- StrCaseCmp(p+1, ext) != 0)\r
- return 0;\r
- \r
- p = name + 3;\r
- d = buf;\r
-\r
- while (*p && isdigit(*p))\r
- *(d++) = *(p++);\r
-\r
- *d = 0;\r
- return atoi(buf);\r
-}\r
-\r
-/* Setup xpm_avail */\r
-static int\r
-xpm_getavail(dirname, ext)\r
- char *dirname;\r
- char *ext;\r
-{\r
- DIR *dir;\r
- struct dirent *ent;\r
- int i;\r
-\r
- for (i=0; i<MAXSQSIZE; ++i)\r
- xpm_avail[i] = 0;\r
-\r
- if (appData.debugMode)\r
- fprintf(stderr, "XPM dir:%s:ext:%s:\n", dirname, ext);\r
- \r
- dir = opendir(dirname);\r
- if (!dir)\r
- {\r
- fprintf(stderr, _("%s: Can't access XPM directory %s\n"), \r
- programName, dirname);\r
- exit(1);\r
- }\r
- \r
- while ((ent=readdir(dir)) != NULL) {\r
- i = xpm_getsize(ent->d_name, NAMLEN(ent), ext);\r
- if (i > 0 && i < MAXSQSIZE)\r
- xpm_avail[i] = 1;\r
- }\r
-\r
- closedir(dir);\r
-\r
- return 0;\r
-}\r
-\r
-void\r
-xpm_print_avail(fp, ext)\r
- FILE *fp;\r
- char *ext;\r
-{\r
- int i;\r
-\r
- fprintf(fp, _("Available `%s' sizes:\n"), ext);\r
- for (i=1; i<MAXSQSIZE; ++i) {\r
- if (xpm_avail[i])\r
- printf("%d\n", i);\r
- }\r
-}\r
-\r
-/* Return XPM piecesize closest to size */\r
-int\r
-xpm_closest_to(dirname, size, ext)\r
- char *dirname;\r
- int size;\r
- char *ext;\r
-{\r
- int i;\r
- int sm_diff = MAXSQSIZE;\r
- int sm_index = 0;\r
- int diff;\r
- \r
- xpm_getavail(dirname, ext);\r
-\r
- if (appData.debugMode)\r
- xpm_print_avail(stderr, ext);\r
- \r
- for (i=1; i<MAXSQSIZE; ++i) {\r
- if (xpm_avail[i]) {\r
- diff = size - i;\r
- diff = (diff<0) ? -diff : diff;\r
- if (diff < sm_diff) {\r
- sm_diff = diff;\r
- sm_index = i;\r
- }\r
- }\r
- }\r
-\r
- if (!sm_index) {\r
- fprintf(stderr, _("Error: No `%s' files!\n"), ext);\r
- exit(1);\r
- }\r
-\r
- return sm_index;\r
-}\r
-#else /* !HAVE_DIR_STRUCT */\r
-/* If we are on a system without a DIR struct, we can't\r
- read the directory, so we can't collect a list of\r
- filenames, etc., so we can't do any size-fitting. */\r
-int\r
-xpm_closest_to(dirname, size, ext)\r
- char *dirname;\r
- int size;\r
- char *ext;\r
-{\r
- fprintf(stderr, _("\\r
-Warning: No DIR structure found on this system --\n\\r
- Unable to autosize for XPM/XIM pieces.\n\\r
- Please report this error to frankm@hiwaay.net.\n\\r
- Include system type & operating system in message.\n"));\r
- return size;\r
-}\r
-#endif /* HAVE_DIR_STRUCT */\r
-\r
-static char *cnames[9] = { "black", "red", "green", "yellow", "blue",\r
- "magenta", "cyan", "white" };\r
-typedef struct {\r
- int attr, bg, fg;\r
-} TextColors;\r
-TextColors textColors[(int)NColorClasses];\r
-\r
-/* String is: "fg, bg, attr". Which is 0, 1, 2 */\r
-static int\r
-parse_color(str, which)\r
- char *str;\r
- int which;\r
-{\r
- char *p, buf[100], *d;\r
- int i;\r
- \r
- if (strlen(str) > 99) /* watch bounds on buf */\r
- return -1;\r
-\r
- p = str;\r
- d = buf;\r
- for (i=0; i<which; ++i) {\r
- p = strchr(p, ',');\r
- if (!p)\r
- return -1;\r
- ++p;\r
- }\r
-\r
- /* Could be looking at something like:\r
- black, , 1\r
- .. in which case we want to stop on a comma also */\r
- while (*p && *p != ',' && !isalpha(*p) && !isdigit(*p))\r
- ++p;\r
-\r
- if (*p == ',') {\r
- return -1; /* Use default for empty field */\r
- }\r
- \r
- if (which == 2 || isdigit(*p))\r
- return atoi(p);\r
- \r
- while (*p && isalpha(*p))\r
- *(d++) = *(p++);\r
-\r
- *d = 0;\r
-\r
- for (i=0; i<8; ++i) {\r
- if (!StrCaseCmp(buf, cnames[i]))\r
- return which? (i+40) : (i+30);\r
- }\r
- if (!StrCaseCmp(buf, "default")) return -1;\r
-\r
- fprintf(stderr, _("%s: unrecognized color %s\n"), programName, buf);\r
- return -2;\r
-}\r
-\r
-static int\r
-parse_cpair(cc, str)\r
- ColorClass cc;\r
- char *str;\r
-{\r
- if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {\r
- fprintf(stderr, _("%s: can't parse foreground color in `%s'\n"),\r
- programName, str);\r
- return -1;\r
- }\r
-\r
- /* bg and attr are optional */\r
- textColors[(int)cc].bg = parse_color(str, 1);\r
- if ((textColors[(int)cc].attr = parse_color(str, 2)) < 0) {\r
- textColors[(int)cc].attr = 0;\r
- }\r
- return 0;\r
-}\r
-\r
-\r
-/* Arrange to catch delete-window events */\r
-Atom wm_delete_window;\r
-void\r
-CatchDeleteWindow(Widget w, String procname)\r
-{\r
- char buf[MSG_SIZ];\r
- XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);\r
- sprintf(buf, "<Message>WM_PROTOCOLS: %s() \n", procname);\r
- XtAugmentTranslations(w, XtParseTranslationTable(buf));\r
-}\r
-\r
-void\r
-BoardToTop()\r
-{\r
- Arg args[16];\r
- XtSetArg(args[0], XtNiconic, False);\r
- XtSetValues(shellWidget, args, 1);\r
-\r
- XtPopup(shellWidget, XtGrabNone); /* Raise if lowered */\r
-}\r
-\r
-#ifdef IDSIZES\r
- // eventually, all layout determining code should go into a subroutine, but until then IDSIZE remains undefined\r
-#else\r
-#define BoardSize int\r
-void InitDrawingSizes(BoardSize boardSize, int flags)\r
-{ // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)\r
- Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;\r
- Arg args[16];\r
- XtGeometryResult gres;\r
- int i;\r
-\r
- if(!formWidget) return;\r
-\r
- /*\r
- * Enable shell resizing.\r
- */\r
- shellArgs[0].value = (XtArgVal) &w;\r
- shellArgs[1].value = (XtArgVal) &h;\r
- XtGetValues(shellWidget, shellArgs, 2);\r
-\r
- shellArgs[4].value = 2*w; shellArgs[2].value = 10;\r
- shellArgs[5].value = 2*h; shellArgs[3].value = 10;\r
- XtSetValues(shellWidget, &shellArgs[2], 4);\r
-\r
- XtSetArg(args[0], XtNdefaultDistance, &sep);\r
- XtGetValues(formWidget, args, 1);\r
-\r
- boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);\r
- boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);\r
- CreateGrid();\r
-\r
- XtSetArg(args[0], XtNwidth, boardWidth);\r
- XtSetArg(args[1], XtNheight, boardHeight);\r
- XtSetValues(boardWidget, args, 2);\r
-\r
- timerWidth = (boardWidth - sep) / 2;\r
- XtSetArg(args[0], XtNwidth, timerWidth);\r
- XtSetValues(whiteTimerWidget, args, 1);\r
- XtSetValues(blackTimerWidget, args, 1);\r
-\r
- XawFormDoLayout(formWidget, False);\r
-\r
- if (appData.titleInWindow) {\r
- i = 0;\r
- XtSetArg(args[i], XtNborderWidth, &bor); i++;\r
- XtSetArg(args[i], XtNheight, &h); i++;\r
- XtGetValues(titleWidget, args, i);\r
- if (smallLayout) {\r
- w = boardWidth - 2*bor;\r
- } else {\r
- XtSetArg(args[0], XtNwidth, &w);\r
- XtGetValues(menuBarWidget, args, 1);\r
- w = boardWidth - w - sep - 2*bor - 2; // WIDTH_FUDGE\r
- }\r
-\r
- gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);\r
- if (gres != XtGeometryYes && appData.debugMode) {\r
- fprintf(stderr,\r
- _("%s: titleWidget geometry error %d %d %d %d %d\n"),\r
- programName, gres, w, h, wr, hr);\r
- }\r
- }\r
-\r
- XawFormDoLayout(formWidget, True);\r
-\r
- /*\r
- * Inhibit shell resizing.\r
- */\r
- shellArgs[0].value = w = (XtArgVal) boardWidth + marginW;\r
- shellArgs[1].value = h = (XtArgVal) boardHeight + marginH;\r
- shellArgs[4].value = shellArgs[2].value = w;\r
- shellArgs[5].value = shellArgs[3].value = h;\r
- XtSetValues(shellWidget, &shellArgs[0], 6);\r
-}\r
-#endif\r
-\r
-int\r
-main(argc, argv)\r
- int argc;\r
- char **argv;\r
-{\r
- int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;\r
- XSetWindowAttributes window_attributes;\r
- Arg args[16];\r
- Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;\r
- XrmValue vFrom, vTo;\r
- XtGeometryResult gres;\r
- char *p;\r
- XrmDatabase xdb;\r
- int forceMono = False;\r
-#define INDIRECTION\r
-#ifdef INDIRECTION\r
- // [HGM] before anything else, expand any indirection files amongst options\r
- char *argvCopy[1000]; // 1000 seems enough\r
- char newArgs[10000]; // holds actual characters\r
- int k = 0;\r
-\r
- srandom(time(0)); // [HGM] book: make random truly random\r
-\r
- j = 0;\r
- for(i=0; i<argc; i++) {\r
- if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }\r
-//fprintf(stderr, "arg %s\n", argv[i]);\r
- if(argv[i][0] != '@') argvCopy[j++] = argv[i]; else {\r
- char c;\r
- FILE *f = fopen(argv[i]+1, "rb");\r
- if(f == NULL) { fprintf(stderr, _("ignore %s\n"), argv[i]); continue; } // do not expand non-existing\r
- argvCopy[j++] = newArgs + k; // get ready for first argument from file\r
- while((c = fgetc(f)) != EOF) { // each line of file inserts 1 argument in the list\r
- if(c == '\n') {\r
- if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }\r
- newArgs[k++] = 0; // terminate current arg\r
- if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }\r
- argvCopy[j++] = newArgs + k; // get ready for next\r
- } else {\r
- if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }\r
- newArgs[k++] = c;\r
- }\r
- }\r
- newArgs[k] = 0;\r
- j--;\r
- fclose(f);\r
- }\r
- }\r
- argvCopy[j] = NULL;\r
- argv = argvCopy;\r
- argc = j;\r
-#if 0\r
- if(appData.debugMode,1) { // OK, appData is not initialized here yet...\r
- for(i=0; i<argc; i++) fprintf(stderr, "argv[%2d] = '%s'\n", i, argv[i]);\r
- }\r
-#endif\r
-#endif\r
-\r
-\r
- setbuf(stdout, NULL);\r
- setbuf(stderr, NULL);\r
- debugFP = stderr;\r
- \r
- programName = strrchr(argv[0], '/');\r
- if (programName == NULL)\r
- programName = argv[0];\r
- else\r
- programName++;\r
-\r
-#ifdef ENABLE_NLS\r
- XtSetLanguageProc(NULL, NULL, NULL);\r
- bindtextdomain(PRODUCT, LOCALEDIR);\r
- bind_textdomain_codeset(PRODUCT, "UTF-8");\r
- textdomain(PRODUCT);\r
-#endif\r
-\r
- shellWidget =\r
- XtAppInitialize(&appContext, "XBoard", shellOptions,\r
- XtNumber(shellOptions),\r
- &argc, argv, xboardResources, NULL, 0);\r
- if (argc > 1) {\r
- fprintf(stderr, _("%s: unrecognized argument %s\n"),\r
- programName, argv[1]);\r
- exit(2);\r
- }\r
- \r
- if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {\r
- chessDir = ".";\r
- } else {\r
- if (chdir(chessDir) != 0) {\r
- fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);\r
- perror(chessDir);\r
- exit(1);\r
- }\r
- }\r
- \r
- p = getenv("HOME");\r
- if (p == NULL) p = "/tmp";\r
- i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;\r
- gameCopyFilename = (char*) malloc(i);\r
- gamePasteFilename = (char*) malloc(i);\r
- sprintf(gameCopyFilename, "%s/.xboard%05uc.pgn", p, getpid());\r
- sprintf(gamePasteFilename, "%s/.xboard%05up.pgn", p, getpid());\r
-\r
- XtGetApplicationResources(shellWidget, (XtPointer) &appData,\r
- clientResources, XtNumber(clientResources),\r
- NULL, 0);\r
-\r
- if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) {\r
- /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */\r
- if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL) {\r
- printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile);\r
- exit(errno);\r
- }\r
- setbuf(debugFP, NULL);\r
- }\r
- \r
- /* [HGM,HR] make sure board size is acceptable */\r
- if(appData.NrFiles > BOARD_SIZE ||\r
- appData.NrRanks > BOARD_SIZE )\r
- DisplayFatalError(_("Recompile with BOARD_SIZE > 12, to support this size"), 0, 2);\r
-\r
-#if !HIGHDRAG\r
- /* This feature does not work; animation needs a rewrite */\r
- appData.highlightDragging = FALSE;\r
-#endif\r
- InitBackEnd1();\r
-\r
- xDisplay = XtDisplay(shellWidget);\r
- xScreen = DefaultScreen(xDisplay);\r
- wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);\r
-\r
- gameInfo.variant = StringToVariant(appData.variant);\r
- InitPosition(FALSE);\r
-#if 0\r
- /*\r
- * Determine boardSize\r
- */\r
- gameInfo.boardWidth = gameInfo.boardHeight = 8; // [HGM] boardsize: make sure we start as 8x8\r
-\r
-//#ifndef IDSIZE\r
- // [HGM] as long as we have not created the possibility to change size while running, start with requested size\r
- gameInfo.boardWidth = appData.NrFiles > 0 ? appData.NrFiles : 8; \r
- gameInfo.boardHeight = appData.NrRanks > 0 ? appData.NrRanks : 8;\r
- gameInfo.holdingsWidth = appData.holdingsSize > 0 ? 2 : 0;\r
-#endif\r
-\r
-\r
-#ifdef IDSIZE\r
- InitDrawingSizes(-1, 0); // [HGM] initsize: make this into a subroutine\r
-#else\r
- if (isdigit(appData.boardSize[0])) {\r
- i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,\r
- &lineGap, &clockFontPxlSize, &coordFontPxlSize,\r
- &fontPxlSize, &smallLayout, &tinyLayout);\r
- if (i == 0) {\r
- fprintf(stderr, _("%s: bad boardSize syntax %s\n"),\r
- programName, appData.boardSize);\r
- exit(2);\r
- }\r
- if (i < 7) {\r
- /* Find some defaults; use the nearest known size */\r
- SizeDefaults *szd, *nearest;\r
- int distance = 99999;\r
- nearest = szd = sizeDefaults;\r
- while (szd->name != NULL) {\r
- if (abs(szd->squareSize - squareSize) < distance) {\r
- nearest = szd;\r
- distance = abs(szd->squareSize - squareSize);\r
- if (distance == 0) break;\r
- }\r
- szd++;\r
- }\r
- if (i < 2) lineGap = nearest->lineGap;\r
- if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;\r
- if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;\r
- if (i < 5) fontPxlSize = nearest->fontPxlSize;\r
- if (i < 6) smallLayout = nearest->smallLayout;\r
- if (i < 7) tinyLayout = nearest->tinyLayout;\r
- }\r
- } else {\r
- SizeDefaults *szd = sizeDefaults;\r
- if (*appData.boardSize == NULLCHAR) {\r
- while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize ||\r
- DisplayHeight(xDisplay, xScreen) < szd->minScreenSize) {\r
- szd++;\r
- }\r
- if (szd->name == NULL) szd--;\r
- } else {\r
- while (szd->name != NULL &&\r
- StrCaseCmp(szd->name, appData.boardSize) != 0) szd++;\r
- if (szd->name == NULL) {\r
- fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),\r
- programName, appData.boardSize);\r
- exit(2);\r
- }\r
- }\r
- squareSize = szd->squareSize;\r
- lineGap = szd->lineGap;\r
- clockFontPxlSize = szd->clockFontPxlSize;\r
- coordFontPxlSize = szd->coordFontPxlSize;\r
- fontPxlSize = szd->fontPxlSize;\r
- smallLayout = szd->smallLayout;\r
- tinyLayout = szd->tinyLayout;\r
- }\r
-\r
- /* Now, using squareSize as a hint, find a good XPM/XIM set size */\r
- if (strlen(appData.pixmapDirectory) > 0) {\r
- p = ExpandPathName(appData.pixmapDirectory);\r
- if (!p) {\r
- fprintf(stderr, _("Error expanding path name \"%s\"\n"),\r
- appData.pixmapDirectory);\r
- exit(1);\r
- }\r
- if (appData.debugMode) {\r
- fprintf(stderr, _("\\r
-XBoard square size (hint): %d\n\\r
-%s fulldir:%s:\n"), squareSize, IMAGE_EXT, p);\r
- }\r
- squareSize = xpm_closest_to(p, squareSize, IMAGE_EXT);\r
- if (appData.debugMode) {\r
- fprintf(stderr, _("Closest %s size: %d\n"), IMAGE_EXT, squareSize);\r
- }\r
- }\r
- \r
- /* [HR] height treated separately (hacked) */\r
- boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);\r
- boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);\r
- if (appData.showJail == 1) {\r
- /* Jail on top and bottom */\r
- XtSetArg(boardArgs[1], XtNwidth, boardWidth);\r
- XtSetArg(boardArgs[2], XtNheight,\r
- boardHeight + 2*(lineGap + squareSize));\r
- } else if (appData.showJail == 2) {\r
- /* Jail on sides */\r
- XtSetArg(boardArgs[1], XtNwidth,\r
- boardWidth + 2*(lineGap + squareSize));\r
- XtSetArg(boardArgs[2], XtNheight, boardHeight);\r
- } else {\r
- /* No jail */\r
- XtSetArg(boardArgs[1], XtNwidth, boardWidth);\r
- XtSetArg(boardArgs[2], XtNheight, boardHeight);\r
- }\r
-\r
- /*\r
- * Determine what fonts to use.\r
- */\r
- appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);\r
- clockFontID = XLoadFont(xDisplay, appData.clockFont);\r
- clockFontStruct = XQueryFont(xDisplay, clockFontID);\r
- appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);\r
- coordFontID = XLoadFont(xDisplay, appData.coordFont);\r
- coordFontStruct = XQueryFont(xDisplay, coordFontID);\r
- appData.font = FindFont(appData.font, fontPxlSize);\r
- countFontID = XLoadFont(xDisplay, appData.coordFont); // [HGM] holdings\r
- countFontStruct = XQueryFont(xDisplay, countFontID);\r
-// appData.font = FindFont(appData.font, fontPxlSize);\r
-\r
- xdb = XtDatabase(xDisplay);\r
- XrmPutStringResource(&xdb, "*font", appData.font);\r
-\r
- /*\r
- * Detect if there are not enough colors available and adapt.\r
- */\r
- if (DefaultDepth(xDisplay, xScreen) <= 2) {\r
- appData.monoMode = True;\r
- }\r
-\r
- if (!appData.monoMode) {\r
- vFrom.addr = (caddr_t) appData.lightSquareColor;\r
- vFrom.size = strlen(appData.lightSquareColor);\r
- XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);\r
- if (vTo.addr == NULL) {\r
- appData.monoMode = True;\r
- forceMono = True;\r
- } else {\r
- lightSquareColor = *(Pixel *) vTo.addr;\r
- }\r
- }\r
- if (!appData.monoMode) {\r
- vFrom.addr = (caddr_t) appData.darkSquareColor;\r
- vFrom.size = strlen(appData.darkSquareColor);\r
- XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);\r
- if (vTo.addr == NULL) {\r
- appData.monoMode = True;\r
- forceMono = True;\r
- } else {\r
- darkSquareColor = *(Pixel *) vTo.addr;\r
- }\r
- }\r
- if (!appData.monoMode) {\r
- vFrom.addr = (caddr_t) appData.whitePieceColor;\r
- vFrom.size = strlen(appData.whitePieceColor);\r
- XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);\r
- if (vTo.addr == NULL) {\r
- appData.monoMode = True;\r
- forceMono = True;\r
- } else {\r
- whitePieceColor = *(Pixel *) vTo.addr;\r
- }\r
- }\r
- if (!appData.monoMode) {\r
- vFrom.addr = (caddr_t) appData.blackPieceColor;\r
- vFrom.size = strlen(appData.blackPieceColor);\r
- XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);\r
- if (vTo.addr == NULL) {\r
- appData.monoMode = True;\r
- forceMono = True;\r
- } else {\r
- blackPieceColor = *(Pixel *) vTo.addr;\r
- }\r
- }\r
-\r
- if (!appData.monoMode) {\r
- vFrom.addr = (caddr_t) appData.highlightSquareColor;\r
- vFrom.size = strlen(appData.highlightSquareColor);\r
- XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);\r
- if (vTo.addr == NULL) {\r
- appData.monoMode = True;\r
- forceMono = True;\r
- } else {\r
- highlightSquareColor = *(Pixel *) vTo.addr;\r
- }\r
- }\r
-\r
- if (!appData.monoMode) {\r
- vFrom.addr = (caddr_t) appData.premoveHighlightColor;\r
- vFrom.size = strlen(appData.premoveHighlightColor);\r
- XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);\r
- if (vTo.addr == NULL) {\r
- appData.monoMode = True;\r
- forceMono = True;\r
- } else {\r
- premoveHighlightColor = *(Pixel *) vTo.addr;\r
- }\r
- }\r
-\r
- if (forceMono) {\r
- fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),\r
- programName);\r
- }\r
-\r
- if (appData.monoMode && appData.debugMode) {\r
- fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),\r
- (unsigned long) XWhitePixel(xDisplay, xScreen),\r
- (unsigned long) XBlackPixel(xDisplay, xScreen));\r
- }\r
- \r
- if (parse_cpair(ColorShout, appData.colorShout) < 0 ||\r
- parse_cpair(ColorSShout, appData.colorSShout) < 0 ||\r
- parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||\r
- parse_cpair(ColorChannel, appData.colorChannel) < 0 ||\r
- parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||\r
- parse_cpair(ColorTell, appData.colorTell) < 0 ||\r
- parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||\r
- parse_cpair(ColorRequest, appData.colorRequest) < 0 ||\r
- parse_cpair(ColorSeek, appData.colorSeek) < 0 ||\r
- parse_cpair(ColorNormal, appData.colorNormal) < 0)\r
- {\r
- if (appData.colorize) {\r
- fprintf(stderr,\r
- _("%s: can't parse color names; disabling colorization\n"),\r
- programName);\r
- }\r
- appData.colorize = FALSE;\r
- }\r
- textColors[ColorNone].fg = textColors[ColorNone].bg = -1;\r
- textColors[ColorNone].attr = 0;\r
- \r
- XtAppAddActions(appContext, boardActions, XtNumber(boardActions));\r
- \r
- /*\r
- * widget hierarchy\r
- */\r
- if (tinyLayout) {\r
- layoutName = "tinyLayout";\r
- } else if (smallLayout) {\r
- layoutName = "smallLayout";\r
- } else {\r
- layoutName = "normalLayout";\r
- }\r
- /* Outer layoutWidget is there only to provide a name for use in\r
- resources that depend on the layout style */\r
- layoutWidget =\r
- XtCreateManagedWidget(layoutName, formWidgetClass, shellWidget,\r
- layoutArgs, XtNumber(layoutArgs));\r
- formWidget =\r
- XtCreateManagedWidget("form", formWidgetClass, layoutWidget,\r
- formArgs, XtNumber(formArgs));\r
- XtSetArg(args[0], XtNdefaultDistance, &sep);\r
- XtGetValues(formWidget, args, 1);\r
-\r
- j = 0;\r
- widgetList[j++] = menuBarWidget = CreateMenuBar(menuBar);\r
- XtSetArg(args[0], XtNtop, XtChainTop);\r
- XtSetArg(args[1], XtNbottom, XtChainTop);\r
- XtSetValues(menuBarWidget, args, 2);\r
-\r
- widgetList[j++] = whiteTimerWidget =\r
- XtCreateWidget("whiteTime", labelWidgetClass,\r
- formWidget, timerArgs, XtNumber(timerArgs));\r
- XtSetArg(args[0], XtNfont, clockFontStruct);\r
- XtSetArg(args[1], XtNtop, XtChainTop);\r
- XtSetArg(args[2], XtNbottom, XtChainTop);\r
- XtSetValues(whiteTimerWidget, args, 3);\r
- \r
- widgetList[j++] = blackTimerWidget =\r
- XtCreateWidget("blackTime", labelWidgetClass,\r
- formWidget, timerArgs, XtNumber(timerArgs));\r
- XtSetArg(args[0], XtNfont, clockFontStruct);\r
- XtSetArg(args[1], XtNtop, XtChainTop);\r
- XtSetArg(args[2], XtNbottom, XtChainTop);\r
- XtSetValues(blackTimerWidget, args, 3);\r
- \r
- if (appData.titleInWindow) {\r
- widgetList[j++] = titleWidget = \r
- XtCreateWidget("title", labelWidgetClass, formWidget,\r
- titleArgs, XtNumber(titleArgs));\r
- XtSetArg(args[0], XtNtop, XtChainTop);\r
- XtSetArg(args[1], XtNbottom, XtChainTop);\r
- XtSetValues(titleWidget, args, 2);\r
- }\r
-\r
- if (appData.showButtonBar) {\r
- widgetList[j++] = buttonBarWidget = CreateButtonBar(buttonBar);\r
- XtSetArg(args[0], XtNleft, XtChainRight); // [HGM] glue to right window edge\r
- XtSetArg(args[1], XtNright, XtChainRight); // for good run-time sizing\r
- XtSetArg(args[2], XtNtop, XtChainTop);\r
- XtSetArg(args[3], XtNbottom, XtChainTop);\r
- XtSetValues(buttonBarWidget, args, 4);\r
- }\r
-\r
- widgetList[j++] = messageWidget =\r
- XtCreateWidget("message", labelWidgetClass, formWidget,\r
- messageArgs, XtNumber(messageArgs));\r
- XtSetArg(args[0], XtNtop, XtChainTop);\r
- XtSetArg(args[1], XtNbottom, XtChainTop);\r
- XtSetValues(messageWidget, args, 2);\r
-\r
- widgetList[j++] = boardWidget =\r
- XtCreateWidget("board", widgetClass, formWidget, boardArgs,\r
- XtNumber(boardArgs));\r
-\r
- XtManageChildren(widgetList, j);\r
- \r
- timerWidth = (boardWidth - sep) / 2;\r
- XtSetArg(args[0], XtNwidth, timerWidth);\r
- XtSetValues(whiteTimerWidget, args, 1);\r
- XtSetValues(blackTimerWidget, args, 1);\r
- \r
- XtSetArg(args[0], XtNbackground, &timerBackgroundPixel);\r
- XtSetArg(args[1], XtNforeground, &timerForegroundPixel);\r
- XtGetValues(whiteTimerWidget, args, 2);\r
- \r
- if (appData.showButtonBar) {\r
- XtSetArg(args[0], XtNbackground, &buttonBackgroundPixel);\r
- XtSetArg(args[1], XtNforeground, &buttonForegroundPixel);\r
- XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);\r
- }\r
-\r
- /*\r
- * formWidget uses these constraints but they are stored\r
- * in the children.\r
- */\r
- i = 0;\r
- XtSetArg(args[i], XtNfromHoriz, 0); i++;\r
- XtSetValues(menuBarWidget, args, i);\r
- if (appData.titleInWindow) {\r
- if (smallLayout) {\r
- i = 0;\r
- XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;\r
- XtSetValues(whiteTimerWidget, args, i);\r
- i = 0;\r
- XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;\r
- XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;\r
- XtSetValues(blackTimerWidget, args, i);\r
- i = 0;\r
- XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;\r
- XtSetArg(args[i], XtNjustify, XtJustifyLeft); i++;\r
- XtSetValues(titleWidget, args, i);\r
- i = 0;\r
- XtSetArg(args[i], XtNfromVert, titleWidget); i++;\r
- XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;\r
- XtSetValues(messageWidget, args, i);\r
- if (appData.showButtonBar) {\r
- i = 0;\r
- XtSetArg(args[i], XtNfromVert, titleWidget); i++;\r
- XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;\r
- XtSetValues(buttonBarWidget, args, i);\r
- }\r
- } else {\r
- i = 0;\r
- XtSetArg(args[i], XtNfromVert, titleWidget); i++;\r
- XtSetValues(whiteTimerWidget, args, i);\r
- i = 0;\r
- XtSetArg(args[i], XtNfromVert, titleWidget); i++;\r
- XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;\r
- XtSetValues(blackTimerWidget, args, i);\r
- i = 0;\r
- XtSetArg(args[i], XtNfromHoriz, menuBarWidget); i++;\r
- XtSetValues(titleWidget, args, i);\r
- i = 0;\r
- XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;\r
- XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;\r
- XtSetValues(messageWidget, args, i);\r
- if (appData.showButtonBar) {\r
- i = 0;\r
- XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;\r
- XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;\r
- XtSetValues(buttonBarWidget, args, i);\r
- }\r
- }\r
- } else {\r
- i = 0;\r
- XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;\r
- XtSetValues(whiteTimerWidget, args, i);\r
- i = 0;\r
- XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;\r
- XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;\r
- XtSetValues(blackTimerWidget, args, i);\r
- i = 0;\r
- XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;\r
- XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;\r
- XtSetValues(messageWidget, args, i);\r
- if (appData.showButtonBar) {\r
- i = 0;\r
- XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;\r
- XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;\r
- XtSetValues(buttonBarWidget, args, i);\r
- }\r
- }\r
- i = 0;\r
- XtSetArg(args[0], XtNfromVert, messageWidget);\r
- XtSetArg(args[1], XtNtop, XtChainTop);\r
- XtSetArg(args[2], XtNbottom, XtChainBottom);\r
- XtSetArg(args[3], XtNleft, XtChainLeft);\r
- XtSetArg(args[4], XtNright, XtChainRight);\r
- XtSetValues(boardWidget, args, 5);\r
-\r
- XtRealizeWidget(shellWidget);\r
-\r
- /*\r
- * Correct the width of the message and title widgets.\r
- * It is not known why some systems need the extra fudge term.\r
- * The value "2" is probably larger than needed.\r
- */\r
- XawFormDoLayout(formWidget, False);\r
-\r
-#define WIDTH_FUDGE 2\r
- i = 0;\r
- XtSetArg(args[i], XtNborderWidth, &bor); i++;\r
- XtSetArg(args[i], XtNheight, &h); i++;\r
- XtGetValues(messageWidget, args, i);\r
- if (appData.showButtonBar) {\r
- i = 0;\r
- XtSetArg(args[i], XtNwidth, &w); i++;\r
- XtGetValues(buttonBarWidget, args, i);\r
- w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;\r
- } else {\r
- w = boardWidth - 2*bor + 1; /*!! +1 compensates for kludge below */\r
- }\r
-\r
- gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);\r
- if (gres != XtGeometryYes && appData.debugMode) {\r
- fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),\r
- programName, gres, w, h, wr, hr);\r
- }\r
- \r
- /* !! Horrible hack to work around bug in XFree86 4.0.1 (X11R6.4.3) */\r
- /* The size used for the child widget in layout lags one resize behind\r
- its true size, so we resize a second time, 1 pixel smaller. Yeech! */\r
- w--;\r
- gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);\r
- if (gres != XtGeometryYes && appData.debugMode) {\r
- fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),\r
- programName, gres, w, h, wr, hr);\r
- }\r
- /* !! end hack */\r
- XtSetArg(args[0], XtNleft, XtChainLeft); // [HGM] glue ends for good run-time sizing\r
- XtSetArg(args[1], XtNright, XtChainRight);\r
- XtSetValues(messageWidget, args, 2);\r
-\r
- if (appData.titleInWindow) {\r
- i = 0;\r
- XtSetArg(args[i], XtNborderWidth, &bor); i++;\r
- XtSetArg(args[i], XtNheight, &h); i++;\r
- XtGetValues(titleWidget, args, i);\r
- if (smallLayout) {\r
- w = boardWidth - 2*bor;\r
- } else {\r
- XtSetArg(args[0], XtNwidth, &w);\r
- XtGetValues(menuBarWidget, args, 1);\r
- w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;\r
- }\r
-\r
- gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);\r
- if (gres != XtGeometryYes && appData.debugMode) {\r
- fprintf(stderr,\r
- _("%s: titleWidget geometry error %d %d %d %d %d\n"),\r
- programName, gres, w, h, wr, hr);\r
- }\r
- }\r
- XawFormDoLayout(formWidget, True);\r
-\r
- xBoardWindow = XtWindow(boardWidget);\r
-\r
- // [HGM] it seems the layout code ends here, but perhaps the color stuff is size independent and would\r
- // not need to go into InitDrawingSizes().\r
-#endif \r
-\r
- /* \r
- * Create X checkmark bitmap and initialize option menu checks.\r
- */\r
- ReadBitmap(&xMarkPixmap, "checkmark.bm",\r
- checkmark_bits, checkmark_width, checkmark_height);\r
- XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);\r
- if (appData.alwaysPromoteToQueen) {\r
- XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),\r
- args, 1);\r
- }\r
- if (appData.animateDragging) {\r
- XtSetValues(XtNameToWidget(menuBarWidget,\r
- "menuOptions.Animate Dragging"),\r
- args, 1);\r
- }\r
- if (appData.animate) {\r
- XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),\r
- args, 1);\r
- }\r
- if (appData.autoComment) {\r
- XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),\r
- args, 1);\r
- }\r
- if (appData.autoCallFlag) {\r
- XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),\r
- args, 1);\r
- }\r
- if (appData.autoFlipView) {\r
- XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Auto Flip View"),\r
- args, 1);\r
- }\r
- if (appData.autoObserve) {\r
- XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),\r
- args, 1);\r
- }\r
- if (appData.autoRaiseBoard) {\r
- XtSetValues(XtNameToWidget(menuBarWidget,\r
- "menuOptions.Auto Raise Board"), args, 1);\r
- }\r
- if (appData.autoSaveGames) {\r
- XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),\r
- args, 1);\r
- }\r
- if (appData.saveGameFile[0] != NULLCHAR) {\r
- /* Can't turn this off from menu */\r
- XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),\r
- args, 1);\r
- XtSetSensitive(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),\r
- False);\r
-\r
- }\r
- if (appData.blindfold) {\r
- XtSetValues(XtNameToWidget(menuBarWidget,\r
- "menuOptions.Blindfold"), args, 1);\r
- }\r
- if (appData.flashCount > 0) {\r
- XtSetValues(XtNameToWidget(menuBarWidget,\r
- "menuOptions.Flash Moves"),\r
- args, 1);\r
- }\r
- if (appData.getMoveList) {\r
- XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),\r
- args, 1);\r
- }\r
-#if HIGHDRAG\r
- if (appData.highlightDragging) {\r
- XtSetValues(XtNameToWidget(menuBarWidget,\r
- "menuOptions.Highlight Dragging"),\r
- args, 1);\r
- }\r
-#endif\r
- if (appData.highlightLastMove) {\r
- XtSetValues(XtNameToWidget(menuBarWidget,\r
- "menuOptions.Highlight Last Move"),\r
- args, 1);\r
- }\r
- if (appData.icsAlarm) {\r
- XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.ICS Alarm"),\r
- args, 1);\r
- }\r
- if (appData.ringBellAfterMoves) {\r
- XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),\r
- args, 1);\r
- }\r
- if (appData.oldSaveStyle) {\r
- XtSetValues(XtNameToWidget(menuBarWidget,\r
- "menuOptions.Old Save Style"), args, 1);\r
- }\r
- if (appData.periodicUpdates) {\r
- XtSetValues(XtNameToWidget(menuBarWidget,\r
- "menuOptions.Periodic Updates"), args, 1);\r
- } \r
- if (appData.ponderNextMove) {\r
- XtSetValues(XtNameToWidget(menuBarWidget,\r
- "menuOptions.Ponder Next Move"), args, 1);\r
- } \r
- if (appData.popupExitMessage) {\r
- XtSetValues(XtNameToWidget(menuBarWidget,\r
- "menuOptions.Popup Exit Message"), args, 1);\r
- } \r
- if (appData.popupMoveErrors) {\r
- XtSetValues(XtNameToWidget(menuBarWidget,\r
- "menuOptions.Popup Move Errors"), args, 1);\r
- } \r
- if (appData.premove) {\r
- XtSetValues(XtNameToWidget(menuBarWidget,\r
- "menuOptions.Premove"), args, 1);\r
- }\r
- if (appData.quietPlay) {\r
- XtSetValues(XtNameToWidget(menuBarWidget,\r
- "menuOptions.Quiet Play"), args, 1);\r
- }\r
- if (appData.showCoords) {\r
- XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),\r
- args, 1);\r
- }\r
- if (appData.hideThinkingFromHuman) {\r
- XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),\r
- args, 1);\r
- }\r
- if (appData.testLegality) {\r
- XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Test Legality"),\r
- args, 1);\r
- }\r
-\r
- /*\r
- * Create an icon.\r
- */\r
- ReadBitmap(&wIconPixmap, "icon_white.bm",\r
- icon_white_bits, icon_white_width, icon_white_height);\r
- ReadBitmap(&bIconPixmap, "icon_black.bm",\r
- icon_black_bits, icon_black_width, icon_black_height);\r
- iconPixmap = wIconPixmap;\r
- i = 0;\r
- XtSetArg(args[i], XtNiconPixmap, iconPixmap); i++;\r
- XtSetValues(shellWidget, args, i);\r
- \r
- /*\r
- * Create a cursor for the board widget.\r
- */\r
- window_attributes.cursor = XCreateFontCursor(xDisplay, XC_hand2);\r
- XChangeWindowAttributes(xDisplay, xBoardWindow,\r
- CWCursor, &window_attributes);\r
- \r
- /*\r
- * Inhibit shell resizing.\r
- */\r
- shellArgs[0].value = (XtArgVal) &w;\r
- shellArgs[1].value = (XtArgVal) &h;\r
- XtGetValues(shellWidget, shellArgs, 2);\r
- shellArgs[4].value = shellArgs[2].value = w;\r
- shellArgs[5].value = shellArgs[3].value = h;\r
- XtSetValues(shellWidget, &shellArgs[2], 4);\r
- marginW = w - boardWidth; // [HGM] needed to set new shellWidget size when we resize board\r
- marginH = h - boardHeight;\r
-\r
- CatchDeleteWindow(shellWidget, "QuitProc");\r
-\r
- CreateGCs();\r
- CreateGrid();\r
-#if HAVE_LIBXPM\r
- if (appData.bitmapDirectory[0] != NULLCHAR) {\r
- CreatePieces();\r
- } else {\r
- CreateXPMPieces();\r
- }\r
-#else\r
- CreateXIMPieces();\r
- /* Create regular pieces */\r
- if (!useImages) CreatePieces();\r
-#endif \r
-\r
- CreatePieceMenus();\r
-\r
- if (appData.animate || appData.animateDragging)\r
- CreateAnimVars();\r
- \r
- XtAugmentTranslations(formWidget,\r
- XtParseTranslationTable(globalTranslations));\r
- XtAugmentTranslations(boardWidget,\r
- XtParseTranslationTable(boardTranslations));\r
- XtAugmentTranslations(whiteTimerWidget,\r
- XtParseTranslationTable(whiteTranslations));\r
- XtAugmentTranslations(blackTimerWidget,\r
- XtParseTranslationTable(blackTranslations));\r
-\r
- /* Why is the following needed on some versions of X instead\r
- * of a translation? */\r
- XtAddEventHandler(boardWidget, ExposureMask, False,\r
- (XtEventHandler) EventProc, NULL);\r
- /* end why */\r
-\r
- InitBackEnd2();\r
- \r
- if (errorExitStatus == -1) {\r
- if (appData.icsActive) {\r
- /* We now wait until we see "login:" from the ICS before\r
- sending the logon script (problems with timestamp otherwise) */\r
- /*ICSInitScript();*/\r
- if (appData.icsInputBox) ICSInputBoxPopUp();\r
- }\r
-\r
- signal(SIGINT, IntSigHandler);\r
- signal(SIGTERM, IntSigHandler);\r
- if (*appData.cmailGameName != NULLCHAR) {\r
- signal(SIGUSR1, CmailSigHandler);\r
- }\r
- }\r
- InitPosition(TRUE);\r
-\r
- XtAppMainLoop(appContext);\r
- if (appData.debugMode) fclose(debugFP); // [DM] debug\r
- return 0;\r
-}\r
-\r
-void\r
-ShutDownFrontEnd()\r
-{\r
- if (appData.icsActive && oldICSInteractionTitle != NULL) {\r
- DisplayIcsInteractionTitle(oldICSInteractionTitle);\r
- }\r
- unlink(gameCopyFilename);\r
- unlink(gamePasteFilename);\r
-}\r
-\r
-RETSIGTYPE\r
-IntSigHandler(sig)\r
- int sig;\r
-{\r
- ExitEvent(sig);\r
-}\r
-\r
-RETSIGTYPE\r
-CmailSigHandler(sig)\r
- int sig;\r
-{\r
- int dummy = 0;\r
- int error;\r
-\r
- signal(SIGUSR1, SIG_IGN); /* suspend handler */\r
-\r
- /* Activate call-back function CmailSigHandlerCallBack() */\r
- OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);\r
-\r
- signal(SIGUSR1, CmailSigHandler); /* re-activate handler */\r
-}\r
-\r
-void\r
-CmailSigHandlerCallBack(isr, closure, message, count, error)\r
- InputSourceRef isr;\r
- VOIDSTAR closure;\r
- char *message;\r
- int count;\r
- int error;\r
-{\r
- BoardToTop();\r
- ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */\r
-}\r
-/**** end signal code ****/\r
-\r
-\r
-void\r
-ICSInitScript()\r
-{\r
- FILE *f;\r
- char buf[MSG_SIZ];\r
- char *p;\r
-\r
- f = fopen(appData.icsLogon, "r");\r
- if (f == NULL) {\r
- p = getenv("HOME");\r
- if (p != NULL) {\r
- strcpy(buf, p);\r
- strcat(buf, "/");\r
- strcat(buf, appData.icsLogon);\r
- f = fopen(buf, "r");\r
- }\r
- }\r
- if (f != NULL)\r
- ProcessICSInitScript(f);\r
-}\r
-\r
-void\r
-ResetFrontEnd()\r
-{\r
- CommentPopDown();\r
- EditCommentPopDown();\r
- TagsPopDown();\r
- return;\r
-}\r
-\r
-typedef struct {\r
- char *name;\r
- Boolean value;\r
-} Enables;\r
-\r
-void\r
-SetMenuEnables(enab)\r
- Enables *enab;\r
-{\r
- Widget w;\r
- if (!menuBarWidget) return;\r
- while (enab->name != NULL) {\r
- w = XtNameToWidget(menuBarWidget, enab->name);\r
- if (w == NULL) {\r
- DisplayError(enab->name, 0);\r
- } else {\r
- XtSetSensitive(w, enab->value);\r
- }\r
- enab++;\r
- }\r
-}\r
-\r
-Enables icsEnables[] = {\r
- { "menuFile.Mail Move", False },\r
- { "menuFile.Reload CMail Message", False },\r
- { "menuMode.Machine Black", False },\r
- { "menuMode.Machine White", False },\r
- { "menuMode.Analysis Mode", False },\r
- { "menuMode.Analyze File", False },\r
- { "menuMode.Two Machines", False },\r
-#ifndef ZIPPY\r
- { "menuHelp.Hint", False },\r
- { "menuHelp.Book", False },\r
- { "menuStep.Move Now", False },\r
- { "menuOptions.Periodic Updates", False }, \r
- { "menuOptions.Hide Thinking", False },\r
- { "menuOptions.Ponder Next Move", False },\r
-#endif\r
- { NULL, False }\r
-};\r
-\r
-Enables ncpEnables[] = { \r
- { "menuFile.Mail Move", False },\r
- { "menuFile.Reload CMail Message", False },\r
- { "menuMode.Machine White", False },\r
- { "menuMode.Machine Black", False },\r
- { "menuMode.Analysis Mode", False },\r
- { "menuMode.Analyze File", False },\r
- { "menuMode.Two Machines", False },\r
- { "menuMode.ICS Client", False },\r
- { "menuMode.ICS Input Box", False },\r
- { "Action", False },\r
- { "menuStep.Revert", False },\r
- { "menuStep.Move Now", False },\r
- { "menuStep.Retract Move", False },\r
- { "menuOptions.Auto Comment", False },\r
- { "menuOptions.Auto Flag", False },\r
- { "menuOptions.Auto Flip View", False },\r
- { "menuOptions.Auto Observe", False },\r
- { "menuOptions.Auto Raise Board", False },\r
- { "menuOptions.Get Move List", False },\r
- { "menuOptions.ICS Alarm", False },\r
- { "menuOptions.Move Sound", False },\r
- { "menuOptions.Quiet Play", False },\r
- { "menuOptions.Hide Thinking", False },\r
- { "menuOptions.Periodic Updates", False }, \r
- { "menuOptions.Ponder Next Move", False },\r
- { "menuHelp.Hint", False },\r
- { "menuHelp.Book", False },\r
- { NULL, False }\r
-};\r
-\r
-Enables gnuEnables[] = { \r
- { "menuMode.ICS Client", False },\r
- { "menuMode.ICS Input Box", False },\r
- { "menuAction.Accept", False },\r
- { "menuAction.Decline", False },\r
- { "menuAction.Rematch", False },\r
- { "menuAction.Adjourn", False },\r
- { "menuAction.Stop Examining", False },\r
- { "menuAction.Stop Observing", False },\r
- { "menuStep.Revert", False },\r
- { "menuOptions.Auto Comment", False },\r
- { "menuOptions.Auto Observe", False },\r
- { "menuOptions.Auto Raise Board", False },\r
- { "menuOptions.Get Move List", False },\r
- { "menuOptions.Premove", False },\r
- { "menuOptions.Quiet Play", False },\r
-\r
- /* The next two options rely on SetCmailMode being called *after* */\r
- /* SetGNUMode so that when GNU is being used to give hints these */\r
- /* menu options are still available */\r
-\r
- { "menuFile.Mail Move", False },\r
- { "menuFile.Reload CMail Message", False },\r
- { NULL, False }\r
-};\r
-\r
-Enables cmailEnables[] = { \r
- { "Action", True },\r
- { "menuAction.Call Flag", False },\r
- { "menuAction.Draw", True },\r
- { "menuAction.Adjourn", False },\r
- { "menuAction.Abort", False },\r
- { "menuAction.Stop Observing", False },\r
- { "menuAction.Stop Examining", False },\r
- { "menuFile.Mail Move", True },\r
- { "menuFile.Reload CMail Message", True },\r
- { NULL, False }\r
-};\r
-\r
-Enables trainingOnEnables[] = { \r
- { "menuMode.Edit Comment", False },\r
- { "menuMode.Pause", False },\r
- { "menuStep.Forward", False },\r
- { "menuStep.Backward", False },\r
- { "menuStep.Forward to End", False },\r
- { "menuStep.Back to Start", False },\r
- { "menuStep.Move Now", False },\r
- { "menuStep.Truncate Game", False },\r
- { NULL, False }\r
-};\r
-\r
-Enables trainingOffEnables[] = { \r
- { "menuMode.Edit Comment", True },\r
- { "menuMode.Pause", True },\r
- { "menuStep.Forward", True },\r
- { "menuStep.Backward", True },\r
- { "menuStep.Forward to End", True },\r
- { "menuStep.Back to Start", True },\r
- { "menuStep.Move Now", True },\r
- { "menuStep.Truncate Game", True },\r
- { NULL, False }\r
-};\r
-\r
-Enables machineThinkingEnables[] = {\r
- { "menuFile.Load Game", False },\r
- { "menuFile.Load Next Game", False },\r
- { "menuFile.Load Previous Game", False },\r
- { "menuFile.Reload Same Game", False },\r
- { "menuFile.Paste Game", False },\r
- { "menuFile.Load Position", False },\r
- { "menuFile.Load Next Position", False },\r
- { "menuFile.Load Previous Position", False },\r
- { "menuFile.Reload Same Position", False },\r
- { "menuFile.Paste Position", False },\r
- { "menuMode.Machine White", False },\r
- { "menuMode.Machine Black", False },\r
- { "menuMode.Two Machines", False },\r
- { "menuStep.Retract Move", False },\r
- { NULL, False }\r
-};\r
-\r
-Enables userThinkingEnables[] = {\r
- { "menuFile.Load Game", True },\r
- { "menuFile.Load Next Game", True },\r
- { "menuFile.Load Previous Game", True },\r
- { "menuFile.Reload Same Game", True },\r
- { "menuFile.Paste Game", True },\r
- { "menuFile.Load Position", True },\r
- { "menuFile.Load Next Position", True },\r
- { "menuFile.Load Previous Position", True },\r
- { "menuFile.Reload Same Position", True },\r
- { "menuFile.Paste Position", True },\r
- { "menuMode.Machine White", True },\r
- { "menuMode.Machine Black", True },\r
- { "menuMode.Two Machines", True },\r
- { "menuStep.Retract Move", True },\r
- { NULL, False }\r
-};\r
-\r
-void SetICSMode()\r
-{\r
- SetMenuEnables(icsEnables);\r
-\r
-#ifdef ZIPPY\r
- if (appData.zippyPlay && !appData.noChessProgram) /* [DM] icsEngineAnalyze */\r
- XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);\r
-#endif\r
-}\r
-\r
-void\r
-SetNCPMode()\r
-{\r
- SetMenuEnables(ncpEnables);\r
-}\r
-\r
-void\r
-SetGNUMode()\r
-{\r
- SetMenuEnables(gnuEnables);\r
-}\r
-\r
-void\r
-SetCmailMode()\r
-{\r
- SetMenuEnables(cmailEnables);\r
-}\r
-\r
-void\r
-SetTrainingModeOn()\r
-{\r
- SetMenuEnables(trainingOnEnables);\r
- if (appData.showButtonBar) {\r
- XtSetSensitive(buttonBarWidget, False);\r
- }\r
- CommentPopDown();\r
-}\r
-\r
-void\r
-SetTrainingModeOff()\r
-{\r
- SetMenuEnables(trainingOffEnables);\r
- if (appData.showButtonBar) {\r
- XtSetSensitive(buttonBarWidget, True);\r
- }\r
-}\r
-\r
-void\r
-SetUserThinkingEnables()\r
-{\r
- if (appData.noChessProgram) return;\r
- SetMenuEnables(userThinkingEnables);\r
-}\r
-\r
-void\r
-SetMachineThinkingEnables()\r
-{\r
- if (appData.noChessProgram) return;\r
- SetMenuEnables(machineThinkingEnables);\r
- switch (gameMode) {\r
- case MachinePlaysBlack:\r
- case MachinePlaysWhite:\r
- case TwoMachinesPlay:\r
- XtSetSensitive(XtNameToWidget(menuBarWidget,\r
- ModeToWidgetName(gameMode)), True);\r
- break;\r
- default:\r
- break;\r
- }\r
-}\r
-\r
-#define Abs(n) ((n)<0 ? -(n) : (n))\r
-\r
-/*\r
- * Find a font that matches "pattern" that is as close as\r
- * possible to the targetPxlSize. Prefer fonts that are k\r
- * pixels smaller to fonts that are k pixels larger. The\r
- * pattern must be in the X Consortium standard format, \r
- * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".\r
- * The return value should be freed with XtFree when no\r
- * longer needed.\r
- */\r
-char *FindFont(pattern, targetPxlSize)\r
- char *pattern;\r
- int targetPxlSize;\r
-{\r
- char **fonts, *p, *best, *scalable, *scalableTail;\r
- int i, j, nfonts, minerr, err, pxlSize;\r
-\r
-#ifdef ENABLE_NLS\r
- char **missing_list;\r
- int missing_count;\r
- char *def_string, *base_fnt_lst, strInt[3];\r
- XFontSet fntSet;\r
- XFontStruct **fnt_list;\r
-\r
- base_fnt_lst = calloc(1, strlen(pattern) + 3);\r
- sprintf(strInt, "%d", targetPxlSize);\r
- p = strstr(pattern, "--");\r
- strncpy(base_fnt_lst, pattern, p - pattern + 2);\r
- strcat(base_fnt_lst, strInt);\r
- strcat(base_fnt_lst, strchr(p + 2, '-'));\r
-\r
- if ((fntSet = XCreateFontSet(xDisplay, \r
- base_fnt_lst, \r
- &missing_list, \r
- &missing_count, \r
- &def_string)) == NULL) {\r
-\r
- fprintf(stderr, _("Unable to create font set.\n"));\r
- exit (2);\r
- }\r
-\r
- nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);\r
-#else\r
- fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);\r
- if (nfonts < 1) {\r
- fprintf(stderr, _("%s: no fonts match pattern %s\n"),\r
- programName, pattern);\r
- exit(2);\r
- }\r
-#endif\r
-\r
- best = fonts[0];\r
- scalable = NULL;\r
- minerr = 999999;\r
- for (i=0; i<nfonts; i++) {\r
- j = 0;\r
- p = fonts[i];\r
- if (*p != '-') continue;\r
- while (j < 7) {\r
- if (*p == NULLCHAR) break;\r
- if (*p++ == '-') j++;\r
- }\r
- if (j < 7) continue;\r
- pxlSize = atoi(p);\r
- if (pxlSize == 0) {\r
- scalable = fonts[i];\r
- scalableTail = p;\r
- } else {\r
- err = pxlSize - targetPxlSize;\r
- if (Abs(err) < Abs(minerr) ||\r
- (minerr > 0 && err < 0 && -err == minerr)) {\r
- best = fonts[i];\r
- minerr = err;\r
- }\r
- }\r
- }\r
- if (scalable && Abs(minerr) > appData.fontSizeTolerance) {\r
- /* If the error is too big and there is a scalable font,\r
- use the scalable font. */\r
- int headlen = scalableTail - scalable;\r
- p = (char *) XtMalloc(strlen(scalable) + 10);\r
- while (isdigit(*scalableTail)) scalableTail++;\r
- sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);\r
- } else {\r
- p = (char *) XtMalloc(strlen(best) + 1);\r
- strcpy(p, best);\r
- }\r
- if (appData.debugMode) {\r
- fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),\r
- pattern, targetPxlSize, p);\r
- }\r
-#ifdef ENABLE_NLS\r
- if (missing_count > 0)\r
- XFreeStringList(missing_list);\r
- XFreeFontSet(xDisplay, fntSet);\r
-#else\r
- XFreeFontNames(fonts);\r
-#endif\r
- return p;\r
-}\r
-\r
-void CreateGCs()\r
-{\r
- XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground\r
- | GCBackground | GCFunction | GCPlaneMask;\r
- XGCValues gc_values;\r
- GC copyInvertedGC;\r
- \r
- gc_values.plane_mask = AllPlanes;\r
- gc_values.line_width = lineGap;\r
- gc_values.line_style = LineSolid;\r
- gc_values.function = GXcopy;\r
- \r
- gc_values.foreground = XBlackPixel(xDisplay, xScreen);\r
- gc_values.background = XBlackPixel(xDisplay, xScreen);\r
- lineGC = XtGetGC(shellWidget, value_mask, &gc_values);\r
- \r
- gc_values.foreground = XBlackPixel(xDisplay, xScreen);\r
- gc_values.background = XWhitePixel(xDisplay, xScreen);\r
- coordGC = XtGetGC(shellWidget, value_mask, &gc_values);\r
- XSetFont(xDisplay, coordGC, coordFontID);\r
- \r
- // [HGM] make font for holdings counts (white on black0\r
- gc_values.foreground = XWhitePixel(xDisplay, xScreen);\r
- gc_values.background = XBlackPixel(xDisplay, xScreen);\r
- countGC = XtGetGC(shellWidget, value_mask, &gc_values);\r
- XSetFont(xDisplay, countGC, countFontID);\r
- \r
- if (appData.monoMode) {\r
- gc_values.foreground = XWhitePixel(xDisplay, xScreen);\r
- gc_values.background = XWhitePixel(xDisplay, xScreen);\r
- highlineGC = XtGetGC(shellWidget, value_mask, &gc_values); \r
-\r
- gc_values.foreground = XWhitePixel(xDisplay, xScreen);\r
- gc_values.background = XBlackPixel(xDisplay, xScreen);\r
- lightSquareGC = wbPieceGC \r
- = XtGetGC(shellWidget, value_mask, &gc_values);\r
-\r
- gc_values.foreground = XBlackPixel(xDisplay, xScreen);\r
- gc_values.background = XWhitePixel(xDisplay, xScreen);\r
- darkSquareGC = bwPieceGC\r
- = XtGetGC(shellWidget, value_mask, &gc_values);\r
-\r
- if (DefaultDepth(xDisplay, xScreen) == 1) {\r
- /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */\r
- gc_values.function = GXcopyInverted;\r
- copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);\r
- gc_values.function = GXcopy;\r
- if (XBlackPixel(xDisplay, xScreen) == 1) {\r
- bwPieceGC = darkSquareGC;\r
- wbPieceGC = copyInvertedGC;\r
- } else {\r
- bwPieceGC = copyInvertedGC;\r
- wbPieceGC = lightSquareGC;\r
- }\r
- }\r
- } else {\r
- gc_values.foreground = highlightSquareColor;\r
- gc_values.background = highlightSquareColor;\r
- highlineGC = XtGetGC(shellWidget, value_mask, &gc_values); \r
-\r
- gc_values.foreground = premoveHighlightColor;\r
- gc_values.background = premoveHighlightColor;\r
- prelineGC = XtGetGC(shellWidget, value_mask, &gc_values); \r
-\r
- gc_values.foreground = lightSquareColor;\r
- gc_values.background = darkSquareColor;\r
- lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);\r
- \r
- gc_values.foreground = darkSquareColor;\r
- gc_values.background = lightSquareColor;\r
- darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);\r
-\r
- gc_values.foreground = jailSquareColor;\r
- gc_values.background = jailSquareColor;\r
- jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);\r
-\r
- gc_values.foreground = whitePieceColor;\r
- gc_values.background = darkSquareColor;\r
- wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);\r
- \r
- gc_values.foreground = whitePieceColor;\r
- gc_values.background = lightSquareColor;\r
- wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);\r
- \r
- gc_values.foreground = whitePieceColor;\r
- gc_values.background = jailSquareColor;\r
- wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);\r
- \r
- gc_values.foreground = blackPieceColor;\r
- gc_values.background = darkSquareColor;\r
- bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);\r
- \r
- gc_values.foreground = blackPieceColor;\r
- gc_values.background = lightSquareColor;\r
- blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);\r
-\r
- gc_values.foreground = blackPieceColor;\r
- gc_values.background = jailSquareColor;\r
- bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);\r
- }\r
-}\r
-\r
-void loadXIM(xim, xmask, filename, dest, mask)\r
- XImage *xim;\r
- XImage *xmask;\r
- char *filename;\r
- Pixmap *dest;\r
- Pixmap *mask;\r
-{\r
- int x, y, w, h, p;\r
- FILE *fp;\r
- Pixmap temp;\r
- XGCValues values;\r
- GC maskGC;\r
-\r
- fp = fopen(filename, "rb");\r
- if (!fp) {\r
- fprintf(stderr, _("%s: error loading XIM!\n"), programName);\r
- exit(1);\r
- }\r
- \r
- w = fgetc(fp);\r
- h = fgetc(fp);\r
- \r
- for (y=0; y<h; ++y) {\r
- for (x=0; x<h; ++x) {\r
- p = fgetc(fp);\r
-\r
- switch (p) {\r
- case 0: \r
- XPutPixel(xim, x, y, blackPieceColor); \r
- if (xmask)\r
- XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));\r
- break;\r
- case 1: \r
- XPutPixel(xim, x, y, darkSquareColor); \r
- if (xmask)\r
- XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));\r
- break;\r
- case 2: \r
- XPutPixel(xim, x, y, whitePieceColor); \r
- if (xmask)\r
- XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));\r
- break;\r
- case 3: \r
- XPutPixel(xim, x, y, lightSquareColor);\r
- if (xmask)\r
- XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));\r
- break;\r
- }\r
- }\r
- }\r
-\r
- /* create Pixmap of piece */\r
- *dest = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),\r
- w, h, xim->depth);\r
- XPutImage(xDisplay, *dest, lightSquareGC, xim,\r
- 0, 0, 0, 0, w, h); \r
-\r
- /* create Pixmap of clipmask \r
- Note: We assume the white/black pieces have the same\r
- outline, so we make only 6 masks. This is okay\r
- since the XPM clipmask routines do the same. */\r
- if (xmask) {\r
- temp = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),\r
- w, h, xim->depth);\r
- XPutImage(xDisplay, temp, lightSquareGC, xmask,\r
- 0, 0, 0, 0, w, h); \r
-\r
- /* now create the 1-bit version */\r
- *mask = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),\r
- w, h, 1);\r
-\r
- values.foreground = 1;\r
- values.background = 0;\r
-\r
- /* Don't use XtGetGC, not read only */\r
- maskGC = XCreateGC(xDisplay, *mask, \r
- GCForeground | GCBackground, &values);\r
- XCopyPlane(xDisplay, temp, *mask, maskGC, \r
- 0, 0, squareSize, squareSize, 0, 0, 1);\r
- XFreePixmap(xDisplay, temp);\r
- }\r
-}\r
-\r
-void CreateXIMPieces()\r
-{\r
- int piece, kind;\r
- char buf[MSG_SIZ];\r
- u_int ss;\r
- static char *ximkind[] = { "ll", "ld", "dl", "dd" };\r
- XImage *ximtemp;\r
-\r
- ss = squareSize;\r
-\r
- /* The XSynchronize calls were copied from CreatePieces.\r
- Not sure if needed, but can't hurt */\r
- XSynchronize(xDisplay, True); /* Work-around for xlib/xt\r
- buffering bug */\r
- \r
- /* temp needed by loadXIM() */\r
- ximtemp = XGetImage(xDisplay, DefaultRootWindow(xDisplay),\r
- 0, 0, ss, ss, AllPlanes, XYPixmap);\r
-\r
- if (strlen(appData.pixmapDirectory) == 0) {\r
- useImages = 0;\r
- } else {\r
- useImages = 1;\r
- if (appData.monoMode) {\r
- DisplayFatalError(_("XIM pieces cannot be used in monochrome mode"),\r
- 0, 2);\r
- ExitEvent(2);\r
- }\r
- fprintf(stderr, _("\nLoading XIMs...\n"));\r
- /* Load pieces */\r
- for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {\r
- fprintf(stderr, "%d", piece+1);\r
- for (kind=0; kind<4; kind++) {\r
- fprintf(stderr, ".");\r
- sprintf(buf, "%s/%c%s%u.xim",\r
- ExpandPathName(appData.pixmapDirectory),\r
- ToLower(PieceToChar((ChessSquare)piece)),\r
- ximkind[kind], ss);\r
- ximPieceBitmap[kind][piece] =\r
- XGetImage(xDisplay, DefaultRootWindow(xDisplay),\r
- 0, 0, ss, ss, AllPlanes, XYPixmap);\r
- if (appData.debugMode)\r
- fprintf(stderr, _("(File:%s:) "), buf);\r
- loadXIM(ximPieceBitmap[kind][piece], \r
- ximtemp, buf,\r
- &(xpmPieceBitmap[kind][piece]),\r
- &(ximMaskPm[piece%(int)BlackPawn]));\r
- }\r
- fprintf(stderr," ");\r
- }\r
- /* Load light and dark squares */\r
- /* If the LSQ and DSQ pieces don't exist, we will \r
- draw them with solid squares. */\r
- sprintf(buf, "%s/lsq%u.xim", ExpandPathName(appData.pixmapDirectory), ss);\r
- if (access(buf, 0) != 0) {\r
- useImageSqs = 0;\r
- } else {\r
- useImageSqs = 1;\r
- fprintf(stderr, _("light square "));\r
- ximLightSquare= \r
- XGetImage(xDisplay, DefaultRootWindow(xDisplay),\r
- 0, 0, ss, ss, AllPlanes, XYPixmap);\r
- if (appData.debugMode)\r
- fprintf(stderr, _("(File:%s:) "), buf);\r
-\r
- loadXIM(ximLightSquare, NULL, buf, &xpmLightSquare, NULL);\r
- fprintf(stderr, _("dark square "));\r
- sprintf(buf, "%s/dsq%u.xim",\r
- ExpandPathName(appData.pixmapDirectory), ss);\r
- if (appData.debugMode)\r
- fprintf(stderr, _("(File:%s:) "), buf);\r
- ximDarkSquare= \r
- XGetImage(xDisplay, DefaultRootWindow(xDisplay),\r
- 0, 0, ss, ss, AllPlanes, XYPixmap);\r
- loadXIM(ximDarkSquare, NULL, buf, &xpmDarkSquare, NULL);\r
- xpmJailSquare = xpmLightSquare;\r
- }\r
- fprintf(stderr, _("Done.\n"));\r
- }\r
- XSynchronize(xDisplay, False); /* Work-around for xlib/xt buffering bug */\r
-}\r
-\r
-#if HAVE_LIBXPM\r
-void CreateXPMPieces()\r
-{\r
- int piece, kind, r;\r
- char buf[MSG_SIZ];\r
- u_int ss = squareSize;\r
- XpmAttributes attr;\r
- static char *xpmkind[] = { "ll", "ld", "dl", "dd" };\r
- XpmColorSymbol symbols[4];\r
-\r
-#if 0\r
- /* Apparently some versions of Xpm don't define XpmFormat at all --tpm */\r
- if (appData.debugMode) {\r
- fprintf(stderr, "XPM Library Version: %d.%d%c\n", \r
- XpmFormat, XpmVersion, (char)('a' + XpmRevision - 1));\r
- }\r
-#endif\r
- \r
- /* The XSynchronize calls were copied from CreatePieces.\r
- Not sure if needed, but can't hurt */\r
- XSynchronize(xDisplay, True); /* Work-around for xlib/xt buffering bug */\r
- \r
- /* Setup translations so piece colors match square colors */\r
- symbols[0].name = "light_piece";\r
- symbols[0].value = appData.whitePieceColor;\r
- symbols[1].name = "dark_piece";\r
- symbols[1].value = appData.blackPieceColor;\r
- symbols[2].name = "light_square";\r
- symbols[2].value = appData.lightSquareColor;\r
- symbols[3].name = "dark_square";\r
- symbols[3].value = appData.darkSquareColor;\r
-\r
- attr.valuemask = XpmColorSymbols;\r
- attr.colorsymbols = symbols;\r
- attr.numsymbols = 4;\r
-\r
- if (appData.monoMode) {\r
- DisplayFatalError(_("XPM pieces cannot be used in monochrome mode"),\r
- 0, 2);\r
- ExitEvent(2);\r
- }\r
- if (strlen(appData.pixmapDirectory) == 0) {\r
- XpmPieces* pieces = builtInXpms;\r
- useImages = 1;\r
- /* Load pieces */\r
- while (pieces->size != squareSize && pieces->size) pieces++;\r
- if (!pieces->size) {\r
- fprintf(stderr, _("No builtin XPM pieces of size %d\n"), squareSize);\r
- exit(1);\r
- }\r
- for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {\r
- for (kind=0; kind<4; kind++) {\r
-\r
- if ((r=XpmCreatePixmapFromData(xDisplay, xBoardWindow,\r
- pieces->xpm[piece][kind],\r
- &(xpmPieceBitmap[kind][piece]),\r
- NULL, &attr)) != 0) {\r
- fprintf(stderr, _("Error %d loading XPM image \"%s\"\n"),\r
- r, buf);\r
- exit(1); \r
- } \r
- } \r
- }\r
- useImageSqs = 0;\r
- xpmJailSquare = xpmLightSquare;\r
- } else {\r
- useImages = 1;\r
- \r
- fprintf(stderr, _("\nLoading XPMs...\n"));\r
-\r
- /* Load pieces */\r
- for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {\r
- fprintf(stderr, "%d ", piece+1);\r
- for (kind=0; kind<4; kind++) {\r
- sprintf(buf, "%s/%c%s%u.xpm",\r
- ExpandPathName(appData.pixmapDirectory),\r
- ToLower(PieceToChar((ChessSquare)piece)),\r
- xpmkind[kind], ss);\r
- if (appData.debugMode) {\r
- fprintf(stderr, _("(File:%s:) "), buf);\r
- }\r
- if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,\r
- &(xpmPieceBitmap[kind][piece]),\r
- NULL, &attr)) != 0) {\r
- fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"),\r
- r, buf);\r
- exit(1); \r
- } \r
- } \r
- }\r
- /* Load light and dark squares */\r
- /* If the LSQ and DSQ pieces don't exist, we will \r
- draw them with solid squares. */\r
- fprintf(stderr, _("light square "));\r
- sprintf(buf, "%s/lsq%u.xpm", ExpandPathName(appData.pixmapDirectory), ss);\r
- if (access(buf, 0) != 0) {\r
- useImageSqs = 0;\r
- } else {\r
- useImageSqs = 1;\r
- if (appData.debugMode)\r
- fprintf(stderr, _("(File:%s:) "), buf);\r
-\r
- if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,\r
- &xpmLightSquare, NULL, &attr)) != 0) {\r
- fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);\r
- exit(1);\r
- }\r
- fprintf(stderr, _("dark square "));\r
- sprintf(buf, "%s/dsq%u.xpm",\r
- ExpandPathName(appData.pixmapDirectory), ss);\r
- if (appData.debugMode) {\r
- fprintf(stderr, _("(File:%s:) "), buf);\r
- }\r
- if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,\r
- &xpmDarkSquare, NULL, &attr)) != 0) {\r
- fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);\r
- exit(1);\r
- }\r
- }\r
- xpmJailSquare = xpmLightSquare;\r
- fprintf(stderr, _("Done.\n"));\r
- }\r
- XSynchronize(xDisplay, False); /* Work-around for xlib/xt\r
- buffering bug */ \r
-}\r
-#endif /* HAVE_LIBXPM */\r
-\r
-#if HAVE_LIBXPM\r
-/* No built-in bitmaps */\r
-void CreatePieces()\r
-{\r
- int piece, kind;\r
- char buf[MSG_SIZ];\r
- u_int ss = squareSize;\r
- \r
- XSynchronize(xDisplay, True); /* Work-around for xlib/xt\r
- buffering bug */\r
-\r
- for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {\r
- for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {\r
- sprintf(buf, "%c%u%c.bm", ToLower(PieceToChar((ChessSquare)piece)),\r
- ss, kind == SOLID ? 's' : 'o');\r
- ReadBitmap(&pieceBitmap[kind][piece], buf, NULL, ss, ss);\r
- }\r
- }\r
- \r
- XSynchronize(xDisplay, False); /* Work-around for xlib/xt\r
- buffering bug */\r
-}\r
-#else\r
-/* With built-in bitmaps */\r
-void CreatePieces()\r
-{\r
- BuiltInBits* bib = builtInBits;\r
- int piece, kind;\r
- char buf[MSG_SIZ];\r
- u_int ss = squareSize;\r
- \r
- XSynchronize(xDisplay, True); /* Work-around for xlib/xt\r
- buffering bug */\r
-\r
- while (bib->squareSize != ss && bib->squareSize != 0) bib++;\r
-\r
- for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {\r
- for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {\r
- sprintf(buf, "%c%u%c.bm", ToLower(PieceToChar((ChessSquare)piece)),\r
- ss, kind == SOLID ? 's' : 'o');\r
- ReadBitmap(&pieceBitmap[kind][piece], buf,\r
- bib->bits[kind][piece], ss, ss);\r
- }\r
- }\r
- \r
- XSynchronize(xDisplay, False); /* Work-around for xlib/xt\r
- buffering bug */\r
-}\r
-#endif\r
-\r
-void ReadBitmap(pm, name, bits, wreq, hreq)\r
- Pixmap *pm;\r
- String name;\r
- unsigned char bits[];\r
- u_int wreq, hreq;\r
-{\r
- int x_hot, y_hot;\r
- u_int w, h;\r
- int errcode;\r
- char msg[MSG_SIZ], fullname[MSG_SIZ];\r
- \r
- if (*appData.bitmapDirectory != NULLCHAR) {\r
- strcpy(fullname, appData.bitmapDirectory);\r
- strcat(fullname, "/");\r
- strcat(fullname, name);\r
- errcode = XReadBitmapFile(xDisplay, xBoardWindow, fullname,\r
- &w, &h, pm, &x_hot, &y_hot);\r
- if (errcode != BitmapSuccess) {\r
- switch (errcode) {\r
- case BitmapOpenFailed:\r
- sprintf(msg, _("Can't open bitmap file %s"), fullname);\r
- break;\r
- case BitmapFileInvalid:\r
- sprintf(msg, _("Invalid bitmap in file %s"), fullname);\r
- break;\r
- case BitmapNoMemory:\r
- sprintf(msg, _("Ran out of memory reading bitmap file %s"),\r
- fullname);\r
- break;\r
- default:\r
- sprintf(msg, _("Unknown XReadBitmapFile error %d on file %s"),\r
- errcode, fullname);\r
- break;\r
- }\r
- fprintf(stderr, _("%s: %s...using built-in\n"),\r
- programName, msg);\r
- } else if (w != wreq || h != hreq) {\r
- fprintf(stderr,\r
- _("%s: Bitmap %s is %dx%d, not %dx%d...using built-in\n"),\r
- programName, fullname, w, h, wreq, hreq);\r
- } else {\r
- return;\r
- }\r
- }\r
- if (bits == NULL) {\r
-#if 0\r
- fprintf(stderr, _("%s: No built-in bitmap for %s; giving up\n"),\r
- programName, name);\r
- exit(1);\r
-#endif\r
- ; // [HGM] bitmaps: make it non-fatal if we have no bitmap;\r
- } else {\r
- *pm = XCreateBitmapFromData(xDisplay, xBoardWindow, (char *) bits,\r
- wreq, hreq);\r
- }\r
-}\r
-\r
-void CreateGrid()\r
-{\r
- int i, j;\r
- \r
- if (lineGap == 0) return;\r
-\r
- /* [HR] Split this into 2 loops for non-square boards. */\r
-\r
- for (i = 0; i < BOARD_HEIGHT + 1; i++) {\r
- gridSegments[i].x1 = 0;\r
- gridSegments[i].x2 =\r
- lineGap + BOARD_WIDTH * (squareSize + lineGap);\r
- gridSegments[i].y1 = gridSegments[i].y2\r
- = lineGap / 2 + (i * (squareSize + lineGap));\r
- }\r
-\r
- for (j = 0; j < BOARD_WIDTH + 1; j++) {\r
- gridSegments[j + i].y1 = 0;\r
- gridSegments[j + i].y2 =\r
- lineGap + BOARD_HEIGHT * (squareSize + lineGap);\r
- gridSegments[j + i].x1 = gridSegments[j + i].x2\r
- = lineGap / 2 + (j * (squareSize + lineGap));\r
- }\r
-}\r
-\r
-static void MenuBarSelect(w, addr, index)\r
- Widget w;\r
- caddr_t addr;\r
- caddr_t index;\r
-{\r
- XtActionProc proc = (XtActionProc) addr;\r
-\r
- (proc)(NULL, NULL, NULL, NULL);\r
-}\r
-\r
-void CreateMenuBarPopup(parent, name, mb)\r
- Widget parent;\r
- String name;\r
- Menu *mb;\r
-{\r
- int j;\r
- Widget menu, entry;\r
- MenuItem *mi;\r
- Arg args[16];\r
-\r
- menu = XtCreatePopupShell(name, simpleMenuWidgetClass,\r
- parent, NULL, 0);\r
- j = 0;\r
- XtSetArg(args[j], XtNleftMargin, 20); j++;\r
- XtSetArg(args[j], XtNrightMargin, 20); j++;\r
- mi = mb->mi;\r
- while (mi->string != NULL) {\r
- if (strcmp(mi->string, "----") == 0) {\r
- entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,\r
- menu, args, j);\r
- } else {\r
- XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string)));\r
- entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass,\r
- menu, args, j+1);\r
- XtAddCallback(entry, XtNcallback,\r
- (XtCallbackProc) MenuBarSelect,\r
- (caddr_t) mi->proc);\r
- }\r
- mi++;\r
- }\r
-} \r
-\r
-Widget CreateMenuBar(mb)\r
- Menu *mb;\r
-{\r
- int j;\r
- Widget anchor, menuBar;\r
- Arg args[16];\r
- char menuName[MSG_SIZ];\r
-\r
- j = 0;\r
- XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;\r
- XtSetArg(args[j], XtNvSpace, 0); j++;\r
- XtSetArg(args[j], XtNborderWidth, 0); j++;\r
- menuBar = XtCreateWidget("menuBar", boxWidgetClass,\r
- formWidget, args, j);\r
-\r
- while (mb->name != NULL) {\r
- strcpy(menuName, "menu");\r
- strcat(menuName, mb->name);\r
- j = 0;\r
- XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;\r
- if (tinyLayout) {\r
- char shortName[2];\r
- shortName[0] = _(mb->name)[0];\r
- shortName[1] = NULLCHAR;\r
- XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;\r
- }\r
- else {\r
- XtSetArg(args[j], XtNlabel, XtNewString(_(mb->name))); j++;\r
- }\r
-\r
- XtSetArg(args[j], XtNborderWidth, 0); j++;\r
- anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,\r
- menuBar, args, j);\r
- CreateMenuBarPopup(menuBar, menuName, mb);\r
- mb++;\r
- }\r
- return menuBar;\r
-}\r
-\r
-Widget CreateButtonBar(mi)\r
- MenuItem *mi;\r
-{\r
- int j;\r
- Widget button, buttonBar;\r
- Arg args[16];\r
-\r
- j = 0;\r
- XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;\r
- if (tinyLayout) {\r
- XtSetArg(args[j], XtNhSpace, 0); j++;\r
- }\r
- XtSetArg(args[j], XtNborderWidth, 0); j++;\r
- XtSetArg(args[j], XtNvSpace, 0); j++;\r
- buttonBar = XtCreateWidget("buttonBar", boxWidgetClass,\r
- formWidget, args, j);\r
-\r
- while (mi->string != NULL) {\r
- j = 0;\r
- if (tinyLayout) {\r
- XtSetArg(args[j], XtNinternalWidth, 2); j++;\r
- XtSetArg(args[j], XtNborderWidth, 0); j++;\r
- }\r
- XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string))); j++;\r
- button = XtCreateManagedWidget(mi->string, commandWidgetClass,\r
- buttonBar, args, j);\r
- XtAddCallback(button, XtNcallback,\r
- (XtCallbackProc) MenuBarSelect,\r
- (caddr_t) mi->proc);\r
- mi++;\r
- }\r
- return buttonBar;\r
-} \r
-\r
-Widget\r
-CreatePieceMenu(name, color)\r
- char *name;\r
- int color;\r
-{\r
- int i;\r
- Widget entry, menu;\r
- Arg args[16];\r
- ChessSquare selection;\r
-\r
- menu = XtCreatePopupShell(name, simpleMenuWidgetClass,\r
- boardWidget, args, 0);\r
- \r
- for (i = 0; i < PIECE_MENU_SIZE; i++) {\r
- String item = pieceMenuStrings[color][i];\r
- \r
- if (strcmp(item, "----") == 0) {\r
- entry = XtCreateManagedWidget(item, smeLineObjectClass,\r
- menu, NULL, 0);\r
- } else {\r
- XtSetArg(args[0], XtNlabel, XtNewString(_(item))); \r
- entry = XtCreateManagedWidget(item, smeBSBObjectClass,\r
- menu, args, 1);\r
- selection = pieceMenuTranslation[color][i];\r
- XtAddCallback(entry, XtNcallback,\r
- (XtCallbackProc) PieceMenuSelect,\r
- (caddr_t) selection);\r
- if (selection == WhitePawn || selection == BlackPawn) {\r
- XtSetArg(args[0], XtNpopupOnEntry, entry);\r
- XtSetValues(menu, args, 1);\r
- }\r
- }\r
- }\r
- return menu;\r
-}\r
-\r
-void\r
-CreatePieceMenus()\r
-{\r
- int i;\r
- Widget entry;\r
- Arg args[16];\r
- ChessSquare selection;\r
-\r
- whitePieceMenu = CreatePieceMenu("menuW", 0);\r
- blackPieceMenu = CreatePieceMenu("menuB", 1);\r
- \r
- XtRegisterGrabAction(PieceMenuPopup, True,\r
- (unsigned)(ButtonPressMask|ButtonReleaseMask),\r
- GrabModeAsync, GrabModeAsync);\r
-\r
- XtSetArg(args[0], XtNlabel, _("Drop"));\r
- dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,\r
- boardWidget, args, 1);\r
- for (i = 0; i < DROP_MENU_SIZE; i++) {\r
- String item = dropMenuStrings[i];\r
- \r
- if (strcmp(item, "----") == 0) {\r
- entry = XtCreateManagedWidget(item, smeLineObjectClass,\r
- dropMenu, NULL, 0);\r
- } else {\r
- XtSetArg(args[0], XtNlabel, XtNewString(_(item))); \r
- entry = XtCreateManagedWidget(item, smeBSBObjectClass,\r
- dropMenu, args, 1);\r
- selection = dropMenuTranslation[i];\r
- XtAddCallback(entry, XtNcallback,\r
- (XtCallbackProc) DropMenuSelect,\r
- (caddr_t) selection);\r
- }\r
- }\r
-} \r
-\r
-void SetupDropMenu()\r
-{\r
- int i, j, count;\r
- char label[32];\r
- Arg args[16];\r
- Widget entry;\r
- char* p;\r
-\r
- for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {\r
- entry = XtNameToWidget(dropMenu, dmEnables[i].widget);\r
- p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,\r
- dmEnables[i].piece);\r
- XtSetSensitive(entry, p != NULL || !appData.testLegality\r
- /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse\r
- && !appData.icsActive));\r
- count = 0;\r
- while (p && *p++ == dmEnables[i].piece) count++;\r
- sprintf(label, "%s %d", dmEnables[i].widget, count);\r
- j = 0;\r
- XtSetArg(args[j], XtNlabel, label); j++;\r
- XtSetValues(entry, args, j);\r
- }\r
-}\r
-\r
-void PieceMenuPopup(w, event, params, num_params)\r
- Widget w;\r
- XEvent *event;\r
- String *params;\r
- Cardinal *num_params;\r
-{\r
- String whichMenu;\r
- if (event->type != ButtonPress) return;\r
- if (errorUp) ErrorPopDown();\r
- switch (gameMode) {\r
- case EditPosition:\r
- case IcsExamining:\r
- whichMenu = params[0];\r
- break;\r
- case IcsPlayingWhite:\r
- case IcsPlayingBlack:\r
- case EditGame:\r
- case MachinePlaysWhite:\r
- case MachinePlaysBlack:\r
- if (appData.testLegality &&\r
- gameInfo.variant != VariantBughouse &&\r
- gameInfo.variant != VariantCrazyhouse) return;\r
- SetupDropMenu();\r
- whichMenu = "menuD";\r
- break;\r
- default:\r
- return;\r
- }\r
- \r
- if (((pmFromX = EventToSquare(event->xbutton.x, BOARD_WIDTH)) < 0) ||\r
- ((pmFromY = EventToSquare(event->xbutton.y, BOARD_HEIGHT)) < 0)) {\r
- pmFromX = pmFromY = -1;\r
- return;\r
- }\r
- if (flipView)\r
- pmFromX = BOARD_WIDTH - 1 - pmFromX;\r
- else\r
- pmFromY = BOARD_HEIGHT - 1 - pmFromY;\r
- \r
- XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));\r
-}\r
-\r
-static void PieceMenuSelect(w, piece, junk)\r
- Widget w;\r
- ChessSquare piece;\r
- caddr_t junk;\r
-{\r
- if (pmFromX < 0 || pmFromY < 0) return;\r
- EditPositionMenuEvent(piece, pmFromX, pmFromY);\r
-}\r
-\r
-static void DropMenuSelect(w, piece, junk)\r
- Widget w;\r
- ChessSquare piece;\r
- caddr_t junk;\r
-{\r
- if (pmFromX < 0 || pmFromY < 0) return;\r
- DropMenuEvent(piece, pmFromX, pmFromY);\r
-}\r
-\r
-void WhiteClock(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- if (gameMode == EditPosition || gameMode == IcsExamining) {\r
- SetWhiteToPlayEvent();\r
- } else if (gameMode == IcsPlayingBlack || gameMode == MachinePlaysWhite) {\r
- CallFlagEvent();\r
- }\r
-}\r
-\r
-void BlackClock(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- if (gameMode == EditPosition || gameMode == IcsExamining) {\r
- SetBlackToPlayEvent();\r
- } else if (gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) {\r
- CallFlagEvent();\r
- }\r
-}\r
-\r
-\r
-/*\r
- * If the user selects on a border boundary, return -1; if off the board,\r
- * return -2. Otherwise map the event coordinate to the square.\r
- */\r
-int EventToSquare(x, limit)\r
- int x;\r
-{\r
- if (x <= 0) \r
- return -2;\r
- if (x < lineGap)\r
- return -1;\r
- x -= lineGap;\r
- if ((x % (squareSize + lineGap)) >= squareSize)\r
- return -1;\r
- x /= (squareSize + lineGap);\r
- if (x >= limit)\r
- return -2;\r
- return x;\r
-}\r
-\r
-static void do_flash_delay(msec)\r
- unsigned long msec;\r
-{\r
- TimeDelay(msec);\r
-}\r
-\r
-static void drawHighlight(file, rank, gc)\r
- int file, rank;\r
- GC gc;\r
-{\r
- int x, y;\r
-\r
- if (lineGap == 0 || appData.blindfold) return;\r
- \r
- if (flipView) {\r
- x = lineGap/2 + ((BOARD_WIDTH-1)-file) * \r
- (squareSize + lineGap);\r
- y = lineGap/2 + rank * (squareSize + lineGap);\r
- } else {\r
- x = lineGap/2 + file * (squareSize + lineGap);\r
- y = lineGap/2 + ((BOARD_HEIGHT-1)-rank) * \r
- (squareSize + lineGap);\r
- }\r
- \r
- XDrawRectangle(xDisplay, xBoardWindow, gc, x, y,\r
- squareSize+lineGap, squareSize+lineGap);\r
-}\r
-\r
-int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;\r
-int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;\r
-\r
-void\r
-SetHighlights(fromX, fromY, toX, toY)\r
- int fromX, fromY, toX, toY;\r
-{\r
- if (hi1X != fromX || hi1Y != fromY) {\r
- if (hi1X >= 0 && hi1Y >= 0) {\r
- drawHighlight(hi1X, hi1Y, lineGC);\r
- }\r
- if (fromX >= 0 && fromY >= 0) {\r
- drawHighlight(fromX, fromY, highlineGC);\r
- }\r
- }\r
- if (hi2X != toX || hi2Y != toY) {\r
- if (hi2X >= 0 && hi2Y >= 0) {\r
- drawHighlight(hi2X, hi2Y, lineGC);\r
- }\r
- if (toX >= 0 && toY >= 0) {\r
- drawHighlight(toX, toY, highlineGC);\r
- }\r
- }\r
- hi1X = fromX;\r
- hi1Y = fromY;\r
- hi2X = toX;\r
- hi2Y = toY;\r
-}\r
-\r
-void\r
-ClearHighlights()\r
-{\r
- SetHighlights(-1, -1, -1, -1);\r
-}\r
-\r
-\r
-void\r
-SetPremoveHighlights(fromX, fromY, toX, toY)\r
- int fromX, fromY, toX, toY;\r
-{\r
- if (pm1X != fromX || pm1Y != fromY) {\r
- if (pm1X >= 0 && pm1Y >= 0) {\r
- drawHighlight(pm1X, pm1Y, lineGC);\r
- }\r
- if (fromX >= 0 && fromY >= 0) {\r
- drawHighlight(fromX, fromY, prelineGC);\r
- }\r
- }\r
- if (pm2X != toX || pm2Y != toY) {\r
- if (pm2X >= 0 && pm2Y >= 0) {\r
- drawHighlight(pm2X, pm2Y, lineGC);\r
- }\r
- if (toX >= 0 && toY >= 0) {\r
- drawHighlight(toX, toY, prelineGC);\r
- }\r
- }\r
- pm1X = fromX;\r
- pm1Y = fromY;\r
- pm2X = toX;\r
- pm2Y = toY;\r
-}\r
-\r
-void\r
-ClearPremoveHighlights()\r
-{\r
- SetPremoveHighlights(-1, -1, -1, -1);\r
-}\r
-\r
-static void BlankSquare(x, y, color, piece, dest)\r
- int x, y, color;\r
- ChessSquare piece;\r
- Drawable dest;\r
-{\r
- if (useImages && useImageSqs) {\r
- Pixmap pm;\r
- switch (color) {\r
- case 1: /* light */\r
- pm = xpmLightSquare;\r
- break;\r
- case 0: /* dark */\r
- pm = xpmDarkSquare;\r
- break;\r
- case 2: /* neutral */\r
- default:\r
- pm = xpmJailSquare;\r
- break;\r
- }\r
- XCopyArea(xDisplay, pm, dest, wlPieceGC, 0, 0,\r
- squareSize, squareSize, x, y);\r
- } else {\r
- GC gc;\r
- switch (color) {\r
- case 1: /* light */\r
- gc = lightSquareGC;\r
- break;\r
- case 0: /* dark */\r
- gc = darkSquareGC;\r
- break;\r
- case 2: /* neutral */\r
- default:\r
- gc = jailSquareGC;\r
- break;\r
- }\r
- XFillRectangle(xDisplay, dest, gc, x, y, squareSize, squareSize);\r
- }\r
-}\r
-\r
-/*\r
- I split out the routines to draw a piece so that I could\r
- make a generic flash routine.\r
-*/\r
-static void monoDrawPiece_1bit(piece, square_color, x, y, dest)\r
- ChessSquare piece;\r
- int square_color, x, y;\r
- Drawable dest;\r
-{\r
- /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */\r
- switch (square_color) {\r
- case 1: /* light */\r
- case 2: /* neutral */\r
- default:\r
- XCopyArea(xDisplay, (int) piece < (int) BlackPawn\r
- ? *pieceToOutline(piece)\r
- : *pieceToSolid(piece),\r
- dest, bwPieceGC, 0, 0,\r
- squareSize, squareSize, x, y);\r
- break;\r
- case 0: /* dark */\r
- XCopyArea(xDisplay, (int) piece < (int) BlackPawn\r
- ? *pieceToSolid(piece)\r
- : *pieceToOutline(piece),\r
- dest, wbPieceGC, 0, 0,\r
- squareSize, squareSize, x, y);\r
- break;\r
- }\r
-}\r
-\r
-static void monoDrawPiece(piece, square_color, x, y, dest)\r
- ChessSquare piece;\r
- int square_color, x, y;\r
- Drawable dest;\r
-{\r
- switch (square_color) {\r
- case 1: /* light */\r
- case 2: /* neutral */\r
- default:\r
- XCopyPlane(xDisplay, (int) piece < (int) BlackPawn\r
- ? *pieceToOutline(piece)\r
- : *pieceToSolid(piece),\r
- dest, bwPieceGC, 0, 0,\r
- squareSize, squareSize, x, y, 1);\r
- break;\r
- case 0: /* dark */\r
- XCopyPlane(xDisplay, (int) piece < (int) BlackPawn\r
- ? *pieceToSolid(piece)\r
- : *pieceToOutline(piece),\r
- dest, wbPieceGC, 0, 0,\r
- squareSize, squareSize, x, y, 1);\r
- break;\r
- }\r
-}\r
-\r
-static void colorDrawPiece(piece, square_color, x, y, dest)\r
- ChessSquare piece;\r
- int square_color, x, y;\r
- Drawable dest;\r
-{\r
- if(pieceToSolid(piece) == NULL) return; // [HGM] bitmaps: make it non-fatal if we have no bitmap;\r
- switch (square_color) {\r
- case 1: /* light */\r
- XCopyPlane(xDisplay, *pieceToSolid(piece),\r
- dest, (int) piece < (int) BlackPawn\r
- ? wlPieceGC : blPieceGC, 0, 0,\r
- squareSize, squareSize, x, y, 1);\r
- break;\r
- case 0: /* dark */\r
- XCopyPlane(xDisplay, *pieceToSolid(piece),\r
- dest, (int) piece < (int) BlackPawn\r
- ? wdPieceGC : bdPieceGC, 0, 0,\r
- squareSize, squareSize, x, y, 1);\r
- break;\r
- case 2: /* neutral */\r
- default:\r
- XCopyPlane(xDisplay, *pieceToSolid(piece),\r
- dest, (int) piece < (int) BlackPawn\r
- ? wjPieceGC : bjPieceGC, 0, 0,\r
- squareSize, squareSize, x, y, 1);\r
- break;\r
- }\r
-}\r
-\r
-static void colorDrawPieceImage(piece, square_color, x, y, dest)\r
- ChessSquare piece;\r
- int square_color, x, y;\r
- Drawable dest;\r
-{\r
- int kind;\r
-\r
- switch (square_color) {\r
- case 1: /* light */\r
- case 2: /* neutral */\r
- default:\r
- if ((int)piece < (int) BlackPawn) {\r
- kind = 0;\r
- } else {\r
- kind = 2;\r
- piece -= BlackPawn;\r
- }\r
- break;\r
- case 0: /* dark */\r
- if ((int)piece < (int) BlackPawn) {\r
- kind = 1;\r
- } else {\r
- kind = 3;\r
- piece -= BlackPawn;\r
- }\r
- break;\r
- }\r
- XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],\r
- dest, wlPieceGC, 0, 0,\r
- squareSize, squareSize, x, y); \r
-}\r
-\r
-typedef void (*DrawFunc)();\r
-\r
-DrawFunc ChooseDrawFunc()\r
-{\r
- if (appData.monoMode) {\r
- if (DefaultDepth(xDisplay, xScreen) == 1) {\r
- return monoDrawPiece_1bit;\r
- } else {\r
- return monoDrawPiece;\r
- }\r
- } else {\r
- if (useImages)\r
- return colorDrawPieceImage;\r
- else\r
- return colorDrawPiece;\r
- }\r
-}\r
-\r
-/* [HR] determine square color depending on chess variant. */\r
-static int SquareColor(row, column)\r
- int row, column;\r
-{\r
- int square_color;\r
-\r
- if (gameInfo.variant == VariantXiangqi) {\r
- if (column >= 3 && column <= 5 && row >= 0 && row <= 2) {\r
- square_color = 1;\r
- } else if (column >= 3 && column <= 5 && row >= 7 && row <= 9) {\r
- square_color = 0;\r
- } else if (row <= 4) {\r
- square_color = 0;\r
- } else {\r
- square_color = 1;\r
- }\r
- } else {\r
- square_color = ((column + row) % 2) == 1;\r
- }\r
-\r
- /* [hgm] holdings: next line makes all holdings squares light */\r
- if(column < BOARD_LEFT || column >= BOARD_RGHT) square_color = 1;\r
- \r
- return square_color;\r
-}\r
-\r
-void DrawSquare(row, column, piece, do_flash)\r
- int row, column, do_flash;\r
- ChessSquare piece;\r
-{\r
- int square_color, x, y, direction, font_ascent, font_descent;\r
- int i;\r
- char string[2];\r
- XCharStruct overall;\r
- DrawFunc drawfunc;\r
- int flash_delay;\r
-\r
- if(gameInfo.variant == VariantShogi) { // [HGM] shogi: in shogi Q is used for Lance\r
- if(piece == WhiteQueen) piece = WhiteLance; else\r
- if(piece == BlackQueen) piece = BlackLance;\r
- }\r
-#ifdef GOTHIC\r
- else if(gameInfo.variant == VariantGothic) { // [HGM] shogi: in Gothic Chancelor has alternative look\r
- if(piece == WhiteMarshall) piece = WhiteSilver; else\r
- if(piece == BlackMarshall) piece = BlackSilver;\r
- }\r
-#endif\r
-\r
- /* Calculate delay in milliseconds (2-delays per complete flash) */\r
- flash_delay = 500 / appData.flashRate;\r
- \r
- if (flipView) {\r
- x = lineGap + ((BOARD_WIDTH-1)-column) * \r
- (squareSize + lineGap);\r
- y = lineGap + row * (squareSize + lineGap);\r
- } else {\r
- x = lineGap + column * (squareSize + lineGap);\r
- y = lineGap + ((BOARD_HEIGHT-1)-row) * \r
- (squareSize + lineGap);\r
- }\r
- \r
- square_color = SquareColor(row, column);\r
- \r
- if ( // [HGM] holdings: blank out area between board and holdings\r
- column == BOARD_LEFT-1 || column == BOARD_RGHT\r
- || (column == BOARD_LEFT-2 && row < BOARD_HEIGHT-gameInfo.holdingsSize)\r
- || (column == BOARD_RGHT+1 && row >= gameInfo.holdingsSize) ) {\r
- BlankSquare(x, y, 2, EmptySquare, xBoardWindow);\r
-\r
- // [HGM] print piece counts next to holdings\r
- string[1] = NULLCHAR;\r
- if (column == (flipView ? BOARD_LEFT-1 : BOARD_RGHT) && piece > 1 ) {\r
- string[0] = '0' + piece;\r
- XTextExtents(countFontStruct, string, 1, &direction, \r
- &font_ascent, &font_descent, &overall);\r
- if (appData.monoMode) {\r
- XDrawImageString(xDisplay, xBoardWindow, countGC,\r
- x + squareSize - overall.width - 2, \r
- y + font_ascent + 1, string, 1);\r
- } else {\r
- XDrawString(xDisplay, xBoardWindow, countGC,\r
- x + squareSize - overall.width - 2, \r
- y + font_ascent + 1, string, 1);\r
- }\r
- }\r
- if (column == (flipView ? BOARD_RGHT : BOARD_LEFT-1) && piece > 1) {\r
- string[0] = '0' + piece;\r
- XTextExtents(countFontStruct, string, 1, &direction, \r
- &font_ascent, &font_descent, &overall);\r
- if (appData.monoMode) {\r
- XDrawImageString(xDisplay, xBoardWindow, countGC,\r
- x + 2, y + font_ascent + 1, string, 1);\r
- } else {\r
- XDrawString(xDisplay, xBoardWindow, countGC,\r
- x + 2, y + font_ascent + 1, string, 1);\r
- } \r
- } \r
- } else {\r
- if (piece == EmptySquare || appData.blindfold) {\r
- BlankSquare(x, y, square_color, piece, xBoardWindow);\r
- } else {\r
- drawfunc = ChooseDrawFunc();\r
- if (do_flash && appData.flashCount > 0) {\r
- for (i=0; i<appData.flashCount; ++i) {\r
-\r
- drawfunc(piece, square_color, x, y, xBoardWindow);\r
- XSync(xDisplay, False);\r
- do_flash_delay(flash_delay);\r
-\r
- BlankSquare(x, y, square_color, piece, xBoardWindow);\r
- XSync(xDisplay, False);\r
- do_flash_delay(flash_delay);\r
- }\r
- }\r
- drawfunc(piece, square_color, x, y, xBoardWindow);\r
- }\r
- }\r
- \r
- string[1] = NULLCHAR;\r
- if (appData.showCoords && row == (flipView ? BOARD_HEIGHT-1 : 0)\r
- && column >= BOARD_LEFT && column < BOARD_RGHT) {\r
- string[0] = 'a' + column - BOARD_LEFT;\r
- XTextExtents(coordFontStruct, string, 1, &direction, \r
- &font_ascent, &font_descent, &overall);\r
- if (appData.monoMode) {\r
- XDrawImageString(xDisplay, xBoardWindow, coordGC,\r
- x + squareSize - overall.width - 2, \r
- y + squareSize - font_descent - 1, string, 1);\r
- } else {\r
- XDrawString(xDisplay, xBoardWindow, coordGC,\r
- x + squareSize - overall.width - 2, \r
- y + squareSize - font_descent - 1, string, 1);\r
- }\r
- }\r
- if (appData.showCoords && column == (flipView ? BOARD_RGHT-1 : BOARD_LEFT)) {\r
- string[0] = ONE + row;\r
- XTextExtents(coordFontStruct, string, 1, &direction, \r
- &font_ascent, &font_descent, &overall);\r
- if (appData.monoMode) {\r
- XDrawImageString(xDisplay, xBoardWindow, coordGC,\r
- x + 2, y + font_ascent + 1, string, 1);\r
- } else {\r
- XDrawString(xDisplay, xBoardWindow, coordGC,\r
- x + 2, y + font_ascent + 1, string, 1);\r
- } \r
- } \r
-}\r
-\r
-\r
-/* Why is this needed on some versions of X? */\r
-void EventProc(widget, unused, event)\r
- Widget widget;\r
- caddr_t unused;\r
- XEvent *event;\r
-{\r
- if (!XtIsRealized(widget))\r
- return;\r
-\r
- switch (event->type) {\r
- case Expose:\r
- if (event->xexpose.count > 0) return; /* no clipping is done */\r
- XDrawPosition(widget, True, NULL);\r
- break;\r
- default:\r
- return;\r
- }\r
-}\r
-/* end why */\r
-\r
-void DrawPosition(fullRedraw, board)\r
- /*Boolean*/int fullRedraw;\r
- Board board;\r
-{\r
- XDrawPosition(boardWidget, fullRedraw, board);\r
-}\r
-\r
-/* Returns 1 if there are "too many" differences between b1 and b2\r
- (i.e. more than 1 move was made) */\r
-static int too_many_diffs(b1, b2)\r
- Board b1, b2;\r
-{\r
- int i, j;\r
- int c = 0;\r
- \r
- for (i=0; i<BOARD_HEIGHT; ++i) {\r
- for (j=0; j<BOARD_WIDTH; ++j) {\r
- if (b1[i][j] != b2[i][j]) {\r
- if (++c > 4) /* Castling causes 4 diffs */\r
- return 1;\r
- }\r
- }\r
- }\r
-\r
- return 0;\r
-}\r
-\r
-/* Matrix describing castling maneuvers */\r
-/* Row, ColRookFrom, ColKingFrom, ColRookTo, ColKingTo */\r
-static int castling_matrix[4][5] = {\r
- { 0, 0, 4, 3, 2 }, /* 0-0-0, white */\r
- { 0, 7, 4, 5, 6 }, /* 0-0, white */\r
- { 7, 0, 4, 3, 2 }, /* 0-0-0, black */\r
- { 7, 7, 4, 5, 6 } /* 0-0, black */\r
-};\r
-\r
-/* Checks whether castling occurred. If it did, *rrow and *rcol\r
- are set to the destination (row,col) of the rook that moved.\r
- \r
- Returns 1 if castling occurred, 0 if not.\r
- \r
- Note: Only handles a max of 1 castling move, so be sure\r
- to call too_many_diffs() first.\r
- */\r
-static int check_castle_draw(newb, oldb, rrow, rcol)\r
- Board newb, oldb;\r
- int *rrow, *rcol;\r
-{\r
- int i, *r, j;\r
- int match;\r
-\r
- /* For each type of castling... */\r
- for (i=0; i<4; ++i) {\r
- r = castling_matrix[i];\r
-\r
- /* Check the 4 squares involved in the castling move */\r
- match = 0;\r
- for (j=1; j<=4; ++j) {\r
- if (newb[r[0]][r[j]] == oldb[r[0]][r[j]]) {\r
- match = 1;\r
- break;\r
- }\r
- }\r
-\r
- if (!match) {\r
- /* All 4 changed, so it must be a castling move */\r
- *rrow = r[0];\r
- *rcol = r[3];\r
- return 1;\r
- }\r
- }\r
- return 0;\r
-}\r
-\r
-static int damage[BOARD_SIZE][BOARD_SIZE];\r
-\r
-/*\r
- * event handler for redrawing the board\r
- */\r
-void XDrawPosition(w, repaint, board)\r
- Widget w;\r
- /*Boolean*/int repaint;\r
- Board board;\r
-{\r
- int i, j, do_flash;\r
- static int lastFlipView = 0;\r
- static int lastBoardValid = 0;\r
- static Board lastBoard;\r
- Arg args[16];\r
- int rrow, rcol;\r
- \r
- if (board == NULL) {\r
- if (!lastBoardValid) return;\r
- board = lastBoard;\r
- }\r
- if (!lastBoardValid || lastFlipView != flipView) {\r
- XtSetArg(args[0], XtNleftBitmap, (flipView ? xMarkPixmap : None));\r
- XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flip View"),\r
- args, 1);\r
- }\r
-\r
- /*\r
- * It would be simpler to clear the window with XClearWindow()\r
- * but this causes a very distracting flicker.\r
- */\r
- \r
- if (!repaint && lastBoardValid && lastFlipView == flipView) {\r
-\r
- /* If too much changes (begin observing new game, etc.), don't\r
- do flashing */\r
- do_flash = too_many_diffs(board, lastBoard) ? 0 : 1;\r
-\r
- /* Special check for castling so we don't flash both the king\r
- and the rook (just flash the king). */\r
- if (do_flash) {\r
- if (check_castle_draw(board, lastBoard, &rrow, &rcol)) {\r
- /* Draw rook with NO flashing. King will be drawn flashing later */\r
- DrawSquare(rrow, rcol, board[rrow][rcol], 0);\r
- lastBoard[rrow][rcol] = board[rrow][rcol];\r
- }\r
- }\r
-\r
- /* First pass -- Draw (newly) empty squares and repair damage. \r
- This prevents you from having a piece show up twice while it \r
- is flashing on its new square */\r
- for (i = 0; i < BOARD_HEIGHT; i++)\r
- for (j = 0; j < BOARD_WIDTH; j++)\r
- if ((board[i][j] != lastBoard[i][j] && board[i][j] == EmptySquare)\r
- || damage[i][j]) {\r
- DrawSquare(i, j, board[i][j], 0);\r
- damage[i][j] = False;\r
- }\r
-\r
- /* Second pass -- Draw piece(s) in new position and flash them */\r
- for (i = 0; i < BOARD_HEIGHT; i++)\r
- for (j = 0; j < BOARD_WIDTH; j++)\r
- if (board[i][j] != lastBoard[i][j]) {\r
- DrawSquare(i, j, board[i][j], do_flash); \r
- }\r
- } else {\r
- if (lineGap > 0)\r
- XDrawSegments(xDisplay, xBoardWindow, lineGC,\r
- gridSegments, BOARD_HEIGHT + BOARD_WIDTH + 2);\r
- \r
- for (i = 0; i < BOARD_HEIGHT; i++)\r
- for (j = 0; j < BOARD_WIDTH; j++) {\r
- DrawSquare(i, j, board[i][j], 0);\r
- damage[i][j] = False;\r
- }\r
- }\r
-\r
- CopyBoard(lastBoard, board);\r
- lastBoardValid = 1;\r
- lastFlipView = flipView;\r
-\r
- /* Draw highlights */\r
- if (pm1X >= 0 && pm1Y >= 0) {\r
- drawHighlight(pm1X, pm1Y, prelineGC);\r
- }\r
- if (pm2X >= 0 && pm2Y >= 0) {\r
- drawHighlight(pm2X, pm2Y, prelineGC);\r
- }\r
- if (hi1X >= 0 && hi1Y >= 0) {\r
- drawHighlight(hi1X, hi1Y, highlineGC);\r
- }\r
- if (hi2X >= 0 && hi2Y >= 0) {\r
- drawHighlight(hi2X, hi2Y, highlineGC);\r
- }\r
-\r
- /* If piece being dragged around board, must redraw that too */\r
- DrawDragPiece();\r
-\r
- XSync(xDisplay, False);\r
-}\r
-\r
-\r
-/*\r
- * event handler for redrawing the board\r
- */\r
-void DrawPositionProc(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- XDrawPosition(w, True, NULL);\r
-}\r
-\r
-\r
-/*\r
- * event handler for parsing user moves\r
- */\r
-// [HGM] This routine will need quite some reworking. Although the backend still supports the old\r
-// way of doing things, by calling UserMoveEvent() to test the legality of the move and then perform\r
-// it at the end, and doing all kind of preliminary tests here (e.g. to weed out self-captures), it\r
-// should be made to use the new way, of calling UserMoveTest early to determine the legality of the\r
-// move, (which will weed out the illegal selfcaptures and moves into the holdings, and flag promotions),\r
-// and at the end FinishMove() to perform the move after optional promotion popups.\r
-// For now I patched it to allow self-capture with King, and suppress clicks between board and holdings.\r
-void HandleUserMove(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- int x, y;\r
- Boolean saveAnimate;\r
- static int second = 0;\r
- \r
- if (w != boardWidget || errorExitStatus != -1) return;\r
-\r
- if (event->type == ButtonPress) ErrorPopDown();\r
-\r
- if (promotionUp) {\r
- if (event->type == ButtonPress) {\r
- XtPopdown(promotionShell);\r
- XtDestroyWidget(promotionShell);\r
- promotionUp = False;\r
- ClearHighlights();\r
- fromX = fromY = -1;\r
- } else {\r
- return;\r
- }\r
- }\r
- \r
- x = EventToSquare(event->xbutton.x, BOARD_WIDTH);\r
- y = EventToSquare(event->xbutton.y, BOARD_HEIGHT);\r
- if (!flipView && y >= 0) {\r
- y = BOARD_HEIGHT - 1 - y;\r
- }\r
- if (flipView && x >= 0) {\r
- x = BOARD_WIDTH - 1 - x;\r
- }\r
-\r
- /* [HGM] holdings: next 5 lines: ignore all clicks between board and holdings */\r
- if(event->type == ButtonPress\r
- && ( x == BOARD_LEFT-1 || x == BOARD_RGHT\r
- || x == BOARD_LEFT-2 && y < BOARD_HEIGHT-gameInfo.holdingsSize\r
- || x == BOARD_RGHT+1 && y >= gameInfo.holdingsSize) )\r
- return;\r
-\r
- if (fromX == -1) {\r
- if (event->type == ButtonPress) {\r
- /* First square */ \r
- if (OKToStartUserMove(x, y)) {\r
- fromX = x;\r
- fromY = y;\r
- second = 0;\r
- DragPieceBegin(event->xbutton.x, event->xbutton.y);\r
- if (appData.highlightDragging) {\r
- SetHighlights(x, y, -1, -1);\r
- }\r
- } \r
- }\r
- return;\r
- }\r
-\r
- /* fromX != -1 */\r
- if (event->type == ButtonPress && gameMode != EditPosition &&\r
- x >= 0 && y >= 0) {\r
- ChessSquare fromP;\r
- ChessSquare toP;\r
-\r
- /* Check if clicking again on the same color piece */\r
- fromP = boards[currentMove][fromY][fromX];\r
- toP = boards[currentMove][y][x];\r
- if ((WhitePawn <= fromP && fromP < WhiteKing && // [HGM] this test should go, as UserMoveTest now does it.\r
- WhitePawn <= toP && toP <= WhiteKing) || // For now I made it less critical by exempting King\r
- (BlackPawn <= fromP && fromP < BlackKing && // moves, to not interfere with FRC castlings.\r
- BlackPawn <= toP && toP <= BlackKing)) {\r
- /* Clicked again on same color piece -- changed his mind */\r
- second = (x == fromX && y == fromY);\r
- if (appData.highlightDragging) {\r
- SetHighlights(x, y, -1, -1);\r
- } else {\r
- ClearHighlights();\r
- }\r
- if (OKToStartUserMove(x, y)) {\r
- fromX = x;\r
- fromY = y;\r
- DragPieceBegin(event->xbutton.x, event->xbutton.y);\r
- }\r
- return;\r
- }\r
- }\r
-\r
- if (event->type == ButtonRelease && x == fromX && y == fromY) {\r
- DragPieceEnd(event->xbutton.x, event->xbutton.y);\r
- if (appData.animateDragging) {\r
- /* Undo animation damage if any */\r
- DrawPosition(FALSE, NULL);\r
- }\r
- if (second) {\r
- /* Second up/down in same square; just abort move */\r
- second = 0;\r
- fromX = fromY = -1;\r
- ClearHighlights();\r
- gotPremove = 0;\r
- ClearPremoveHighlights();\r
- } else {\r
- /* First upclick in same square; start click-click mode */\r
- SetHighlights(x, y, -1, -1);\r
- }\r
- return;\r
- } \r
-\r
- /* Completed move */\r
- toX = x;\r
- toY = y;\r
- saveAnimate = appData.animate;\r
- if (event->type == ButtonPress) {\r
- /* Finish clickclick move */\r
- if (appData.animate || appData.highlightLastMove) {\r
- SetHighlights(fromX, fromY, toX, toY);\r
- } else {\r
- ClearHighlights();\r
- }\r
- } else {\r
- /* Finish drag move */\r
- if (appData.highlightLastMove) {\r
- SetHighlights(fromX, fromY, toX, toY);\r
- } else {\r
- ClearHighlights();\r
- }\r
- DragPieceEnd(event->xbutton.x, event->xbutton.y);\r
- /* Don't animate move and drag both */\r
- appData.animate = FALSE;\r
- }\r
- if (IsPromotion(fromX, fromY, toX, toY)) {\r
- if (appData.alwaysPromoteToQueen) {\r
- UserMoveEvent(fromX, fromY, toX, toY, 'q');\r
- if (!appData.highlightLastMove || gotPremove) ClearHighlights();\r
- if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);\r
- fromX = fromY = -1;\r
- } else {\r
- SetHighlights(fromX, fromY, toX, toY);\r
- PromotionPopUp();\r
- }\r
- } else {\r
- UserMoveEvent(fromX, fromY, toX, toY, NULLCHAR);\r
- if (!appData.highlightLastMove || gotPremove) ClearHighlights();\r
- if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);\r
- fromX = fromY = -1;\r
- }\r
- appData.animate = saveAnimate;\r
- if (appData.animate || appData.animateDragging) {\r
- /* Undo animation damage if needed */\r
- DrawPosition(FALSE, NULL);\r
- }\r
-}\r
-\r
-void AnimateUserMove (Widget w, XEvent * event,\r
- String * params, Cardinal * nParams)\r
-{\r
- DragPieceMove(event->xmotion.x, event->xmotion.y);\r
-}\r
-\r
-Widget CommentCreate(name, text, mutable, callback, lines)\r
- char *name, *text;\r
- int /*Boolean*/ mutable;\r
- XtCallbackProc callback;\r
- int lines;\r
-{\r
- Arg args[16];\r
- Widget shell, layout, form, edit, b_ok, b_cancel, b_clear, b_close, b_edit;\r
- Dimension bw_width;\r
- int j;\r
-\r
- j = 0;\r
- XtSetArg(args[j], XtNwidth, &bw_width); j++;\r
- XtGetValues(boardWidget, args, j);\r
-\r
- j = 0;\r
- XtSetArg(args[j], XtNresizable, True); j++;\r
-#if TOPLEVEL\r
- shell =\r
- XtCreatePopupShell(name, topLevelShellWidgetClass,\r
- shellWidget, args, j);\r
-#else\r
- shell =\r
- XtCreatePopupShell(name, transientShellWidgetClass,\r
- shellWidget, args, j);\r
-#endif\r
- layout =\r
- XtCreateManagedWidget(layoutName, formWidgetClass, shell,\r
- layoutArgs, XtNumber(layoutArgs));\r
- form =\r
- XtCreateManagedWidget("form", formWidgetClass, layout,\r
- formArgs, XtNumber(formArgs));\r
-\r
- j = 0;\r
- if (mutable) {\r
- XtSetArg(args[j], XtNeditType, XawtextEdit); j++;\r
- XtSetArg(args[j], XtNuseStringInPlace, False); j++;\r
- }\r
- XtSetArg(args[j], XtNstring, text); j++;\r
- XtSetArg(args[j], XtNtop, XtChainTop); j++;\r
- XtSetArg(args[j], XtNbottom, XtChainBottom); j++;\r
- XtSetArg(args[j], XtNleft, XtChainLeft); j++;\r
- XtSetArg(args[j], XtNright, XtChainRight); j++;\r
- XtSetArg(args[j], XtNresizable, True); j++;\r
- XtSetArg(args[j], XtNwidth, bw_width); j++; /*force wider than buttons*/\r
-#if 0\r
- XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;\r
-#else\r
- /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */\r
- XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;\r
-#endif\r
- XtSetArg(args[j], XtNautoFill, True); j++;\r
- XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;\r
- edit =\r
- XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);\r
-\r
- if (mutable) {\r
- j = 0;\r
- XtSetArg(args[j], XtNfromVert, edit); j++;\r
- XtSetArg(args[j], XtNtop, XtChainBottom); j++;\r
- XtSetArg(args[j], XtNbottom, XtChainBottom); j++;\r
- XtSetArg(args[j], XtNleft, XtChainLeft); j++;\r
- XtSetArg(args[j], XtNright, XtChainLeft); j++;\r
- b_ok =\r
- XtCreateManagedWidget(_("ok"), commandWidgetClass, form, args, j);\r
- XtAddCallback(b_ok, XtNcallback, callback, (XtPointer) 0);\r
-\r
- j = 0;\r
- XtSetArg(args[j], XtNfromVert, edit); j++;\r
- XtSetArg(args[j], XtNfromHoriz, b_ok); j++;\r
- XtSetArg(args[j], XtNtop, XtChainBottom); j++;\r
- XtSetArg(args[j], XtNbottom, XtChainBottom); j++;\r
- XtSetArg(args[j], XtNleft, XtChainLeft); j++;\r
- XtSetArg(args[j], XtNright, XtChainLeft); j++;\r
- b_cancel =\r
- XtCreateManagedWidget(_("cancel"), commandWidgetClass, form, args, j);\r
- XtAddCallback(b_cancel, XtNcallback, callback, (XtPointer) 0);\r
-\r
- j = 0;\r
- XtSetArg(args[j], XtNfromVert, edit); j++;\r
- XtSetArg(args[j], XtNfromHoriz, b_cancel); j++;\r
- XtSetArg(args[j], XtNtop, XtChainBottom); j++;\r
- XtSetArg(args[j], XtNbottom, XtChainBottom); j++;\r
- XtSetArg(args[j], XtNleft, XtChainLeft); j++;\r
- XtSetArg(args[j], XtNright, XtChainLeft); j++;\r
- b_clear =\r
- XtCreateManagedWidget(_("clear"), commandWidgetClass, form, args, j);\r
- XtAddCallback(b_clear, XtNcallback, callback, (XtPointer) 0);\r
- } else {\r
- j = 0;\r
- XtSetArg(args[j], XtNfromVert, edit); j++;\r
- XtSetArg(args[j], XtNtop, XtChainBottom); j++;\r
- XtSetArg(args[j], XtNbottom, XtChainBottom); j++;\r
- XtSetArg(args[j], XtNleft, XtChainLeft); j++;\r
- XtSetArg(args[j], XtNright, XtChainLeft); j++;\r
- b_close =\r
- XtCreateManagedWidget(_("close"), commandWidgetClass, form, args, j);\r
- XtAddCallback(b_close, XtNcallback, callback, (XtPointer) 0);\r
-\r
- j = 0;\r
- XtSetArg(args[j], XtNfromVert, edit); j++;\r
- XtSetArg(args[j], XtNfromHoriz, b_close); j++;\r
- XtSetArg(args[j], XtNtop, XtChainBottom); j++;\r
- XtSetArg(args[j], XtNbottom, XtChainBottom); j++;\r
- XtSetArg(args[j], XtNleft, XtChainLeft); j++;\r
- XtSetArg(args[j], XtNright, XtChainLeft); j++;\r
- b_edit =\r
- XtCreateManagedWidget(_("edit"), commandWidgetClass, form, args, j);\r
- XtAddCallback(b_edit, XtNcallback, callback, (XtPointer) 0);\r
- }\r
-\r
- XtRealizeWidget(shell);\r
-\r
- if (commentX == -1) {\r
- int xx, yy;\r
- Window junk;\r
- Dimension pw_height;\r
- Dimension ew_height;\r
-\r
- j = 0;\r
- XtSetArg(args[j], XtNheight, &ew_height); j++;\r
- XtGetValues(edit, args, j);\r
-\r
- j = 0;\r
- XtSetArg(args[j], XtNheight, &pw_height); j++;\r
- XtGetValues(shell, args, j);\r
- commentH = pw_height + (lines - 1) * ew_height;\r
- commentW = bw_width - 16;\r
-\r
- XSync(xDisplay, False);\r
-#ifdef NOTDEF\r
- /* This code seems to tickle an X bug if it is executed too soon\r
- after xboard starts up. The coordinates get transformed as if\r
- the main window was positioned at (0, 0).\r
- */\r
- XtTranslateCoords(shellWidget,\r
- (bw_width - commentW) / 2, 0 - commentH / 2,\r
- &commentX, &commentY);\r
-#else /*!NOTDEF*/\r
- XTranslateCoordinates(xDisplay, XtWindow(shellWidget),\r
- RootWindowOfScreen(XtScreen(shellWidget)),\r
- (bw_width - commentW) / 2, 0 - commentH / 2,\r
- &xx, &yy, &junk);\r
- commentX = xx;\r
- commentY = yy;\r
-#endif /*!NOTDEF*/\r
- if (commentY < 0) commentY = 0; /*avoid positioning top offscreen*/\r
- }\r
- j = 0;\r
- XtSetArg(args[j], XtNheight, commentH); j++;\r
- XtSetArg(args[j], XtNwidth, commentW); j++;\r
- XtSetArg(args[j], XtNx, commentX); j++;\r
- XtSetArg(args[j], XtNy, commentY); j++;\r
- XtSetValues(shell, args, j);\r
- XtSetKeyboardFocus(shell, edit);\r
-\r
- return shell;\r
-}\r
-\r
-/* Used for analysis window and ICS input window */\r
-Widget MiscCreate(name, text, mutable, callback, lines)\r
- char *name, *text;\r
- int /*Boolean*/ mutable;\r
- XtCallbackProc callback;\r
- int lines;\r
-{\r
- Arg args[16];\r
- Widget shell, layout, form, edit;\r
- Position x, y;\r
- Dimension bw_width, pw_height, ew_height, w, h;\r
- int j;\r
- int xx, yy;\r
- Window junk;\r
-\r
- j = 0;\r
- XtSetArg(args[j], XtNresizable, True); j++;\r
-#if TOPLEVEL\r
- shell =\r
- XtCreatePopupShell(name, topLevelShellWidgetClass,\r
- shellWidget, args, j);\r
-#else\r
- shell =\r
- XtCreatePopupShell(name, transientShellWidgetClass,\r
- shellWidget, args, j);\r
-#endif\r
- layout =\r
- XtCreateManagedWidget(layoutName, formWidgetClass, shell,\r
- layoutArgs, XtNumber(layoutArgs));\r
- form =\r
- XtCreateManagedWidget("form", formWidgetClass, layout,\r
- formArgs, XtNumber(formArgs));\r
-\r
- j = 0;\r
- if (mutable) {\r
- XtSetArg(args[j], XtNeditType, XawtextEdit); j++;\r
- XtSetArg(args[j], XtNuseStringInPlace, False); j++;\r
- }\r
- XtSetArg(args[j], XtNstring, text); j++;\r
- XtSetArg(args[j], XtNtop, XtChainTop); j++;\r
- XtSetArg(args[j], XtNbottom, XtChainBottom); j++;\r
- XtSetArg(args[j], XtNleft, XtChainLeft); j++;\r
- XtSetArg(args[j], XtNright, XtChainRight); j++;\r
- XtSetArg(args[j], XtNresizable, True); j++;\r
-#if 0\r
- XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;\r
-#else\r
- /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */\r
- XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;\r
-#endif\r
- XtSetArg(args[j], XtNautoFill, True); j++;\r
- XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;\r
- edit =\r
- XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);\r
-\r
- XtRealizeWidget(shell);\r
-\r
- j = 0;\r
- XtSetArg(args[j], XtNwidth, &bw_width); j++;\r
- XtGetValues(boardWidget, args, j);\r
-\r
- j = 0;\r
- XtSetArg(args[j], XtNheight, &ew_height); j++;\r
- XtGetValues(edit, args, j);\r
-\r
- j = 0;\r
- XtSetArg(args[j], XtNheight, &pw_height); j++;\r
- XtGetValues(shell, args, j);\r
- h = pw_height + (lines - 1) * ew_height;\r
- w = bw_width - 16;\r
-\r
- XSync(xDisplay, False);\r
-#ifdef NOTDEF\r
- /* This code seems to tickle an X bug if it is executed too soon\r
- after xboard starts up. The coordinates get transformed as if\r
- the main window was positioned at (0, 0).\r
- */\r
- XtTranslateCoords(shellWidget, (bw_width - w) / 2, 0 - h / 2, &x, &y);\r
-#else /*!NOTDEF*/\r
- XTranslateCoordinates(xDisplay, XtWindow(shellWidget),\r
- RootWindowOfScreen(XtScreen(shellWidget)),\r
- (bw_width - w) / 2, 0 - h / 2, &xx, &yy, &junk);\r
-#endif /*!NOTDEF*/\r
- x = xx;\r
- y = yy;\r
- if (y < 0) y = 0; /*avoid positioning top offscreen*/\r
-\r
- j = 0;\r
- XtSetArg(args[j], XtNheight, h); j++;\r
- XtSetArg(args[j], XtNwidth, w); j++;\r
- XtSetArg(args[j], XtNx, x); j++;\r
- XtSetArg(args[j], XtNy, y); j++;\r
- XtSetValues(shell, args, j);\r
-\r
- return shell;\r
-}\r
-\r
-\r
-static int savedIndex; /* gross that this is global */\r
-\r
-void EditCommentPopUp(index, title, text)\r
- int index;\r
- char *title, *text;\r
-{\r
- Widget edit;\r
- Arg args[16];\r
- int j;\r
-\r
- savedIndex = index;\r
- if (text == NULL) text = "";\r
-\r
- if (editShell == NULL) {\r
- editShell =\r
- CommentCreate(title, text, True, EditCommentCallback, 4); \r
- XtRealizeWidget(editShell);\r
- CatchDeleteWindow(editShell, "EditCommentPopDown");\r
- } else {\r
- edit = XtNameToWidget(editShell, "*form.text");\r
- j = 0;\r
- XtSetArg(args[j], XtNstring, text); j++;\r
- XtSetValues(edit, args, j);\r
- j = 0;\r
- XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;\r
- XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;\r
- XtSetValues(editShell, args, j);\r
- }\r
-\r
- XtPopup(editShell, XtGrabNone);\r
-\r
- editUp = True;\r
- j = 0;\r
- XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;\r
- XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),\r
- args, j);\r
-}\r
-\r
-void EditCommentCallback(w, client_data, call_data)\r
- Widget w;\r
- XtPointer client_data, call_data;\r
-{\r
- String name, val;\r
- Arg args[16];\r
- int j;\r
- Widget edit;\r
-\r
- j = 0;\r
- XtSetArg(args[j], XtNlabel, &name); j++;\r
- XtGetValues(w, args, j);\r
-\r
- if (strcmp(name, _("ok")) == 0) {\r
- edit = XtNameToWidget(editShell, "*form.text");\r
- j = 0;\r
- XtSetArg(args[j], XtNstring, &val); j++;\r
- XtGetValues(edit, args, j);\r
- ReplaceComment(savedIndex, val);\r
- EditCommentPopDown();\r
- } else if (strcmp(name, _("cancel")) == 0) {\r
- EditCommentPopDown();\r
- } else if (strcmp(name, _("clear")) == 0) {\r
- edit = XtNameToWidget(editShell, "*form.text");\r
- XtCallActionProc(edit, "select-all", NULL, NULL, 0);\r
- XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);\r
- }\r
-}\r
-\r
-void EditCommentPopDown()\r
-{\r
- Arg args[16];\r
- int j;\r
-\r
- if (!editUp) return;\r
- j = 0;\r
- XtSetArg(args[j], XtNx, &commentX); j++;\r
- XtSetArg(args[j], XtNy, &commentY); j++;\r
- XtSetArg(args[j], XtNheight, &commentH); j++;\r
- XtSetArg(args[j], XtNwidth, &commentW); j++;\r
- XtGetValues(editShell, args, j);\r
- XtPopdown(editShell);\r
- editUp = False;\r
- j = 0;\r
- XtSetArg(args[j], XtNleftBitmap, None); j++;\r
- XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),\r
- args, j);\r
-}\r
-\r
-void ICSInputBoxPopUp()\r
-{\r
- Widget edit;\r
- Arg args[16];\r
- int j;\r
- char *title = _("ICS Input");\r
- XtTranslations tr;\r
- \r
- if (ICSInputShell == NULL) {\r
- ICSInputShell = MiscCreate(title, "", True, NULL, 1);\r
- tr = XtParseTranslationTable(ICSInputTranslations);\r
- edit = XtNameToWidget(ICSInputShell, "*form.text");\r
- XtOverrideTranslations(edit, tr);\r
- XtRealizeWidget(ICSInputShell);\r
- CatchDeleteWindow(ICSInputShell, "ICSInputBoxPopDown");\r
- \r
- } else {\r
- edit = XtNameToWidget(ICSInputShell, "*form.text");\r
- j = 0;\r
- XtSetArg(args[j], XtNstring, ""); j++;\r
- XtSetValues(edit, args, j);\r
- j = 0;\r
- XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;\r
- XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;\r
- XtSetValues(ICSInputShell, args, j);\r
- }\r
-\r
- XtPopup(ICSInputShell, XtGrabNone);\r
- XtSetKeyboardFocus(ICSInputShell, edit);\r
-\r
- ICSInputBoxUp = True;\r
- j = 0;\r
- XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;\r
- XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),\r
- args, j);\r
-}\r
-\r
-void ICSInputSendText()\r
-{\r
- Widget edit;\r
- int j;\r
- Arg args[16];\r
- String val;\r
- \r
- edit = XtNameToWidget(ICSInputShell, "*form.text");\r
- j = 0;\r
- XtSetArg(args[j], XtNstring, &val); j++;\r
- XtGetValues(edit, args, j);\r
- SendMultiLineToICS(val);\r
- XtCallActionProc(edit, "select-all", NULL, NULL, 0);\r
- XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);\r
-}\r
-\r
-void ICSInputBoxPopDown()\r
-{\r
- Arg args[16];\r
- int j;\r
-\r
- if (!ICSInputBoxUp) return;\r
- j = 0;\r
- XtPopdown(ICSInputShell);\r
- ICSInputBoxUp = False;\r
- j = 0;\r
- XtSetArg(args[j], XtNleftBitmap, None); j++;\r
- XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),\r
- args, j);\r
-}\r
-\r
-void CommentPopUp(title, text)\r
- char *title, *text;\r
-{\r
- Arg args[16];\r
- int j;\r
- Widget edit;\r
-\r
- if (commentShell == NULL) {\r
- commentShell =\r
- CommentCreate(title, text, False, CommentCallback, 4);\r
- XtRealizeWidget(commentShell);\r
- CatchDeleteWindow(commentShell, "CommentPopDown");\r
- } else {\r
- edit = XtNameToWidget(commentShell, "*form.text");\r
- j = 0;\r
- XtSetArg(args[j], XtNstring, text); j++;\r
- XtSetValues(edit, args, j);\r
- j = 0;\r
- XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;\r
- XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;\r
- XtSetValues(commentShell, args, j);\r
- }\r
-\r
- XtPopup(commentShell, XtGrabNone);\r
- XSync(xDisplay, False);\r
-\r
- commentUp = True;\r
-}\r
-\r
-void AnalysisPopUp(title, text)\r
- char *title, *text;\r
-{\r
- Arg args[16];\r
- int j;\r
- Widget edit;\r
-\r
- if (analysisShell == NULL) {\r
- analysisShell = MiscCreate(title, text, False, NULL, 4);\r
- XtRealizeWidget(analysisShell);\r
- CatchDeleteWindow(analysisShell, "AnalysisPopDown");\r
-\r
- } else {\r
- edit = XtNameToWidget(analysisShell, "*form.text");\r
- j = 0;\r
- XtSetArg(args[j], XtNstring, text); j++;\r
- XtSetValues(edit, args, j);\r
- j = 0;\r
- XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;\r
- XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;\r
- XtSetValues(analysisShell, args, j);\r
- }\r
-\r
- if (!analysisUp) {\r
- XtPopup(analysisShell, XtGrabNone);\r
- }\r
- XSync(xDisplay, False);\r
-\r
- analysisUp = True;\r
-}\r
-\r
-void CommentCallback(w, client_data, call_data)\r
- Widget w;\r
- XtPointer client_data, call_data;\r
-{\r
- String name;\r
- Arg args[16];\r
- int j;\r
-\r
- j = 0;\r
- XtSetArg(args[j], XtNlabel, &name); j++;\r
- XtGetValues(w, args, j);\r
-\r
- if (strcmp(name, _("close")) == 0) {\r
- CommentPopDown();\r
- } else if (strcmp(name, _("edit")) == 0) {\r
- CommentPopDown();\r
- EditCommentEvent();\r
- }\r
-}\r
-\r
-\r
-void CommentPopDown()\r
-{\r
- Arg args[16];\r
- int j;\r
-\r
- if (!commentUp) return;\r
- j = 0;\r
- XtSetArg(args[j], XtNx, &commentX); j++;\r
- XtSetArg(args[j], XtNy, &commentY); j++;\r
- XtSetArg(args[j], XtNwidth, &commentW); j++;\r
- XtSetArg(args[j], XtNheight, &commentH); j++;\r
- XtGetValues(commentShell, args, j);\r
- XtPopdown(commentShell);\r
- XSync(xDisplay, False);\r
- commentUp = False;\r
-}\r
-\r
-void AnalysisPopDown()\r
-{\r
- if (!analysisUp) return;\r
- XtPopdown(analysisShell);\r
- XSync(xDisplay, False);\r
- analysisUp = False;\r
- if (appData.icsEngineAnalyze) ExitAnalyzeMode(); /* [DM] icsEngineAnalyze */\r
-}\r
-\r
-\r
-void FileNamePopUp(label, def, proc, openMode)\r
- char *label;\r
- char *def;\r
- FileProc proc;\r
- char *openMode;\r
-{\r
- Arg args[16];\r
- Widget popup, layout, dialog, edit;\r
- Window root, child;\r
- int x, y, i;\r
- int win_x, win_y;\r
- unsigned int mask;\r
- \r
- fileProc = proc; /* I can't see a way not */\r
- fileOpenMode = openMode; /* to use globals here */\r
- \r
- i = 0;\r
- XtSetArg(args[i], XtNresizable, True); i++;\r
- XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;\r
- XtSetArg(args[i], XtNtitle, XtNewString(_("File name prompt"))); i++;\r
- fileNameShell = popup =\r
- XtCreatePopupShell("File name prompt", transientShellWidgetClass,\r
- shellWidget, args, i);\r
- \r
- layout =\r
- XtCreateManagedWidget(layoutName, formWidgetClass, popup,\r
- layoutArgs, XtNumber(layoutArgs));\r
- \r
- i = 0;\r
- XtSetArg(args[i], XtNlabel, label); i++;\r
- XtSetArg(args[i], XtNvalue, def); i++;\r
- XtSetArg(args[i], XtNborderWidth, 0); i++;\r
- dialog = XtCreateManagedWidget("fileName", dialogWidgetClass,\r
- layout, args, i);\r
- \r
- XawDialogAddButton(dialog, _("ok"), FileNameCallback, (XtPointer) dialog);\r
- XawDialogAddButton(dialog, _("cancel"), FileNameCallback,\r
- (XtPointer) dialog);\r
- \r
- XtRealizeWidget(popup);\r
- CatchDeleteWindow(popup, "FileNamePopDown");\r
- \r
- XQueryPointer(xDisplay, xBoardWindow, &root, &child,\r
- &x, &y, &win_x, &win_y, &mask);\r
- \r
- XtSetArg(args[0], XtNx, x - 10);\r
- XtSetArg(args[1], XtNy, y - 30);\r
- XtSetValues(popup, args, 2);\r
- \r
- XtPopup(popup, XtGrabExclusive);\r
- filenameUp = True;\r
- \r
- edit = XtNameToWidget(dialog, "*value");\r
- XtSetKeyboardFocus(popup, edit);\r
-}\r
-\r
-void FileNamePopDown()\r
-{\r
- if (!filenameUp) return;\r
- XtPopdown(fileNameShell);\r
- XtDestroyWidget(fileNameShell);\r
- filenameUp = False;\r
- ModeHighlight();\r
-}\r
-\r
-void FileNameCallback(w, client_data, call_data)\r
- Widget w;\r
- XtPointer client_data, call_data;\r
-{\r
- String name;\r
- Arg args[16];\r
- \r
- XtSetArg(args[0], XtNlabel, &name);\r
- XtGetValues(w, args, 1);\r
- \r
- if (strcmp(name, _("cancel")) == 0) {\r
- FileNamePopDown();\r
- return;\r
- }\r
- \r
- FileNameAction(w, NULL, NULL, NULL);\r
-}\r
-\r
-void FileNameAction(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- char buf[MSG_SIZ];\r
- String name;\r
- FILE *f;\r
- char *p, *fullname;\r
- int index;\r
-\r
- name = XawDialogGetValueString(w = XtParent(w));\r
- \r
- if ((name != NULL) && (*name != NULLCHAR)) {\r
- strcpy(buf, name);\r
- XtPopdown(w = XtParent(XtParent(w)));\r
- XtDestroyWidget(w);\r
- filenameUp = False;\r
-\r
- p = strrchr(buf, ' ');\r
- if (p == NULL) {\r
- index = 0;\r
- } else {\r
- *p++ = NULLCHAR;\r
- index = atoi(p);\r
- }\r
- fullname = ExpandPathName(buf);\r
- if (!fullname) {\r
- ErrorPopUp(_("Error"), _("Can't open file"), FALSE);\r
- }\r
- else {\r
- f = fopen(fullname, fileOpenMode);\r
- if (f == NULL) {\r
- DisplayError(_("Failed to open file"), errno);\r
- } else {\r
- (void) (*fileProc)(f, index, buf);\r
- }\r
- }\r
- ModeHighlight();\r
- return;\r
- }\r
- \r
- XtPopdown(w = XtParent(XtParent(w)));\r
- XtDestroyWidget(w);\r
- filenameUp = False;\r
- ModeHighlight();\r
-}\r
-\r
-void PromotionPopUp()\r
-{\r
- Arg args[16];\r
- Widget dialog, layout;\r
- Position x, y;\r
- Dimension bw_width, pw_width;\r
- int j;\r
-\r
- j = 0;\r
- XtSetArg(args[j], XtNwidth, &bw_width); j++;\r
- XtGetValues(boardWidget, args, j);\r
- \r
- j = 0;\r
- XtSetArg(args[j], XtNresizable, True); j++;\r
- XtSetArg(args[j], XtNtitle, XtNewString(_("Promotion"))); j++;\r
- promotionShell =\r
- XtCreatePopupShell("Promotion", transientShellWidgetClass,\r
- shellWidget, args, j);\r
- layout =\r
- XtCreateManagedWidget(layoutName, formWidgetClass, promotionShell,\r
- layoutArgs, XtNumber(layoutArgs));\r
- \r
- j = 0;\r
- XtSetArg(args[j], XtNlabel, _("Promote pawn to what?")); j++;\r
- XtSetArg(args[j], XtNborderWidth, 0); j++;\r
- dialog = XtCreateManagedWidget("promotion", dialogWidgetClass,\r
- layout, args, j);\r
- \r
- XawDialogAddButton(dialog, _("Queen"), PromotionCallback, \r
- (XtPointer) dialog);\r
- XawDialogAddButton(dialog, _("Rook"), PromotionCallback, \r
- (XtPointer) dialog);\r
- XawDialogAddButton(dialog, _("Bishop"), PromotionCallback, \r
- (XtPointer) dialog);\r
- XawDialogAddButton(dialog, _("Knight"), PromotionCallback, \r
- (XtPointer) dialog);\r
- if (!appData.testLegality || gameInfo.variant == VariantSuicide ||\r
- gameInfo.variant == VariantGiveaway) {\r
- XawDialogAddButton(dialog, _("King"), PromotionCallback, \r
- (XtPointer) dialog);\r
- }\r
- XawDialogAddButton(dialog, _("cancel"), PromotionCallback, \r
- (XtPointer) dialog);\r
- \r
- XtRealizeWidget(promotionShell);\r
- CatchDeleteWindow(promotionShell, "PromotionPopDown");\r
- \r
- j = 0;\r
- XtSetArg(args[j], XtNwidth, &pw_width); j++;\r
- XtGetValues(promotionShell, args, j);\r
- \r
- XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,\r
- lineGap + squareSize/3 +\r
- ((toY == BOARD_HEIGHT-1) ^ (flipView) ?\r
- 0 : 6*(squareSize + lineGap)), &x, &y);\r
- \r
- j = 0;\r
- XtSetArg(args[j], XtNx, x); j++;\r
- XtSetArg(args[j], XtNy, y); j++;\r
- XtSetValues(promotionShell, args, j);\r
- \r
- XtPopup(promotionShell, XtGrabNone);\r
- \r
- promotionUp = True;\r
-}\r
-\r
-void PromotionPopDown()\r
-{\r
- if (!promotionUp) return;\r
- XtPopdown(promotionShell);\r
- XtDestroyWidget(promotionShell);\r
- promotionUp = False;\r
-}\r
-\r
-void PromotionCallback(w, client_data, call_data)\r
- Widget w;\r
- XtPointer client_data, call_data;\r
-{\r
- String name;\r
- Arg args[16];\r
- int promoChar;\r
- \r
- XtSetArg(args[0], XtNlabel, &name);\r
- XtGetValues(w, args, 1);\r
- \r
- PromotionPopDown();\r
- \r
- if (fromX == -1) return;\r
- \r
- if (strcmp(name, _("cancel")) == 0) {\r
- fromX = fromY = -1;\r
- ClearHighlights();\r
- return;\r
- } else if (strcmp(name, _("Knight")) == 0) {\r
- promoChar = 'n';\r
- } else {\r
- promoChar = ToLower(name[0]);\r
- }\r
-\r
- UserMoveEvent(fromX, fromY, toX, toY, promoChar);\r
-\r
- if (!appData.highlightLastMove || gotPremove) ClearHighlights();\r
- if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);\r
- fromX = fromY = -1;\r
-}\r
-\r
-\r
-void ErrorCallback(w, client_data, call_data)\r
- Widget w;\r
- XtPointer client_data, call_data;\r
-{\r
- errorUp = False;\r
- XtPopdown(w = XtParent(XtParent(XtParent(w))));\r
- XtDestroyWidget(w);\r
- if (errorExitStatus != -1) ExitEvent(errorExitStatus);\r
-}\r
-\r
-\r
-void ErrorPopDown()\r
-{\r
- if (!errorUp) return;\r
- errorUp = False;\r
- XtPopdown(errorShell);\r
- XtDestroyWidget(errorShell);\r
- if (errorExitStatus != -1) ExitEvent(errorExitStatus);\r
-}\r
-\r
-void ErrorPopUp(title, label, modal)\r
- char *title, *label;\r
- int modal;\r
-{\r
- Arg args[16];\r
- Widget dialog, layout;\r
- Position x, y;\r
- int xx, yy;\r
- Window junk;\r
- Dimension bw_width, pw_width;\r
- Dimension pw_height;\r
- int i;\r
- \r
- i = 0;\r
- XtSetArg(args[i], XtNresizable, True); i++;\r
- XtSetArg(args[i], XtNtitle, title); i++;\r
- errorShell = \r
- XtCreatePopupShell("errorpopup", transientShellWidgetClass,\r
- shellWidget, args, i);\r
- layout =\r
- XtCreateManagedWidget(layoutName, formWidgetClass, errorShell,\r
- layoutArgs, XtNumber(layoutArgs));\r
- \r
- i = 0;\r
- XtSetArg(args[i], XtNlabel, label); i++;\r
- XtSetArg(args[i], XtNborderWidth, 0); i++;\r
- dialog = XtCreateManagedWidget("dialog", dialogWidgetClass,\r
- layout, args, i);\r
- \r
- XawDialogAddButton(dialog, _("ok"), ErrorCallback, (XtPointer) dialog);\r
- \r
- XtRealizeWidget(errorShell);\r
- CatchDeleteWindow(errorShell, "ErrorPopDown");\r
- \r
- i = 0;\r
- XtSetArg(args[i], XtNwidth, &bw_width); i++;\r
- XtGetValues(boardWidget, args, i);\r
- i = 0;\r
- XtSetArg(args[i], XtNwidth, &pw_width); i++;\r
- XtSetArg(args[i], XtNheight, &pw_height); i++;\r
- XtGetValues(errorShell, args, i);\r
-\r
-#ifdef NOTDEF\r
- /* This code seems to tickle an X bug if it is executed too soon\r
- after xboard starts up. The coordinates get transformed as if\r
- the main window was positioned at (0, 0).\r
- */\r
- XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,\r
- 0 - pw_height + squareSize / 3, &x, &y);\r
-#else\r
- XTranslateCoordinates(xDisplay, XtWindow(boardWidget),\r
- RootWindowOfScreen(XtScreen(boardWidget)),\r
- (bw_width - pw_width) / 2,\r
- 0 - pw_height + squareSize / 3, &xx, &yy, &junk);\r
- x = xx;\r
- y = yy;\r
-#endif\r
- if (y < 0) y = 0; /*avoid positioning top offscreen*/\r
-\r
- i = 0;\r
- XtSetArg(args[i], XtNx, x); i++;\r
- XtSetArg(args[i], XtNy, y); i++;\r
- XtSetValues(errorShell, args, i);\r
-\r
- errorUp = True;\r
- XtPopup(errorShell, modal ? XtGrabExclusive : XtGrabNone);\r
-}\r
-\r
-/* Disable all user input other than deleting the window */\r
-static int frozen = 0;\r
-void FreezeUI()\r
-{\r
- if (frozen) return;\r
- /* Grab by a widget that doesn't accept input */\r
- XtAddGrab(messageWidget, TRUE, FALSE);\r
- frozen = 1;\r
-}\r
-\r
-/* Undo a FreezeUI */\r
-void ThawUI()\r
-{\r
- if (!frozen) return;\r
- XtRemoveGrab(messageWidget);\r
- frozen = 0;\r
-}\r
-\r
-char *ModeToWidgetName(mode)\r
- GameMode mode;\r
-{\r
- switch (mode) {\r
- case BeginningOfGame:\r
- if (appData.icsActive)\r
- return "menuMode.ICS Client";\r
- else if (appData.noChessProgram ||\r
- *appData.cmailGameName != NULLCHAR)\r
- return "menuMode.Edit Game";\r
- else\r
- return "menuMode.Machine Black";\r
- case MachinePlaysBlack:\r
- return "menuMode.Machine Black";\r
- case MachinePlaysWhite:\r
- return "menuMode.Machine White";\r
- case AnalyzeMode:\r
- return "menuMode.Analysis Mode";\r
- case AnalyzeFile:\r
- return "menuMode.Analyze File";\r
- case TwoMachinesPlay:\r
- return "menuMode.Two Machines";\r
- case EditGame:\r
- return "menuMode.Edit Game";\r
- case PlayFromGameFile:\r
- return "menuFile.Load Game";\r
- case EditPosition:\r
- return "menuMode.Edit Position";\r
- case Training:\r
- return "menuMode.Training";\r
- case IcsPlayingWhite:\r
- case IcsPlayingBlack:\r
- case IcsObserving:\r
- case IcsIdle:\r
- case IcsExamining:\r
- return "menuMode.ICS Client";\r
- default:\r
- case EndOfGame:\r
- return NULL;\r
- }\r
-} \r
-\r
-void ModeHighlight()\r
-{\r
- Arg args[16];\r
- static int oldPausing = FALSE;\r
- static GameMode oldmode = (GameMode) -1;\r
- char *wname;\r
- \r
- if (!boardWidget || !XtIsRealized(boardWidget)) return;\r
-\r
- if (pausing != oldPausing) {\r
- oldPausing = pausing;\r
- if (pausing) {\r
- XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);\r
- } else {\r
- XtSetArg(args[0], XtNleftBitmap, None);\r
- }\r
- XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Pause"),\r
- args, 1);\r
-\r
- if (appData.showButtonBar) {\r
-#if 0\r
- if (pausing) {\r
- XtSetArg(args[0], XtNbackground, buttonForegroundPixel);\r
- XtSetArg(args[1], XtNforeground, buttonBackgroundPixel);\r
- } else {\r
- XtSetArg(args[0], XtNbackground, buttonBackgroundPixel);\r
- XtSetArg(args[1], XtNforeground, buttonForegroundPixel);\r
- }\r
-#else\r
- /* Always toggle, don't set. Previous code messes up when\r
- invoked while the button is pressed, as releasing it\r
- toggles the state again. */\r
- {\r
- Pixel oldbg, oldfg;\r
- XtSetArg(args[0], XtNbackground, &oldbg);\r
- XtSetArg(args[1], XtNforeground, &oldfg);\r
- XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON),\r
- args, 2);\r
- XtSetArg(args[0], XtNbackground, oldfg);\r
- XtSetArg(args[1], XtNforeground, oldbg);\r
- }\r
-#endif\r
- XtSetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);\r
- }\r
- }\r
-\r
- wname = ModeToWidgetName(oldmode);\r
- if (wname != NULL) {\r
- XtSetArg(args[0], XtNleftBitmap, None);\r
- XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);\r
- }\r
- wname = ModeToWidgetName(gameMode);\r
- if (wname != NULL) {\r
- XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);\r
- XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);\r
- }\r
- oldmode = gameMode;\r
-\r
- /* Maybe all the enables should be handled here, not just this one */\r
- XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Training"),\r
- gameMode == Training || gameMode == PlayFromGameFile);\r
-}\r
-\r
-\r
-/*\r
- * Button/menu procedures\r
- */\r
-void ResetProc(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- ResetGameEvent();\r
- AnalysisPopDown();\r
-}\r
-\r
-int LoadGamePopUp(f, gameNumber, title)\r
- FILE *f;\r
- int gameNumber;\r
- char *title;\r
-{\r
- cmailMsgLoaded = FALSE;\r
- if (gameNumber == 0) {\r
- int error = GameListBuild(f);\r
- if (error) {\r
- DisplayError(_("Cannot build game list"), error);\r
- } else if (!ListEmpty(&gameList) &&\r
- ((ListGame *) gameList.tailPred)->number > 1) {\r
- GameListPopUp(f, title);\r
- return TRUE;\r
- }\r
- GameListDestroy();\r
- gameNumber = 1;\r
- }\r
- return LoadGame(f, gameNumber, title, FALSE);\r
-}\r
-\r
-void LoadGameProc(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {\r
- Reset(FALSE, TRUE);\r
- }\r
- FileNamePopUp(_("Load game file name?"), "", LoadGamePopUp, "rb");\r
-}\r
-\r
-void LoadNextGameProc(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- ReloadGame(1);\r
-}\r
-\r
-void LoadPrevGameProc(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- ReloadGame(-1);\r
-}\r
-\r
-void ReloadGameProc(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- ReloadGame(0);\r
-}\r
-\r
-void LoadNextPositionProc(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- ReloadPosition(1);\r
-}\r
-\r
-void LoadPrevPositionProc(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- ReloadPosition(-1);\r
-}\r
-\r
-void ReloadPositionProc(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- ReloadPosition(0);\r
-}\r
-\r
-void LoadPositionProc(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {\r
- Reset(FALSE, TRUE);\r
- }\r
- FileNamePopUp(_("Load position file name?"), "", LoadPosition, "rb");\r
-}\r
-\r
-void SaveGameProc(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- FileNamePopUp(_("Save game file name?"),\r
- DefaultFileName(appData.oldSaveStyle ? "game" : "pgn"),\r
- SaveGame, "a");\r
-}\r
-\r
-void SavePositionProc(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- FileNamePopUp(_("Save position file name?"),\r
- DefaultFileName(appData.oldSaveStyle ? "pos" : "fen"),\r
- SavePosition, "a");\r
-}\r
-\r
-void ReloadCmailMsgProc(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- ReloadCmailMsgEvent(FALSE);\r
-}\r
-\r
-void MailMoveProc(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- MailMoveEvent();\r
-}\r
-\r
-/* this variable is shared between CopyPositionProc and SendPositionSelection */\r
-static char *selected_fen_position=NULL;\r
-\r
-static Boolean\r
-SendPositionSelection(Widget w, Atom *selection, Atom *target,\r
- Atom *type_return, XtPointer *value_return,\r
- unsigned long *length_return, int *format_return)\r
-{\r
- char *selection_tmp;\r
-\r
- if (!selected_fen_position) return False; /* should never happen */\r
- if (*target == XA_STRING){\r
- /* note: since no XtSelectionDoneProc was registered, Xt will\r
- * automatically call XtFree on the value returned. So have to\r
- * make a copy of it allocated with XtMalloc */\r
- selection_tmp= XtMalloc(strlen(selected_fen_position)+16);\r
- strcpy(selection_tmp, selected_fen_position);\r
-\r
- *value_return=selection_tmp;\r
- *length_return=strlen(selection_tmp);\r
- *type_return=XA_STRING;\r
- *format_return = 8; /* bits per byte */\r
- return True;\r
- } else {\r
- return False;\r
- } \r
-}\r
-\r
-/* note: when called from menu all parameters are NULL, so no clue what the\r
- * Widget which was clicked on was, or what the click event was\r
- */\r
-void CopyPositionProc(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
- {\r
- int ret;\r
-\r
- if (selected_fen_position) free(selected_fen_position);\r
- selected_fen_position = (char *)PositionToFEN(currentMove,1);\r
- if (!selected_fen_position) return;\r
- ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,\r
- CurrentTime,\r
- SendPositionSelection,\r
- NULL/* lose_ownership_proc */ ,\r
- NULL/* transfer_done_proc */);\r
- if (!ret) {\r
- free(selected_fen_position);\r
- selected_fen_position=NULL;\r
- }\r
- }\r
-\r
-/* function called when the data to Paste is ready */\r
-static void\r
-PastePositionCB(Widget w, XtPointer client_data, Atom *selection,\r
- Atom *type, XtPointer value, unsigned long *len, int *format)\r
-{\r
- char *fenstr=value;\r
- if (value==NULL || *len==0) return; /* nothing had been selected to copy */\r
- fenstr[*len]='\0'; /* normally this string is terminated, but be safe */\r
- EditPositionPasteFEN(fenstr);\r
- XtFree(value);\r
-}\r
-\r
-/* called when Paste Position button is pressed,\r
- * all parameters will be NULL */\r
-void PastePositionProc(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,\r
- /* (XtSelectionCallbackProc) */ PastePositionCB,\r
- NULL, /* client_data passed to PastePositionCB */\r
-\r
- /* better to use the time field from the event that triggered the\r
- * call to this function, but that isn't trivial to get\r
- */\r
- CurrentTime\r
- );\r
- return;\r
-}\r
-\r
-static Boolean\r
-SendGameSelection(Widget w, Atom *selection, Atom *target,\r
- Atom *type_return, XtPointer *value_return,\r
- unsigned long *length_return, int *format_return)\r
-{\r
- char *selection_tmp;\r
-\r
- if (*target == XA_STRING){\r
- FILE* f = fopen(gameCopyFilename, "r");\r
- long len;\r
- size_t count;\r
- if (f == NULL) return False;\r
- fseek(f, 0, 2);\r
- len = ftell(f);\r
- rewind(f);\r
- selection_tmp = XtMalloc(len + 1);\r
- count = fread(selection_tmp, 1, len, f);\r
- if (len != count) {\r
- XtFree(selection_tmp);\r
- return False;\r
- }\r
- selection_tmp[len] = NULLCHAR;\r
- *value_return = selection_tmp;\r
- *length_return = len;\r
- *type_return = XA_STRING;\r
- *format_return = 8; /* bits per byte */\r
- return True;\r
- } else {\r
- return False;\r
- } \r
-}\r
-\r
-/* note: when called from menu all parameters are NULL, so no clue what the\r
- * Widget which was clicked on was, or what the click event was\r
- */\r
-void CopyGameProc(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- int ret;\r
-\r
- ret = SaveGameToFile(gameCopyFilename, FALSE);\r
- if (!ret) return;\r
-\r
- ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,\r
- CurrentTime,\r
- SendGameSelection,\r
- NULL/* lose_ownership_proc */ ,\r
- NULL/* transfer_done_proc */);\r
-}\r
-\r
-/* function called when the data to Paste is ready */\r
-static void\r
-PasteGameCB(Widget w, XtPointer client_data, Atom *selection,\r
- Atom *type, XtPointer value, unsigned long *len, int *format)\r
-{\r
- FILE* f;\r
- if (value == NULL || *len == 0) {\r
- return; /* nothing had been selected to copy */\r
- }\r
- f = fopen(gamePasteFilename, "w");\r
- if (f == NULL) {\r
- DisplayError(_("Can't open temp file"), errno);\r
- return;\r
- }\r
- fwrite(value, 1, *len, f);\r
- fclose(f);\r
- XtFree(value);\r
- LoadGameFromFile(gamePasteFilename, 0, gamePasteFilename, TRUE);\r
-}\r
-\r
-/* called when Paste Game button is pressed,\r
- * all parameters will be NULL */\r
-void PasteGameProc(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,\r
- /* (XtSelectionCallbackProc) */ PasteGameCB,\r
- NULL, /* client_data passed to PasteGameCB */\r
-\r
- /* better to use the time field from the event that triggered the\r
- * call to this function, but that isn't trivial to get\r
- */\r
- CurrentTime\r
- );\r
- return;\r
-}\r
-\r
-\r
-void AutoSaveGame()\r
-{\r
- SaveGameProc(NULL, NULL, NULL, NULL);\r
-}\r
-\r
-\r
-void QuitProc(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- ExitEvent(0);\r
-}\r
-\r
-void PauseProc(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- PauseEvent();\r
-}\r
-\r
-\r
-void MachineBlackProc(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- MachineBlackEvent();\r
-}\r
-\r
-void MachineWhiteProc(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- MachineWhiteEvent();\r
-}\r
-\r
-void AnalyzeModeProc(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- char buf[MSG_SIZ];\r
- \r
- if (!first.analysisSupport) {\r
- sprintf(buf, _("%s does not support analysis"), first.tidy);\r
- DisplayError(buf, 0);\r
- return;\r
- }\r
- /* [DM] icsEngineAnalyze [HGM] This is horrible code; reverse the gameMode and isEngineAnalyze tests! */\r
- if (appData.icsActive) {\r
- if (gameMode != IcsObserving) {\r
- sprintf(buf,_("You are not observing a game"));\r
- DisplayError(buf, 0);\r
- /* secure check */\r
- if (appData.icsEngineAnalyze) {\r
- if (appData.debugMode)\r
- fprintf(debugFP, _("Found unexpected active ICS engine analyze \n"));\r
- ExitAnalyzeMode();\r
- ModeHighlight();\r
- }\r
- return;\r
- }\r
- /* if enable, use want disable icsEngineAnalyze */\r
- if (appData.icsEngineAnalyze) {\r
- ExitAnalyzeMode();\r
- ModeHighlight();\r
- return;\r
- }\r
- appData.icsEngineAnalyze = TRUE;\r
- if (appData.debugMode)\r
- fprintf(debugFP, _("ICS engine analyze starting... \n"));\r
- } \r
- if (!appData.showThinking)\r
- ShowThinkingProc(w,event,prms,nprms);\r
-\r
- AnalyzeModeEvent();\r
-}\r
-\r
-void AnalyzeFileProc(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- if (!first.analysisSupport) {\r
- char buf[MSG_SIZ];\r
- sprintf(buf, _("%s does not support analysis"), first.tidy);\r
- DisplayError(buf, 0);\r
- return;\r
- }\r
- Reset(FALSE, TRUE);\r
-\r
- if (!appData.showThinking)\r
- ShowThinkingProc(w,event,prms,nprms);\r
-\r
- AnalyzeFileEvent();\r
- FileNamePopUp(_("File to analyze"), "", LoadGamePopUp, "rb");\r
- AnalysisPeriodicEvent(1);\r
-}\r
-\r
-void TwoMachinesProc(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- TwoMachinesEvent();\r
-}\r
-\r
-void IcsClientProc(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- IcsClientEvent();\r
-}\r
-\r
-void EditGameProc(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- EditGameEvent();\r
-}\r
-\r
-void EditPositionProc(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- EditPositionEvent();\r
-}\r
-\r
-void TrainingProc(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- TrainingEvent();\r
-}\r
-\r
-void EditCommentProc(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- if (editUp) {\r
- EditCommentPopDown();\r
- } else {\r
- EditCommentEvent();\r
- }\r
-}\r
-\r
-void IcsInputBoxProc(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- if (ICSInputBoxUp) {\r
- ICSInputBoxPopDown();\r
- } else {\r
- ICSInputBoxPopUp();\r
- }\r
-}\r
-\r
-void AcceptProc(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- AcceptEvent();\r
-}\r
-\r
-void DeclineProc(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- DeclineEvent();\r
-}\r
-\r
-void RematchProc(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- RematchEvent();\r
-}\r
-\r
-void CallFlagProc(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- CallFlagEvent();\r
-}\r
-\r
-void DrawProc(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- DrawEvent();\r
-}\r
-\r
-void AbortProc(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- AbortEvent();\r
-}\r
-\r
-void AdjournProc(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- AdjournEvent();\r
-}\r
-\r
-void ResignProc(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- ResignEvent();\r
-}\r
-\r
-void EnterKeyProc(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- if (ICSInputBoxUp == True)\r
- ICSInputSendText();\r
-}\r
-\r
-void StopObservingProc(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- StopObservingEvent();\r
-}\r
-\r
-void StopExaminingProc(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- StopExaminingEvent();\r
-}\r
-\r
-\r
-void ForwardProc(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- ForwardEvent();\r
-}\r
-\r
-\r
-void BackwardProc(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- BackwardEvent();\r
-}\r
-\r
-void ToStartProc(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- ToStartEvent();\r
-}\r
-\r
-void ToEndProc(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- ToEndEvent();\r
-}\r
-\r
-void RevertProc(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- RevertEvent();\r
-}\r
-\r
-void TruncateGameProc(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- TruncateGameEvent();\r
-}\r
-void RetractMoveProc(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- RetractMoveEvent();\r
-}\r
-\r
-void MoveNowProc(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- MoveNowEvent();\r
-}\r
-\r
-\r
-void AlwaysQueenProc(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- Arg args[16];\r
-\r
- appData.alwaysPromoteToQueen = !appData.alwaysPromoteToQueen;\r
-\r
- if (appData.alwaysPromoteToQueen) {\r
- XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);\r
- } else {\r
- XtSetArg(args[0], XtNleftBitmap, None);\r
- }\r
- XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),\r
- args, 1);\r
-}\r
-\r
-void AnimateDraggingProc(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- Arg args[16];\r
-\r
- appData.animateDragging = !appData.animateDragging;\r
-\r
- if (appData.animateDragging) {\r
- XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);\r
- CreateAnimVars();\r
- } else {\r
- XtSetArg(args[0], XtNleftBitmap, None);\r
- }\r
- XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Dragging"),\r
- args, 1);\r
-}\r
-\r
-void AnimateMovingProc(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- Arg args[16];\r
-\r
- appData.animate = !appData.animate;\r
-\r
- if (appData.animate) {\r
- XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);\r
- CreateAnimVars();\r
- } else {\r
- XtSetArg(args[0], XtNleftBitmap, None);\r
- }\r
- XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),\r
- args, 1);\r
-}\r
-\r
-void AutocommProc(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- Arg args[16];\r
-\r
- appData.autoComment = !appData.autoComment;\r
-\r
- if (appData.autoComment) {\r
- XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);\r
- } else {\r
- XtSetArg(args[0], XtNleftBitmap, None);\r
- }\r
- XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),\r
- args, 1);\r
-}\r
-\r
-\r
-void AutoflagProc(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- Arg args[16];\r
-\r
- appData.autoCallFlag = !appData.autoCallFlag;\r
-\r
- if (appData.autoCallFlag) {\r
- XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);\r
- } else {\r
- XtSetArg(args[0], XtNleftBitmap, None);\r
- }\r
- XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),\r
- args, 1);\r
-}\r
-\r
-void AutoflipProc(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- Arg args[16];\r
-\r
- appData.autoFlipView = !appData.autoFlipView;\r
-\r
- if (appData.autoFlipView) {\r
- XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);\r
- } else {\r
- XtSetArg(args[0], XtNleftBitmap, None);\r
- }\r
- XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flip View"),\r
- args, 1);\r
-}\r
-\r
-void AutobsProc(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- Arg args[16];\r
-\r
- appData.autoObserve = !appData.autoObserve;\r
-\r
- if (appData.autoObserve) {\r
- XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);\r
- } else {\r
- XtSetArg(args[0], XtNleftBitmap, None);\r
- }\r
- XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),\r
- args, 1);\r
-}\r
-\r
-void AutoraiseProc(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- Arg args[16];\r
-\r
- appData.autoRaiseBoard = !appData.autoRaiseBoard;\r
-\r
- if (appData.autoRaiseBoard) {\r
- XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);\r
- } else {\r
- XtSetArg(args[0], XtNleftBitmap, None);\r
- }\r
- XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Raise Board"),\r
- args, 1);\r
-}\r
-\r
-void AutosaveProc(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- Arg args[16];\r
-\r
- appData.autoSaveGames = !appData.autoSaveGames;\r
-\r
- if (appData.autoSaveGames) {\r
- XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);\r
- } else {\r
- XtSetArg(args[0], XtNleftBitmap, None);\r
- }\r
- XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),\r
- args, 1);\r
-}\r
-\r
-void BlindfoldProc(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- Arg args[16];\r
-\r
- appData.blindfold = !appData.blindfold;\r
-\r
- if (appData.blindfold) {\r
- XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);\r
- } else {\r
- XtSetArg(args[0], XtNleftBitmap, None);\r
- }\r
- XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Blindfold"),\r
- args, 1);\r
-\r
- DrawPosition(True, NULL);\r
-}\r
-\r
-void TestLegalityProc(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- Arg args[16];\r
-\r
- appData.testLegality = !appData.testLegality;\r
-\r
- if (appData.testLegality) {\r
- XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);\r
- } else {\r
- XtSetArg(args[0], XtNleftBitmap, None);\r
- }\r
- XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Test Legality"),\r
- args, 1);\r
-}\r
-\r
-\r
-void FlashMovesProc(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- Arg args[16];\r
-\r
- if (appData.flashCount == 0) {\r
- appData.flashCount = 3;\r
- } else {\r
- appData.flashCount = -appData.flashCount;\r
- }\r
-\r
- if (appData.flashCount > 0) {\r
- XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);\r
- } else {\r
- XtSetArg(args[0], XtNleftBitmap, None);\r
- }\r
- XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flash Moves"),\r
- args, 1);\r
-}\r
-\r
-void FlipViewProc(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- flipView = !flipView;\r
- DrawPosition(True, NULL);\r
-}\r
-\r
-void GetMoveListProc(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- Arg args[16];\r
-\r
- appData.getMoveList = !appData.getMoveList;\r
-\r
- if (appData.getMoveList) {\r
- XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);\r
- GetMoveListEvent();\r
- } else {\r
- XtSetArg(args[0], XtNleftBitmap, None);\r
- }\r
- XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),\r
- args, 1);\r
-}\r
-\r
-#if HIGHDRAG\r
-void HighlightDraggingProc(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- Arg args[16];\r
-\r
- appData.highlightDragging = !appData.highlightDragging;\r
-\r
- if (appData.highlightDragging) {\r
- XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);\r
- } else {\r
- XtSetArg(args[0], XtNleftBitmap, None);\r
- }\r
- XtSetValues(XtNameToWidget(menuBarWidget,\r
- "menuOptions.Highlight Dragging"), args, 1);\r
-}\r
-#endif\r
-\r
-void HighlightLastMoveProc(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- Arg args[16];\r
-\r
- appData.highlightLastMove = !appData.highlightLastMove;\r
-\r
- if (appData.highlightLastMove) {\r
- XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);\r
- } else {\r
- XtSetArg(args[0], XtNleftBitmap, None);\r
- }\r
- XtSetValues(XtNameToWidget(menuBarWidget,\r
- "menuOptions.Highlight Last Move"), args, 1);\r
-}\r
-\r
-void IcsAlarmProc(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- Arg args[16];\r
-\r
- appData.icsAlarm = !appData.icsAlarm;\r
-\r
- if (appData.icsAlarm) {\r
- XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);\r
- } else {\r
- XtSetArg(args[0], XtNleftBitmap, None);\r
- }\r
- XtSetValues(XtNameToWidget(menuBarWidget,\r
- "menuOptions.ICS Alarm"), args, 1);\r
-}\r
-\r
-void MoveSoundProc(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- Arg args[16];\r
-\r
- appData.ringBellAfterMoves = !appData.ringBellAfterMoves;\r
-\r
- if (appData.ringBellAfterMoves) {\r
- XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);\r
- } else {\r
- XtSetArg(args[0], XtNleftBitmap, None);\r
- }\r
- XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),\r
- args, 1);\r
-}\r
-\r
-\r
-void OldSaveStyleProc(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- Arg args[16];\r
-\r
- appData.oldSaveStyle = !appData.oldSaveStyle;\r
-\r
- if (appData.oldSaveStyle) {\r
- XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);\r
- } else {\r
- XtSetArg(args[0], XtNleftBitmap, None);\r
- }\r
- XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Old Save Style"),\r
- args, 1);\r
-}\r
-\r
-void PeriodicUpdatesProc(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- Arg args[16];\r
-\r
- PeriodicUpdatesEvent(!appData.periodicUpdates);\r
- \r
- if (appData.periodicUpdates) {\r
- XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);\r
- } else {\r
- XtSetArg(args[0], XtNleftBitmap, None);\r
- }\r
- XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Periodic Updates"),\r
- args, 1);\r
-}\r
-\r
-void PonderNextMoveProc(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- Arg args[16];\r
-\r
- PonderNextMoveEvent(!appData.ponderNextMove);\r
-\r
- if (appData.ponderNextMove) {\r
- XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);\r
- } else {\r
- XtSetArg(args[0], XtNleftBitmap, None);\r
- }\r
- XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Ponder Next Move"),\r
- args, 1);\r
-}\r
-\r
-void PopupExitMessageProc(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- Arg args[16];\r
-\r
- appData.popupExitMessage = !appData.popupExitMessage;\r
-\r
- if (appData.popupExitMessage) {\r
- XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);\r
- } else {\r
- XtSetArg(args[0], XtNleftBitmap, None);\r
- }\r
- XtSetValues(XtNameToWidget(menuBarWidget,\r
- "menuOptions.Popup Exit Message"), args, 1);\r
-}\r
-\r
-void PopupMoveErrorsProc(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- Arg args[16];\r
-\r
- appData.popupMoveErrors = !appData.popupMoveErrors;\r
-\r
- if (appData.popupMoveErrors) {\r
- XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);\r
- } else {\r
- XtSetArg(args[0], XtNleftBitmap, None);\r
- }\r
- XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Popup Move Errors"),\r
- args, 1);\r
-}\r
-\r
-void PremoveProc(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- Arg args[16];\r
-\r
- appData.premove = !appData.premove;\r
-\r
- if (appData.premove) {\r
- XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);\r
- } else {\r
- XtSetArg(args[0], XtNleftBitmap, None);\r
- }\r
- XtSetValues(XtNameToWidget(menuBarWidget,\r
- "menuOptions.Premove"), args, 1);\r
-}\r
-\r
-void QuietPlayProc(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- Arg args[16];\r
-\r
- appData.quietPlay = !appData.quietPlay;\r
-\r
- if (appData.quietPlay) {\r
- XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);\r
- } else {\r
- XtSetArg(args[0], XtNleftBitmap, None);\r
- }\r
- XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Quiet Play"),\r
- args, 1);\r
-}\r
-\r
-void ShowCoordsProc(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- Arg args[16];\r
-\r
- appData.showCoords = !appData.showCoords;\r
-\r
- if (appData.showCoords) {\r
- XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);\r
- } else {\r
- XtSetArg(args[0], XtNleftBitmap, None);\r
- }\r
- XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),\r
- args, 1);\r
-\r
- DrawPosition(True, NULL);\r
-}\r
-\r
-void ShowThinkingProc(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- Arg args[16];\r
-\r
- appData.showThinking = !appData.showThinking; // [HGM] thinking: tken out of ShowThinkingEvent\r
- ShowThinkingEvent();\r
-#if 0\r
- // [HGM] thinking: currently no suc menu item; replaced by Hide Thinking (From Human)\r
- if (appData.showThinking) {\r
- XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);\r
- } else {\r
- XtSetArg(args[0], XtNleftBitmap, None);\r
- }\r
- XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Thinking"),\r
- args, 1);\r
-#endif\r
-}\r
-\r
-void HideThinkingProc(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- Arg args[16];\r
-\r
- appData.hideThinkingFromHuman = !appData.hideThinkingFromHuman; // [HGM] thinking: tken out of ShowThinkingEvent\r
- ShowThinkingEvent();\r
-\r
- if (appData.hideThinkingFromHuman) {\r
- XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);\r
- } else {\r
- XtSetArg(args[0], XtNleftBitmap, None);\r
- }\r
- XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),\r
- args, 1);\r
-}\r
-\r
-void InfoProc(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- char buf[MSG_SIZ];\r
- sprintf(buf, "xterm -e info --directory %s --directory . -f %s &",\r
- INFODIR, INFOFILE);\r
- system(buf);\r
-}\r
-\r
-void ManProc(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- char buf[MSG_SIZ];\r
- String name;\r
- if (nprms && *nprms > 0)\r
- name = prms[0];\r
- else\r
- name = "xboard";\r
- sprintf(buf, "xterm -e man %s &", name);\r
- system(buf);\r
-}\r
-\r
-void HintProc(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- HintEvent();\r
-}\r
-\r
-void BookProc(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- BookEvent();\r
-}\r
-\r
-void AboutProc(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- char buf[MSG_SIZ];\r
-#if ZIPPY\r
- char *zippy = " (with Zippy code)";\r
-#else\r
- char *zippy = "";\r
-#endif\r
- sprintf(buf, "%s%s\n\n%s\n%s\n%s\n%s\n\n%s%s\n%s",\r
- programVersion, zippy,\r
- "Copyright 1991 Digital Equipment Corporation",\r
- "Enhancements Copyright 1992-2001 Free Software Foundation",\r
- "Enhancements Copyright 2005 Alessandro Scotti",\r
- "Enhancements Copyright 2007-2008 H.G.Muller",\r
- PRODUCT, " is free software and carries NO WARRANTY;",\r
- "see the file COPYING for more information.");\r
- ErrorPopUp(_("About XBoard"), buf, FALSE);\r
-}\r
-\r
-void DebugProc(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- appData.debugMode = !appData.debugMode;\r
-}\r
-\r
-void AboutGameProc(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- AboutGameEvent();\r
-}\r
-\r
-void NothingProc(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- return;\r
-}\r
-\r
-void Iconify(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- Arg args[16];\r
- \r
- fromX = fromY = -1;\r
- XtSetArg(args[0], XtNiconic, True);\r
- XtSetValues(shellWidget, args, 1);\r
-}\r
-\r
-void DisplayMessage(message, extMessage)\r
- char *message, *extMessage;\r
-{\r
- char buf[MSG_SIZ];\r
- Arg arg;\r
- \r
- if (extMessage) {\r
- if (*message) {\r
- sprintf(buf, "%s %s", message, extMessage);\r
- message = buf;\r
- } else {\r
- message = extMessage;\r
- }\r
- }\r
- XtSetArg(arg, XtNlabel, message);\r
- XtSetValues(messageWidget, &arg, 1);\r
-}\r
-\r
-void DisplayTitle(text)\r
- char *text;\r
-{\r
- Arg args[16];\r
- int i;\r
- char title[MSG_SIZ];\r
- char icon[MSG_SIZ];\r
-\r
- if (text == NULL) text = "";\r
-\r
- if (appData.titleInWindow) {\r
- i = 0;\r
- XtSetArg(args[i], XtNlabel, text); i++;\r
- XtSetValues(titleWidget, args, i);\r
- }\r
-\r
- if (*text != NULLCHAR) {\r
- strcpy(icon, text);\r
- strcpy(title, text);\r
- } else if (appData.icsActive) {\r
- sprintf(icon, "%s", appData.icsHost);\r
- sprintf(title, "%s: %s", programName, appData.icsHost);\r
- } else if (appData.cmailGameName[0] != NULLCHAR) {\r
- sprintf(icon, "%s", "CMail");\r
- sprintf(title, "%s: %s", programName, "CMail");\r
-#ifdef GOTHIC\r
- // [HGM] license: This stuff should really be done in back-end, but WinBoard already had a pop-up for it\r
- } else if (gameInfo.variant == VariantGothic) {\r
- strcpy(icon, programName);\r
- strcpy(title, GOTHIC);\r
-#endif\r
-#ifdef FALCON\r
- } else if (gameInfo.variant == VariantFalcon) {\r
- strcpy(icon, programName);\r
- strcpy(title, FALCON);\r
-#endif\r
- } else if (appData.noChessProgram) {\r
- strcpy(icon, programName);\r
- strcpy(title, programName);\r
- } else {\r
- strcpy(icon, first.tidy);\r
- sprintf(title, "%s: %s", programName, first.tidy);\r
- }\r
- i = 0;\r
- XtSetArg(args[i], XtNiconName, (XtArgVal) icon); i++;\r
- XtSetArg(args[i], XtNtitle, (XtArgVal) title); i++;\r
- XtSetValues(shellWidget, args, i);\r
-}\r
-\r
-\r
-void DisplayError(message, error)\r
- String message;\r
- int error;\r
-{\r
- char buf[MSG_SIZ];\r
-\r
- if (error == 0) {\r
- if (appData.debugMode || appData.matchMode) {\r
- fprintf(stderr, "%s: %s\n", programName, message);\r
- }\r
- } else {\r
- if (appData.debugMode || appData.matchMode) {\r
- fprintf(stderr, "%s: %s: %s\n",\r
- programName, message, strerror(error));\r
- }\r
- sprintf(buf, "%s: %s", message, strerror(error));\r
- message = buf;\r
- } \r
- ErrorPopUp(_("Error"), message, FALSE);\r
-}\r
-\r
-\r
-void DisplayMoveError(message)\r
- String message;\r
-{\r
- fromX = fromY = -1;\r
- ClearHighlights();\r
- DrawPosition(FALSE, NULL);\r
- if (appData.debugMode || appData.matchMode) {\r
- fprintf(stderr, "%s: %s\n", programName, message);\r
- }\r
- if (appData.popupMoveErrors) {\r
- ErrorPopUp(_("Error"), message, FALSE);\r
- } else {\r
- DisplayMessage(message, "");\r
- }\r
-}\r
-\r
-\r
-void DisplayFatalError(message, error, status)\r
- String message;\r
- int error, status;\r
-{\r
- char buf[MSG_SIZ];\r
-\r
- errorExitStatus = status;\r
- if (error == 0) {\r
- fprintf(stderr, "%s: %s\n", programName, message);\r
- } else {\r
- fprintf(stderr, "%s: %s: %s\n",\r
- programName, message, strerror(error));\r
- sprintf(buf, "%s: %s", message, strerror(error));\r
- message = buf;\r
- }\r
- if (appData.popupExitMessage && boardWidget && XtIsRealized(boardWidget)) {\r
- ErrorPopUp(status ? _("Fatal Error") : _("Exiting"), message, TRUE);\r
- } else {\r
- ExitEvent(status);\r
- }\r
-}\r
-\r
-void DisplayInformation(message)\r
- String message;\r
-{\r
- ErrorPopDown();\r
- ErrorPopUp(_("Information"), message, TRUE);\r
-}\r
-\r
-void DisplayNote(message)\r
- String message;\r
-{\r
- ErrorPopDown();\r
- ErrorPopUp(_("Note"), message, FALSE);\r
-}\r
-\r
-static int\r
-NullXErrorCheck(dpy, error_event)\r
- Display *dpy;\r
- XErrorEvent *error_event;\r
-{\r
- return 0;\r
-}\r
-\r
-void DisplayIcsInteractionTitle(message)\r
- String message;\r
-{\r
- if (oldICSInteractionTitle == NULL) {\r
- /* Magic to find the old window title, adapted from vim */\r
- char *wina = getenv("WINDOWID");\r
- if (wina != NULL) {\r
- Window win = (Window) atoi(wina);\r
- Window root, parent, *children;\r
- unsigned int nchildren;\r
- int (*oldHandler)() = XSetErrorHandler(NullXErrorCheck);\r
- for (;;) {\r
- if (XFetchName(xDisplay, win, &oldICSInteractionTitle)) break;\r
- if (!XQueryTree(xDisplay, win, &root, &parent,\r
- &children, &nchildren)) break;\r
- if (children) XFree((void *)children);\r
- if (parent == root || parent == 0) break;\r
- win = parent;\r
- }\r
- XSetErrorHandler(oldHandler);\r
- }\r
- if (oldICSInteractionTitle == NULL) {\r
- oldICSInteractionTitle = "xterm"; \r
- }\r
- } \r
- printf("\033]0;%s\007", message);\r
- fflush(stdout);\r
-}\r
-\r
-char pendingReplyPrefix[MSG_SIZ];\r
-ProcRef pendingReplyPR;\r
-\r
-void AskQuestionProc(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- if (*nprms != 4) {\r
- fprintf(stderr, _("AskQuestionProc needed 4 parameters, got %d\n"),\r
- *nprms);\r
- return;\r
- }\r
- AskQuestionEvent(prms[0], prms[1], prms[2], prms[3]);\r
-}\r
-\r
-void AskQuestionPopDown()\r
-{\r
- if (!askQuestionUp) return;\r
- XtPopdown(askQuestionShell);\r
- XtDestroyWidget(askQuestionShell);\r
- askQuestionUp = False;\r
-}\r
-\r
-void AskQuestionReplyAction(w, event, prms, nprms)\r
- Widget w;\r
- XEvent *event;\r
- String *prms;\r
- Cardinal *nprms;\r
-{\r
- char buf[MSG_SIZ];\r
- int err;\r
- String reply;\r
-\r
- reply = XawDialogGetValueString(w = XtParent(w));\r
- strcpy(buf, pendingReplyPrefix);\r
- if (*buf) strcat(buf, " ");\r
- strcat(buf, reply);\r
- strcat(buf, "\n");\r
- OutputToProcess(pendingReplyPR, buf, strlen(buf), &err);\r
- AskQuestionPopDown();\r
-\r
- if (err) DisplayFatalError(_("Error writing to chess program"), err, 0);\r
-}\r
-\r
-void AskQuestionCallback(w, client_data, call_data)\r
- Widget w;\r
- XtPointer client_data, call_data;\r
-{\r
- String name;\r
- Arg args[16];\r
-\r
- XtSetArg(args[0], XtNlabel, &name);\r
- XtGetValues(w, args, 1);\r
- \r
- if (strcmp(name, _("cancel")) == 0) {\r
- AskQuestionPopDown();\r
- } else {\r
- AskQuestionReplyAction(w, NULL, NULL, NULL);\r
- }\r
-}\r
-\r
-void AskQuestion(title, question, replyPrefix, pr)\r
- char *title, *question, *replyPrefix;\r
- ProcRef pr;\r
-{\r
- Arg args[16];\r
- Widget popup, layout, dialog, edit;\r
- Window root, child;\r
- int x, y, i;\r
- int win_x, win_y;\r
- unsigned int mask;\r
- \r
- strcpy(pendingReplyPrefix, replyPrefix);\r
- pendingReplyPR = pr;\r
- \r
- i = 0;\r
- XtSetArg(args[i], XtNresizable, True); i++;\r
- XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;\r
- askQuestionShell = popup =\r
- XtCreatePopupShell(title, transientShellWidgetClass,\r
- shellWidget, args, i);\r
- \r
- layout =\r
- XtCreateManagedWidget(layoutName, formWidgetClass, popup,\r
- layoutArgs, XtNumber(layoutArgs));\r
- \r
- i = 0;\r
- XtSetArg(args[i], XtNlabel, question); i++;\r
- XtSetArg(args[i], XtNvalue, ""); i++;\r
- XtSetArg(args[i], XtNborderWidth, 0); i++;\r
- dialog = XtCreateManagedWidget("question", dialogWidgetClass,\r
- layout, args, i);\r
- \r
- XawDialogAddButton(dialog, _("enter"), AskQuestionCallback,\r
- (XtPointer) dialog);\r
- XawDialogAddButton(dialog, _("cancel"), AskQuestionCallback,\r
- (XtPointer) dialog);\r
-\r
- XtRealizeWidget(popup);\r
- CatchDeleteWindow(popup, "AskQuestionPopDown");\r
- \r
- XQueryPointer(xDisplay, xBoardWindow, &root, &child,\r
- &x, &y, &win_x, &win_y, &mask);\r
- \r
- XtSetArg(args[0], XtNx, x - 10);\r
- XtSetArg(args[1], XtNy, y - 30);\r
- XtSetValues(popup, args, 2);\r
- \r
- XtPopup(popup, XtGrabExclusive);\r
- askQuestionUp = True;\r
- \r
- edit = XtNameToWidget(dialog, "*value");\r
- XtSetKeyboardFocus(popup, edit);\r
-}\r
-\r
-\r
-void\r
-PlaySound(name)\r
- char *name;\r
-{\r
- if (*name == NULLCHAR) {\r
- return;\r
- } else if (strcmp(name, "$") == 0) {\r
- putc(BELLCHAR, stderr);\r
- } else {\r
- char buf[2048];\r
- sprintf(buf, "%s '%s' &", appData.soundProgram, name);\r
- system(buf);\r
- }\r
-}\r
-\r
-void\r
-RingBell()\r
-{\r
- PlaySound(appData.soundMove);\r
-}\r
-\r
-void\r
-PlayIcsWinSound()\r
-{\r
- PlaySound(appData.soundIcsWin);\r
-}\r
-\r
-void\r
-PlayIcsLossSound()\r
-{\r
- PlaySound(appData.soundIcsLoss);\r
-}\r
-\r
-void\r
-PlayIcsDrawSound()\r
-{\r
- PlaySound(appData.soundIcsDraw);\r
-}\r
-\r
-void\r
-PlayIcsUnfinishedSound()\r
-{\r
- PlaySound(appData.soundIcsUnfinished);\r
-}\r
-\r
-void\r
-PlayAlarmSound()\r
-{\r
- PlaySound(appData.soundIcsAlarm);\r
-}\r
-\r
-void\r
-EchoOn()\r
-{\r
- system("stty echo");\r
-}\r
-\r
-void\r
-EchoOff()\r
-{\r
- system("stty -echo");\r
-}\r
-\r
-void\r
-Colorize(cc, continuation)\r
- ColorClass cc;\r
- int continuation;\r
-{\r
- char buf[MSG_SIZ];\r
- int count, outCount, error;\r
-\r
- if (textColors[(int)cc].bg > 0) {\r
- if (textColors[(int)cc].fg > 0) {\r
- sprintf(buf, "\033[0;%d;%d;%dm", textColors[(int)cc].attr,\r
- textColors[(int)cc].fg, textColors[(int)cc].bg);\r
- } else {\r
- sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,\r
- textColors[(int)cc].bg);\r
- }\r
- } else {\r
- if (textColors[(int)cc].fg > 0) {\r
- sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,\r
- textColors[(int)cc].fg);\r
- } else {\r
- sprintf(buf, "\033[0;%dm", textColors[(int)cc].attr);\r
- }\r
- }\r
- count = strlen(buf);\r
- outCount = OutputToProcess(NoProc, buf, count, &error);\r
- if (outCount < count) {\r
- DisplayFatalError(_("Error writing to display"), error, 1);\r
- }\r
-\r
- if (continuation) return;\r
- switch (cc) {\r
- case ColorShout:\r
- PlaySound(appData.soundShout);\r
- break;\r
- case ColorSShout:\r
- PlaySound(appData.soundSShout);\r
- break;\r
- case ColorChannel1:\r
- PlaySound(appData.soundChannel1);\r
- break;\r
- case ColorChannel:\r
- PlaySound(appData.soundChannel);\r
- break;\r
- case ColorKibitz:\r
- PlaySound(appData.soundKibitz);\r
- break;\r
- case ColorTell:\r
- PlaySound(appData.soundTell);\r
- break;\r
- case ColorChallenge:\r
- PlaySound(appData.soundChallenge);\r
- break;\r
- case ColorRequest:\r
- PlaySound(appData.soundRequest);\r
- break;\r
- case ColorSeek:\r
- PlaySound(appData.soundSeek);\r
- break;\r
- case ColorNormal:\r
- case ColorNone:\r
- default:\r
- break;\r
- }\r
-}\r
-\r
-char *UserName()\r
-{\r
- return getpwuid(getuid())->pw_name;\r
-}\r
-\r
-static char *ExpandPathName(path)\r
- char *path;\r
-{\r
- static char static_buf[2000];\r
- char *d, *s, buf[2000];\r
- struct passwd *pwd;\r
- \r
- s = path;\r
- d = static_buf;\r
-\r
- while (*s && isspace(*s))\r
- ++s;\r
-\r
- if (!*s) {\r
- *d = 0;\r
- return static_buf;\r
- }\r
-\r
- if (*s == '~') {\r
- if (*(s+1) == '/') {\r
- strcpy(d, getpwuid(getuid())->pw_dir);\r
- strcat(d, s+1);\r
- }\r
- else {\r
- strcpy(buf, s+1);\r
- *strchr(buf, '/') = 0;\r
- pwd = getpwnam(buf);\r
- if (!pwd)\r
- {\r
- fprintf(stderr, _("ERROR: Unknown user %s (in path %s)\n"),\r
- buf, path);\r
- return NULL;\r
- }\r
- strcpy(d, pwd->pw_dir);\r
- strcat(d, strchr(s+1, '/'));\r
- }\r
- }\r
- else\r
- strcpy(d, s);\r
-\r
- return static_buf;\r
-} \r
-\r
-char *HostName()\r
-{\r
- static char host_name[MSG_SIZ];\r
- \r
-#if HAVE_GETHOSTNAME\r
- gethostname(host_name, MSG_SIZ);\r
- return host_name;\r
-#else /* not HAVE_GETHOSTNAME */\r
-# if HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H\r
- sysinfo(SI_HOSTNAME, host_name, MSG_SIZ);\r
- return host_name;\r
-# else /* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */\r
- return "localhost";\r
-# endif/* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */\r
-#endif /* not HAVE_GETHOSTNAME */\r
-}\r
-\r
-XtIntervalId delayedEventTimerXID = 0;\r
-DelayedEventCallback delayedEventCallback = 0;\r
-\r
-void\r
-FireDelayedEvent()\r
-{\r
- delayedEventTimerXID = 0;\r
- delayedEventCallback();\r
-}\r
-\r
-void\r
-ScheduleDelayedEvent(cb, millisec)\r
- DelayedEventCallback cb; long millisec;\r
-{\r
- delayedEventCallback = cb;\r
- delayedEventTimerXID =\r
- XtAppAddTimeOut(appContext, millisec,\r
- (XtTimerCallbackProc) FireDelayedEvent, (XtPointer) 0);\r
-}\r
-\r
-DelayedEventCallback\r
-GetDelayedEvent()\r
-{\r
- if (delayedEventTimerXID) {\r
- return delayedEventCallback;\r
- } else {\r
- return NULL;\r
- }\r
-}\r
-\r
-void\r
-CancelDelayedEvent()\r
-{\r
- if (delayedEventTimerXID) {\r
- XtRemoveTimeOut(delayedEventTimerXID);\r
- delayedEventTimerXID = 0;\r
- }\r
-}\r
-\r
-XtIntervalId loadGameTimerXID = 0;\r
-\r
-int LoadGameTimerRunning()\r
-{\r
- return loadGameTimerXID != 0;\r
-}\r
-\r
-int StopLoadGameTimer()\r
-{\r
- if (loadGameTimerXID != 0) {\r
- XtRemoveTimeOut(loadGameTimerXID);\r
- loadGameTimerXID = 0;\r
- return TRUE;\r
- } else {\r
- return FALSE;\r
- }\r
-}\r
-\r
-void\r
-LoadGameTimerCallback(arg, id)\r
- XtPointer arg;\r
- XtIntervalId *id;\r
-{\r
- loadGameTimerXID = 0;\r
- AutoPlayGameLoop();\r
-}\r
-\r
-void\r
-StartLoadGameTimer(millisec)\r
- long millisec;\r
-{\r
- loadGameTimerXID =\r
- XtAppAddTimeOut(appContext, millisec,\r
- (XtTimerCallbackProc) LoadGameTimerCallback,\r
- (XtPointer) 0);\r
-}\r
-\r
-XtIntervalId analysisClockXID = 0;\r
-\r
-void\r
-AnalysisClockCallback(arg, id)\r
- XtPointer arg;\r
- XtIntervalId *id;\r
-{\r
- if (gameMode == AnalyzeMode || gameMode == AnalyzeFile \r
- || appData.icsEngineAnalyze) { // [DM]\r
- AnalysisPeriodicEvent(0);\r
- StartAnalysisClock();\r
- }\r
-}\r
-\r
-void\r
-StartAnalysisClock()\r
-{\r
- analysisClockXID =\r
- XtAppAddTimeOut(appContext, 2000,\r
- (XtTimerCallbackProc) AnalysisClockCallback,\r
- (XtPointer) 0);\r
-}\r
-\r
-XtIntervalId clockTimerXID = 0;\r
-\r
-int ClockTimerRunning()\r
-{\r
- return clockTimerXID != 0;\r
-}\r
-\r
-int StopClockTimer()\r
-{\r
- if (clockTimerXID != 0) {\r
- XtRemoveTimeOut(clockTimerXID);\r
- clockTimerXID = 0;\r
- return TRUE;\r
- } else {\r
- return FALSE;\r
- }\r
-}\r
-\r
-void\r
-ClockTimerCallback(arg, id)\r
- XtPointer arg;\r
- XtIntervalId *id;\r
-{\r
- clockTimerXID = 0;\r
- DecrementClocks();\r
-}\r
-\r
-void\r
-StartClockTimer(millisec)\r
- long millisec;\r
-{\r
- clockTimerXID =\r
- XtAppAddTimeOut(appContext, millisec,\r
- (XtTimerCallbackProc) ClockTimerCallback,\r
- (XtPointer) 0);\r
-}\r
-\r
-void\r
-DisplayTimerLabel(w, color, timer, highlight)\r
- Widget w;\r
- char *color;\r
- long timer;\r
- int highlight;\r
-{\r
- char buf[MSG_SIZ];\r
- Arg args[16];\r
- \r
- if (appData.clockMode) {\r
- sprintf(buf, "%s: %s", color, TimeString(timer));\r
- XtSetArg(args[0], XtNlabel, buf);\r
- } else {\r
- sprintf(buf, "%s ", color);\r
- XtSetArg(args[0], XtNlabel, buf);\r
- }\r
- \r
- if (highlight) {\r
- XtSetArg(args[1], XtNbackground, timerForegroundPixel);\r
- XtSetArg(args[2], XtNforeground, timerBackgroundPixel);\r
- } else {\r
- XtSetArg(args[1], XtNbackground, timerBackgroundPixel);\r
- XtSetArg(args[2], XtNforeground, timerForegroundPixel);\r
- }\r
- \r
- XtSetValues(w, args, 3);\r
-}\r
-\r
-void\r
-DisplayWhiteClock(timeRemaining, highlight)\r
- long timeRemaining;\r
- int highlight;\r
-{\r
- Arg args[16];\r
-\r
- if(appData.noGUI) return;\r
- DisplayTimerLabel(whiteTimerWidget, _("White"), timeRemaining, highlight);\r
- if (highlight && iconPixmap == bIconPixmap) {\r
- iconPixmap = wIconPixmap;\r
- XtSetArg(args[0], XtNiconPixmap, iconPixmap);\r
- XtSetValues(shellWidget, args, 1);\r
- }\r
-}\r
-\r
-void\r
-DisplayBlackClock(timeRemaining, highlight)\r
- long timeRemaining;\r
- int highlight;\r
-{\r
- Arg args[16];\r
-\r
- if(appData.noGUI) return;\r
- DisplayTimerLabel(blackTimerWidget, _("Black"), timeRemaining, highlight);\r
- if (highlight && iconPixmap == wIconPixmap) {\r
- iconPixmap = bIconPixmap;\r
- XtSetArg(args[0], XtNiconPixmap, iconPixmap);\r
- XtSetValues(shellWidget, args, 1);\r
- }\r
-}\r
-\r
-#define CPNone 0\r
-#define CPReal 1\r
-#define CPComm 2\r
-#define CPSock 3\r
-#define CPLoop 4\r
-typedef int CPKind;\r
-\r
-typedef struct {\r
- CPKind kind;\r
- int pid;\r
- int fdTo, fdFrom; \r
-} ChildProc;\r
-\r
-\r
-int StartChildProcess(cmdLine, dir, pr)\r
- char *cmdLine; \r
- char *dir;\r
- ProcRef *pr;\r
-{\r
- char *argv[64], *p;\r
- int i, pid;\r
- int to_prog[2], from_prog[2];\r
- ChildProc *cp;\r
- char buf[MSG_SIZ];\r
- \r
- if (appData.debugMode) {\r
- fprintf(stderr, "StartChildProcess (dir=\"%s\") %s\n",dir, cmdLine);\r
- }\r
-\r
- /* We do NOT feed the cmdLine to the shell; we just\r
- parse it into blank-separated arguments in the\r
- most simple-minded way possible.\r
- */\r
- i = 0;\r
- strcpy(buf, cmdLine);\r
- p = buf;\r
- for (;;) {\r
- argv[i++] = p;\r
- p = strchr(p, ' ');\r
- if (p == NULL) break;\r
- *p++ = NULLCHAR;\r
- }\r
- argv[i] = NULL;\r
-\r
- SetUpChildIO(to_prog, from_prog);\r
-\r
- if ((pid = fork()) == 0) {\r
- /* Child process */\r
- // [HGM] PSWBTM: made order resistant against case where fd of created pipe was 0 or 1\r
- close(to_prog[1]); // first close the unused pipe ends\r
- close(from_prog[0]);\r
- dup2(to_prog[0], 0); // to_prog was created first, nd is the only one to use 0 or 1\r
- dup2(from_prog[1], 1);\r
- if(to_prog[0] >= 2) close(to_prog[0]); // if 0 or 1, the dup2 already cosed the original\r
- close(from_prog[1]); // and closing again loses one of the pipes!\r
- if(fileno(stderr) >= 2) // better safe than sorry...\r
- dup2(1, fileno(stderr)); /* force stderr to the pipe */\r
-\r
- if (dir[0] != NULLCHAR && chdir(dir) != 0) {\r
- perror(dir);\r
- exit(1);\r
- }\r
-\r
- nice(appData.niceEngines); // [HGM] nice: adjust priority of engine proc\r
-\r
- execvp(argv[0], argv);\r
- \r
- /* If we get here, exec failed */\r
- perror(argv[0]);\r
- exit(1);\r
- }\r
- \r
- /* Parent process */\r
- close(to_prog[0]);\r
- close(from_prog[1]);\r
- \r
- cp = (ChildProc *) calloc(1, sizeof(ChildProc));\r
- cp->kind = CPReal;\r
- cp->pid = pid;\r
- cp->fdFrom = from_prog[0];\r
- cp->fdTo = to_prog[1];\r
- *pr = (ProcRef) cp;\r
- return 0;\r
-}\r
-\r
-// [HGM] kill: implement the 'hard killing' of AS's Winboard_x\r
-static RETSIGTYPE AlarmCallBack(int n)\r
-{\r
- return;\r
-}\r
-\r
-void\r
-DestroyChildProcess(pr, signalType)\r
- ProcRef pr;\r
- int signalType;\r
-{\r
- ChildProc *cp = (ChildProc *) pr;\r
-\r
- if (cp->kind != CPReal) return;\r
- cp->kind = CPNone;\r
- if (signalType == 10) { // [HGM] kill: if it does not terminate in 3 sec, kill\r
- signal(SIGALRM, AlarmCallBack);\r
- alarm(3);\r
- if(wait((int *) 0) == -1) { // process does not terminate on its own accord\r
- kill(cp->pid, SIGKILL); // kill it forcefully\r
- wait((int *) 0); // and wait again\r
- }\r
- } else {\r
- if (signalType) {\r
- kill(cp->pid, signalType == 9 ? SIGKILL : SIGTERM); // [HGM] kill: use hard kill if so requested\r
- }\r
- /* Process is exiting either because of the kill or because of\r
- a quit command sent by the backend; either way, wait for it to die.\r
- */\r
- wait((int *) 0);\r
- }\r
- close(cp->fdFrom);\r
- close(cp->fdTo);\r
-}\r
-\r
-void\r
-InterruptChildProcess(pr)\r
- ProcRef pr;\r
-{\r
- ChildProc *cp = (ChildProc *) pr;\r
-\r
- if (cp->kind != CPReal) return;\r
- (void) kill(cp->pid, SIGINT); /* stop it thinking */\r
-}\r
-\r
-int OpenTelnet(host, port, pr)\r
- char *host;\r
- char *port;\r
- ProcRef *pr;\r
-{\r
- char cmdLine[MSG_SIZ];\r
-\r
- if (port[0] == NULLCHAR) {\r
- sprintf(cmdLine, "%s %s", appData.telnetProgram, host);\r
- } else {\r
- sprintf(cmdLine, "%s %s %s", appData.telnetProgram, host, port);\r
- }\r
- return StartChildProcess(cmdLine, "", pr);\r
-}\r
-\r
-int OpenTCP(host, port, pr)\r
- char *host;\r
- char *port;\r
- ProcRef *pr;\r
-{\r
-#if OMIT_SOCKETS\r
- DisplayFatalError(_("Socket support is not configured in"), 0, 2);\r
-#else /* !OMIT_SOCKETS */\r
- int s;\r
- struct sockaddr_in sa;\r
- struct hostent *hp;\r
- unsigned short uport;\r
- ChildProc *cp;\r
-\r
- if ((s = socket(AF_INET, SOCK_STREAM, 6)) < 0) {\r
- return errno;\r
- }\r
-\r
- memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));\r
- sa.sin_family = AF_INET;\r
- sa.sin_addr.s_addr = INADDR_ANY;\r
- uport = (unsigned short) 0;\r
- sa.sin_port = htons(uport);\r
- if (bind(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)) < 0) {\r
- return errno;\r
- }\r
-\r
- memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));\r
- if (!(hp = gethostbyname(host))) {\r
- int b0, b1, b2, b3;\r
- if (sscanf(host, "%d.%d.%d.%d", &b0, &b1, &b2, &b3) == 4) {\r
- hp = (struct hostent *) calloc(1, sizeof(struct hostent));\r
- hp->h_addrtype = AF_INET;\r
- hp->h_length = 4;\r
- hp->h_addr_list = (char **) calloc(2, sizeof(char *));\r
- hp->h_addr_list[0] = (char *) malloc(4);\r
- hp->h_addr_list[0][0] = b0;\r
- hp->h_addr_list[0][1] = b1;\r
- hp->h_addr_list[0][2] = b2;\r
- hp->h_addr_list[0][3] = b3;\r
- } else {\r
- return ENOENT;\r
- }\r
- }\r
- sa.sin_family = hp->h_addrtype;\r
- uport = (unsigned short) atoi(port);\r
- sa.sin_port = htons(uport);\r
- memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);\r
-\r
- if (connect(s, (struct sockaddr *) &sa, \r
- sizeof(struct sockaddr_in)) < 0) {\r
- return errno;\r
- }\r
-\r
- cp = (ChildProc *) calloc(1, sizeof(ChildProc));\r
- cp->kind = CPSock;\r
- cp->pid = 0;\r
- cp->fdFrom = s;\r
- cp->fdTo = s;\r
- *pr = (ProcRef) cp;\r
-\r
-#endif /* !OMIT_SOCKETS */\r
-\r
- return 0;\r
-}\r
-\r
-int OpenCommPort(name, pr)\r
- char *name;\r
- ProcRef *pr;\r
-{\r
- int fd;\r
- ChildProc *cp;\r
-\r
- fd = open(name, 2, 0);\r
- if (fd < 0) return errno;\r
-\r
- cp = (ChildProc *) calloc(1, sizeof(ChildProc));\r
- cp->kind = CPComm;\r
- cp->pid = 0;\r
- cp->fdFrom = fd;\r
- cp->fdTo = fd;\r
- *pr = (ProcRef) cp;\r
-\r
- return 0;\r
-}\r
-\r
-int OpenLoopback(pr)\r
- ProcRef *pr;\r
-{\r
- ChildProc *cp;\r
- int to[2], from[2];\r
-\r
- SetUpChildIO(to, from);\r
-\r
- cp = (ChildProc *) calloc(1, sizeof(ChildProc));\r
- cp->kind = CPLoop;\r
- cp->pid = 0;\r
- cp->fdFrom = to[0]; /* note not from[0]; we are doing a loopback */\r
- cp->fdTo = to[1];\r
- *pr = (ProcRef) cp;\r
-\r
- return 0;\r
-}\r
-\r
-int OpenRcmd(host, user, cmd, pr)\r
- char *host, *user, *cmd;\r
- ProcRef *pr;\r
-{\r
- DisplayFatalError(_("internal rcmd not implemented for Unix"), 0, 1);\r
- return -1;\r
-} \r
-\r
-#define INPUT_SOURCE_BUF_SIZE 8192\r
-\r
-typedef struct {\r
- CPKind kind;\r
- int fd;\r
- int lineByLine;\r
- char *unused;\r
- InputCallback func;\r
- XtInputId xid;\r
- char buf[INPUT_SOURCE_BUF_SIZE];\r
- VOIDSTAR closure;\r
-} InputSource;\r
-\r
-void\r
-DoInputCallback(closure, source, xid) \r
- caddr_t closure;\r
- int *source;\r
- XtInputId *xid;\r
-{\r
- InputSource *is = (InputSource *) closure;\r
- int count;\r
- int error;\r
- char *p, *q;\r
-\r
- if (is->lineByLine) {\r
- count = read(is->fd, is->unused,\r
- INPUT_SOURCE_BUF_SIZE - (is->unused - is->buf));\r
- if (count <= 0) {\r
- (is->func)(is, is->closure, is->buf, count, count ? errno : 0);\r
- return;\r
- }\r
- is->unused += count;\r
- p = is->buf;\r
- while (p < is->unused) {\r
- q = memchr(p, '\n', is->unused - p);\r
- if (q == NULL) break;\r
- q++;\r
- (is->func)(is, is->closure, p, q - p, 0);\r
- p = q;\r
- }\r
- q = is->buf;\r
- while (p < is->unused) {\r
- *q++ = *p++;\r
- }\r
- is->unused = q;\r
- } else {\r
- count = read(is->fd, is->buf, INPUT_SOURCE_BUF_SIZE);\r
- if (count == -1)\r
- error = errno;\r
- else\r
- error = 0;\r
- (is->func)(is, is->closure, is->buf, count, error);\r
- } \r
-}\r
-\r
-InputSourceRef AddInputSource(pr, lineByLine, func, closure)\r
- ProcRef pr;\r
- int lineByLine;\r
- InputCallback func;\r
- VOIDSTAR closure;\r
-{\r
- InputSource *is;\r
- ChildProc *cp = (ChildProc *) pr;\r
-\r
- is = (InputSource *) calloc(1, sizeof(InputSource));\r
- is->lineByLine = lineByLine;\r
- is->func = func;\r
- if (pr == NoProc) {\r
- is->kind = CPReal;\r
- is->fd = fileno(stdin);\r
- } else {\r
- is->kind = cp->kind;\r
- is->fd = cp->fdFrom;\r
- }\r
- if (lineByLine) {\r
- is->unused = is->buf;\r
- }\r
- \r
- is->xid = XtAppAddInput(appContext, is->fd,\r
- (XtPointer) (XtInputReadMask),\r
- (XtInputCallbackProc) DoInputCallback,\r
- (XtPointer) is);\r
- is->closure = closure;\r
- return (InputSourceRef) is;\r
-}\r
-\r
-void\r
-RemoveInputSource(isr)\r
- InputSourceRef isr;\r
-{\r
- InputSource *is = (InputSource *) isr;\r
-\r
- if (is->xid == 0) return;\r
- XtRemoveInput(is->xid);\r
- is->xid = 0;\r
-}\r
-\r
-int OutputToProcess(pr, message, count, outError)\r
- ProcRef pr;\r
- char *message;\r
- int count;\r
- int *outError;\r
-{\r
- ChildProc *cp = (ChildProc *) pr;\r
- int outCount;\r
-\r
- if (pr == NoProc)\r
- outCount = fwrite(message, 1, count, stdout);\r
- else\r
- outCount = write(cp->fdTo, message, count);\r
-\r
- if (outCount == -1)\r
- *outError = errno;\r
- else\r
- *outError = 0;\r
-\r
- return outCount;\r
-}\r
-\r
-/* Output message to process, with "ms" milliseconds of delay\r
- between each character. This is needed when sending the logon\r
- script to ICC, which for some reason doesn't like the\r
- instantaneous send. */\r
-int OutputToProcessDelayed(pr, message, count, outError, msdelay)\r
- ProcRef pr;\r
- char *message;\r
- int count;\r
- int *outError;\r
- long msdelay;\r
-{\r
- ChildProc *cp = (ChildProc *) pr;\r
- int outCount = 0;\r
- int r;\r
- \r
- while (count--) {\r
- r = write(cp->fdTo, message++, 1);\r
- if (r == -1) {\r
- *outError = errno;\r
- return outCount;\r
- }\r
- ++outCount;\r
- if (msdelay >= 0)\r
- TimeDelay(msdelay);\r
- }\r
-\r
- return outCount;\r
-}\r
-\r
-/**** Animation code by Hugh Fisher, DCS, ANU.\r
-\r
- Known problem: if a window overlapping the board is\r
- moved away while a piece is being animated underneath,\r
- the newly exposed area won't be updated properly.\r
- I can live with this.\r
-\r
- Known problem: if you look carefully at the animation\r
- of pieces in mono mode, they are being drawn as solid\r
- shapes without interior detail while moving. Fixing\r
- this would be a major complication for minimal return.\r
-****/\r
-\r
-/* Masks for XPM pieces. Black and white pieces can have\r
- different shapes, but in the interest of retaining my\r
- sanity pieces must have the same outline on both light\r
- and dark squares, and all pieces must use the same\r
- background square colors/images. */\r
-\r
-static void\r
-CreateAnimMasks (pieceDepth)\r
- int pieceDepth;\r
-{\r
- ChessSquare piece;\r
- Pixmap buf;\r
- GC bufGC, maskGC;\r
- int kind, n;\r
- unsigned long plane;\r
- XGCValues values;\r
-\r
- /* Need a bitmap just to get a GC with right depth */\r
- buf = XCreatePixmap(xDisplay, xBoardWindow,\r
- 8, 8, 1);\r
- values.foreground = 1;\r
- values.background = 0;\r
- /* Don't use XtGetGC, not read only */\r
- maskGC = XCreateGC(xDisplay, buf,\r
- GCForeground | GCBackground, &values);\r
- XFreePixmap(xDisplay, buf);\r
-\r
- buf = XCreatePixmap(xDisplay, xBoardWindow,\r
- squareSize, squareSize, pieceDepth); \r
- values.foreground = XBlackPixel(xDisplay, xScreen);\r
- values.background = XWhitePixel(xDisplay, xScreen);\r
- bufGC = XCreateGC(xDisplay, buf,\r
- GCForeground | GCBackground, &values);\r
-\r
- for (piece = WhitePawn; piece <= BlackKing; piece++) {\r
- /* Begin with empty mask */\r
- xpmMask[piece] = XCreatePixmap(xDisplay, xBoardWindow,\r
- squareSize, squareSize, 1);\r
- XSetFunction(xDisplay, maskGC, GXclear);\r
- XFillRectangle(xDisplay, xpmMask[piece], maskGC,\r
- 0, 0, squareSize, squareSize);\r
- \r
- /* Take a copy of the piece */\r
- if (White(piece))\r
- kind = 0;\r
- else\r
- kind = 2;\r
- XSetFunction(xDisplay, bufGC, GXcopy);\r
- XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn],\r
- buf, bufGC,\r
- 0, 0, squareSize, squareSize, 0, 0);\r
- \r
- /* XOR the background (light) over the piece */\r
- XSetFunction(xDisplay, bufGC, GXxor);\r
- if (useImageSqs)\r
- XCopyArea(xDisplay, xpmLightSquare, buf, bufGC,\r
- 0, 0, squareSize, squareSize, 0, 0);\r
- else {\r
- XSetForeground(xDisplay, bufGC, lightSquareColor);\r
- XFillRectangle(xDisplay, buf, bufGC, 0, 0, squareSize, squareSize);\r
- }\r
- \r
- /* We now have an inverted piece image with the background\r
- erased. Construct mask by just selecting all the non-zero\r
- pixels - no need to reconstruct the original image. */\r
- XSetFunction(xDisplay, maskGC, GXor);\r
- plane = 1;\r
- /* Might be quicker to download an XImage and create bitmap\r
- data from it rather than this N copies per piece, but it\r
- only takes a fraction of a second and there is a much\r
- longer delay for loading the pieces. */\r
- for (n = 0; n < pieceDepth; n ++) {\r
- XCopyPlane(xDisplay, buf, xpmMask[piece], maskGC,\r
- 0, 0, squareSize, squareSize,\r
- 0, 0, plane);\r
- plane = plane << 1;\r
- }\r
- }\r
- /* Clean up */\r
- XFreePixmap(xDisplay, buf);\r
- XFreeGC(xDisplay, bufGC);\r
- XFreeGC(xDisplay, maskGC);\r
-}\r
-\r
-static void\r
-InitAnimState (anim, info)\r
- AnimState * anim;\r
- XWindowAttributes * info;\r
-{\r
- XtGCMask mask;\r
- XGCValues values;\r
- \r
- /* Each buffer is square size, same depth as window */\r
- anim->saveBuf = XCreatePixmap(xDisplay, xBoardWindow,\r
- squareSize, squareSize, info->depth);\r
- anim->newBuf = XCreatePixmap(xDisplay, xBoardWindow,\r
- squareSize, squareSize, info->depth);\r
-\r
- /* Create a plain GC for blitting */\r
- mask = GCForeground | GCBackground | GCFunction |\r
- GCPlaneMask | GCGraphicsExposures;\r
- values.foreground = XBlackPixel(xDisplay, xScreen);\r
- values.background = XWhitePixel(xDisplay, xScreen);\r
- values.function = GXcopy;\r
- values.plane_mask = AllPlanes;\r
- values.graphics_exposures = False;\r
- anim->blitGC = XCreateGC(xDisplay, xBoardWindow, mask, &values);\r
-\r
- /* Piece will be copied from an existing context at\r
- the start of each new animation/drag. */\r
- anim->pieceGC = XCreateGC(xDisplay, xBoardWindow, 0, &values);\r
-\r
- /* Outline will be a read-only copy of an existing */\r
- anim->outlineGC = None;\r
-}\r
-\r
-static void\r
-CreateAnimVars ()\r
-{\r
- static int done = 0;\r
- XWindowAttributes info;\r
-\r
- if (done) return;\r
- done = 1;\r
- XGetWindowAttributes(xDisplay, xBoardWindow, &info);\r
- \r
- InitAnimState(&game, &info);\r
- InitAnimState(&player, &info);\r
- \r
- /* For XPM pieces, we need bitmaps to use as masks. */\r
- if (useImages)\r
- CreateAnimMasks(info.depth);\r
-}\r
-\r
-#ifndef HAVE_USLEEP\r
-\r
-static Boolean frameWaiting;\r
-\r
-static RETSIGTYPE FrameAlarm (sig)\r
- int sig;\r
-{\r
- frameWaiting = False;\r
- /* In case System-V style signals. Needed?? */\r
- signal(SIGALRM, FrameAlarm);\r
-}\r
-\r
-static void\r
-FrameDelay (time)\r
- int time;\r
-{\r
- struct itimerval delay;\r
- \r
- XSync(xDisplay, False);\r
-\r
- if (time > 0) {\r
- frameWaiting = True;\r
- signal(SIGALRM, FrameAlarm);\r
- delay.it_interval.tv_sec = \r
- delay.it_value.tv_sec = time / 1000;\r
- delay.it_interval.tv_usec = \r
- delay.it_value.tv_usec = (time % 1000) * 1000;\r
- setitimer(ITIMER_REAL, &delay, NULL);\r
-#if 0\r
- /* Ugh -- busy-wait! --tpm */\r
- while (frameWaiting); \r
-#else\r
- while (frameWaiting) pause();\r
-#endif\r
- delay.it_interval.tv_sec = delay.it_value.tv_sec = 0;\r
- delay.it_interval.tv_usec = delay.it_value.tv_usec = 0;\r
- setitimer(ITIMER_REAL, &delay, NULL);\r
- }\r
-}\r
-\r
-#else\r
-\r
-static void\r
-FrameDelay (time)\r
- int time;\r
-{\r
- XSync(xDisplay, False);\r
- if (time > 0)\r
- usleep(time * 1000);\r
-}\r
-\r
-#endif\r
-\r
-/* Convert board position to corner of screen rect and color */\r
-\r
-static void\r
-ScreenSquare(column, row, pt, color)\r
- int column; int row; XPoint * pt; int * color;\r
-{\r
- if (flipView) {\r
- pt->x = lineGap + ((BOARD_WIDTH-1)-column) * (squareSize + lineGap);\r
- pt->y = lineGap + row * (squareSize + lineGap);\r
- } else {\r
- pt->x = lineGap + column * (squareSize + lineGap);\r
- pt->y = lineGap + ((BOARD_HEIGHT-1)-row) * (squareSize + lineGap);\r
- }\r
- *color = SquareColor(row, column);\r
-}\r
-\r
-/* Convert window coords to square */\r
-\r
-static void\r
-BoardSquare(x, y, column, row)\r
- int x; int y; int * column; int * row;\r
-{\r
- *column = EventToSquare(x, BOARD_WIDTH);\r
- if (flipView && *column >= 0)\r
- *column = BOARD_WIDTH - 1 - *column;\r
- *row = EventToSquare(y, BOARD_HEIGHT);\r
- if (!flipView && *row >= 0)\r
- *row = BOARD_HEIGHT - 1 - *row;\r
-}\r
-\r
-/* Utilities */\r
-\r
-#undef Max /* just in case */\r
-#undef Min\r
-#define Max(a, b) ((a) > (b) ? (a) : (b))\r
-#define Min(a, b) ((a) < (b) ? (a) : (b))\r
-\r
-static void\r
-SetRect(rect, x, y, width, height)\r
- XRectangle * rect; int x; int y; int width; int height;\r
-{\r
- rect->x = x;\r
- rect->y = y;\r
- rect->width = width;\r
- rect->height = height;\r
-}\r
-\r
-/* Test if two frames overlap. If they do, return\r
- intersection rect within old and location of\r
- that rect within new. */\r
- \r
-static Boolean\r
-Intersect(old, new, size, area, pt)\r
- XPoint * old; XPoint * new;\r
- int size; XRectangle * area; XPoint * pt;\r
-{\r
- if (old->x > new->x + size || new->x > old->x + size ||\r
- old->y > new->y + size || new->y > old->y + size) {\r
- return False;\r
- } else {\r
- SetRect(area, Max(new->x - old->x, 0), Max(new->y - old->y, 0),\r
- size - abs(old->x - new->x), size - abs(old->y - new->y));\r
- pt->x = Max(old->x - new->x, 0);\r
- pt->y = Max(old->y - new->y, 0);\r
- return True;\r
- }\r
-}\r
-\r
-/* For two overlapping frames, return the rect(s)\r
- in the old that do not intersect with the new. */\r
- \r
-static void\r
-CalcUpdateRects(old, new, size, update, nUpdates)\r
- XPoint * old; XPoint * new; int size;\r
- XRectangle update[]; int * nUpdates;\r
-{\r
- int count;\r
-\r
- /* If old = new (shouldn't happen) then nothing to draw */\r
- if (old->x == new->x && old->y == new->y) {\r
- *nUpdates = 0;\r
- return;\r
- }\r
- /* Work out what bits overlap. Since we know the rects\r
- are the same size we don't need a full intersect calc. */\r
- count = 0;\r
- /* Top or bottom edge? */\r
- if (new->y > old->y) {\r
- SetRect(&(update[count]), old->x, old->y, size, new->y - old->y);\r
- count ++;\r
- } else if (old->y > new->y) {\r
- SetRect(&(update[count]), old->x, old->y + size - (old->y - new->y),\r
- size, old->y - new->y);\r
- count ++;\r
- }\r
- /* Left or right edge - don't overlap any update calculated above. */\r
- if (new->x > old->x) {\r
- SetRect(&(update[count]), old->x, Max(new->y, old->y),\r
- new->x - old->x, size - abs(new->y - old->y));\r
- count ++;\r
- } else if (old->x > new->x) {\r
- SetRect(&(update[count]), new->x + size, Max(new->y, old->y),\r
- old->x - new->x, size - abs(new->y - old->y));\r
- count ++;\r
- }\r
- /* Done */\r
- *nUpdates = count;\r
-}\r
-\r
-/* Generate a series of frame coords from start->mid->finish.\r
- The movement rate doubles until the half way point is\r
- reached, then halves back down to the final destination,\r
- which gives a nice slow in/out effect. The algorithmn\r
- may seem to generate too many intermediates for short\r
- moves, but remember that the purpose is to attract the\r
- viewers attention to the piece about to be moved and\r
- then to where it ends up. Too few frames would be less\r
- noticeable. */\r
-\r
-static void\r
-Tween(start, mid, finish, factor, frames, nFrames)\r
- XPoint * start; XPoint * mid;\r
- XPoint * finish; int factor;\r
- XPoint frames[]; int * nFrames;\r
-{\r
- int fraction, n, count;\r
-\r
- count = 0;\r
-\r
- /* Slow in, stepping 1/16th, then 1/8th, ... */\r
- fraction = 1;\r
- for (n = 0; n < factor; n++)\r
- fraction *= 2;\r
- for (n = 0; n < factor; n++) {\r
- frames[count].x = start->x + (mid->x - start->x) / fraction;\r
- frames[count].y = start->y + (mid->y - start->y) / fraction;\r
- count ++;\r
- fraction = fraction / 2;\r
- }\r
- \r
- /* Midpoint */\r
- frames[count] = *mid;\r
- count ++;\r
- \r
- /* Slow out, stepping 1/2, then 1/4, ... */\r
- fraction = 2;\r
- for (n = 0; n < factor; n++) {\r
- frames[count].x = finish->x - (finish->x - mid->x) / fraction;\r
- frames[count].y = finish->y - (finish->y - mid->y) / fraction;\r
- count ++;\r
- fraction = fraction * 2;\r
- }\r
- *nFrames = count;\r
-}\r
-\r
-/* Draw a piece on the screen without disturbing what's there */\r
-\r
-static void\r
-SelectGCMask(piece, clip, outline, mask)\r
- ChessSquare piece; GC * clip; GC * outline; Pixmap * mask;\r
-{\r
- GC source;\r
-\r
- /* Bitmap for piece being moved. */\r
- if (appData.monoMode) {\r
- *mask = *pieceToSolid(piece);\r
- } else if (useImages) {\r
-#if HAVE_LIBXPM\r
- *mask = xpmMask[piece];\r
-#else\r
- *mask = ximMaskPm[piece%(int)BlackPawn];\r
-#endif\r
- } else {\r
- *mask = *pieceToSolid(piece);\r
- }\r
-\r
- /* GC for piece being moved. Square color doesn't matter, but\r
- since it gets modified we make a copy of the original. */\r
- if (White(piece)) {\r
- if (appData.monoMode)\r
- source = bwPieceGC;\r
- else\r
- source = wlPieceGC;\r
- } else {\r
- if (appData.monoMode)\r
- source = wbPieceGC;\r
- else\r
- source = blPieceGC;\r
- }\r
- XCopyGC(xDisplay, source, 0xFFFFFFFF, *clip);\r
- \r
- /* Outline only used in mono mode and is not modified */\r
- if (White(piece))\r
- *outline = bwPieceGC;\r
- else\r
- *outline = wbPieceGC;\r
-}\r
-\r
-static void\r
-OverlayPiece(piece, clip, outline, dest)\r
- ChessSquare piece; GC clip; GC outline; Drawable dest;\r
-{\r
- int kind;\r
- \r
- if (!useImages) {\r
- /* Draw solid rectangle which will be clipped to shape of piece */\r
- XFillRectangle(xDisplay, dest, clip,\r
- 0, 0, squareSize, squareSize);\r
- if (appData.monoMode)\r
- /* Also draw outline in contrasting color for black\r
- on black / white on white cases */\r
- XCopyPlane(xDisplay, *pieceToOutline(piece), dest, outline,\r
- 0, 0, squareSize, squareSize, 0, 0, 1);\r
- } else {\r
- /* Copy the piece */\r
- if (White(piece))\r
- kind = 0;\r
- else\r
- kind = 2;\r
- XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn],\r
- dest, clip,\r
- 0, 0, squareSize, squareSize,\r
- 0, 0); \r
- }\r
-}\r
-\r
-/* Animate the movement of a single piece */\r
-\r
-static void \r
-BeginAnimation(anim, piece, startColor, start)\r
- AnimState *anim;\r
- ChessSquare piece;\r
- int startColor;\r
- XPoint * start;\r
-{\r
- Pixmap mask;\r
- \r
- /* The old buffer is initialised with the start square (empty) */\r
- BlankSquare(0, 0, startColor, EmptySquare, anim->saveBuf);\r
- anim->prevFrame = *start;\r
- \r
- /* The piece will be drawn using its own bitmap as a matte */\r
- SelectGCMask(piece, &anim->pieceGC, &anim->outlineGC, &mask);\r
- XSetClipMask(xDisplay, anim->pieceGC, mask);\r
-}\r
-\r
-static void\r
-AnimationFrame(anim, frame, piece)\r
- AnimState *anim;\r
- XPoint *frame;\r
- ChessSquare piece;\r
-{\r
- XRectangle updates[4];\r
- XRectangle overlap;\r
- XPoint pt;\r
- int count, i;\r
- \r
- /* Save what we are about to draw into the new buffer */\r
- XCopyArea(xDisplay, xBoardWindow, anim->newBuf, anim->blitGC,\r
- frame->x, frame->y, squareSize, squareSize,\r
- 0, 0);\r
- \r
- /* Erase bits of the previous frame */\r
- if (Intersect(&anim->prevFrame, frame, squareSize, &overlap, &pt)) {\r
- /* Where the new frame overlapped the previous,\r
- the contents in newBuf are wrong. */\r
- XCopyArea(xDisplay, anim->saveBuf, anim->newBuf, anim->blitGC,\r
- overlap.x, overlap.y,\r
- overlap.width, overlap.height,\r
- pt.x, pt.y);\r
- /* Repaint the areas in the old that don't overlap new */\r
- CalcUpdateRects(&anim->prevFrame, frame, squareSize, updates, &count);\r
- for (i = 0; i < count; i++)\r
- XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,\r
- updates[i].x - anim->prevFrame.x,\r
- updates[i].y - anim->prevFrame.y,\r
- updates[i].width, updates[i].height,\r
- updates[i].x, updates[i].y);\r
- } else {\r
- /* Easy when no overlap */\r
- XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,\r
- 0, 0, squareSize, squareSize,\r
- anim->prevFrame.x, anim->prevFrame.y);\r
- }\r
-\r
- /* Save this frame for next time round */\r
- XCopyArea(xDisplay, anim->newBuf, anim->saveBuf, anim->blitGC,\r
- 0, 0, squareSize, squareSize,\r
- 0, 0);\r
- anim->prevFrame = *frame;\r
- \r
- /* Draw piece over original screen contents, not current,\r
- and copy entire rect. Wipes out overlapping piece images. */\r
- OverlayPiece(piece, anim->pieceGC, anim->outlineGC, anim->newBuf);\r
- XCopyArea(xDisplay, anim->newBuf, xBoardWindow, anim->blitGC,\r
- 0, 0, squareSize, squareSize,\r
- frame->x, frame->y);\r
-}\r
-\r
-static void\r
-EndAnimation (anim, finish)\r
- AnimState *anim;\r
- XPoint *finish;\r
-{\r
- XRectangle updates[4];\r
- XRectangle overlap;\r
- XPoint pt;\r
- int count, i;\r
-\r
- /* The main code will redraw the final square, so we\r
- only need to erase the bits that don't overlap. */\r
- if (Intersect(&anim->prevFrame, finish, squareSize, &overlap, &pt)) {\r
- CalcUpdateRects(&anim->prevFrame, finish, squareSize, updates, &count);\r
- for (i = 0; i < count; i++)\r
- XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,\r
- updates[i].x - anim->prevFrame.x,\r
- updates[i].y - anim->prevFrame.y,\r
- updates[i].width, updates[i].height,\r
- updates[i].x, updates[i].y);\r
- } else {\r
- XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,\r
- 0, 0, squareSize, squareSize,\r
- anim->prevFrame.x, anim->prevFrame.y);\r
- }\r
-}\r
-\r
-static void\r
-FrameSequence(anim, piece, startColor, start, finish, frames, nFrames)\r
- AnimState *anim;\r
- ChessSquare piece; int startColor;\r
- XPoint * start; XPoint * finish;\r
- XPoint frames[]; int nFrames;\r
-{\r
- int n;\r
-\r
- BeginAnimation(anim, piece, startColor, start);\r
- for (n = 0; n < nFrames; n++) {\r
- AnimationFrame(anim, &(frames[n]), piece);\r
- FrameDelay(appData.animSpeed);\r
- }\r
- EndAnimation(anim, finish);\r
-}\r
-\r
-/* Main control logic for deciding what to animate and how */\r
-\r
-void\r
-AnimateMove(board, fromX, fromY, toX, toY)\r
- Board board;\r
- int fromX;\r
- int fromY;\r
- int toX;\r
- int toY;\r
-{\r
- ChessSquare piece;\r
- int hop;\r
- XPoint start, finish, mid;\r
- XPoint frames[kFactor * 2 + 1];\r
- int nFrames, startColor, endColor;\r
-\r
- /* Are we animating? */\r
- if (!appData.animate || appData.blindfold)\r
- return;\r
-\r
- if (fromY < 0 || fromX < 0 || toX < 0 || toY < 0) return;\r
- piece = board[fromY][fromX];\r
- if (piece >= EmptySquare) return;\r
-\r
-#if DONT_HOP\r
- hop = FALSE;\r
-#else\r
- hop = (piece == WhiteKnight || piece == BlackKnight);\r
-#endif\r
-\r
- if (appData.debugMode) {\r
- fprintf(debugFP, hop ? _("AnimateMove: piece %d hops from %d,%d to %d,%d \n") :\r
- _("AnimateMove: piece %d slides from %d,%d to %d,%d \n"),\r
- piece, fromX, fromY, toX, toY); }\r
-\r
- ScreenSquare(fromX, fromY, &start, &startColor);\r
- ScreenSquare(toX, toY, &finish, &endColor);\r
-\r
- if (hop) {\r
- /* Knight: make diagonal movement then straight */\r
- if (abs(toY - fromY) < abs(toX - fromX)) {\r
- mid.x = start.x + (finish.x - start.x) / 2;\r
- mid.y = finish.y;\r
- } else {\r
- mid.x = finish.x;\r
- mid.y = start.y + (finish.y - start.y) / 2;\r
- }\r
- } else {\r
- mid.x = start.x + (finish.x - start.x) / 2;\r
- mid.y = start.y + (finish.y - start.y) / 2;\r
- }\r
- \r
- /* Don't use as many frames for very short moves */\r
- if (abs(toY - fromY) + abs(toX - fromX) <= 2)\r
- Tween(&start, &mid, &finish, kFactor - 1, frames, &nFrames);\r
- else\r
- Tween(&start, &mid, &finish, kFactor, frames, &nFrames);\r
- FrameSequence(&game, piece, startColor, &start, &finish, frames, nFrames);\r
- \r
- /* Be sure end square is redrawn */\r
- damage[toY][toX] = True;\r
-}\r
-\r
-static void\r
-DragPieceBegin(x, y)\r
- int x; int y;\r
-{\r
- int boardX, boardY, color;\r
- XPoint corner;\r
-\r
- /* Are we animating? */\r
- if (!appData.animateDragging || appData.blindfold)\r
- return;\r
- \r
- /* Figure out which square we start in and the\r
- mouse position relative to top left corner. */\r
- BoardSquare(x, y, &boardX, &boardY);\r
- player.startBoardX = boardX;\r
- player.startBoardY = boardY;\r
- ScreenSquare(boardX, boardY, &corner, &color);\r
- player.startSquare = corner;\r
- player.startColor = color;\r
-#if 0\r
- /* Start from exactly where the piece is. This can be confusing\r
- if you start dragging far from the center of the square; most\r
- or all of the piece can be over a different square from the one\r
- the mouse pointer is in. */\r
- player.mouseDelta.x = x - corner.x;\r
- player.mouseDelta.y = y - corner.y;\r
-#else\r
- /* As soon as we start dragging, the piece will jump slightly to\r
- be centered over the mouse pointer. */\r
- player.mouseDelta.x = squareSize/2;\r
- player.mouseDelta.y = squareSize/2;\r
-#endif\r
- /* Initialise animation */\r
- player.dragPiece = PieceForSquare(boardX, boardY);\r
- /* Sanity check */\r
- if (player.dragPiece >= 0 && player.dragPiece < EmptySquare) {\r
- player.dragActive = True;\r
- BeginAnimation(&player, player.dragPiece, color, &corner);\r
- /* Mark this square as needing to be redrawn. Note that\r
- we don't remove the piece though, since logically (ie\r
- as seen by opponent) the move hasn't been made yet. */\r
- damage[boardY][boardX] = True;\r
- } else {\r
- player.dragActive = False;\r
- }\r
-}\r
-\r
-static void\r
-DragPieceMove(x, y)\r
- int x; int y;\r
-{\r
- XPoint corner;\r
-\r
- /* Are we animating? */\r
- if (!appData.animateDragging || appData.blindfold)\r
- return;\r
- \r
- /* Sanity check */\r
- if (! player.dragActive)\r
- return;\r
- /* Move piece, maintaining same relative position\r
- of mouse within square */\r
- corner.x = x - player.mouseDelta.x;\r
- corner.y = y - player.mouseDelta.y;\r
- AnimationFrame(&player, &corner, player.dragPiece);\r
-#if HIGHDRAG\r
- if (appData.highlightDragging) {\r
- int boardX, boardY;\r
- BoardSquare(x, y, &boardX, &boardY);\r
- SetHighlights(fromX, fromY, boardX, boardY);\r
- }\r
-#endif\r
-}\r
-\r
-static void\r
-DragPieceEnd(x, y)\r
- int x; int y;\r
-{\r
- int boardX, boardY, color;\r
- XPoint corner;\r
-\r
- /* Are we animating? */\r
- if (!appData.animateDragging || appData.blindfold)\r
- return;\r
- \r
- /* Sanity check */\r
- if (! player.dragActive)\r
- return;\r
- /* Last frame in sequence is square piece is\r
- placed on, which may not match mouse exactly. */\r
- BoardSquare(x, y, &boardX, &boardY);\r
- ScreenSquare(boardX, boardY, &corner, &color);\r
- EndAnimation(&player, &corner);\r
-\r
- /* Be sure end square is redrawn */\r
- damage[boardY][boardX] = True;\r
-\r
- /* This prevents weird things happening with fast successive\r
- clicks which on my Sun at least can cause motion events\r
- without corresponding press/release. */\r
- player.dragActive = False;\r
-}\r
-\r
-/* Handle expose event while piece being dragged */\r
-\r
-static void\r
-DrawDragPiece ()\r
-{\r
- if (!player.dragActive || appData.blindfold)\r
- return;\r
-\r
- /* What we're doing: logically, the move hasn't been made yet,\r
- so the piece is still in it's original square. But visually\r
- it's being dragged around the board. So we erase the square\r
- that the piece is on and draw it at the last known drag point. */\r
- BlankSquare(player.startSquare.x, player.startSquare.y,\r
- player.startColor, EmptySquare, xBoardWindow);\r
- AnimationFrame(&player, &player.prevFrame, player.dragPiece);\r
- damage[player.startBoardY][player.startBoardX] = TRUE;\r
-}\r
-\r
-void\r
-SetProgramStats( FrontEndProgramStats * stats )\r
-{\r
- // [HR] TODO\r
- // [HGM] done, but perhaps backend should call this directly?\r
- EngineOutputUpdate( stats );\r
-}\r
+/*
+ * xboard.c -- X front end for XBoard
+ *
+ * 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:
+ * ------------------------------------------------------------------------
+ * All Rights Reserved
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notice appear in all copies and that
+ * both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of Digital not be
+ * used in advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission.
+ *
+ * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+ * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ * ------------------------------------------------------------------------
+ *
+ * The following terms apply to the enhanced version of XBoard
+ * distributed by the Free Software Foundation:
+ * ------------------------------------------------------------------------
+ *
+ * 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 3 of the License, or (at
+ * your option) any later version.
+ *
+ * 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, see http://www.gnu.org/licenses/. *
+ *
+ *------------------------------------------------------------------------
+ ** See the file ChangeLog for a revision history. */
+
+#define HIGHDRAG 1
+
+#include "config.h"
+
+#include <stdio.h>
+#include <ctype.h>
+#include <signal.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <pwd.h>
+#include <math.h>
+
+#if !OMIT_SOCKETS
+# if HAVE_SYS_SOCKET_H
+# include <sys/socket.h>
+# include <netinet/in.h>
+# include <netdb.h>
+# else /* not HAVE_SYS_SOCKET_H */
+# if HAVE_LAN_SOCKET_H
+# include <lan/socket.h>
+# include <lan/in.h>
+# include <lan/netdb.h>
+# else /* not HAVE_LAN_SOCKET_H */
+# define OMIT_SOCKETS 1
+# endif /* not HAVE_LAN_SOCKET_H */
+# endif /* not HAVE_SYS_SOCKET_H */
+#endif /* !OMIT_SOCKETS */
+
+#if STDC_HEADERS
+# include <stdlib.h>
+# include <string.h>
+#else /* not STDC_HEADERS */
+extern char *getenv();
+# if HAVE_STRING_H
+# include <string.h>
+# else /* not HAVE_STRING_H */
+# include <strings.h>
+# endif /* not HAVE_STRING_H */
+#endif /* not STDC_HEADERS */
+
+#if HAVE_SYS_FCNTL_H
+# include <sys/fcntl.h>
+#else /* not HAVE_SYS_FCNTL_H */
+# if HAVE_FCNTL_H
+# include <fcntl.h>
+# endif /* HAVE_FCNTL_H */
+#endif /* not HAVE_SYS_FCNTL_H */
+
+#if HAVE_SYS_SYSTEMINFO_H
+# include <sys/systeminfo.h>
+#endif /* HAVE_SYS_SYSTEMINFO_H */
+
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else
+# if HAVE_SYS_TIME_H
+# include <sys/time.h>
+# else
+# include <time.h>
+# endif
+#endif
+
+#if HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+#if HAVE_SYS_WAIT_H
+# include <sys/wait.h>
+#endif
+
+#if HAVE_DIRENT_H
+# include <dirent.h>
+# define NAMLEN(dirent) strlen((dirent)->d_name)
+# define HAVE_DIR_STRUCT
+#else
+# define dirent direct
+# define NAMLEN(dirent) (dirent)->d_namlen
+# if HAVE_SYS_NDIR_H
+# include <sys/ndir.h>
+# define HAVE_DIR_STRUCT
+# endif
+# if HAVE_SYS_DIR_H
+# include <sys/dir.h>
+# define HAVE_DIR_STRUCT
+# endif
+# if HAVE_NDIR_H
+# include <ndir.h>
+# define HAVE_DIR_STRUCT
+# endif
+#endif
+
+#if ENABLE_NLS
+#include <locale.h>
+#endif
+
+#include <X11/Intrinsic.h>
+#include <X11/StringDefs.h>
+#include <X11/Shell.h>
+#include <X11/cursorfont.h>
+#include <X11/Xatom.h>
+#include <X11/Xmu/Atoms.h>
+#if USE_XAW3D
+#include <X11/Xaw3d/Dialog.h>
+#include <X11/Xaw3d/Form.h>
+#include <X11/Xaw3d/List.h>
+#include <X11/Xaw3d/Label.h>
+#include <X11/Xaw3d/SimpleMenu.h>
+#include <X11/Xaw3d/SmeBSB.h>
+#include <X11/Xaw3d/SmeLine.h>
+#include <X11/Xaw3d/Box.h>
+#include <X11/Xaw3d/MenuButton.h>
+#include <X11/Xaw3d/Text.h>
+#include <X11/Xaw3d/AsciiText.h>
+#else
+#include <X11/Xaw/Dialog.h>
+#include <X11/Xaw/Form.h>
+#include <X11/Xaw/List.h>
+#include <X11/Xaw/Label.h>
+#include <X11/Xaw/SimpleMenu.h>
+#include <X11/Xaw/SmeBSB.h>
+#include <X11/Xaw/SmeLine.h>
+#include <X11/Xaw/Box.h>
+#include <X11/Xaw/MenuButton.h>
+#include <X11/Xaw/Text.h>
+#include <X11/Xaw/AsciiText.h>
+#endif
+
+// [HGM] bitmaps: put before incuding the bitmaps / pixmaps, to know how many piece types there are.
+#include "common.h"
+
+#if HAVE_LIBXPM
+#include <X11/xpm.h>
+#include "pixmaps/pixmaps.h"
+#define IMAGE_EXT "xpm"
+#else
+#define IMAGE_EXT "xim"
+#include "bitmaps/bitmaps.h"
+#endif
+
+#include "bitmaps/icon_white.bm"
+#include "bitmaps/icon_black.bm"
+#include "bitmaps/checkmark.bm"
+
+#include "frontend.h"
+#include "backend.h"
+#include "backendz.h"
+#include "moves.h"
+#include "xboard.h"
+#include "childio.h"
+#include "xgamelist.h"
+#include "xhistory.h"
+#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
+#endif
+#define usleep(t) _sleep2(((t)+500)/1000)
+#endif
+
+#ifdef ENABLE_NLS
+# define _(s) gettext (s)
+# define N_(s) gettext_noop (s)
+#else
+# define _(s) (s)
+# define N_(s) s
+#endif
+
+typedef struct {
+ String string;
+ 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 *filter, 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((int redo));
+void CreateAnyPieces 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));
+Widget CreateButtonBar P ((MenuItem *mi));
+#if ENABLE_NLS
+char *InsertPxlSize P((char *pattern, int targetPxlSize));
+XFontSet CreateFontSet P((char *base_fnt_lst));
+#else
+char *FindFont P((char *pattern, int targetPxlSize));
+#endif
+void PieceMenuPopup P((Widget w, XEvent *event,
+ String *params, Cardinal *num_params));
+static void PieceMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
+static void DropMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
+void ReadBitmap P((Pixmap *pm, String name, unsigned char bits[],
+ u_int wreq, u_int hreq));
+void CreateGrid P((void));
+int EventToSquare P((int x, int limit));
+void DrawSquare P((int row, int column, ChessSquare piece, int do_flash));
+void EventProc P((Widget widget, caddr_t unused, XEvent *event));
+void MoveTypeInProc P((Widget widget, caddr_t unused, XEvent *event));
+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,
+ 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 ICSInputBoxPopUp P((void));
+void ICSInputBoxPopDown P((void));
+void FileNamePopUp P((char *label, char *def, char *filter,
+ FileProc proc, char *openMode));
+void FileNamePopDown P((void));
+void FileNameCallback P((Widget w, XtPointer client_data,
+ XtPointer call_data));
+void FileNameAction P((Widget w, XEvent *event,
+ String *prms, Cardinal *nprms));
+void AskQuestionReplyAction P((Widget w, XEvent *event,
+ String *prms, Cardinal *nprms));
+void AskQuestionProc P((Widget w, XEvent *event,
+ String *prms, Cardinal *nprms));
+void AskQuestionPopDown P((void));
+void PromotionPopDown P((void));
+void PromotionCallback P((Widget w, XtPointer client_data,
+ XtPointer call_data));
+void SelectCommand P((Widget w, XtPointer client_data, XtPointer call_data));
+void ResetProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
+void LoadGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
+void LoadNextGameProc P((Widget w, XEvent *event, String *prms,
+ Cardinal *nprms));
+void LoadPrevGameProc P((Widget w, XEvent *event, String *prms,
+ Cardinal *nprms));
+void ReloadGameProc P((Widget w, XEvent *event, String *prms,
+ Cardinal *nprms));
+void LoadPositionProc P((Widget w, XEvent *event,
+ String *prms, Cardinal *nprms));
+void LoadNextPositionProc P((Widget w, XEvent *event, String *prms,
+ Cardinal *nprms));
+void LoadPrevPositionProc P((Widget w, XEvent *event, String *prms,
+ Cardinal *nprms));
+void ReloadPositionProc P((Widget w, XEvent *event, String *prms,
+ Cardinal *nprms));
+void CopyPositionProc P((Widget w, XEvent *event, String *prms,
+ Cardinal *nprms));
+void PastePositionProc P((Widget w, XEvent *event, String *prms,
+ Cardinal *nprms));
+void CopyGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
+void CopyGameListProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
+void PasteGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
+void SaveGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
+void SavePositionProc P((Widget w, XEvent *event,
+ String *prms, Cardinal *nprms));
+void MailMoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
+void ReloadCmailMsgProc P((Widget w, XEvent *event, String *prms,
+ Cardinal *nprms));
+void QuitProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
+void PauseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
+void MachineBlackProc P((Widget w, XEvent *event, String *prms,
+ Cardinal *nprms));
+void MachineWhiteProc P((Widget w, XEvent *event,
+ String *prms, Cardinal *nprms));
+void AnalyzeModeProc P((Widget w, XEvent *event,
+ String *prms, Cardinal *nprms));
+void AnalyzeFileProc P((Widget w, XEvent *event,
+ String *prms, Cardinal *nprms));
+void TwoMachinesProc P((Widget w, XEvent *event, String *prms,
+ Cardinal *nprms));
+void MatchProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
+void MatchOptionsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
+void IcsClientProc P((Widget w, XEvent *event, String *prms,
+ Cardinal *nprms));
+void EditGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
+void EditPositionProc P((Widget w, XEvent *event,
+ String *prms, Cardinal *nprms));
+void TrainingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
+void EditCommentProc P((Widget w, XEvent *event,
+ String *prms, Cardinal *nprms));
+void IcsInputBoxProc P((Widget w, XEvent *event,
+ String *prms, Cardinal *nprms));
+void AcceptProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
+void DeclineProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
+void RematchProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
+void CallFlagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
+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 TypeInProc 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,
+ Cardinal *nprms));
+void MoveNowProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
+void AlwaysQueenProc P((Widget w, XEvent *event, String *prms,
+ Cardinal *nprms));
+void AnimateDraggingProc P((Widget w, XEvent *event, String *prms,
+ Cardinal *nprms));
+void AnimateMovingProc P((Widget w, XEvent *event, String *prms,
+ Cardinal *nprms));
+void AutoflagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
+void AutoflipProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
+void BlindfoldProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
+void FlashMovesProc P((Widget w, XEvent *event, String *prms,
+ Cardinal *nprms));
+void FlipViewProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
+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 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,
+ Cardinal *nprms));
+void PopupMoveErrorsProc P((Widget w, XEvent *event, String *prms,
+ Cardinal *nprms));
+void PopupExitMessageProc P((Widget w, XEvent *event, String *prms,
+ Cardinal *nprms));
+//void PremoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
+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));
+void BookProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
+void AboutGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
+void AboutProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
+void DebugProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
+void NothingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
+void Iconify P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
+void DisplayMove P((int moveNumber));
+void DisplayTitle P((char *title));
+void ICSInitScript P((void));
+int LoadGamePopUp P((FILE *f, int gameNumber, char *title));
+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 DragPieceMove 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 OptionsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
+void NewVariantProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
+void IcsTextProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
+void LoadEngineProc 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 IcsOptionsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
+void SoundOptionsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
+void BoardOptionsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
+void LoadOptionsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
+void SaveOptionsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
+void EditBookProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
+void SelectMove P((Widget w, XEvent * event, String * params, Cardinal * nParams));
+void GameListOptionsPopDown P(());
+void GenericPopDown 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
+*/
+int xtVersion = XtSpecificationRelease;
+
+int xScreen;
+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, countGC;
+Pixmap iconPixmap, wIconPixmap, bIconPixmap, xMarkPixmap;
+Widget shellWidget, layoutWidget, formWidget, boardWidget, messageWidget,
+ whiteTimerWidget, blackTimerWidget, titleWidget, widgetList[16],
+ commentShell, promotionShell, whitePieceMenu, blackPieceMenu, dropMenu,
+ menuBarWidget, buttonBarWidget, editShell, errorShell, analysisShell,
+ ICSInputShell, fileNameShell, askQuestionShell;
+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];
+#if ENABLE_NLS
+XFontSet fontSet, clockFontSet;
+#else
+Font clockFontID;
+XFontStruct *clockFontStruct;
+#endif
+Font coordFontID, countFontID;
+XFontStruct *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,
+ errorUp = False, errorExitStatus = -1, lineGap, defaultLineGap;
+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;
+
+extern Widget shells[];
+extern Boolean shellUp[];
+
+#define SOLID 0
+#define OUTLINE 1
+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;
+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][(piece) % (int)BlackPawn]
+#define pieceToOutline(piece) &pieceBitmap[OUTLINE][(piece) % (int)BlackPawn]
+
+#define White(piece) ((int)(piece) < (int)BlackPawn)
+
+/* Variables for doing smooth animation. This whole thing
+ would be much easier if the board was double-buffered,
+ but that would require a fairly major rewrite. */
+
+typedef struct {
+ Pixmap saveBuf;
+ Pixmap newBuf;
+ GC blitGC, pieceGC, outlineGC;
+ XPoint startSquare, prevFrame, mouseDelta;
+ int startColor;
+ int dragPiece;
+ Boolean dragActive;
+ int startBoardX, startBoardY;
+ } AnimState;
+
+/* There can be two pieces being animated at once: a player
+ can begin dragging a piece before the remote opponent has moved. */
+
+static AnimState game, player;
+
+/* Bitmaps for use as masks when drawing XPM pieces.
+ Need one for each black and white piece. */
+static Pixmap xpmMask[BlackKing + 1];
+
+/* This magic number is the number of intermediate frames used
+ in each half of the animation. For short moves it's reduced
+ by 1. The total number of frames will be factor * 2 + 1. */
+#define kFactor 4
+
+SizeDefaults sizeDefaults[] = SIZE_DEFAULTS;
+
+MenuItem fileMenu[] = {
+ {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},
+ {N_("Copy Game List"), "Copy Game List", CopyGameListProc},
+ {"----", 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},
+ {N_("Edit Book"), "Edit Book", EditBookProc},
+ {"----", 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},
+ {N_("ICS text menu"), "ICStex", IcsTextProc},
+ {"----", NULL, NothingProc},
+ {N_("Tags"), "Show Tags", EditTagsProc},
+ {N_("Comments"), "Show Comments", EditCommentProc},
+ {N_("ICS Input Box"), "ICS Input Box", IcsInputBoxProc},
+ {"----", NULL, NothingProc},
+ {N_("Board..."), "Board Options", BoardOptionsProc},
+ {N_("Game List Tags..."), "Game List", GameListOptionsPopUp},
+ {NULL, NULL, NULL}
+};
+
+MenuItem modeMenu[] = {
+ {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_("Machine Match"), "Machine Match", MatchProc},
+ {N_("Pause Pause"), "Pause", PauseProc},
+ {NULL, NULL, NULL}
+};
+
+MenuItem actionMenu[] = {
+ {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 engineMenu[] = {
+ {N_("Load New Engine ..."), "Load Engine", LoadEngineProc},
+ {"----", NULL, NothingProc},
+ {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[] = {
+#define OPTIONSDIALOG
+#ifdef OPTIONSDIALOG
+ {N_("General ..."), "General", OptionsProc},
+#endif
+ {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_("ICS ..."), "ICS", IcsOptionsProc},
+ {N_("Match ..."), "Match", MatchOptionsProc},
+ {N_("Load Game ..."), "Load Game", LoadOptionsProc},
+ {N_("Save Game ..."), "Save Game", SaveOptionsProc},
+// {N_(" ..."), "", OptionsProc},
+ {N_("Game List ..."), "Game List", GameListOptionsPopUp},
+ {N_("Sounds ..."), "Sounds", SoundOptionsProc},
+ {"----", NULL, NothingProc},
+#ifndef OPTIONSDIALOG
+ {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 Flag Ctrl+Shift+F"), "Auto Flag", AutoflagProc},
+ {N_("Auto Flip View"), "Auto Flip View", AutoflipProc},
+ {N_("Blindfold"), "Blindfold", BlindfoldProc},
+ {N_("Flash Moves"), "Flash Moves", FlashMovesProc},
+#if HIGHDRAG
+ {N_("Highlight Dragging"), "Highlight Dragging", HighlightDraggingProc},
+#endif
+ {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_("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},
+#endif
+ {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"), "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"), "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}
+};
+
+#define PAUSE_BUTTON "P"
+MenuItem buttonBar[] = {
+ {"<<", "<<", ToStartProc},
+ {"<", "<", BackwardProc},
+ {PAUSE_BUTTON, PAUSE_BUTTON, PauseProc},
+ {">", ">", ForwardProc},
+ {">>", ">>", ToEndProc},
+ {NULL, NULL, NULL}
+};
+
+#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_("Elephant"), N_("Cannon"),
+ N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
+ N_("Empty square"), N_("Clear board") },
+ { N_("Black"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
+ N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
+ N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
+ N_("Empty square"), N_("Clear board") }
+};
+/* must be in same order as pieceMenuStrings! */
+ChessSquare pieceMenuTranslation[2][PIECE_MENU_SIZE] = {
+ { WhitePlay, (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
+ WhiteRook, WhiteQueen, WhiteKing, (ChessSquare) 0, WhiteAlfil,
+ WhiteCannon, WhiteAngel, WhiteMarshall, (ChessSquare) 0,
+ PromotePiece, DemotePiece, EmptySquare, ClearBoard },
+ { BlackPlay, (ChessSquare) 0, BlackPawn, BlackKnight, BlackBishop,
+ BlackRook, BlackQueen, BlackKing, (ChessSquare) 0, BlackAlfil,
+ BlackCannon, BlackAngel, BlackMarshall, (ChessSquare) 0,
+ PromotePiece, DemotePiece, EmptySquare, ClearBoard },
+};
+
+#define DROP_MENU_SIZE 6
+String dropMenuStrings[DROP_MENU_SIZE] = {
+ "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"), N_("Queen")
+ };
+/* must be in same order as dropMenuStrings! */
+ChessSquare dropMenuTranslation[DROP_MENU_SIZE] = {
+ (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
+ WhiteRook, WhiteQueen
+};
+
+typedef struct {
+ char piece;
+ char* widget;
+} DropMenuEnables;
+
+DropMenuEnables dmEnables[] = {
+ { 'P', "Pawn" },
+ { 'N', "Knight" },
+ { 'B', "Bishop" },
+ { 'R', "Rook" },
+ { 'Q', "Queen" }
+};
+
+Arg shellArgs[] = {
+ { XtNwidth, 0 },
+ { XtNheight, 0 },
+ { XtNminWidth, 0 },
+ { XtNminHeight, 0 },
+ { XtNmaxWidth, 0 },
+ { XtNmaxHeight, 0 }
+};
+
+Arg layoutArgs[] = {
+ { XtNborderWidth, 0 },
+ { XtNdefaultDistance, 0 },
+};
+
+Arg formArgs[] = {
+ { XtNborderWidth, 0 },
+ { XtNresizable, (XtArgVal) True },
+};
+
+Arg boardArgs[] = {
+ { XtNborderWidth, 0 },
+ { XtNwidth, 0 },
+ { XtNheight, 0 }
+};
+
+Arg titleArgs[] = {
+ { XtNjustify, (XtArgVal) XtJustifyRight },
+ { XtNlabel, (XtArgVal) "..." },
+ { XtNresizable, (XtArgVal) True },
+ { XtNresize, (XtArgVal) False }
+};
+
+Arg messageArgs[] = {
+ { XtNjustify, (XtArgVal) XtJustifyLeft },
+ { XtNlabel, (XtArgVal) "..." },
+ { XtNresizable, (XtArgVal) True },
+ { XtNresize, (XtArgVal) False }
+};
+
+Arg timerArgs[] = {
+ { XtNborderWidth, 0 },
+ { XtNjustify, (XtArgVal) XtJustifyLeft }
+};
+
+XtResource clientResources[] = {
+ { "flashCount", "flashCount", XtRInt, sizeof(int),
+ XtOffset(AppDataPtr, flashCount), XtRImmediate,
+ (XtPointer) FLASH_COUNT },
+};
+
+XrmOptionDescRec shellOptions[] = {
+ { "-flashCount", "flashCount", XrmoptionSepArg, NULL },
+ { "-flash", "flashCount", XrmoptionNoArg, "3" },
+ { "-xflash", "flashCount", XrmoptionNoArg, "0" },
+};
+
+XtActionsRec boardActions[] = {
+ { "DrawPosition", DrawPositionProc },
+ { "HandleUserMove", HandleUserMove },
+ { "AnimateUserMove", AnimateUserMove },
+ { "HandlePV", HandlePV },
+ { "SelectPV", SelectPV },
+ { "StopPV", StopPV },
+ { "FileNameAction", FileNameAction },
+ { "AskQuestionProc", AskQuestionProc },
+ { "AskQuestionReplyAction", AskQuestionReplyAction },
+ { "PieceMenuPopup", PieceMenuPopup },
+ { "WhiteClock", WhiteClock },
+ { "BlackClock", BlackClock },
+ { "Iconify", Iconify },
+ { "ResetProc", ResetProc },
+ { "NewVariantProc", NewVariantProc },
+ { "LoadGameProc", LoadGameProc },
+ { "LoadNextGameProc", LoadNextGameProc },
+ { "LoadPrevGameProc", LoadPrevGameProc },
+ { "LoadSelectedProc", LoadSelectedProc },
+ { "SetFilterProc", SetFilterProc },
+ { "ReloadGameProc", ReloadGameProc },
+ { "LoadPositionProc", LoadPositionProc },
+ { "LoadNextPositionProc", LoadNextPositionProc },
+ { "LoadPrevPositionProc", LoadPrevPositionProc },
+ { "ReloadPositionProc", ReloadPositionProc },
+ { "CopyPositionProc", CopyPositionProc },
+ { "PastePositionProc", PastePositionProc },
+ { "CopyGameProc", CopyGameProc },
+ { "CopyGameListProc", CopyGameListProc },
+ { "PasteGameProc", PasteGameProc },
+ { "SaveGameProc", SaveGameProc },
+ { "SavePositionProc", SavePositionProc },
+ { "MailMoveProc", MailMoveProc },
+ { "ReloadCmailMsgProc", ReloadCmailMsgProc },
+ { "QuitProc", QuitProc },
+ { "MachineWhiteProc", MachineWhiteProc },
+ { "MachineBlackProc", MachineBlackProc },
+ { "AnalysisModeProc", AnalyzeModeProc },
+ { "AnalyzeFileProc", AnalyzeFileProc },
+ { "TwoMachinesProc", TwoMachinesProc },
+ { "IcsClientProc", IcsClientProc },
+ { "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 },
+ { "EditBookProc", EditBookProc },
+ { "EditCommentProc", EditCommentProc },
+ { "IcsInputBoxProc", IcsInputBoxProc },
+ { "PauseProc", PauseProc },
+ { "AcceptProc", AcceptProc },
+ { "DeclineProc", DeclineProc },
+ { "RematchProc", RematchProc },
+ { "CallFlagProc", CallFlagProc },
+ { "DrawProc", DrawProc },
+ { "AdjournProc", AdjournProc },
+ { "AbortProc", AbortProc },
+ { "ResignProc", ResignProc },
+ { "AdjuWhiteProc", AdjuWhiteProc },
+ { "AdjuBlackProc", AdjuBlackProc },
+ { "AdjuDrawProc", AdjuDrawProc },
+ { "TypeInProc", TypeInProc },
+ { "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 },
+ { "FlipViewProc", FlipViewProc },
+ { "PonderNextMoveProc", PonderNextMoveProc },
+#ifndef OPTIONSDIALOG
+ { "AlwaysQueenProc", AlwaysQueenProc },
+ { "AnimateDraggingProc", AnimateDraggingProc },
+ { "AnimateMovingProc", AnimateMovingProc },
+ { "AutoflagProc", AutoflagProc },
+ { "AutoflipProc", AutoflipProc },
+ { "BlindfoldProc", BlindfoldProc },
+ { "FlashMovesProc", FlashMovesProc },
+#if HIGHDRAG
+ { "HighlightDraggingProc", HighlightDraggingProc },
+#endif
+ { "HighlightLastMoveProc", HighlightLastMoveProc },
+// { "IcsAlarmProc", IcsAlarmProc },
+ { "MoveSoundProc", MoveSoundProc },
+ { "PeriodicUpdatesProc", PeriodicUpdatesProc },
+ { "PopupExitMessageProc", PopupExitMessageProc },
+ { "PopupMoveErrorsProc", PopupMoveErrorsProc },
+// { "PremoveProc", PremoveProc },
+ { "ShowCoordsProc", ShowCoordsProc },
+ { "ShowThinkingProc", ShowThinkingProc },
+ { "HideThinkingProc", HideThinkingProc },
+ { "TestLegalityProc", TestLegalityProc },
+#endif
+ { "SaveSettingsProc", SaveSettingsProc },
+ { "SaveOnExitProc", SaveOnExitProc },
+ { "InfoProc", InfoProc },
+ { "ManProc", ManProc },
+ { "HintProc", HintProc },
+ { "BookProc", BookProc },
+ { "AboutGameProc", AboutGameProc },
+ { "AboutProc", AboutProc },
+ { "DebugProc", DebugProc },
+ { "NothingProc", NothingProc },
+ { "CommentClick", (XtActionProc) CommentClick },
+ { "CommentPopDown", (XtActionProc) CommentPopDown },
+ { "TagsPopDown", (XtActionProc) TagsPopDown },
+ { "ErrorPopDown", (XtActionProc) ErrorPopDown },
+ { "ICSInputBoxPopDown", (XtActionProc) ICSInputBoxPopDown },
+ { "FileNamePopDown", (XtActionProc) FileNamePopDown },
+ { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown },
+ { "GameListPopDown", (XtActionProc) GameListPopDown },
+ { "GameListOptionsPopDown", (XtActionProc) GameListOptionsPopDown },
+ { "PromotionPopDown", (XtActionProc) PromotionPopDown },
+ { "EngineOutputPopDown", (XtActionProc) EngineOutputPopDown },
+ { "EvalGraphPopDown", (XtActionProc) EvalGraphPopDown },
+ { "GenericPopDown", (XtActionProc) GenericPopDown },
+ { "CopyMemoProc", (XtActionProc) CopyMemoProc },
+ { "SelectMove", (XtActionProc) SelectMove },
+};
+
+char globalTranslations[] =
+ ":<Key>F9: ResignProc() \n \
+ :Ctrl<Key>n: ResetProc() \n \
+ :Meta<Key>V: NewVariantProc() \n \
+ :Ctrl<Key>o: LoadGameProc() \n \
+ :Meta<Key>Next: LoadNextGameProc() \n \
+ :Meta<Key>Prior: LoadPrevGameProc() \n \
+ :Ctrl<Key>s: SaveGameProc() \n \
+ :Ctrl<Key>c: CopyGameProc() \n \
+ :Ctrl<Key>v: PasteGameProc() \n \
+ :Ctrl<Key>O: LoadPositionProc() \n \
+ :Shift<Key>Next: LoadNextPositionProc() \n \
+ :Shift<Key>Prior: LoadPrevPositionProc() \n \
+ :Ctrl<Key>S: SavePositionProc() \n \
+ :Ctrl<Key>C: CopyPositionProc() \n \
+ :Ctrl<Key>V: PastePositionProc() \n \
+ :Ctrl<Key>q: QuitProc() \n \
+ :Ctrl<Key>w: MachineWhiteProc() \n \
+ :Ctrl<Key>b: MachineBlackProc() \n \
+ :Ctrl<Key>t: TwoMachinesProc() \n \
+ :Ctrl<Key>a: AnalysisModeProc() \n \
+ :Ctrl<Key>f: AnalyzeFileProc() \n \
+ :Ctrl<Key>e: EditGameProc() \n \
+ :Ctrl<Key>E: EditPositionProc() \n \
+ :Meta<Key>O: EngineOutputProc() \n \
+ :Meta<Key>E: EvalGraphProc() \n \
+ :Meta<Key>G: ShowGameListProc() \n \
+ :Meta<Key>H: ShowMoveListProc() \n \
+ :<Key>Pause: PauseProc() \n \
+ :<Key>F3: AcceptProc() \n \
+ :<Key>F4: DeclineProc() \n \
+ :<Key>F12: RematchProc() \n \
+ :<Key>F5: CallFlagProc() \n \
+ :<Key>F6: DrawProc() \n \
+ :<Key>F7: AdjournProc() \n \
+ :<Key>F8: AbortProc() \n \
+ :<Key>F10: StopObservingProc() \n \
+ :<Key>F11: StopExaminingProc() \n \
+ :Meta Ctrl<Key>F12: DebugProc() \n \
+ :Meta<Key>End: ToEndProc() \n \
+ :Meta<Key>Right: ForwardProc() \n \
+ :Meta<Key>Home: ToStartProc() \n \
+ :Meta<Key>Left: BackwardProc() \n \
+ :<Key>Home: RevertProc() \n \
+ :<Key>End: TruncateGameProc() \n \
+ :Ctrl<Key>m: MoveNowProc() \n \
+ :Ctrl<Key>x: RetractMoveProc() \n \
+ :Meta<Key>J: EngineMenuProc() \n \
+ :Meta<Key>U: UciMenuProc() \n \
+ :Meta<Key>T: TimeControlProc() \n \
+ :Ctrl<Key>P: PonderNextMoveProc() \n "
+#ifndef OPTIONSDIALOG
+ "\
+ :Ctrl<Key>Q: AlwaysQueenProc() \n \
+ :Ctrl<Key>F: AutoflagProc() \n \
+ :Ctrl<Key>A: AnimateMovingProc() \n \
+ :Ctrl<Key>L: TestLegalityProc() \n \
+ :Ctrl<Key>H: HideThinkingProc() \n "
+#endif
+ "\
+ :<Key>-: Iconify() \n \
+ :<Key>F1: ManProc() \n \
+ :<Key>F2: FlipViewProc() \n \
+ <KeyDown>.: BackwardProc() \n \
+ <KeyUp>.: ForwardProc() \n \
+ Shift<Key>1: AskQuestionProc(\"Direct command\",\
+ \"Send to chess program:\",,1) \n \
+ Shift<Key>2: AskQuestionProc(\"Direct command\",\
+ \"Send to second chess program:\",,2) \n";
+
+char boardTranslations[] =
+ "<Btn1Down>: HandleUserMove(0) \n \
+ Shift<Btn1Up>: HandleUserMove(1) \n \
+ <Btn1Up>: HandleUserMove(0) \n \
+ <Btn1Motion>: AnimateUserMove() \n \
+ <Btn3Motion>: HandlePV() \n \
+ <Btn3Up>: PieceMenuPopup(menuB) \n \
+ Shift<Btn2Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD)\
+ PieceMenuPopup(menuB) \n \
+ Any<Btn2Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD) \
+ PieceMenuPopup(menuW) \n \
+ Shift<Btn3Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD)\
+ PieceMenuPopup(menuW) \n \
+ Any<Btn3Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD) \
+ PieceMenuPopup(menuB) \n";
+
+char whiteTranslations[] = "<BtnDown>: WhiteClock()\n";
+char blackTranslations[] = "<BtnDown>: BlackClock()\n";
+
+char ICSInputTranslations[] =
+ "<Key>Up: UpKeyProc() \n "
+ "<Key>Down: DownKeyProc() \n "
+ "<Key>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[] = "<Btn3Down>: extend-end() select-start() CommentClick() \n";
+
+String xboardResources[] = {
+ "*fileName*value.translations: #override\\n <Key>Return: FileNameAction()",
+ "*question*value.translations: #override\\n <Key>Return: AskQuestionReplyAction()",
+ "*errorpopup*translations: #override\\n <Key>Return: ErrorPopDown()",
+ NULL
+ };
+
+
+/* Max possible square size */
+#define MAXSQSIZE 256
+
+static int xpm_avail[MAXSQSIZE];
+
+#ifdef HAVE_DIR_STRUCT
+
+/* Extract piece size from filename */
+static int
+xpm_getsize(name, len, ext)
+ char *name;
+ int len;
+ char *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;
+
+ while (*p && isdigit(*p))
+ *(d++) = *(p++);
+
+ *d = 0;
+ return atoi(buf);
+}
+
+/* Setup xpm_avail */
+static int
+xpm_getavail(dirname, ext)
+ char *dirname;
+ char *ext;
+{
+ DIR *dir;
+ struct dirent *ent;
+ int i;
+
+ for (i=0; i<MAXSQSIZE; ++i)
+ xpm_avail[i] = 0;
+
+ 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"),
+ programName, dirname);
+ exit(1);
+ }
+
+ while ((ent=readdir(dir)) != NULL) {
+ i = xpm_getsize(ent->d_name, NAMLEN(ent), ext);
+ if (i > 0 && i < MAXSQSIZE)
+ xpm_avail[i] = 1;
+ }
+
+ closedir(dir);
+
+ return 0;
+}
+
+void
+xpm_print_avail(fp, ext)
+ FILE *fp;
+ char *ext;
+{
+ int i;
+
+ fprintf(fp, _("Available `%s' sizes:\n"), ext);
+ for (i=1; i<MAXSQSIZE; ++i) {
+ if (xpm_avail[i])
+ printf("%d\n", i);
+ }
+}
+
+/* Return XPM piecesize closest to size */
+int
+xpm_closest_to(dirname, size, ext)
+ char *dirname;
+ int size;
+ char *ext;
+{
+ int i;
+ 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<MAXSQSIZE; ++i) {
+ if (xpm_avail[i]) {
+ diff = size - i;
+ diff = (diff<0) ? -diff : diff;
+ if (diff < sm_diff) {
+ sm_diff = diff;
+ sm_index = i;
+ }
+ }
+ }
+
+ if (!sm_index) {
+ fprintf(stderr, _("Error: No `%s' files!\n"), ext);
+ exit(1);
+ }
+
+ return sm_index;
+}
+#else /* !HAVE_DIR_STRUCT */
+/* If we are on a system without a DIR struct, we can't
+ read the directory, so we can't collect a list of
+ filenames, etc., so we can't do any size-fitting. */
+int
+xpm_closest_to(dirname, size, ext)
+ char *dirname;
+ int size;
+ char *ext;
+{
+ fprintf(stderr, _("\
+Warning: No DIR structure found on this system --\n\
+ Unable to autosize for XPM/XIM pieces.\n\
+ Please report this error to %s.\n\
+ Include system type & operating system in message.\n"), PACKAGE_BUGREPORT););
+ return size;
+}
+#endif /* HAVE_DIR_STRUCT */
+
+static char *cnames[9] = { "black", "red", "green", "yellow", "blue",
+ "magenta", "cyan", "white" };
+typedef struct {
+ int attr, bg, fg;
+} TextColors;
+TextColors textColors[(int)NColorClasses];
+
+/* String is: "fg, bg, attr". Which is 0, 1, 2 */
+static int
+parse_color(str, which)
+ char *str;
+ int which;
+{
+ char *p, buf[100], *d;
+ int i;
+
+ if (strlen(str) > 99) /* watch bounds on buf */
+ return -1;
+
+ p = str;
+ d = buf;
+ for (i=0; i<which; ++i) {
+ p = strchr(p, ',');
+ if (!p)
+ return -1;
+ ++p;
+ }
+
+ /* Could be looking at something like:
+ black, , 1
+ .. in which case we want to stop on a comma also */
+ while (*p && *p != ',' && !isalpha(*p) && !isdigit(*p))
+ ++p;
+
+ if (*p == ',') {
+ return -1; /* Use default for empty field */
+ }
+
+ if (which == 2 || isdigit(*p))
+ return atoi(p);
+
+ while (*p && isalpha(*p))
+ *(d++) = *(p++);
+
+ *d = 0;
+
+ for (i=0; i<8; ++i) {
+ if (!StrCaseCmp(buf, cnames[i]))
+ return which? (i+40) : (i+30);
+ }
+ if (!StrCaseCmp(buf, "default")) return -1;
+
+ fprintf(stderr, _("%s: unrecognized color %s\n"), programName, buf);
+ return -2;
+}
+
+static int
+parse_cpair(cc, str)
+ ColorClass cc;
+ char *str;
+{
+ if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {
+ fprintf(stderr, _("%s: can't parse foreground color in `%s'\n"),
+ programName, str);
+ return -1;
+ }
+
+ /* bg and attr are optional */
+ textColors[(int)cc].bg = parse_color(str, 1);
+ if ((textColors[(int)cc].attr = parse_color(str, 2)) < 0) {
+ textColors[(int)cc].attr = 0;
+ }
+ return 0;
+}
+
+
+/* Arrange to catch delete-window events */
+Atom wm_delete_window;
+void
+CatchDeleteWindow(Widget w, String procname)
+{
+ char buf[MSG_SIZ];
+ XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
+ snprintf(buf, sizeof(buf), "<Message>WM_PROTOCOLS: %s() \n", procname);
+ XtAugmentTranslations(w, XtParseTranslationTable(buf));
+}
+
+void
+BoardToTop()
+{
+ Arg args[16];
+ XtSetArg(args[0], XtNiconic, False);
+ XtSetValues(shellWidget, args, 1);
+
+ 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 fontIsSet[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 && size<MAX_SIZE) { // for now, fixed limit
+ fontTable[number][size] = strdup(strchr(name, ':')+1);
+ fontValid[number][size] = True;
+ }
+ return;
+ }
+ switch(number) {
+ case 0: // CLOCK_FONT
+ appData.clockFont = strdup(name);
+ break;
+ case 1: // MESSAGE_FONT
+ appData.font = strdup(name);
+ break;
+ case 2: // COORD_FONT
+ appData.coordFont = strdup(name);
+ break;
+ default:
+ return;
+ }
+ fontIsSet[number] = True; // [HGM] font: indicate a font was specified (not from settings file)
+}
+
+void
+SetFontDefaults()
+{ // only 2 fonts currently
+ appData.clockFont = CLOCK_FONT_NAME;
+ appData.coordFont = COORD_FONT_NAME;
+ appData.font = DEFAULT_FONT_NAME;
+}
+
+void
+CreateFonts()
+{ // no-op, until we identify the code for this already in XBoard and move it here
+}
+
+void
+ParseColor(int n, char *name)
+{ // in XBoard, just copy the color-name string
+ if(colorVariable[n]) *(char**)colorVariable[n] = strdup(name);
+}
+
+void
+ParseTextAttribs(ColorClass cc, char *s)
+{
+ (&appData.colorShout)[cc] = strdup(s);
+}
+
+void
+ParseBoardSize(void *addr, char *name)
+{
+ appData.boardSize = strdup(name);
+}
+
+void
+LoadAllSounds()
+{ // In XBoard the sound-playing program takes care of obtaining the actual sound
+}
+
+void
+SetCommPortDefaults()
+{ // for now, this is a no-op, as the corresponding option does not exist in XBoard
+}
+
+// [HGM] args: these three cases taken out to stay in front-end
+void
+SaveFontArg(FILE *f, ArgDescriptor *ad)
+{
+ char *name;
+ int i, n = (int)(intptr_t)ad->argLoc;
+ 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; i<NUM_SIZES; i++) // [HGM] font: current font becomes standard for current size
+ if(sizeDefaults[i].squareSize == squareSize) { // only for standard sizes!
+ fontTable[n][squareSize] = strdup(name);
+ fontValid[n][squareSize] = True;
+ break;
+ }
+ for(i=0; i<MAX_SIZE; i++) if(fontValid[n][i]) // [HGM] font: store all standard fonts
+ fprintf(f, OPTCHAR "%s" SEPCHAR "\"size%d:%s\"\n", ad->argName, 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)(intptr_t)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)(intptr_t)ad->argLoc])
+ fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", ad->argName, *(char**)colorVariable[(int)(intptr_t)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;
+
+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);
+ if(MoveHistoryIsUp()) GetActualPlacement(shells[7], &wpMoveHistory);
+ if(EvalGraphIsUp()) GetActualPlacement(evalGraphShell, &wpEvalGraph);
+ if(GameListIsUp()) GetActualPlacement(gameListShell, &wpGameList);
+ if(shellUp[1]) GetActualPlacement(shells[1], &wpComment);
+ if(shellUp[2]) GetActualPlacement(shells[2], &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<argc; i++)
+ {
+ if( (strchr(argv[i], ' ') || strchr(argv[i], '\n') ||strchr(argv[i], '\t') || argv[i][0] == NULLCHAR)
+ && argv[i][0] != '{' )
+ snprintf(buf, sizeof(buf)/sizeof(buf[0]), "{%s} ", argv[i]);
+ else
+ snprintf(buf, sizeof(buf)/sizeof(buf[0]), "%s ", argv[i]);
+ strncat(line, buf, 128*1024 - strlen(line) - 1 );
+ }
+
+ line[strlen(line)-1] = NULLCHAR;
+ return line;
+}
+
+//--------------------------------------------------------------------------------------------
+
+extern Boolean twoBoards, partnerUp;
+
+#ifdef IDSIZES
+ // eventually, all layout determining code should go into a subroutine, but until then IDSIZE remains undefined
+#else
+#define BoardSize int
+void InitDrawingSizes(BoardSize boardSize, int flags)
+{ // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
+ Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
+ Arg args[16];
+ XtGeometryResult gres;
+ int i;
+
+ if(!formWidget) return;
+
+ /*
+ * Enable shell resizing.
+ */
+ shellArgs[0].value = (XtArgVal) &w;
+ shellArgs[1].value = (XtArgVal) &h;
+ XtGetValues(shellWidget, shellArgs, 2);
+
+ shellArgs[4].value = 3*w; shellArgs[2].value = 10;
+ shellArgs[5].value = 2*h; shellArgs[3].value = 10;
+ XtSetValues(shellWidget, &shellArgs[2], 4);
+
+ XtSetArg(args[0], XtNdefaultDistance, &sep);
+ XtGetValues(formWidget, args, 1);
+
+ if(appData.overrideLineGap >= 0) lineGap = appData.overrideLineGap;
+ boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
+ boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
+ CreateGrid();
+ hOffset = boardWidth + 10;
+ for(i=0; i<BOARD_WIDTH+BOARD_HEIGHT+2; i++) { // [HGM] dual: grid for second board
+ secondSegments[i] = gridSegments[i];
+ secondSegments[i].x1 += hOffset;
+ secondSegments[i].x2 += hOffset;
+ }
+
+ XtSetArg(args[0], XtNwidth, boardWidth);
+ XtSetArg(args[1], XtNheight, boardHeight);
+ XtSetValues(boardWidget, args, 2);
+
+ timerWidth = (boardWidth - sep) / 2;
+ XtSetArg(args[0], XtNwidth, timerWidth);
+ XtSetValues(whiteTimerWidget, args, 1);
+ XtSetValues(blackTimerWidget, args, 1);
+
+ XawFormDoLayout(formWidget, False);
+
+ if (appData.titleInWindow) {
+ i = 0;
+ XtSetArg(args[i], XtNborderWidth, &bor); i++;
+ XtSetArg(args[i], XtNheight, &h); i++;
+ XtGetValues(titleWidget, args, i);
+ if (smallLayout) {
+ w = boardWidth - 2*bor;
+ } else {
+ XtSetArg(args[0], XtNwidth, &w);
+ XtGetValues(menuBarWidget, args, 1);
+ w = boardWidth - w - sep - 2*bor - 2; // WIDTH_FUDGE
+ }
+
+ gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
+ if (gres != XtGeometryYes && appData.debugMode) {
+ fprintf(stderr,
+ _("%s: titleWidget geometry error %d %d %d %d %d\n"),
+ programName, gres, w, h, wr, hr);
+ }
+ }
+
+ XawFormDoLayout(formWidget, True);
+
+ /*
+ * Inhibit shell resizing.
+ */
+ shellArgs[0].value = w = (XtArgVal) boardWidth + marginW + twoBoards*hOffset; // [HGM] dual
+ shellArgs[1].value = h = (XtArgVal) boardHeight + marginH;
+ shellArgs[4].value = shellArgs[2].value = w;
+ shellArgs[5].value = shellArgs[3].value = h;
+ XtSetValues(shellWidget, &shellArgs[0], 6);
+
+ // [HGM] pieces: tailor piece bitmaps to needs of specific variant
+ // (only for xpm)
+ if(useImages) {
+ for(i=0; i<4; i++) {
+ int p;
+ for(p=0; p<=(int)WhiteKing; p++)
+ xpmPieceBitmap[i][p] = xpmPieceBitmap2[i][p]; // defaults
+ if(gameInfo.variant == VariantShogi) {
+ xpmPieceBitmap[i][(int)WhiteCannon] = xpmPieceBitmap2[i][(int)WhiteKing+1];
+ xpmPieceBitmap[i][(int)WhiteNightrider] = xpmPieceBitmap2[i][(int)WhiteKing+2];
+ xpmPieceBitmap[i][(int)WhiteSilver] = xpmPieceBitmap2[i][(int)WhiteKing+3];
+ xpmPieceBitmap[i][(int)WhiteGrasshopper] = xpmPieceBitmap2[i][(int)WhiteKing+4];
+ xpmPieceBitmap[i][(int)WhiteQueen] = xpmPieceBitmap2[i][(int)WhiteLance];
+ }
+#ifdef GOTHIC
+ if(gameInfo.variant == VariantGothic) {
+ xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteSilver];
+ }
+#endif
+ if(gameInfo.variant == VariantSChess && (squareSize == 49 || squareSize == 72)) {
+ xpmPieceBitmap[i][(int)WhiteAngel] = xpmPieceBitmap2[i][(int)WhiteFalcon];
+ xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteAlfil];
+ }
+#if !HAVE_LIBXPM
+ // [HGM] why are thee ximMasks used at all? the ximPieceBitmaps seem to be never used!
+ for(p=0; p<=(int)WhiteKing; p++)
+ ximMaskPm[p] = ximMaskPm2[p]; // defaults
+ if(gameInfo.variant == VariantShogi) {
+ ximMaskPm[(int)WhiteCannon] = ximMaskPm2[(int)WhiteKing+1];
+ ximMaskPm[(int)WhiteNightrider] = ximMaskPm2[(int)WhiteKing+2];
+ ximMaskPm[(int)WhiteSilver] = ximMaskPm2[(int)WhiteKing+3];
+ ximMaskPm[(int)WhiteGrasshopper] = ximMaskPm2[(int)WhiteKing+4];
+ ximMaskPm[(int)WhiteQueen] = ximMaskPm2[(int)WhiteLance];
+ }
+#ifdef GOTHIC
+ if(gameInfo.variant == VariantGothic) {
+ ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[(int)WhiteSilver];
+ }
+#endif
+ if(gameInfo.variant == VariantSChess && (squareSize == 49 || squareSize == 72)) {
+ ximMaskPm[(int)WhiteAngel] = ximMaskPm2[(int)WhiteFalcon];
+ ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[(int)WhiteAlfil];
+ }
+#endif
+ }
+ } else {
+ for(i=0; i<2; i++) {
+ int p;
+ for(p=0; p<=(int)WhiteKing; p++)
+ pieceBitmap[i][p] = pieceBitmap2[i][p]; // defaults
+ if(gameInfo.variant == VariantShogi) {
+ pieceBitmap[i][(int)WhiteCannon] = pieceBitmap2[i][(int)WhiteKing+1];
+ pieceBitmap[i][(int)WhiteNightrider] = pieceBitmap2[i][(int)WhiteKing+2];
+ pieceBitmap[i][(int)WhiteSilver] = pieceBitmap2[i][(int)WhiteKing+3];
+ pieceBitmap[i][(int)WhiteGrasshopper] = pieceBitmap2[i][(int)WhiteKing+4];
+ pieceBitmap[i][(int)WhiteQueen] = pieceBitmap2[i][(int)WhiteLance];
+ }
+#ifdef GOTHIC
+ if(gameInfo.variant == VariantGothic) {
+ pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteSilver];
+ }
+#endif
+ if(gameInfo.variant == VariantSChess && (squareSize == 49 || squareSize == 72)) {
+ pieceBitmap[i][(int)WhiteAngel] = pieceBitmap2[i][(int)WhiteFalcon];
+ pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteAlfil];
+ }
+ }
+ }
+#if HAVE_LIBXPM
+ CreateAnimVars();
+#endif
+}
+#endif
+
+void ParseIcsTextColors()
+{ // [HGM] tken out of main(), so it can be called from ICS-Options dialog
+ if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
+ parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
+ parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
+ parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
+ parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
+ parse_cpair(ColorTell, appData.colorTell) < 0 ||
+ parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
+ parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
+ parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
+ parse_cpair(ColorNormal, appData.colorNormal) < 0)
+ {
+ if (appData.colorize) {
+ fprintf(stderr,
+ _("%s: can't parse color names; disabling colorization\n"),
+ programName);
+ }
+ appData.colorize = FALSE;
+ }
+}
+
+int MakeColors()
+{ // [HGM] taken out of main(), so it can be called from BoardOptions dialog
+ XrmValue vFrom, vTo;
+ int forceMono = False;
+
+ if (!appData.monoMode) {
+ vFrom.addr = (caddr_t) appData.lightSquareColor;
+ vFrom.size = strlen(appData.lightSquareColor);
+ XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
+ if (vTo.addr == NULL) {
+ appData.monoMode = True;
+ forceMono = True;
+ } else {
+ lightSquareColor = *(Pixel *) vTo.addr;
+ }
+ }
+ if (!appData.monoMode) {
+ vFrom.addr = (caddr_t) appData.darkSquareColor;
+ vFrom.size = strlen(appData.darkSquareColor);
+ XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
+ if (vTo.addr == NULL) {
+ appData.monoMode = True;
+ forceMono = True;
+ } else {
+ darkSquareColor = *(Pixel *) vTo.addr;
+ }
+ }
+ if (!appData.monoMode) {
+ vFrom.addr = (caddr_t) appData.whitePieceColor;
+ vFrom.size = strlen(appData.whitePieceColor);
+ XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
+ if (vTo.addr == NULL) {
+ appData.monoMode = True;
+ forceMono = True;
+ } else {
+ whitePieceColor = *(Pixel *) vTo.addr;
+ }
+ }
+ if (!appData.monoMode) {
+ vFrom.addr = (caddr_t) appData.blackPieceColor;
+ vFrom.size = strlen(appData.blackPieceColor);
+ XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
+ if (vTo.addr == NULL) {
+ appData.monoMode = True;
+ forceMono = True;
+ } else {
+ blackPieceColor = *(Pixel *) vTo.addr;
+ }
+ }
+
+ if (!appData.monoMode) {
+ vFrom.addr = (caddr_t) appData.highlightSquareColor;
+ vFrom.size = strlen(appData.highlightSquareColor);
+ XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
+ if (vTo.addr == NULL) {
+ appData.monoMode = True;
+ forceMono = True;
+ } else {
+ highlightSquareColor = *(Pixel *) vTo.addr;
+ }
+ }
+
+ if (!appData.monoMode) {
+ vFrom.addr = (caddr_t) appData.premoveHighlightColor;
+ vFrom.size = strlen(appData.premoveHighlightColor);
+ XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
+ if (vTo.addr == NULL) {
+ appData.monoMode = True;
+ forceMono = True;
+ } else {
+ premoveHighlightColor = *(Pixel *) vTo.addr;
+ }
+ }
+ return forceMono;
+}
+
+void
+CreateAnyPieces()
+{ // [HGM] taken out of main
+#if HAVE_LIBXPM
+ if (appData.monoMode && // [HGM] no sense to go on to certain doom
+ (appData.bitmapDirectory == NULL || appData.bitmapDirectory[0] == NULLCHAR))
+ appData.bitmapDirectory = DEF_BITMAP_DIR;
+
+ if (appData.bitmapDirectory[0] != NULLCHAR) {
+ CreatePieces();
+ } else {
+ CreateXPMPieces();
+ CreateXPMBoard(appData.liteBackTextureFile, 1);
+ CreateXPMBoard(appData.darkBackTextureFile, 0);
+ }
+#else
+ CreateXIMPieces();
+ /* Create regular pieces */
+ if (!useImages) CreatePieces();
+#endif
+}
+
+int
+main(argc, argv)
+ int argc;
+ char **argv;
+{
+ int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
+ XSetWindowAttributes window_attributes;
+ Arg args[16];
+ Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
+ XrmValue vFrom, vTo;
+ XtGeometryResult gres;
+ char *p;
+ XrmDatabase xdb;
+ int forceMono = False;
+
+ srandom(time(0)); // [HGM] book: make random truly random
+
+ setbuf(stdout, NULL);
+ setbuf(stderr, NULL);
+ debugFP = stderr;
+
+ if(argc > 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];
+ else
+ programName++;
+
+#ifdef ENABLE_NLS
+ XtSetLanguageProc(NULL, NULL, NULL);
+ bindtextdomain(PACKAGE, LOCALEDIR);
+ textdomain(PACKAGE);
+#endif
+
+ shellWidget =
+ XtAppInitialize(&appContext, "XBoard", shellOptions,
+ XtNumber(shellOptions),
+ &argc, argv, xboardResources, NULL, 0);
+ 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.firstInitString);
+ appData.firstInitString = strdup(buf);
+ EscapeExpand(buf, appData.secondInitString);
+ appData.secondInitString = strdup(buf);
+ EscapeExpand(buf, appData.firstComputerString);
+ appData.firstComputerString = strdup(buf);
+ EscapeExpand(buf, appData.secondComputerString);
+ appData.secondComputerString = strdup(buf);
+ }
+
+ if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
+ chessDir = ".";
+ } else {
+ if (chdir(chessDir) != 0) {
+ fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
+ perror(chessDir);
+ exit(1);
+ }
+ }
+
+ if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) {
+ /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */
+ if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL) {
+ printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile);
+ exit(errno);
+ }
+ setbuf(debugFP, NULL);
+ }
+
+#if ENABLE_NLS
+ if (appData.debugMode) {
+ fprintf(debugFP, "locale = %s\n", setlocale(LC_ALL, NULL));
+ }
+#endif
+
+ /* [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;
+#endif
+ InitBackEnd1();
+
+ xDisplay = XtDisplay(shellWidget);
+ xScreen = DefaultScreen(xDisplay);
+ wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
+
+ 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,
+ &fontPxlSize, &smallLayout, &tinyLayout);
+ if (i == 0) {
+ fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
+ programName, appData.boardSize);
+ exit(2);
+ }
+ if (i < 7) {
+ /* Find some defaults; use the nearest known size */
+ SizeDefaults *szd, *nearest;
+ int distance = 99999;
+ nearest = szd = sizeDefaults;
+ while (szd->name != NULL) {
+ if (abs(szd->squareSize - squareSize) < distance) {
+ nearest = szd;
+ distance = abs(szd->squareSize - squareSize);
+ if (distance == 0) break;
+ }
+ szd++;
+ }
+ if (i < 2) lineGap = nearest->lineGap;
+ if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
+ if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
+ if (i < 5) fontPxlSize = nearest->fontPxlSize;
+ if (i < 6) smallLayout = nearest->smallLayout;
+ if (i < 7) tinyLayout = nearest->tinyLayout;
+ }
+ } else {
+ SizeDefaults *szd = sizeDefaults;
+ if (*appData.boardSize == NULLCHAR) {
+ while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize ||
+ DisplayHeight(xDisplay, xScreen) < szd->minScreenSize) {
+ 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++;
+ if (szd->name == NULL) {
+ fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
+ programName, appData.boardSize);
+ exit(2);
+ }
+ }
+ squareSize = szd->squareSize;
+ lineGap = szd->lineGap;
+ clockFontPxlSize = szd->clockFontPxlSize;
+ coordFontPxlSize = szd->coordFontPxlSize;
+ fontPxlSize = szd->fontPxlSize;
+ smallLayout = szd->smallLayout;
+ tinyLayout = szd->tinyLayout;
+ // [HGM] font: use defaults from settings file if available and not overruled
+ }
+ if(!fontIsSet[CLOCK_FONT] && fontValid[CLOCK_FONT][squareSize])
+ appData.clockFont = fontTable[CLOCK_FONT][squareSize];
+ if(!fontIsSet[MESSAGE_FONT] && fontValid[MESSAGE_FONT][squareSize])
+ appData.font = fontTable[MESSAGE_FONT][squareSize];
+ if(!fontIsSet[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) {
+ p = ExpandPathName(appData.pixmapDirectory);
+ if (!p) {
+ fprintf(stderr, _("Error expanding path name \"%s\"\n"),
+ appData.pixmapDirectory);
+ exit(1);
+ }
+ if (appData.debugMode) {
+ fprintf(stderr, _("\
+XBoard square size (hint): %d\n\
+%s fulldir:%s:\n"), squareSize, IMAGE_EXT, p);
+ }
+ squareSize = xpm_closest_to(p, squareSize, IMAGE_EXT);
+ if (appData.debugMode) {
+ fprintf(stderr, _("Closest %s size: %d\n"), IMAGE_EXT, squareSize);
+ }
+ }
+ defaultLineGap = 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,
+ boardHeight + 2*(lineGap + squareSize));
+ } else if (appData.showJail == 2) {
+ /* Jail on sides */
+ XtSetArg(boardArgs[1], XtNwidth,
+ boardWidth + 2*(lineGap + squareSize));
+ XtSetArg(boardArgs[2], XtNheight, boardHeight);
+ } else {
+ /* No jail */
+ XtSetArg(boardArgs[1], XtNwidth, boardWidth);
+ XtSetArg(boardArgs[2], XtNheight, boardHeight);
+ }
+
+ /*
+ * Determine what fonts to use.
+ */
+#if ENABLE_NLS
+ appData.font = InsertPxlSize(appData.font, fontPxlSize);
+ appData.clockFont = InsertPxlSize(appData.clockFont, clockFontPxlSize);
+ appData.coordFont = InsertPxlSize(appData.coordFont, coordFontPxlSize);
+ fontSet = CreateFontSet(appData.font);
+ clockFontSet = CreateFontSet(appData.clockFont);
+ {
+ /* For the coordFont, use the 0th font of the fontset. */
+ XFontSet coordFontSet = CreateFontSet(appData.coordFont);
+ XFontStruct **font_struct_list;
+ char **font_name_list;
+ XFontsOfFontSet(coordFontSet, &font_struct_list, &font_name_list);
+ coordFontID = XLoadFont(xDisplay, font_name_list[0]);
+ coordFontStruct = XQueryFont(xDisplay, coordFontID);
+ }
+#else
+ appData.font = FindFont(appData.font, fontPxlSize);
+ appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
+ appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
+ clockFontID = XLoadFont(xDisplay, appData.clockFont);
+ clockFontStruct = XQueryFont(xDisplay, clockFontID);
+ coordFontID = XLoadFont(xDisplay, appData.coordFont);
+ coordFontStruct = XQueryFont(xDisplay, coordFontID);
+#endif
+ countFontID = coordFontID; // [HGM] holdings
+ countFontStruct = coordFontStruct;
+
+ xdb = XtDatabase(xDisplay);
+#if ENABLE_NLS
+ XrmPutLineResource(&xdb, "*international: True");
+ vTo.size = sizeof(XFontSet);
+ vTo.addr = (XtPointer) &fontSet;
+ XrmPutResource(&xdb, "*fontSet", XtRFontSet, &vTo);
+#else
+ XrmPutStringResource(&xdb, "*font", appData.font);
+#endif
+
+ /*
+ * Detect if there are not enough colors available and adapt.
+ */
+ if (DefaultDepth(xDisplay, xScreen) <= 2) {
+ appData.monoMode = True;
+ }
+
+ forceMono = MakeColors();
+
+ if (forceMono) {
+ fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
+ programName);
+ appData.monoMode = True;
+ }
+
+ if (appData.lowTimeWarning && !appData.monoMode) {
+ vFrom.addr = (caddr_t) appData.lowTimeWarningColor;
+ vFrom.size = strlen(appData.lowTimeWarningColor);
+ XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
+ if (vTo.addr == NULL)
+ appData.monoMode = True;
+ else
+ lowTimeWarningColor = *(Pixel *) vTo.addr;
+ }
+
+ if (appData.monoMode && appData.debugMode) {
+ fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
+ (unsigned long) XWhitePixel(xDisplay, xScreen),
+ (unsigned long) XBlackPixel(xDisplay, xScreen));
+ }
+
+ ParseIcsTextColors();
+ textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
+ textColors[ColorNone].attr = 0;
+
+ XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
+
+ /*
+ * widget hierarchy
+ */
+ if (tinyLayout) {
+ layoutName = "tinyLayout";
+ } else if (smallLayout) {
+ layoutName = "smallLayout";
+ } else {
+ layoutName = "normalLayout";
+ }
+ /* Outer layoutWidget is there only to provide a name for use in
+ resources that depend on the layout style */
+ layoutWidget =
+ XtCreateManagedWidget(layoutName, formWidgetClass, shellWidget,
+ layoutArgs, XtNumber(layoutArgs));
+ formWidget =
+ XtCreateManagedWidget("form", formWidgetClass, layoutWidget,
+ 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));
+#if ENABLE_NLS
+ XtSetArg(args[0], XtNfontSet, clockFontSet);
+#else
+ XtSetArg(args[0], XtNfont, clockFontStruct);
+#endif
+ XtSetArg(args[1], XtNtop, XtChainTop);
+ XtSetArg(args[2], XtNbottom, XtChainTop);
+ XtSetValues(whiteTimerWidget, args, 3);
+
+ widgetList[j++] = blackTimerWidget =
+ XtCreateWidget("blackTime", labelWidgetClass,
+ formWidget, timerArgs, XtNumber(timerArgs));
+#if ENABLE_NLS
+ XtSetArg(args[0], XtNfontSet, clockFontSet);
+#else
+ XtSetArg(args[0], XtNfont, clockFontStruct);
+#endif
+ XtSetArg(args[1], XtNtop, XtChainTop);
+ XtSetArg(args[2], XtNbottom, XtChainTop);
+ XtSetValues(blackTimerWidget, args, 3);
+
+ if (appData.titleInWindow) {
+ 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);
+ XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
+ }
+
+ /*
+ * formWidget uses these constraints but they are stored
+ * in the children.
+ */
+ i = 0;
+ XtSetArg(args[i], XtNfromHoriz, 0); i++;
+ XtSetValues(menuBarWidget, args, i);
+ if (appData.titleInWindow) {
+ if (smallLayout) {
+ i = 0;
+ XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
+ XtSetValues(whiteTimerWidget, args, i);
+ i = 0;
+ XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
+ XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
+ XtSetValues(blackTimerWidget, args, i);
+ i = 0;
+ XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
+ XtSetArg(args[i], XtNjustify, XtJustifyLeft); i++;
+ XtSetValues(titleWidget, args, i);
+ i = 0;
+ XtSetArg(args[i], XtNfromVert, titleWidget); i++;
+ XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
+ XtSetValues(messageWidget, args, i);
+ if (appData.showButtonBar) {
+ i = 0;
+ XtSetArg(args[i], XtNfromVert, titleWidget); i++;
+ XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
+ XtSetValues(buttonBarWidget, args, i);
+ }
+ } else {
+ i = 0;
+ XtSetArg(args[i], XtNfromVert, titleWidget); i++;
+ XtSetValues(whiteTimerWidget, args, i);
+ i = 0;
+ XtSetArg(args[i], XtNfromVert, titleWidget); i++;
+ XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
+ XtSetValues(blackTimerWidget, args, i);
+ i = 0;
+ XtSetArg(args[i], XtNfromHoriz, menuBarWidget); i++;
+ XtSetValues(titleWidget, args, i);
+ i = 0;
+ XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
+ XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
+ XtSetValues(messageWidget, args, i);
+ if (appData.showButtonBar) {
+ i = 0;
+ XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
+ XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
+ XtSetValues(buttonBarWidget, args, i);
+ }
+ }
+ } else {
+ i = 0;
+ XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
+ XtSetValues(whiteTimerWidget, args, i);
+ i = 0;
+ XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
+ XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
+ XtSetValues(blackTimerWidget, args, i);
+ i = 0;
+ XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
+ XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
+ XtSetValues(messageWidget, args, i);
+ if (appData.showButtonBar) {
+ i = 0;
+ XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
+ XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
+ XtSetValues(buttonBarWidget, args, i);
+ }
+ }
+ i = 0;
+ XtSetArg(args[0], XtNfromVert, messageWidget);
+ 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++;
+ XtSetArg(args[i], XtNheight, &h); i++;
+ XtGetValues(messageWidget, args, i);
+ if (appData.showButtonBar) {
+ i = 0;
+ XtSetArg(args[i], XtNwidth, &w); i++;
+ XtGetValues(buttonBarWidget, args, i);
+ w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
+ } else {
+ w = boardWidth - 2*bor + 1; /*!! +1 compensates for kludge below */
+ }
+
+ gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
+ if (gres != XtGeometryYes && appData.debugMode) {
+ fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
+ programName, gres, w, h, wr, hr);
+ }
+
+ /* !! Horrible hack to work around bug in XFree86 4.0.1 (X11R6.4.3) */
+ /* The size used for the child widget in layout lags one resize behind
+ its true size, so we resize a second time, 1 pixel smaller. Yeech! */
+ w--;
+ gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
+ if (gres != XtGeometryYes && appData.debugMode) {
+ fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
+ 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;
+ XtSetArg(args[i], XtNborderWidth, &bor); i++;
+ XtSetArg(args[i], XtNheight, &h); i++;
+ XtGetValues(titleWidget, args, i);
+ if (smallLayout) {
+ w = boardWidth - 2*bor;
+ } else {
+ XtSetArg(args[0], XtNwidth, &w);
+ XtGetValues(menuBarWidget, args, 1);
+ w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
+ }
+
+ gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
+ if (gres != XtGeometryYes && appData.debugMode) {
+ fprintf(stderr,
+ _("%s: titleWidget geometry error %d %d %d %d %d\n"),
+ programName, gres, w, h, wr, hr);
+ }
+ }
+ XawFormDoLayout(formWidget, True);
+
+ 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",
+ checkmark_bits, checkmark_width, checkmark_height);
+ XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
+#ifndef OPTIONSDIALOG
+ if (appData.alwaysPromoteToQueen) {
+ XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
+ args, 1);
+ }
+ if (appData.animateDragging) {
+ XtSetValues(XtNameToWidget(menuBarWidget,
+ "menuOptions.Animate Dragging"),
+ args, 1);
+ }
+ if (appData.animate) {
+ XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
+ args, 1);
+ }
+ if (appData.autoCallFlag) {
+ XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
+ args, 1);
+ }
+ if (appData.autoFlipView) {
+ XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Auto Flip View"),
+ args, 1);
+ }
+ if (appData.blindfold) {
+ XtSetValues(XtNameToWidget(menuBarWidget,
+ "menuOptions.Blindfold"), args, 1);
+ }
+ if (appData.flashCount > 0) {
+ XtSetValues(XtNameToWidget(menuBarWidget,
+ "menuOptions.Flash Moves"),
+ args, 1);
+ }
+#if HIGHDRAG
+ if (appData.highlightDragging) {
+ XtSetValues(XtNameToWidget(menuBarWidget,
+ "menuOptions.Highlight Dragging"),
+ args, 1);
+ }
+#endif
+ if (appData.highlightLastMove) {
+ XtSetValues(XtNameToWidget(menuBarWidget,
+ "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);
+// }
+ if (appData.ringBellAfterMoves) {
+ XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
+ args, 1);
+ }
+ if (appData.oneClick) {
+ XtSetValues(XtNameToWidget(menuBarWidget,
+ "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);
+// }
+ if (appData.showCoords) {
+ XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
+ args, 1);
+ }
+ if (appData.hideThinkingFromHuman) {
+ XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
+ args, 1);
+ }
+ if (appData.testLegality) {
+ XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Test Legality"),
+ args, 1);
+ }
+#endif
+ if (saveSettingsOnExit) {
+ XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Save Settings on Exit"),
+ args, 1);
+ }
+
+ /*
+ * Create an icon.
+ */
+ ReadBitmap(&wIconPixmap, "icon_white.bm",
+ icon_white_bits, icon_white_width, icon_white_height);
+ ReadBitmap(&bIconPixmap, "icon_black.bm",
+ icon_black_bits, icon_black_width, icon_black_height);
+ iconPixmap = wIconPixmap;
+ 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.
+ */
+ shellArgs[0].value = (XtArgVal) &w;
+ shellArgs[1].value = (XtArgVal) &h;
+ XtGetValues(shellWidget, shellArgs, 2);
+ 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(False);
+ CreateGrid();
+ CreateAnyPieces();
+
+ CreatePieceMenus();
+
+ if (appData.animate || appData.animateDragging)
+ CreateAnimVars();
+
+ XtAugmentTranslations(formWidget,
+ XtParseTranslationTable(globalTranslations));
+ XtAugmentTranslations(boardWidget,
+ XtParseTranslationTable(boardTranslations));
+ XtAugmentTranslations(whiteTimerWidget,
+ XtParseTranslationTable(whiteTranslations));
+ XtAugmentTranslations(blackTimerWidget,
+ XtParseTranslationTable(blackTranslations));
+
+ /* Why is the following needed on some versions of X instead
+ * of a translation? */
+ XtAddEventHandler(boardWidget, ExposureMask|PointerMotionMask, False,
+ (XtEventHandler) EventProc, NULL);
+ /* end why */
+ XtAddEventHandler(formWidget, KeyPressMask, False,
+ (XtEventHandler) MoveTypeInProc, NULL);
+
+ /* [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
+ sending the logon script (problems with timestamp otherwise) */
+ /*ICSInitScript();*/
+ 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);
+ XSetInputFocus(xDisplay, XtWindow(formWidget), RevertToPointerRoot, CurrentTime);
+
+ XtAppMainLoop(appContext);
+ if (appData.debugMode) fclose(debugFP); // [DM] debug
+ return 0;
+}
+
+void
+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;
+{
+ ExitEvent(sig);
+}
+
+RETSIGTYPE
+CmailSigHandler(sig)
+ int sig;
+{
+ int dummy = 0;
+ int error;
+
+ signal(SIGUSR1, SIG_IGN); /* suspend handler */
+
+ /* Activate call-back function CmailSigHandlerCallBack() */
+ OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
+
+ signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
+}
+
+void
+CmailSigHandlerCallBack(isr, closure, message, count, error)
+ InputSourceRef isr;
+ VOIDSTAR closure;
+ char *message;
+ int count;
+ int error;
+{
+ BoardToTop();
+ ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
+}
+/**** end signal code ****/
+
+
+void
+ICSInitScript()
+{
+ /* try to open the icsLogon script, either in the location given
+ * or in the users HOME directory
+ */
+
+ 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);
+ else
+ printf("Warning: Couldn't open icsLogon file (checked %s and %s).\n", appData.icsLogon, buf);
+
+ return;
+}
+
+void
+ResetFrontEnd()
+{
+ CommentPopDown();
+ TagsPopDown();
+ return;
+}
+
+typedef struct {
+ char *name;
+ Boolean value;
+} 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;
+{
+ Widget w;
+ if (!menuBarWidget) return;
+ while (enab->name != NULL) {
+ w = XtNameToWidget(menuBarWidget, enab->name);
+ if (w == NULL) {
+ DisplayError(enab->name, 0);
+ } else {
+ XtSetSensitive(w, enab->value);
+ }
+ enab++;
+ }
+}
+
+Enables icsEnables[] = {
+ { "menuFile.Mail Move", False },
+ { "menuFile.Reload CMail Message", False },
+ { "menuMode.Machine Black", False },
+ { "menuMode.Machine White", False },
+ { "menuMode.Analysis Mode", False },
+ { "menuMode.Analyze File", False },
+ { "menuMode.Two Machines", False },
+ { "menuMode.Machine Match", False },
+#ifndef ZIPPY
+ { "menuEngine.Hint", False },
+ { "menuEngine.Book", False },
+ { "menuEngine.Move Now", False },
+#ifndef OPTIONSDIALOG
+ { "menuOptions.Periodic Updates", False },
+ { "menuOptions.Hide Thinking", False },
+ { "menuOptions.Ponder Next Move", False },
+#endif
+#endif
+ { "menuEngine.Engine #1 Settings", False },
+ { "menuEngine.Engine #2 Settings", False },
+ { "menuEngine.Load Engine", False },
+ { "menuEdit.Annotate", False },
+ { "menuOptions.Match", False },
+ { NULL, False }
+};
+
+Enables ncpEnables[] = {
+ { "menuFile.Mail Move", False },
+ { "menuFile.Reload CMail Message", False },
+ { "menuMode.Machine White", False },
+ { "menuMode.Machine Black", False },
+ { "menuMode.Analysis Mode", False },
+ { "menuMode.Analyze File", False },
+ { "menuMode.Two Machines", False },
+ { "menuMode.Machine Match", False },
+ { "menuMode.ICS Client", False },
+ { "menuView.ICStex", False },
+ { "menuView.ICS Input Box", False },
+ { "Action", 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.ICS", False },
+#ifndef OPTIONSDIALOG
+ { "menuOptions.Auto Flag", False },
+ { "menuOptions.Auto Flip View", False },
+// { "menuOptions.ICS Alarm", False },
+ { "menuOptions.Move Sound", False },
+ { "menuOptions.Hide Thinking", False },
+ { "menuOptions.Periodic Updates", False },
+ { "menuOptions.Ponder Next Move", False },
+#endif
+ { "menuEngine.Hint", False },
+ { "menuEngine.Book", False },
+ { NULL, False }
+};
+
+Enables gnuEnables[] = {
+ { "menuMode.ICS Client", False },
+ { "menuView.ICStex", 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 },
+ { "menuAction.Upload to Examine", False },
+ { "menuEdit.Revert", False },
+ { "menuEdit.Annotate", False },
+ { "menuOptions.ICS", False },
+
+ /* The next two options rely on SetCmailMode being called *after* */
+ /* SetGNUMode so that when GNU is being used to give hints these */
+ /* menu options are still available */
+
+ { "menuFile.Mail Move", False },
+ { "menuFile.Reload CMail Message", False },
+ // [HGM] The following have been added to make a switch from ncp to GNU mode possible
+ { "menuMode.Machine White", True },
+ { "menuMode.Machine Black", True },
+ { "menuMode.Analysis Mode", True },
+ { "menuMode.Analyze File", True },
+ { "menuMode.Two Machines", True },
+ { "menuMode.Machine Match", True },
+ { "menuEngine.Engine #1 Settings", True },
+ { "menuEngine.Engine #2 Settings", True },
+ { "menuEngine.Hint", True },
+ { "menuEngine.Book", True },
+ { "menuEngine.Move Now", True },
+ { "menuEngine.Retract Move", True },
+ { "Action", True },
+ { NULL, False }
+};
+
+Enables cmailEnables[] = {
+ { "Action", True },
+ { "menuAction.Call Flag", False },
+ { "menuAction.Draw", True },
+ { "menuAction.Adjourn", False },
+ { "menuAction.Abort", False },
+ { "menuAction.Stop Observing", False },
+ { "menuAction.Stop Examining", False },
+ { "menuFile.Mail Move", True },
+ { "menuFile.Reload CMail Message", True },
+ { NULL, False }
+};
+
+Enables trainingOnEnables[] = {
+ { "menuMode.Edit Comment", False },
+ { "menuMode.Pause", 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[] = {
+ { "menuMode.Edit Comment", True },
+ { "menuMode.Pause", 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 },
+ { "menuEdit.Paste Game", False },
+ { "menuFile.Load 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 },
+// { "menuMode.Machine Match", 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 },
+ { "menuEdit.Paste Game", True },
+ { "menuFile.Load 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 },
+// { "menuMode.Machine Match", True },
+ { "menuEngine.Retract Move", True },
+ { NULL, False }
+};
+
+void SetICSMode()
+{
+ SetMenuEnables(icsEnables);
+
+#if ZIPPY
+ if (appData.zippyPlay && !appData.noChessProgram) { /* [DM] icsEngineAnalyze */
+ XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
+ XtSetSensitive(XtNameToWidget(menuBarWidget, "menuEngine.Engine #1 Settings"), True);
+ }
+#endif
+}
+
+void
+SetNCPMode()
+{
+ SetMenuEnables(ncpEnables);
+}
+
+void
+SetGNUMode()
+{
+ SetMenuEnables(gnuEnables);
+}
+
+void
+SetCmailMode()
+{
+ SetMenuEnables(cmailEnables);
+}
+
+void
+SetTrainingModeOn()
+{
+ SetMenuEnables(trainingOnEnables);
+ if (appData.showButtonBar) {
+ XtSetSensitive(buttonBarWidget, False);
+ }
+ CommentPopDown();
+}
+
+void
+SetTrainingModeOff()
+{
+ SetMenuEnables(trainingOffEnables);
+ if (appData.showButtonBar) {
+ XtSetSensitive(buttonBarWidget, True);
+ }
+}
+
+void
+SetUserThinkingEnables()
+{
+ if (appData.noChessProgram) return;
+ SetMenuEnables(userThinkingEnables);
+}
+
+void
+SetMachineThinkingEnables()
+{
+ if (appData.noChessProgram) return;
+ SetMenuEnables(machineThinkingEnables);
+ switch (gameMode) {
+ case MachinePlaysBlack:
+ case MachinePlaysWhite:
+ case TwoMachinesPlay:
+ XtSetSensitive(XtNameToWidget(menuBarWidget,
+ ModeToWidgetName(gameMode)), True);
+ break;
+ default:
+ break;
+ }
+}
+
+// [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))
+
+#ifdef ENABLE_NLS
+char *
+InsertPxlSize(pattern, targetPxlSize)
+ char *pattern;
+ int targetPxlSize;
+{
+ char *base_fnt_lst, strInt[12], *p, *q;
+ int alternatives, i, len, strIntLen;
+
+ /*
+ * Replace the "*" (if present) in the pixel-size slot of each
+ * alternative with the targetPxlSize.
+ */
+ p = pattern;
+ alternatives = 1;
+ while ((p = strchr(p, ',')) != NULL) {
+ alternatives++;
+ p++;
+ }
+ snprintf(strInt, sizeof(strInt), "%d", targetPxlSize);
+ strIntLen = strlen(strInt);
+ base_fnt_lst = calloc(1, strlen(pattern) + strIntLen * alternatives + 1);
+
+ p = pattern;
+ q = base_fnt_lst;
+ while (alternatives--) {
+ char *comma = strchr(p, ',');
+ for (i=0; i<14; i++) {
+ char *hyphen = strchr(p, '-');
+ if (!hyphen) break;
+ if (comma && hyphen > comma) break;
+ len = hyphen + 1 - p;
+ if (i == 7 && *p == '*' && len == 2) {
+ p += len;
+ memcpy(q, strInt, strIntLen);
+ q += strIntLen;
+ *q++ = '-';
+ } else {
+ memcpy(q, p, len);
+ p += len;
+ q += len;
+ }
+ }
+ if (!comma) break;
+ len = comma + 1 - p;
+ memcpy(q, p, len);
+ p += len;
+ q += len;
+ }
+ strcpy(q, p);
+
+ return base_fnt_lst;
+}
+
+XFontSet
+CreateFontSet(base_fnt_lst)
+ char *base_fnt_lst;
+{
+ XFontSet fntSet;
+ char **missing_list;
+ int missing_count;
+ char *def_string;
+
+ fntSet = XCreateFontSet(xDisplay, base_fnt_lst,
+ &missing_list, &missing_count, &def_string);
+ if (appData.debugMode) {
+ int i, count;
+ XFontStruct **font_struct_list;
+ char **font_name_list;
+ fprintf(debugFP, "Requested font set for list %s\n", base_fnt_lst);
+ if (fntSet) {
+ fprintf(debugFP, " got list %s, locale %s\n",
+ XBaseFontNameListOfFontSet(fntSet),
+ XLocaleOfFontSet(fntSet));
+ count = XFontsOfFontSet(fntSet, &font_struct_list, &font_name_list);
+ for (i = 0; i < count; i++) {
+ fprintf(debugFP, " got charset %s\n", font_name_list[i]);
+ }
+ }
+ for (i = 0; i < missing_count; i++) {
+ fprintf(debugFP, " missing charset %s\n", missing_list[i]);
+ }
+ }
+ if (fntSet == NULL) {
+ fprintf(stderr, _("Unable to create font set for %s.\n"), base_fnt_lst);
+ exit(2);
+ }
+ return fntSet;
+}
+#else // not ENABLE_NLS
+/*
+ * 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,
+ * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
+ * The return value should be freed with XtFree when no
+ * longer needed.
+ */
+char *
+FindFont(pattern, targetPxlSize)
+ char *pattern;
+ int targetPxlSize;
+{
+ char **fonts, *p, *best, *scalable, *scalableTail;
+ int i, j, nfonts, minerr, err, pxlSize;
+
+ fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
+ if (nfonts < 1) {
+ fprintf(stderr, _("%s: no fonts match pattern %s\n"),
+ programName, pattern);
+ exit(2);
+ }
+
+ best = fonts[0];
+ scalable = NULL;
+ minerr = 999999;
+ for (i=0; i<nfonts; i++) {
+ j = 0;
+ p = fonts[i];
+ if (*p != '-') continue;
+ while (j < 7) {
+ if (*p == NULLCHAR) break;
+ if (*p++ == '-') j++;
+ }
+ if (j < 7) continue;
+ pxlSize = atoi(p);
+ if (pxlSize == 0) {
+ scalable = fonts[i];
+ scalableTail = p;
+ } else {
+ err = pxlSize - targetPxlSize;
+ if (Abs(err) < Abs(minerr) ||
+ (minerr > 0 && err < 0 && -err == minerr)) {
+ best = fonts[i];
+ minerr = err;
+ }
+ }
+ }
+ if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
+ /* If the error is too big and there is a scalable font,
+ use the scalable font. */
+ int headlen = scalableTail - scalable;
+ p = (char *) XtMalloc(strlen(scalable) + 10);
+ while (isdigit(*scalableTail)) scalableTail++;
+ sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
+ } else {
+ 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"),
+ pattern, targetPxlSize, p);
+ }
+ XFreeFontNames(fonts);
+ return p;
+}
+#endif
+
+void DeleteGCs()
+{ // [HGM] deletes GCs that are to be remade, to prevent resource leak;
+ // must be called before all non-first callse to CreateGCs()
+ XtReleaseGC(shellWidget, highlineGC);
+ XtReleaseGC(shellWidget, lightSquareGC);
+ XtReleaseGC(shellWidget, darkSquareGC);
+ XtReleaseGC(shellWidget, lineGC);
+ if (appData.monoMode) {
+ if (DefaultDepth(xDisplay, xScreen) == 1) {
+ XtReleaseGC(shellWidget, wbPieceGC);
+ } else {
+ XtReleaseGC(shellWidget, bwPieceGC);
+ }
+ } else {
+ XtReleaseGC(shellWidget, prelineGC);
+ XtReleaseGC(shellWidget, jailSquareGC);
+ XtReleaseGC(shellWidget, wdPieceGC);
+ XtReleaseGC(shellWidget, wlPieceGC);
+ XtReleaseGC(shellWidget, wjPieceGC);
+ XtReleaseGC(shellWidget, bdPieceGC);
+ XtReleaseGC(shellWidget, blPieceGC);
+ XtReleaseGC(shellWidget, bjPieceGC);
+ }
+}
+
+void CreateGCs(int redo)
+{
+ XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
+ | 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;
+
+ if(redo) {
+ DeleteGCs(); // called a second time; clean up old GCs first
+ } else { // [HGM] grid and font GCs created on first call only
+ 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 black)
+ gc_values.foreground = XWhitePixel(xDisplay, xScreen);
+ gc_values.background = XBlackPixel(xDisplay, xScreen);
+ countGC = XtGetGC(shellWidget, value_mask, &gc_values);
+ XSetFont(xDisplay, countGC, countFontID);
+ }
+ gc_values.foreground = XBlackPixel(xDisplay, xScreen);
+ gc_values.background = XBlackPixel(xDisplay, xScreen);
+ lineGC = XtGetGC(shellWidget, value_mask, &gc_values);
+
+ if (appData.monoMode) {
+ gc_values.foreground = XWhitePixel(xDisplay, xScreen);
+ gc_values.background = XWhitePixel(xDisplay, xScreen);
+ highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
+
+ gc_values.foreground = XWhitePixel(xDisplay, xScreen);
+ gc_values.background = XBlackPixel(xDisplay, xScreen);
+ lightSquareGC = wbPieceGC
+ = XtGetGC(shellWidget, value_mask, &gc_values);
+
+ gc_values.foreground = XBlackPixel(xDisplay, xScreen);
+ gc_values.background = XWhitePixel(xDisplay, xScreen);
+ darkSquareGC = bwPieceGC
+ = XtGetGC(shellWidget, value_mask, &gc_values);
+
+ if (DefaultDepth(xDisplay, xScreen) == 1) {
+ /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
+ gc_values.function = GXcopyInverted;
+ copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
+ gc_values.function = GXcopy;
+ if (XBlackPixel(xDisplay, xScreen) == 1) {
+ bwPieceGC = darkSquareGC;
+ wbPieceGC = copyInvertedGC;
+ } else {
+ bwPieceGC = copyInvertedGC;
+ wbPieceGC = lightSquareGC;
+ }
+ }
+ } else {
+ gc_values.foreground = highlightSquareColor;
+ gc_values.background = highlightSquareColor;
+ highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
+
+ gc_values.foreground = premoveHighlightColor;
+ gc_values.background = premoveHighlightColor;
+ 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);
+
+ gc_values.foreground = jailSquareColor;
+ gc_values.background = jailSquareColor;
+ jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
+
+ 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);
+
+ gc_values.foreground = blackPieceColor;
+ gc_values.background = jailSquareColor;
+ bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
+ }
+}
+
+void loadXIM(xim, xmask, filename, dest, mask)
+ XImage *xim;
+ XImage *xmask;
+ char *filename;
+ Pixmap *dest;
+ Pixmap *mask;
+{
+ int x, y, w, h, p;
+ FILE *fp;
+ Pixmap temp;
+ XGCValues values;
+ GC maskGC;
+
+ fp = fopen(filename, "rb");
+ if (!fp) {
+ fprintf(stderr, _("%s: error loading XIM!\n"), programName);
+ exit(1);
+ }
+
+ w = fgetc(fp);
+ h = fgetc(fp);
+
+ for (y=0; y<h; ++y) {
+ for (x=0; x<h; ++x) {
+ p = fgetc(fp);
+
+ switch (p) {
+ case 0:
+ XPutPixel(xim, x, y, blackPieceColor);
+ if (xmask)
+ XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
+ break;
+ case 1:
+ XPutPixel(xim, x, y, darkSquareColor);
+ if (xmask)
+ XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
+ break;
+ case 2:
+ XPutPixel(xim, x, y, whitePieceColor);
+ if (xmask)
+ XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
+ break;
+ case 3:
+ XPutPixel(xim, x, y, lightSquareColor);
+ if (xmask)
+ XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
+ break;
+ }
+ }
+ }
+
+ fclose(fp);
+
+ /* create Pixmap of piece */
+ *dest = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
+ w, h, xim->depth);
+ XPutImage(xDisplay, *dest, lightSquareGC, xim,
+ 0, 0, 0, 0, w, h);
+
+ /* 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. */
+ if (xmask) {
+ temp = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
+ w, h, xim->depth);
+ XPutImage(xDisplay, temp, lightSquareGC, xmask,
+ 0, 0, 0, 0, w, h);
+
+ /* now create the 1-bit version */
+ *mask = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
+ w, h, 1);
+
+ values.foreground = 1;
+ values.background = 0;
+
+ /* Don't use XtGetGC, not read only */
+ maskGC = XCreateGC(xDisplay, *mask,
+ GCForeground | GCBackground, &values);
+ XCopyPlane(xDisplay, temp, *mask, maskGC,
+ 0, 0, squareSize, squareSize, 0, 0, 1);
+ XFreePixmap(xDisplay, temp);
+ }
+}
+
+
+char pieceBitmapNames[] = "pnbrqfeacwmohijgdvlsukpnsl";
+
+void CreateXIMPieces()
+{
+ int piece, kind;
+ char buf[MSG_SIZ];
+ u_int ss;
+ static char *ximkind[] = { "ll", "ld", "dl", "dd" };
+ XImage *ximtemp;
+
+ ss = squareSize;
+
+ /* 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 */
+
+ /* temp needed by loadXIM() */
+ ximtemp = XGetImage(xDisplay, DefaultRootWindow(xDisplay),
+ 0, 0, ss, ss, AllPlanes, XYPixmap);
+
+ if (strlen(appData.pixmapDirectory) == 0) {
+ useImages = 0;
+ } else {
+ useImages = 1;
+ if (appData.monoMode) {
+ DisplayFatalError(_("XIM pieces cannot be used in monochrome mode"),
+ 0, 2);
+ ExitEvent(2);
+ }
+ fprintf(stderr, _("\nLoading XIMs...\n"));
+ /* Load pieces */
+ for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
+ fprintf(stderr, "%d", piece+1);
+ for (kind=0; kind<4; kind++) {
+ fprintf(stderr, ".");
+ snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xim",
+ ExpandPathName(appData.pixmapDirectory),
+ 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],
+ ximtemp, buf,
+ &(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
+ draw them with solid squares. */
+ 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=
+ XGetImage(xDisplay, DefaultRootWindow(xDisplay),
+ 0, 0, ss, ss, AllPlanes, XYPixmap);
+ if (appData.debugMode)
+ fprintf(stderr, _("(File:%s:) "), buf);
+
+ loadXIM(ximLightSquare, NULL, buf, &xpmLightSquare, NULL);
+ fprintf(stderr, _("dark square "));
+ snprintf(buf,sizeof(buf), "%s/dsq%u.xim",
+ ExpandPathName(appData.pixmapDirectory), ss);
+ if (appData.debugMode)
+ fprintf(stderr, _("(File:%s:) "), buf);
+ ximDarkSquare=
+ XGetImage(xDisplay, DefaultRootWindow(xDisplay),
+ 0, 0, ss, ss, AllPlanes, XYPixmap);
+ loadXIM(ximDarkSquare, NULL, buf, &xpmDarkSquare, NULL);
+ xpmJailSquare = xpmLightSquare;
+ }
+ fprintf(stderr, _("Done.\n"));
+ }
+ XSynchronize(xDisplay, False); /* Work-around for xlib/xt buffering bug */
+}
+
+static VariantClass oldVariant = (VariantClass) -1; // [HGM] pieces: redo every time variant changes
+
+#if HAVE_LIBXPM
+void CreateXPMBoard(char *s, int kind)
+{
+ XpmAttributes attr;
+ attr.valuemask = 0;
+ if(s == NULL || *s == 0 || *s == '*') { useTexture &= ~(kind+1); return; }
+ if (XpmReadFileToPixmap(xDisplay, xBoardWindow, s, &(xpmBoardBitmap[kind]), NULL, &attr) == 0) {
+ useTexture |= kind + 1; textureW[kind] = attr.width; textureH[kind] = attr.height;
+ }
+}
+
+void FreeXPMPieces()
+{ // [HGM] to prevent resoucre leak on calling CreaeXPMPieces() a second time,
+ // thisroutine has to be called t free the old piece pixmaps
+ int piece, kind;
+ for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++)
+ for (kind=0; kind<4; kind++) XFreePixmap(xDisplay, xpmPieceBitmap2[kind][piece]);
+ if(useImageSqs) {
+ XFreePixmap(xDisplay, xpmLightSquare);
+ XFreePixmap(xDisplay, xpmDarkSquare);
+ }
+}
+
+void CreateXPMPieces()
+{
+ int piece, kind, r;
+ char buf[MSG_SIZ];
+ u_int ss = squareSize;
+ XpmAttributes attr;
+ static char *xpmkind[] = { "ll", "ld", "dl", "dd" };
+ XpmColorSymbol symbols[4];
+ static int redo = False;
+
+ if(redo) FreeXPMPieces(); else redo = 1;
+
+ /* 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;
+ symbols[1].name = "dark_piece";
+ symbols[1].value = appData.blackPieceColor;
+ symbols[2].name = "light_square";
+ symbols[2].value = appData.lightSquareColor;
+ symbols[3].name = "dark_square";
+ symbols[3].value = appData.darkSquareColor;
+
+ attr.valuemask = XpmColorSymbols;
+ attr.colorsymbols = symbols;
+ attr.numsymbols = 4;
+
+ if (appData.monoMode) {
+ DisplayFatalError(_("XPM pieces cannot be used in monochrome mode"),
+ 0, 2);
+ ExitEvent(2);
+ }
+ if (strlen(appData.pixmapDirectory) == 0) {
+ XpmPieces* pieces = builtInXpms;
+ useImages = 1;
+ /* Load pieces */
+ while (pieces->size != squareSize && pieces->size) pieces++;
+ if (!pieces->size) {
+ fprintf(stderr, _("No builtin XPM pieces of size %d\n"), squareSize);
+ exit(1);
+ }
+ for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
+ for (kind=0; kind<4; kind++) {
+
+ if ((r=XpmCreatePixmapFromData(xDisplay, xBoardWindow,
+ pieces->xpm[piece][kind],
+ &(xpmPieceBitmap2[kind][piece]),
+ NULL, &attr)) != 0) {
+ fprintf(stderr, _("Error %d loading XPM image \"%s\"\n"),
+ r, buf);
+ 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 + 4; piece++) {
+ fprintf(stderr, "%d ", piece+1);
+ for (kind=0; kind<4; kind++) {
+ snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xpm",
+ ExpandPathName(appData.pixmapDirectory),
+ piece > (int) WhiteKing ? "w" : "",
+ pieceBitmapNames[piece],
+ xpmkind[kind], ss);
+ if (appData.debugMode) {
+ fprintf(stderr, _("(File:%s:) "), buf);
+ }
+ if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
+ &(xpmPieceBitmap2[kind][piece]),
+ NULL, &attr)) != 0) {
+ 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
+ draw them with solid squares. */
+ fprintf(stderr, _("light square "));
+ snprintf(buf, sizeof(buf), "%s/lsq%u.xpm", ExpandPathName(appData.pixmapDirectory), ss);
+ if (access(buf, 0) != 0) {
+ useImageSqs = 0;
+ } else {
+ useImageSqs = 1;
+ if (appData.debugMode)
+ fprintf(stderr, _("(File:%s:) "), buf);
+
+ if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
+ &xpmLightSquare, NULL, &attr)) != 0) {
+ fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
+ exit(1);
+ }
+ fprintf(stderr, _("dark square "));
+ snprintf(buf, sizeof(buf), "%s/dsq%u.xpm",
+ ExpandPathName(appData.pixmapDirectory), ss);
+ if (appData.debugMode) {
+ fprintf(stderr, _("(File:%s:) "), buf);
+ }
+ if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
+ &xpmDarkSquare, NULL, &attr)) != 0) {
+ fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
+ exit(1);
+ }
+ }
+ xpmJailSquare = xpmLightSquare;
+ fprintf(stderr, _("Done.\n"));
+ }
+ oldVariant = -1; // kludge to force re-makig of animation masks
+ XSynchronize(xDisplay, False); /* Work-around for xlib/xt
+ buffering bug */
+}
+#endif /* HAVE_LIBXPM */
+
+#if HAVE_LIBXPM
+/* No built-in bitmaps */
+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 + 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 */
+}
+#else
+/* With built-in bitmaps */
+void CreatePieces()
+{
+ BuiltInBits* bib = builtInBits;
+ 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 + 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 */
+}
+#endif
+
+void ReadBitmap(pm, name, bits, wreq, hreq)
+ Pixmap *pm;
+ String name;
+ unsigned char bits[];
+ u_int wreq, hreq;
+{
+ int x_hot, y_hot;
+ u_int w, h;
+ int errcode;
+ char msg[MSG_SIZ], fullname[MSG_SIZ];
+
+ if (*appData.bitmapDirectory != NULLCHAR) {
+ 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:
+ snprintf(msg, sizeof(msg), _("Can't open bitmap file %s"), fullname);
+ break;
+ case BitmapFileInvalid:
+ snprintf(msg, sizeof(msg), _("Invalid bitmap in file %s"), fullname);
+ break;
+ case BitmapNoMemory:
+ snprintf(msg, sizeof(msg), _("Ran out of memory reading bitmap file %s"),
+ fullname);
+ break;
+ default:
+ snprintf(msg, sizeof(msg), _("Unknown XReadBitmapFile error %d on file %s"),
+ errcode, fullname);
+ break;
+ }
+ fprintf(stderr, _("%s: %s...using built-in\n"),
+ programName, msg);
+ } else if (w != wreq || h != hreq) {
+ fprintf(stderr,
+ _("%s: Bitmap %s is %dx%d, not %dx%d...using built-in\n"),
+ programName, fullname, w, h, wreq, hreq);
+ } else {
+ return;
+ }
+ }
+ if (bits != NULL) {
+ *pm = XCreateBitmapFromData(xDisplay, xBoardWindow, (char *) bits,
+ wreq, hreq);
+ }
+}
+
+void CreateGrid()
+{
+ int i, j;
+
+ if (lineGap == 0) return;
+
+ /* [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));
+ }
+}
+
+static void MenuBarSelect(w, addr, index)
+ Widget w;
+ caddr_t addr;
+ caddr_t index;
+{
+ XtActionProc proc = (XtActionProc) addr;
+
+ (proc)(NULL, NULL, NULL, NULL);
+}
+
+void CreateMenuBarPopup(parent, name, mb)
+ Widget parent;
+ String name;
+ Menu *mb;
+{
+ int j;
+ Widget menu, entry;
+ MenuItem *mi;
+ Arg args[16];
+
+ menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
+ parent, NULL, 0);
+ j = 0;
+ XtSetArg(args[j], XtNleftMargin, 20); j++;
+ XtSetArg(args[j], XtNrightMargin, 20); j++;
+ mi = mb->mi;
+ while (mi->string != NULL) {
+ if (strcmp(mi->string, "----") == 0) {
+ entry = XtCreateManagedWidget(_(mi->string), smeLineObjectClass,
+ menu, args, j);
+ } else {
+ XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string)));
+ entry = XtCreateManagedWidget(mi->ref, smeBSBObjectClass,
+ menu, args, j+1);
+ XtAddCallback(entry, XtNcallback,
+ (XtCallbackProc) MenuBarSelect,
+ (caddr_t) mi->proc);
+ }
+ mi++;
+ }
+}
+
+Widget CreateMenuBar(mb)
+ Menu *mb;
+{
+ int j;
+ Widget anchor, menuBar;
+ Arg args[16];
+ char menuName[MSG_SIZ];
+
+ j = 0;
+ XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
+ XtSetArg(args[j], XtNvSpace, 0); j++;
+ XtSetArg(args[j], XtNborderWidth, 0); j++;
+ menuBar = XtCreateWidget("menuBar", boxWidgetClass,
+ formWidget, args, j);
+
+ while (mb->name != NULL) {
+ 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[1] = NULLCHAR;
+ XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
+ }
+ else {
+ XtSetArg(args[j], XtNlabel, XtNewString(_(mb->name))); j++;
+ }
+
+ XtSetArg(args[j], XtNborderWidth, 0); j++;
+ anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
+ menuBar, args, j);
+ CreateMenuBarPopup(menuBar, menuName, mb);
+ mb++;
+ }
+ return menuBar;
+}
+
+Widget CreateButtonBar(mi)
+ MenuItem *mi;
+{
+ int j;
+ Widget button, buttonBar;
+ Arg args[16];
+
+ j = 0;
+ XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
+ if (tinyLayout) {
+ XtSetArg(args[j], XtNhSpace, 0); j++;
+ }
+ XtSetArg(args[j], XtNborderWidth, 0); j++;
+ XtSetArg(args[j], XtNvSpace, 0); j++;
+ buttonBar = XtCreateWidget("buttonBar", boxWidgetClass,
+ formWidget, args, j);
+
+ while (mi->string != NULL) {
+ j = 0;
+ if (tinyLayout) {
+ XtSetArg(args[j], XtNinternalWidth, 2); j++;
+ XtSetArg(args[j], XtNborderWidth, 0); j++;
+ }
+ XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string))); j++;
+ button = XtCreateManagedWidget(mi->string, commandWidgetClass,
+ buttonBar, args, j);
+ XtAddCallback(button, XtNcallback,
+ (XtCallbackProc) MenuBarSelect,
+ (caddr_t) mi->proc);
+ mi++;
+ }
+ return buttonBar;
+}
+
+Widget
+CreatePieceMenu(name, color)
+ char *name;
+ int color;
+{
+ int i;
+ Widget entry, menu;
+ Arg args[16];
+ ChessSquare selection;
+
+ menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
+ boardWidget, args, 0);
+
+ for (i = 0; i < PIECE_MENU_SIZE; i++) {
+ String item = pieceMenuStrings[color][i];
+
+ if (strcmp(item, "----") == 0) {
+ entry = XtCreateManagedWidget(item, smeLineObjectClass,
+ menu, NULL, 0);
+ } else {
+ XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
+ entry = XtCreateManagedWidget(item, smeBSBObjectClass,
+ menu, args, 1);
+ selection = pieceMenuTranslation[color][i];
+ XtAddCallback(entry, XtNcallback,
+ (XtCallbackProc) PieceMenuSelect,
+ (caddr_t) selection);
+ if (selection == WhitePawn || selection == BlackPawn) {
+ XtSetArg(args[0], XtNpopupOnEntry, entry);
+ XtSetValues(menu, args, 1);
+ }
+ }
+ }
+ return menu;
+}
+
+void
+CreatePieceMenus()
+{
+ int i;
+ Widget entry;
+ Arg args[16];
+ ChessSquare selection;
+
+ whitePieceMenu = CreatePieceMenu("menuW", 0);
+ blackPieceMenu = CreatePieceMenu("menuB", 1);
+
+ XtRegisterGrabAction(PieceMenuPopup, True,
+ (unsigned)(ButtonPressMask|ButtonReleaseMask),
+ GrabModeAsync, GrabModeAsync);
+
+ XtSetArg(args[0], XtNlabel, _("Drop"));
+ dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
+ boardWidget, args, 1);
+ for (i = 0; i < DROP_MENU_SIZE; i++) {
+ String item = dropMenuStrings[i];
+
+ if (strcmp(item, "----") == 0) {
+ entry = XtCreateManagedWidget(item, smeLineObjectClass,
+ dropMenu, NULL, 0);
+ } else {
+ XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
+ entry = XtCreateManagedWidget(item, smeBSBObjectClass,
+ dropMenu, args, 1);
+ selection = dropMenuTranslation[i];
+ XtAddCallback(entry, XtNcallback,
+ (XtCallbackProc) DropMenuSelect,
+ (caddr_t) selection);
+ }
+ }
+}
+
+void SetupDropMenu()
+{
+ int i, j, count;
+ char label[32];
+ Arg args[16];
+ Widget entry;
+ char* p;
+
+ for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
+ entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
+ p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
+ dmEnables[i].piece);
+ XtSetSensitive(entry, p != NULL || !appData.testLegality
+ /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
+ && !appData.icsActive));
+ count = 0;
+ while (p && *p++ == dmEnables[i].piece) count++;
+ snprintf(label, sizeof(label), "%s %d", dmEnables[i].widget, count);
+ j = 0;
+ XtSetArg(args[j], XtNlabel, label); j++;
+ XtSetValues(entry, args, j);
+ }
+}
+
+void PieceMenuPopup(w, event, params, num_params)
+ Widget w;
+ XEvent *event;
+ String *params;
+ Cardinal *num_params;
+{
+ String whichMenu; int menuNr = -2;
+ shiftKey = strcmp(params[0], "menuW"); // used to indicate black
+ 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;
+ }
+ XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
+}
+
+static void PieceMenuSelect(w, piece, junk)
+ Widget w;
+ ChessSquare piece;
+ caddr_t junk;
+{
+ if (pmFromX < 0 || pmFromY < 0) return;
+ EditPositionMenuEvent(piece, pmFromX, pmFromY);
+}
+
+static void DropMenuSelect(w, piece, junk)
+ Widget w;
+ ChessSquare piece;
+ caddr_t junk;
+{
+ if (pmFromX < 0 || pmFromY < 0) return;
+ DropMenuEvent(piece, pmFromX, pmFromY);
+}
+
+void WhiteClock(w, event, prms, nprms)
+ Widget w;
+ XEvent *event;
+ String *prms;
+ Cardinal *nprms;
+{
+ ClockClick(0);
+}
+
+void BlackClock(w, event, prms, nprms)
+ Widget w;
+ XEvent *event;
+ String *prms;
+ Cardinal *nprms;
+{
+ ClockClick(1);
+}
+
+
+/*
+ * If the user selects on a border boundary, return -1; if off the board,
+ * return -2. Otherwise map the event coordinate to the square.
+ */
+int EventToSquare(x, limit)
+ int x;
+{
+ if (x <= 0)
+ return -2;
+ if (x < lineGap)
+ return -1;
+ x -= lineGap;
+ if ((x % (squareSize + lineGap)) >= squareSize)
+ return -1;
+ x /= (squareSize + lineGap);
+ if (x >= limit)
+ return -2;
+ return x;
+}
+
+static void do_flash_delay(msec)
+ unsigned long msec;
+{
+ TimeDelay(msec);
+}
+
+static void drawHighlight(file, rank, gc)
+ int file, rank;
+ GC gc;
+{
+ int x, y;
+
+ if (lineGap == 0) return;
+
+ if (flipView) {
+ 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_HEIGHT-1)-rank) *
+ (squareSize + lineGap);
+ }
+
+ XDrawRectangle(xDisplay, xBoardWindow, gc, x, y,
+ squareSize+lineGap, squareSize+lineGap);
+}
+
+int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
+int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
+
+void
+SetHighlights(fromX, fromY, toX, toY)
+ int fromX, fromY, toX, toY;
+{
+ if (hi1X != fromX || hi1Y != fromY) {
+ 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 (toX >= 0 && toY >= 0) {
+ drawHighlight(toX, toY, highlineGC);
+ }
+ }
+ hi1X = fromX;
+ hi1Y = fromY;
+ hi2X = toX;
+ hi2Y = toY;
+}
+
+void
+ClearHighlights()
+{
+ SetHighlights(-1, -1, -1, -1);
+}
+
+
+void
+SetPremoveHighlights(fromX, fromY, toX, toY)
+ int fromX, fromY, toX, toY;
+{
+ if (pm1X != fromX || pm1Y != fromY) {
+ if (pm1X >= 0 && pm1Y >= 0) {
+ drawHighlight(pm1X, pm1Y, lineGC);
+ }
+ if (fromX >= 0 && fromY >= 0) {
+ drawHighlight(fromX, fromY, prelineGC);
+ }
+ }
+ if (pm2X != toX || pm2Y != toY) {
+ if (pm2X >= 0 && pm2Y >= 0) {
+ drawHighlight(pm2X, pm2Y, lineGC);
+ }
+ if (toX >= 0 && toY >= 0) {
+ drawHighlight(toX, toY, prelineGC);
+ }
+ }
+ pm1X = fromX;
+ pm1Y = fromY;
+ pm2X = toX;
+ pm2Y = toY;
+}
+
+void
+ClearPremoveHighlights()
+{
+ SetPremoveHighlights(-1, -1, -1, -1);
+}
+
+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) {
+ case 1: /* light */
+ pm = xpmLightSquare;
+ break;
+ case 0: /* dark */
+ pm = xpmDarkSquare;
+ break;
+ case 2: /* neutral */
+ default:
+ pm = xpmJailSquare;
+ break;
+ }
+ XCopyArea(xDisplay, pm, dest, wlPieceGC, 0, 0,
+ squareSize, squareSize, x*fac, y*fac);
+ } else {
+ GC gc;
+ switch (color) {
+ case 1: /* light */
+ gc = lightSquareGC;
+ break;
+ case 0: /* dark */
+ gc = darkSquareGC;
+ break;
+ case 2: /* neutral */
+ default:
+ gc = jailSquareGC;
+ break;
+ }
+ XFillRectangle(xDisplay, dest, gc, x*fac, y*fac, squareSize, squareSize);
+ }
+}
+
+/*
+ I split out the routines to draw a piece so that I could
+ make a generic flash routine.
+*/
+static void monoDrawPiece_1bit(piece, square_color, x, y, dest)
+ ChessSquare piece;
+ int square_color, x, y;
+ Drawable dest;
+{
+ /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
+ switch (square_color) {
+ case 1: /* light */
+ case 2: /* neutral */
+ default:
+ XCopyArea(xDisplay, (int) piece < (int) BlackPawn
+ ? *pieceToOutline(piece)
+ : *pieceToSolid(piece),
+ dest, bwPieceGC, 0, 0,
+ squareSize, squareSize, x, y);
+ break;
+ case 0: /* dark */
+ XCopyArea(xDisplay, (int) piece < (int) BlackPawn
+ ? *pieceToSolid(piece)
+ : *pieceToOutline(piece),
+ dest, wbPieceGC, 0, 0,
+ squareSize, squareSize, x, y);
+ break;
+ }
+}
+
+static void monoDrawPiece(piece, square_color, x, y, dest)
+ ChessSquare piece;
+ int square_color, x, y;
+ Drawable dest;
+{
+ switch (square_color) {
+ case 1: /* light */
+ case 2: /* neutral */
+ default:
+ XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
+ ? *pieceToOutline(piece)
+ : *pieceToSolid(piece),
+ dest, bwPieceGC, 0, 0,
+ squareSize, squareSize, x, y, 1);
+ break;
+ case 0: /* dark */
+ XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
+ ? *pieceToSolid(piece)
+ : *pieceToOutline(piece),
+ dest, wbPieceGC, 0, 0,
+ squareSize, squareSize, x, y, 1);
+ break;
+ }
+}
+
+static void colorDrawPiece(piece, square_color, x, y, dest)
+ ChessSquare piece;
+ 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),
+ dest, (int) piece < (int) BlackPawn
+ ? wlPieceGC : blPieceGC, 0, 0,
+ squareSize, squareSize, x, y, 1);
+ break;
+ case 0: /* dark */
+ XCopyPlane(xDisplay, *pieceToSolid(piece),
+ dest, (int) piece < (int) BlackPawn
+ ? wdPieceGC : bdPieceGC, 0, 0,
+ squareSize, squareSize, x, y, 1);
+ break;
+ case 2: /* neutral */
+ default:
+ XCopyPlane(xDisplay, *pieceToSolid(piece),
+ dest, (int) piece < (int) BlackPawn
+ ? wjPieceGC : bjPieceGC, 0, 0,
+ squareSize, squareSize, x, y, 1);
+ break;
+ }
+}
+
+static void colorDrawPieceImage(piece, square_color, x, y, dest)
+ ChessSquare piece;
+ int square_color, x, y;
+ Drawable dest;
+{
+ int kind, p = piece;
+
+ switch (square_color) {
+ case 1: /* light */
+ case 2: /* neutral */
+ default:
+ if ((int)piece < (int) BlackPawn) {
+ kind = 0;
+ } else {
+ kind = 2;
+ piece -= BlackPawn;
+ }
+ break;
+ case 0: /* dark */
+ if ((int)piece < (int) BlackPawn) {
+ kind = 1;
+ } else {
+ kind = 3;
+ piece -= BlackPawn;
+ }
+ break;
+ }
+ if(appData.upsideDown && flipView) { kind ^= 2; p += p < BlackPawn ? BlackPawn : -BlackPawn; }// 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);
+}
+
+typedef void (*DrawFunc)();
+
+DrawFunc ChooseDrawFunc()
+{
+ if (appData.monoMode) {
+ if (DefaultDepth(xDisplay, xScreen) == 1) {
+ return monoDrawPiece_1bit;
+ } else {
+ return monoDrawPiece;
+ }
+ } else {
+ if (useImages)
+ return colorDrawPieceImage;
+ else
+ return colorDrawPiece;
+ }
+}
+
+/* [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;
+{
+ int square_color, x, y, direction, font_ascent, font_descent;
+ int i;
+ char string[2];
+ XCharStruct overall;
+ DrawFunc drawfunc;
+ int flash_delay;
+
+ /* Calculate delay in milliseconds (2-delays per complete flash) */
+ flash_delay = 500 / appData.flashRate;
+
+ if (flipView) {
+ x = lineGap + ((BOARD_WIDTH-1)-column) *
+ (squareSize + lineGap);
+ y = lineGap + row * (squareSize + lineGap);
+ } else {
+ x = lineGap + column * (squareSize + lineGap);
+ y = lineGap + ((BOARD_HEIGHT-1)-row) *
+ (squareSize + lineGap);
+ }
+
+ if(twoBoards && partnerUp) x += hOffset; // [HGM] dual: draw second board
+
+ square_color = SquareColor(row, column);
+
+ if ( // [HGM] holdings: blank out area between board and holdings
+ column == BOARD_LEFT-1 || column == BOARD_RGHT
+ || (column == BOARD_LEFT-2 && row < BOARD_HEIGHT-gameInfo.holdingsSize)
+ || (column == BOARD_RGHT+1 && row >= 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<appData.flashCount; ++i) {
+ drawfunc(piece, square_color, x, y, xBoardWindow);
+ XSync(xDisplay, False);
+ do_flash_delay(flash_delay);
+
+ BlankSquare(x, y, square_color, piece, xBoardWindow, 1);
+ XSync(xDisplay, False);
+ do_flash_delay(flash_delay);
+ }
+ }
+ drawfunc(piece, square_color, x, y, xBoardWindow);
+ }
+ }
+
+ string[1] = NULLCHAR;
+ if (appData.showCoords && row == (flipView ? BOARD_HEIGHT-1 : 0)
+ && column >= 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,
+ y + squareSize - font_descent - 1, string, 1);
+ } else {
+ XDrawString(xDisplay, xBoardWindow, coordGC,
+ x + squareSize - overall.width - 2,
+ y + squareSize - font_descent - 1, string, 1);
+ }
+ }
+ 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,
+ x + 2, y + font_ascent + 1, string, 1);
+ } 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);
+ }
+}
+
+
+/* Why is this needed on some versions of X? */
+void EventProc(widget, unused, event)
+ Widget widget;
+ caddr_t unused;
+ XEvent *event;
+{
+ if (!XtIsRealized(widget))
+ return;
+
+ switch (event->type) {
+ 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;
+ }
+}
+/* end why */
+
+void DrawPosition(fullRedraw, board)
+ /*Boolean*/int fullRedraw;
+ Board board;
+{
+ XDrawPosition(boardWidget, fullRedraw, board);
+}
+
+/* Returns 1 if there are "too many" differences between b1 and b2
+ (i.e. more than 1 move was made) */
+static int too_many_diffs(b1, b2)
+ Board b1, b2;
+{
+ int i, j;
+ int c = 0;
+
+ for (i=0; i<BOARD_HEIGHT; ++i) {
+ for (j=0; j<BOARD_WIDTH; ++j) {
+ if (b1[i][j] != b2[i][j]) {
+ if (++c > 4) /* Castling causes 4 diffs */
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+/* Matrix describing castling maneuvers */
+/* Row, ColRookFrom, ColKingFrom, ColRookTo, ColKingTo */
+static int castling_matrix[4][5] = {
+ { 0, 0, 4, 3, 2 }, /* 0-0-0, white */
+ { 0, 7, 4, 5, 6 }, /* 0-0, white */
+ { 7, 0, 4, 3, 2 }, /* 0-0-0, black */
+ { 7, 7, 4, 5, 6 } /* 0-0, black */
+};
+
+/* 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.
+ */
+static int check_castle_draw(newb, oldb, rrow, rcol)
+ Board newb, oldb;
+ int *rrow, *rcol;
+{
+ int i, *r, j;
+ int match;
+
+ /* For each type of castling... */
+ for (i=0; i<4; ++i) {
+ r = castling_matrix[i];
+
+ /* Check the 4 squares involved in the castling move */
+ match = 0;
+ for (j=1; j<=4; ++j) {
+ if (newb[r[0]][r[j]] == oldb[r[0]][r[j]]) {
+ match = 1;
+ break;
+ }
+ }
+
+ if (!match) {
+ /* All 4 changed, so it must be a castling move */
+ *rrow = r[0];
+ *rcol = r[3];
+ return 1;
+ }
+ }
+ return 0;
+}
+
+// [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
+ */
+void XDrawPosition(w, repaint, board)
+ Widget w;
+ /*Boolean*/int repaint;
+ Board board;
+{
+ int i, j, do_flash;
+ static int lastFlipView = 0;
+ 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[nr]) return;
+ board = lastBoard[nr];
+ }
+ if (!lastBoardValid[nr] || (nr == 0 && lastFlipView != flipView)) {
+ XtSetArg(args[0], XtNleftBitmap, (flipView ? xMarkPixmap : None));
+ XtSetValues(XtNameToWidget(menuBarWidget, "menuView.Flip View"),
+ args, 1);
+ }
+
+ /*
+ * It would be simpler to clear the window with XClearWindow()
+ * but this causes a very distracting flicker.
+ */
+
+ if (!repaint && lastBoardValid[nr] && (nr == 1 || lastFlipView == flipView)) {
+
+ if ( lineGap && IsDrawArrowEnabled())
+ XDrawSegments(xDisplay, xBoardWindow, lineGC,
+ gridSegments, BOARD_HEIGHT + BOARD_WIDTH + 2);
+
+ /* If too much changes (begin observing new game, etc.), don't
+ do flashing */
+ 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[nr], &rrow, &rcol)) {
+ /* Draw rook with NO flashing. King will be drawn flashing later */
+ DrawSquare(rrow, rcol, board[rrow][rcol], 0);
+ 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
+ is flashing on its new square */
+ 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[nr][i][j] = False;
+ }
+
+ /* Second pass -- Draw piece(s) in new position and flash them */
+ 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,
+ 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[nr][i][j] = False;
+ }
+ }
+
+ CopyBoard(lastBoard[nr], board);
+ lastBoardValid[nr] = 1;
+ if(nr == 0) { // [HGM] dual: no highlights on second board yet
+ lastFlipView = flipView;
+
+ /* Draw highlights */
+ if (pm1X >= 0 && pm1Y >= 0) {
+ drawHighlight(pm1X, pm1Y, prelineGC);
+ }
+ if (pm2X >= 0 && pm2Y >= 0) {
+ drawHighlight(pm2X, pm2Y, prelineGC);
+ }
+ if (hi1X >= 0 && hi1Y >= 0) {
+ drawHighlight(hi1X, hi1Y, highlineGC);
+ }
+ 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();
+
+ XSync(xDisplay, False);
+}
+
+
+/*
+ * event handler for redrawing the board
+ */
+void DrawPositionProc(w, event, prms, nprms)
+ Widget w;
+ XEvent *event;
+ String *prms;
+ Cardinal *nprms;
+{
+ XDrawPosition(w, True, NULL);
+}
+
+
+/*
+ * 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;
+{
+ if (w != boardWidget || errorExitStatus != -1) return;
+ if(nprms) shiftKey = !strcmp(prms[0], "1");
+
+ if (promotionUp) {
+ if (event->type == ButtonPress) {
+ XtPopdown(promotionShell);
+ XtDestroyWidget(promotionShell);
+ promotionUp = False;
+ ClearHighlights();
+ fromX = fromY = -1;
+ } else {
+ return;
+ }
+ }
+
+ // [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,
+ String * params, Cardinal * nParams)
+{
+ if(!PromoScroll(event->xmotion.x, event->xmotion.y))
+ 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));
+}
+
+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;
+{
+ savedIndex = index;
+ if (text == NULL) text = "";
+ NewCommentPopup(title, text, index);
+}
+
+void ICSInputBoxPopUp()
+{
+ InputBoxPopup();
+}
+
+extern Option boxOptions[];
+
+void ICSInputSendText()
+{
+ Widget edit;
+ int j;
+ Arg args[16];
+ String val;
+
+ edit = boxOptions[0].handle;
+ 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);
+}
+
+void ICSInputBoxPopDown()
+{
+ PopDown(4);
+}
+
+void CommentPopUp(title, text)
+ char *title, *text;
+{
+ savedIndex = currentMove; // [HGM] vari
+ NewCommentPopup(title, text, currentMove);
+}
+
+void CommentPopDown()
+{
+ PopDown(1);
+}
+
+void FileNamePopUp(label, def, filter, proc, openMode)
+ char *label;
+ char *def;
+ char *filter;
+ FileProc proc;
+ char *openMode;
+{
+ fileProc = proc; /* I can't see a way not */
+ fileOpenMode = openMode; /* to use globals here */
+ { // [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[0] ? def : NULL), filter, openMode, NULL, &name))
+ (void) (*fileProc)(f, index=0, name);
+ }
+}
+
+void FileNamePopDown()
+{
+ if (!filenameUp) return;
+ XtPopdown(fileNameShell);
+ XtDestroyWidget(fileNameShell);
+ filenameUp = False;
+ ModeHighlight();
+}
+
+void FileNameCallback(w, client_data, call_data)
+ Widget w;
+ XtPointer 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);
+}
+
+void FileNameAction(w, event, prms, nprms)
+ Widget w;
+ XEvent *event;
+ String *prms;
+ Cardinal *nprms;
+{
+ char buf[MSG_SIZ];
+ String name;
+ FILE *f;
+ char *p, *fullname;
+ int index;
+
+ name = XawDialogGetValueString(w = XtParent(w));
+
+ if ((name != NULL) && (*name != NULLCHAR)) {
+ safeStrCpy(buf, name, sizeof(buf)/sizeof(buf[0]) );
+ XtPopdown(w = XtParent(XtParent(w)));
+ XtDestroyWidget(w);
+ filenameUp = False;
+
+ p = strrchr(buf, ' ');
+ if (p == NULL) {
+ index = 0;
+ } else {
+ *p++ = NULLCHAR;
+ index = atoi(p);
+ }
+ fullname = ExpandPathName(buf);
+ if (!fullname) {
+ ErrorPopUp(_("Error"), _("Can't open file"), FALSE);
+ }
+ else {
+ f = fopen(fullname, fileOpenMode);
+ if (f == NULL) {
+ DisplayError(_("Failed to open file"), errno);
+ } else {
+ (void) (*fileProc)(f, index, buf);
+ }
+ }
+ ModeHighlight();
+ return;
+ }
+
+ XtPopdown(w = XtParent(XtParent(w)));
+ XtDestroyWidget(w);
+ filenameUp = False;
+ ModeHighlight();
+}
+
+void PromotionPopUp()
+{
+ Arg args[16];
+ Widget dialog, layout;
+ Position x, y;
+ Dimension bw_width, pw_width;
+ int j;
+
+ j = 0;
+ XtSetArg(args[j], XtNwidth, &bw_width); j++;
+ XtGetValues(boardWidget, args, j);
+
+ j = 0;
+ XtSetArg(args[j], XtNresizable, True); j++;
+ XtSetArg(args[j], XtNtitle, XtNewString(_("Promotion"))); j++;
+ promotionShell =
+ XtCreatePopupShell("Promotion", transientShellWidgetClass,
+ shellWidget, args, j);
+ layout =
+ XtCreateManagedWidget(layoutName, formWidgetClass, promotionShell,
+ layoutArgs, XtNumber(layoutArgs));
+
+ j = 0;
+ XtSetArg(args[j], XtNlabel, _("Promote to what?")); j++;
+ XtSetArg(args[j], XtNborderWidth, 0); j++;
+ dialog = XtCreateManagedWidget("promotion", dialogWidgetClass,
+ layout, args, j);
+
+ 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,
+ (XtPointer) dialog);
+ XawDialogAddButton(dialog, _("Bishop"), PromotionCallback,
+ (XtPointer) dialog);
+ XawDialogAddButton(dialog, _("Knight"), PromotionCallback,
+ (XtPointer) dialog);
+ }
+ if (!appData.testLegality || gameInfo.variant == VariantSuicide ||
+ gameInfo.variant == VariantSpartan && !WhiteOnMove(currentMove) ||
+ gameInfo.variant == VariantGiveaway) {
+ XawDialogAddButton(dialog, _("King"), PromotionCallback,
+ (XtPointer) dialog);
+ }
+ if(gameInfo.variant == VariantCapablanca ||
+ gameInfo.variant == VariantGothic ||
+ gameInfo.variant == VariantCapaRandom) {
+ XawDialogAddButton(dialog, _("Archbishop"), PromotionCallback,
+ (XtPointer) dialog);
+ XawDialogAddButton(dialog, _("Chancellor"), PromotionCallback,
+ (XtPointer) dialog);
+ }
+ } else // [HGM] shogi
+ {
+ XawDialogAddButton(dialog, _("Promote"), PromotionCallback,
+ (XtPointer) dialog);
+ XawDialogAddButton(dialog, _("Defer"), PromotionCallback,
+ (XtPointer) dialog);
+ }
+ XawDialogAddButton(dialog, _("cancel"), PromotionCallback,
+ (XtPointer) dialog);
+
+ XtRealizeWidget(promotionShell);
+ CatchDeleteWindow(promotionShell, "PromotionPopDown");
+
+ j = 0;
+ XtSetArg(args[j], XtNwidth, &pw_width); j++;
+ XtGetValues(promotionShell, args, j);
+
+ XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
+ lineGap + squareSize/3 +
+ ((toY == 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;
+}
+
+void PromotionPopDown()
+{
+ if (!promotionUp) return;
+ XtPopdown(promotionShell);
+ XtDestroyWidget(promotionShell);
+ promotionUp = False;
+}
+
+void PromotionCallback(w, client_data, call_data)
+ Widget w;
+ XtPointer 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]);
+ }
+
+ UserMoveEvent(fromX, fromY, toX, toY, promoChar);
+
+ if (!appData.highlightLastMove || gotPremove) ClearHighlights();
+ if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
+ fromX = fromY = -1;
+}
+
+
+void ErrorCallback(w, client_data, call_data)
+ Widget w;
+ XtPointer client_data, call_data;
+{
+ errorUp = False;
+ XtPopdown(w = XtParent(XtParent(XtParent(w))));
+ XtDestroyWidget(w);
+ if (errorExitStatus != -1) ExitEvent(errorExitStatus);
+}
+
+
+void ErrorPopDown()
+{
+ if (!errorUp) return;
+ errorUp = False;
+ XtPopdown(errorShell);
+ XtDestroyWidget(errorShell);
+ if (errorExitStatus != -1) ExitEvent(errorExitStatus);
+}
+
+void ErrorPopUp(title, label, modal)
+ char *title, *label;
+ int modal;
+{
+ Arg args[16];
+ Widget dialog, layout;
+ Position x, y;
+ int xx, yy;
+ Window junk;
+ 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 =
+ 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);
+ i = 0;
+ XtSetArg(args[i], XtNwidth, &pw_width); i++;
+ XtSetArg(args[i], XtNheight, &pw_height); i++;
+ XtGetValues(errorShell, args, i);
+
+#ifdef NOTDEF
+ /* This code seems to tickle an X bug if it is executed too soon
+ after xboard starts up. The coordinates get transformed as if
+ the main window was positioned at (0, 0).
+ */
+ XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
+ 0 - pw_height + squareSize / 3, &x, &y);
+#else
+ XTranslateCoordinates(xDisplay, XtWindow(boardWidget),
+ RootWindowOfScreen(XtScreen(boardWidget)),
+ (bw_width - pw_width) / 2,
+ 0 - pw_height + squareSize / 3, &xx, &yy, &junk);
+ x = xx;
+ y = yy;
+#endif
+ if (y < 0) y = 0; /*avoid positioning top offscreen*/
+
+ i = 0;
+ XtSetArg(args[i], XtNx, x); i++;
+ XtSetArg(args[i], XtNy, y); i++;
+ XtSetValues(errorShell, args, i);
+
+ errorUp = True;
+ XtPopup(errorShell, modal ? XtGrabExclusive : XtGrabNone);
+}
+
+/* Disable all user input other than deleting the window */
+static int frozen = 0;
+void FreezeUI()
+{
+ if (frozen) return;
+ /* Grab by a widget that doesn't accept input */
+ XtAddGrab(messageWidget, TRUE, FALSE);
+ frozen = 1;
+}
+
+/* Undo a FreezeUI */
+void ThawUI()
+{
+ if (!frozen) return;
+ XtRemoveGrab(messageWidget);
+ frozen = 0;
+}
+
+char *ModeToWidgetName(mode)
+ GameMode mode;
+{
+ switch (mode) {
+ case BeginningOfGame:
+ if (appData.icsActive)
+ return "menuMode.ICS Client";
+ else if (appData.noChessProgram ||
+ *appData.cmailGameName != NULLCHAR)
+ return "menuMode.Edit Game";
+ else
+ return "menuMode.Machine Black";
+ case MachinePlaysBlack:
+ return "menuMode.Machine Black";
+ case MachinePlaysWhite:
+ return "menuMode.Machine White";
+ case AnalyzeMode:
+ return "menuMode.Analysis Mode";
+ case AnalyzeFile:
+ return "menuMode.Analyze File";
+ case TwoMachinesPlay:
+ return "menuMode.Two Machines";
+ case EditGame:
+ return "menuMode.Edit Game";
+ case PlayFromGameFile:
+ return "menuFile.Load Game";
+ case EditPosition:
+ return "menuMode.Edit Position";
+ case Training:
+ return "menuMode.Training";
+ case IcsPlayingWhite:
+ case IcsPlayingBlack:
+ case IcsObserving:
+ case IcsIdle:
+ case IcsExamining:
+ return "menuMode.ICS Client";
+ default:
+ case EndOfGame:
+ return NULL;
+ }
+}
+
+void ModeHighlight()
+{
+ Arg args[16];
+ static int oldPausing = FALSE;
+ static GameMode oldmode = (GameMode) -1;
+ char *wname;
+
+ if (!boardWidget || !XtIsRealized(boardWidget)) return;
+
+ if (pausing != oldPausing) {
+ oldPausing = pausing;
+ if (pausing) {
+ XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
+ } else {
+ XtSetArg(args[0], XtNleftBitmap, None);
+ }
+ XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Pause"),
+ args, 1);
+
+ if (appData.showButtonBar) {
+ /* Always toggle, don't set. Previous code messes up when
+ invoked while the button is pressed, as releasing it
+ toggles the state again. */
+ {
+ Pixel oldbg, oldfg;
+ XtSetArg(args[0], XtNbackground, &oldbg);
+ XtSetArg(args[1], XtNforeground, &oldfg);
+ XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON),
+ args, 2);
+ XtSetArg(args[0], XtNbackground, oldfg);
+ XtSetArg(args[1], XtNforeground, oldbg);
+ }
+ XtSetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
+ }
+ }
+
+ wname = ModeToWidgetName(oldmode);
+ if (wname != NULL) {
+ XtSetArg(args[0], XtNleftBitmap, None);
+ XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
+ }
+ wname = ModeToWidgetName(gameMode);
+ if (wname != NULL) {
+ XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
+ XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
+ }
+ oldmode = gameMode;
+ XtSetArg(args[0], XtNleftBitmap, matchMode && matchGame < appData.matchGames ? xMarkPixmap : None);
+ XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Machine Match"), args, 1);
+
+ /* Maybe all the enables should be handled here, not just this one */
+ XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Training"),
+ gameMode == Training || gameMode == PlayFromGameFile);
+}
+
+
+/*
+ * Button/menu procedures
+ */
+void ResetProc(w, event, prms, nprms)
+ Widget w;
+ XEvent *event;
+ String *prms;
+ Cardinal *nprms;
+{
+ ResetGameEvent();
+}
+
+int LoadGamePopUp(f, gameNumber, title)
+ FILE *f;
+ int gameNumber;
+ char *title;
+{
+ cmailMsgLoaded = FALSE;
+ if (gameNumber == 0) {
+ int error = GameListBuild(f);
+ if (error) {
+ DisplayError(_("Cannot build game list"), error);
+ } else if (!ListEmpty(&gameList) &&
+ ((ListGame *) gameList.tailPred)->number > 1) {
+ GameListPopUp(f, title);
+ return TRUE;
+ }
+ GameListDestroy();
+ gameNumber = 1;
+ }
+ return LoadGame(f, gameNumber, title, FALSE);
+}
+
+void LoadGameProc(w, event, prms, nprms)
+ Widget w;
+ XEvent *event;
+ String *prms;
+ Cardinal *nprms;
+{
+ if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
+ Reset(FALSE, TRUE);
+ }
+ FileNamePopUp(_("Load game file name?"), "", ".pgn .game", LoadGamePopUp, "rb");
+}
+
+void LoadNextGameProc(w, event, prms, nprms)
+ Widget w;
+ XEvent *event;
+ String *prms;
+ Cardinal *nprms;
+{
+ ReloadGame(1);
+}
+
+void LoadPrevGameProc(w, event, prms, nprms)
+ Widget w;
+ XEvent *event;
+ String *prms;
+ Cardinal *nprms;
+{
+ ReloadGame(-1);
+}
+
+void ReloadGameProc(w, event, prms, nprms)
+ Widget w;
+ XEvent *event;
+ String *prms;
+ Cardinal *nprms;
+{
+ ReloadGame(0);
+}
+
+void LoadNextPositionProc(w, event, prms, nprms)
+ Widget w;
+ XEvent *event;
+ String *prms;
+ Cardinal *nprms;
+{
+ ReloadPosition(1);
+}
+
+void LoadPrevPositionProc(w, event, prms, nprms)
+ Widget w;
+ XEvent *event;
+ String *prms;
+ Cardinal *nprms;
+{
+ ReloadPosition(-1);
+}
+
+void ReloadPositionProc(w, event, prms, nprms)
+ Widget w;
+ XEvent *event;
+ String *prms;
+ Cardinal *nprms;
+{
+ ReloadPosition(0);
+}
+
+void LoadPositionProc(w, event, prms, nprms)
+ Widget w;
+ XEvent *event;
+ String *prms;
+ Cardinal *nprms;
+{
+ if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
+ Reset(FALSE, TRUE);
+ }
+ FileNamePopUp(_("Load position file name?"), "", ".fen .epd .pos", LoadPosition, "rb");
+}
+
+void SaveGameProc(w, event, prms, nprms)
+ Widget w;
+ XEvent *event;
+ String *prms;
+ Cardinal *nprms;
+{
+ FileNamePopUp(_("Save game file name?"),
+ DefaultFileName(appData.oldSaveStyle ? "game" : "pgn"),
+ appData.oldSaveStyle ? ".game" : ".pgn",
+ SaveGame, "a");
+}
+
+void SavePositionProc(w, event, prms, nprms)
+ Widget w;
+ XEvent *event;
+ String *prms;
+ Cardinal *nprms;
+{
+ FileNamePopUp(_("Save position file name?"),
+ DefaultFileName(appData.oldSaveStyle ? "pos" : "fen"),
+ appData.oldSaveStyle ? ".pos" : ".fen",
+ SavePosition, "a");
+}
+
+void ReloadCmailMsgProc(w, event, prms, nprms)
+ Widget w;
+ XEvent *event;
+ String *prms;
+ Cardinal *nprms;
+{
+ ReloadCmailMsgEvent(FALSE);
+}
+
+void MailMoveProc(w, event, prms, nprms)
+ Widget w;
+ XEvent *event;
+ String *prms;
+ Cardinal *nprms;
+{
+ MailMoveEvent();
+}
+
+/* this variable is shared between CopyPositionProc and SendPositionSelection */
+char *selected_fen_position=NULL;
+
+Boolean
+SendPositionSelection(Widget w, Atom *selection, Atom *target,
+ Atom *type_return, XtPointer *value_return,
+ unsigned long *length_return, int *format_return)
+{
+ char *selection_tmp;
+
+ if (!selected_fen_position) return False; /* should never happen */
+ 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);
+ safeStrCpy(selection_tmp, selected_fen_position, strlen(selected_fen_position)+16 );
+
+ *value_return=selection_tmp;
+ *length_return=strlen(selection_tmp);
+ *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
+ * Widget which was clicked on was, or what the click event was
+ */
+void CopyPositionProc(w, event, prms, nprms)
+ Widget w;
+ XEvent *event;
+ String *prms;
+ Cardinal *nprms;
+ {
+ /*
+ * 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, NULL);
+ if (!selected_fen_position) return;
+ 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 */
+static void
+PastePositionCB(Widget w, XtPointer client_data, Atom *selection,
+ Atom *type, XtPointer value, unsigned long *len, int *format)
+{
+ char *fenstr=value;
+ if (value==NULL || *len==0) return; /* nothing had been selected to copy */
+ fenstr[*len]='\0'; /* normally this string is terminated, but be safe */
+ EditPositionPasteFEN(fenstr);
+ XtFree(value);
+}
+
+/* called when Paste Position button is pressed,
+ * all parameters will be NULL */
+void PastePositionProc(w, event, prms, nprms)
+ Widget w;
+ XEvent *event;
+ String *prms;
+ Cardinal *nprms;
+{
+ XtGetSelectionValue(menuBarWidget,
+ appData.pasteSelection ? XA_PRIMARY: XA_CLIPBOARD(xDisplay), XA_STRING,
+ /* (XtSelectionCallbackProc) */ PastePositionCB,
+ NULL, /* client_data passed to PastePositionCB */
+
+ /* better to use the time field from the event that triggered the
+ * call to this function, but that isn't trivial to get
+ */
+ CurrentTime
+ );
+ return;
+}
+
+static Boolean
+SendGameSelection(Widget w, Atom *selection, Atom *target,
+ Atom *type_return, XtPointer *value_return,
+ unsigned long *length_return, int *format_return)
+{
+ char *selection_tmp;
+
+ if (*target == XA_STRING || *target == XA_UTF8_STRING(xDisplay)){
+ FILE* f = fopen(gameCopyFilename, "r");
+ long len;
+ size_t count;
+ if (f == NULL) return False;
+ fseek(f, 0, 2);
+ len = ftell(f);
+ rewind(f);
+ selection_tmp = XtMalloc(len + 1);
+ count = fread(selection_tmp, 1, len, f);
+ fclose(f);
+ if (len != count) {
+ XtFree(selection_tmp);
+ return False;
+ }
+ selection_tmp[len] = NULLCHAR;
+ *value_return = selection_tmp;
+ *length_return = len;
+ *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;
+ }
+}
+
+void CopySomething()
+{
+ int ret;
+
+ /*
+ * 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 */);
+}
+
+/* note: when called from menu all parameters are NULL, so no clue what the
+ * Widget which was clicked on was, or what the click event was
+ */
+void CopyGameProc(w, event, prms, nprms)
+ Widget w;
+ XEvent *event;
+ String *prms;
+ Cardinal *nprms;
+{
+ int ret;
+
+ ret = SaveGameToFile(gameCopyFilename, FALSE);
+ if (!ret) return;
+
+ CopySomething();
+}
+
+void CopyGameListProc(w, event, prms, nprms)
+ Widget w;
+ XEvent *event;
+ String *prms;
+ Cardinal *nprms;
+{
+ if(!SaveGameListAsText(fopen(gameCopyFilename, "w"))) return;
+ CopySomething();
+}
+
+/* function called when the data to Paste is ready */
+static void
+PasteGameCB(Widget w, XtPointer client_data, Atom *selection,
+ Atom *type, XtPointer value, unsigned long *len, int *format)
+{
+ FILE* f;
+ if (value == NULL || *len == 0) {
+ return; /* nothing had been selected to copy */
+ }
+ f = fopen(gamePasteFilename, "w");
+ if (f == NULL) {
+ DisplayError(_("Can't open temp file"), errno);
+ return;
+ }
+ fwrite(value, 1, *len, f);
+ fclose(f);
+ XtFree(value);
+ LoadGameFromFile(gamePasteFilename, 0, gamePasteFilename, TRUE);
+}
+
+/* called when Paste Game button is pressed,
+ * all parameters will be NULL */
+void PasteGameProc(w, event, prms, nprms)
+ Widget w;
+ XEvent *event;
+ String *prms;
+ Cardinal *nprms;
+{
+ XtGetSelectionValue(menuBarWidget,
+ appData.pasteSelection ? XA_PRIMARY: XA_CLIPBOARD(xDisplay), XA_STRING,
+ /* (XtSelectionCallbackProc) */ PasteGameCB,
+ NULL, /* client_data passed to PasteGameCB */
+
+ /* better to use the time field from the event that triggered the
+ * call to this function, but that isn't trivial to get
+ */
+ CurrentTime
+ );
+ return;
+}
+
+
+void AutoSaveGame()
+{
+ SaveGameProc(NULL, NULL, NULL, NULL);
+}
+
+
+void QuitProc(w, event, prms, nprms)
+ Widget w;
+ XEvent *event;
+ String *prms;
+ Cardinal *nprms;
+{
+ ExitEvent(0);
+}
+
+void PauseProc(w, event, prms, nprms)
+ Widget w;
+ XEvent *event;
+ String *prms;
+ Cardinal *nprms;
+{
+ PauseEvent();
+}
+
+
+void MachineBlackProc(w, event, prms, nprms)
+ Widget w;
+ XEvent *event;
+ String *prms;
+ Cardinal *nprms;
+{
+ MachineBlackEvent();
+}
+
+void MachineWhiteProc(w, event, prms, nprms)
+ Widget w;
+ XEvent *event;
+ String *prms;
+ Cardinal *nprms;
+{
+ MachineWhiteEvent();
+}
+
+void AnalyzeModeProc(w, event, prms, nprms)
+ Widget w;
+ XEvent *event;
+ String *prms;
+ Cardinal *nprms;
+{
+ char buf[MSG_SIZ];
+
+ if (!first.analysisSupport) {
+ snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
+ DisplayError(buf, 0);
+ return;
+ }
+ /* [DM] icsEngineAnalyze [HGM] This is horrible code; reverse the gameMode and isEngineAnalyze tests! */
+ if (appData.icsActive) {
+ if (gameMode != IcsObserving) {
+ 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"));
+ }
+#ifndef OPTIONSDIALOG
+ if (!appData.showThinking)
+ ShowThinkingProc(w,event,prms,nprms);
+#endif
+
+ AnalyzeModeEvent();
+}
+
+void AnalyzeFileProc(w, event, prms, nprms)
+ Widget w;
+ XEvent *event;
+ String *prms;
+ Cardinal *nprms;
+{
+ if (!first.analysisSupport) {
+ char buf[MSG_SIZ];
+ snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
+ DisplayError(buf, 0);
+ return;
+ }
+ Reset(FALSE, TRUE);
+#ifndef OPTIONSDIALOG
+ if (!appData.showThinking)
+ ShowThinkingProc(w,event,prms,nprms);
+#endif
+ AnalyzeFileEvent();
+ FileNamePopUp(_("File to analyze"), "", ".pgn .game", LoadGamePopUp, "rb");
+ AnalysisPeriodicEvent(1);
+}
+
+void TwoMachinesProc(w, event, prms, nprms)
+ Widget w;
+ XEvent *event;
+ String *prms;
+ Cardinal *nprms;
+{
+ TwoMachinesEvent();
+}
+
+void MatchProc(w, event, prms, nprms)
+ Widget w;
+ XEvent *event;
+ String *prms;
+ Cardinal *nprms;
+{
+ MatchEvent(2);
+}
+
+void IcsClientProc(w, event, prms, nprms)
+ Widget w;
+ XEvent *event;
+ String *prms;
+ Cardinal *nprms;
+{
+ IcsClientEvent();
+}
+
+void EditGameProc(w, event, prms, nprms)
+ Widget w;
+ XEvent *event;
+ String *prms;
+ Cardinal *nprms;
+{
+ EditGameEvent();
+}
+
+void EditPositionProc(w, event, prms, nprms)
+ Widget w;
+ XEvent *event;
+ String *prms;
+ Cardinal *nprms;
+{
+ EditPositionEvent();
+}
+
+void TrainingProc(w, event, prms, nprms)
+ Widget w;
+ XEvent *event;
+ String *prms;
+ Cardinal *nprms;
+{
+ TrainingEvent();
+}
+
+void EditCommentProc(w, event, prms, nprms)
+ Widget w;
+ XEvent *event;
+ String *prms;
+ Cardinal *nprms;
+{
+ Arg args[5];
+ int j;
+ if (PopDown(1)) { // popdown succesful
+ j = 0;
+ XtSetArg(args[j], XtNleftBitmap, None); j++;
+ XtSetValues(XtNameToWidget(menuBarWidget, "menuEdit.Edit Comment"), args, j);
+ XtSetValues(XtNameToWidget(menuBarWidget, "menuView.Show Comments"), args, j);
+ } else // was not up
+ EditCommentEvent();
+}
+
+void IcsInputBoxProc(w, event, prms, nprms)
+ Widget w;
+ XEvent *event;
+ String *prms;
+ Cardinal *nprms;
+{
+ if (!PopDown(4)) ICSInputBoxPopUp();
+}
+
+void AcceptProc(w, event, prms, nprms)
+ Widget w;
+ XEvent *event;
+ String *prms;
+ Cardinal *nprms;
+{
+ AcceptEvent();
+}
+
+void DeclineProc(w, event, prms, nprms)
+ Widget w;
+ XEvent *event;
+ String *prms;
+ Cardinal *nprms;
+{
+ DeclineEvent();
+}
+
+void RematchProc(w, event, prms, nprms)
+ Widget w;
+ XEvent *event;
+ String *prms;
+ Cardinal *nprms;
+{
+ RematchEvent();
+}
+
+void CallFlagProc(w, event, prms, nprms)
+ Widget w;
+ XEvent *event;
+ String *prms;
+ Cardinal *nprms;
+{
+ CallFlagEvent();
+}
+
+void DrawProc(w, event, prms, nprms)
+ Widget w;
+ XEvent *event;
+ String *prms;
+ Cardinal *nprms;
+{
+ DrawEvent();
+}
+
+void AbortProc(w, event, prms, nprms)
+ Widget w;
+ XEvent *event;
+ String *prms;
+ Cardinal *nprms;
+{
+ AbortEvent();
+}
+
+void AdjournProc(w, event, prms, nprms)
+ Widget w;
+ XEvent *event;
+ String *prms;
+ Cardinal *nprms;
+{
+ AdjournEvent();
+}
+
+void ResignProc(w, event, prms, nprms)
+ Widget w;
+ XEvent *event;
+ String *prms;
+ Cardinal *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;
+ String *prms;
+ Cardinal *nprms;
+{
+ if (shellUp[4] == True)
+ 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 (!shellUp[4]) return;
+ edit = boxOptions[0].handle;
+ 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 (!shellUp[4]) return;
+ edit = boxOptions[0].handle;
+ 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;
+ String *prms;
+ Cardinal *nprms;
+{
+ StopObservingEvent();
+}
+
+void StopExaminingProc(w, event, prms, nprms)
+ Widget w;
+ XEvent *event;
+ String *prms;
+ Cardinal *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;
+ XEvent *event;
+ String *prms;
+ Cardinal *nprms;
+{
+ ForwardEvent();
+}
+
+
+void BackwardProc(w, event, prms, nprms)
+ Widget w;
+ XEvent *event;
+ String *prms;
+ Cardinal *nprms;
+{
+ BackwardEvent();
+}
+
+void ToStartProc(w, event, prms, nprms)
+ Widget w;
+ XEvent *event;
+ String *prms;
+ Cardinal *nprms;
+{
+ ToStartEvent();
+}
+
+void ToEndProc(w, event, prms, nprms)
+ Widget w;
+ XEvent *event;
+ String *prms;
+ Cardinal *nprms;
+{
+ ToEndEvent();
+}
+
+void RevertProc(w, event, prms, nprms)
+ Widget w;
+ XEvent *event;
+ String *prms;
+ Cardinal *nprms;
+{
+ RevertEvent(False);
+}
+
+void AnnotateProc(w, event, prms, nprms)
+ Widget w;
+ XEvent *event;
+ String *prms;
+ Cardinal *nprms;
+{
+ RevertEvent(True);
+}
+
+void TruncateGameProc(w, event, prms, nprms)
+ Widget w;
+ XEvent *event;
+ String *prms;
+ Cardinal *nprms;
+{
+ TruncateGameEvent();
+}
+void RetractMoveProc(w, event, prms, nprms)
+ Widget w;
+ XEvent *event;
+ String *prms;
+ Cardinal *nprms;
+{
+ RetractMoveEvent();
+}
+
+void MoveNowProc(w, event, prms, nprms)
+ Widget w;
+ XEvent *event;
+ String *prms;
+ Cardinal *nprms;
+{
+ MoveNowEvent();
+}
+
+void FlipViewProc(w, event, prms, nprms)
+ Widget w;
+ XEvent *event;
+ String *prms;
+ Cardinal *nprms;
+{
+ flipView = !flipView;
+ DrawPosition(True, NULL);
+}
+
+void PonderNextMoveProc(w, event, prms, nprms)
+ Widget w;
+ XEvent *event;
+ String *prms;
+ Cardinal *nprms;
+{
+ Arg args[16];
+
+ PonderNextMoveEvent(!appData.ponderNextMove);
+#ifndef OPTIONSDIALOG
+ if (appData.ponderNextMove) {
+ XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
+ } else {
+ XtSetArg(args[0], XtNleftBitmap, None);
+ }
+ XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Ponder Next Move"),
+ args, 1);
+#endif
+}
+
+#ifndef OPTIONSDIALOG
+void AlwaysQueenProc(w, event, prms, nprms)
+ Widget w;
+ XEvent *event;
+ String *prms;
+ Cardinal *nprms;
+{
+ Arg args[16];
+
+ appData.alwaysPromoteToQueen = !appData.alwaysPromoteToQueen;
+
+ if (appData.alwaysPromoteToQueen) {
+ XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
+ } else {
+ XtSetArg(args[0], XtNleftBitmap, None);
+ }
+ XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
+ args, 1);
+}
+
+void AnimateDraggingProc(w, event, prms, nprms)
+ Widget w;
+ XEvent *event;
+ String *prms;
+ Cardinal *nprms;
+{
+ Arg args[16];
+
+ appData.animateDragging = !appData.animateDragging;
+
+ if (appData.animateDragging) {
+ XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
+ CreateAnimVars();
+ } else {
+ XtSetArg(args[0], XtNleftBitmap, None);
+ }
+ XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Dragging"),
+ args, 1);
+}
+
+void AnimateMovingProc(w, event, prms, nprms)
+ Widget w;
+ XEvent *event;
+ String *prms;
+ Cardinal *nprms;
+{
+ Arg args[16];
+
+ appData.animate = !appData.animate;
+
+ if (appData.animate) {
+ XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
+ CreateAnimVars();
+ } else {
+ XtSetArg(args[0], XtNleftBitmap, None);
+ }
+ XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
+ args, 1);
+}
+
+void AutoflagProc(w, event, prms, nprms)
+ Widget w;
+ XEvent *event;
+ String *prms;
+ Cardinal *nprms;
+{
+ Arg args[16];
+
+ appData.autoCallFlag = !appData.autoCallFlag;
+
+ if (appData.autoCallFlag) {
+ XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
+ } else {
+ XtSetArg(args[0], XtNleftBitmap, None);
+ }
+ XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
+ args, 1);
+}
+
+void AutoflipProc(w, event, prms, nprms)
+ Widget w;
+ XEvent *event;
+ String *prms;
+ Cardinal *nprms;
+{
+ Arg args[16];
+
+ appData.autoFlipView = !appData.autoFlipView;
+
+ if (appData.autoFlipView) {
+ XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
+ } else {
+ XtSetArg(args[0], XtNleftBitmap, None);
+ }
+ XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flip View"),
+ args, 1);
+}
+
+void BlindfoldProc(w, event, prms, nprms)
+ Widget w;
+ XEvent *event;
+ String *prms;
+ Cardinal *nprms;
+{
+ Arg args[16];
+
+ appData.blindfold = !appData.blindfold;
+
+ if (appData.blindfold) {
+ XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
+ } else {
+ XtSetArg(args[0], XtNleftBitmap, None);
+ }
+ XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Blindfold"),
+ args, 1);
+
+ DrawPosition(True, NULL);
+}
+
+void TestLegalityProc(w, event, prms, nprms)
+ Widget w;
+ XEvent *event;
+ String *prms;
+ Cardinal *nprms;
+{
+ Arg args[16];
+
+ appData.testLegality = !appData.testLegality;
+
+ if (appData.testLegality) {
+ XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
+ } else {
+ XtSetArg(args[0], XtNleftBitmap, None);
+ }
+ XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Test Legality"),
+ args, 1);
+}
+
+
+void FlashMovesProc(w, event, prms, nprms)
+ Widget w;
+ XEvent *event;
+ String *prms;
+ Cardinal *nprms;
+{
+ Arg args[16];
+
+ if (appData.flashCount == 0) {
+ appData.flashCount = 3;
+ } else {
+ appData.flashCount = -appData.flashCount;
+ }
+
+ if (appData.flashCount > 0) {
+ XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
+ } else {
+ XtSetArg(args[0], XtNleftBitmap, None);
+ }
+ XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flash Moves"),
+ args, 1);
+}
+
+#if HIGHDRAG
+void HighlightDraggingProc(w, event, prms, nprms)
+ Widget w;
+ XEvent *event;
+ String *prms;
+ Cardinal *nprms;
+{
+ Arg args[16];
+
+ appData.highlightDragging = !appData.highlightDragging;
+
+ if (appData.highlightDragging) {
+ XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
+ } else {
+ XtSetArg(args[0], XtNleftBitmap, None);
+ }
+ XtSetValues(XtNameToWidget(menuBarWidget,
+ "menuOptions.Highlight Dragging"), args, 1);
+}
+#endif
+
+void HighlightLastMoveProc(w, event, prms, nprms)
+ Widget w;
+ XEvent *event;
+ String *prms;
+ Cardinal *nprms;
+{
+ Arg args[16];
+
+ appData.highlightLastMove = !appData.highlightLastMove;
+
+ if (appData.highlightLastMove) {
+ XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
+ } else {
+ XtSetArg(args[0], XtNleftBitmap, None);
+ }
+ XtSetValues(XtNameToWidget(menuBarWidget,
+ "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);
+}
+
+#if 0
+void IcsAlarmProc(w, event, prms, nprms)
+ Widget w;
+ XEvent *event;
+ String *prms;
+ Cardinal *nprms;
+{
+ Arg args[16];
+
+ appData.icsAlarm = !appData.icsAlarm;
+
+ if (appData.icsAlarm) {
+ XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
+ } else {
+ XtSetArg(args[0], XtNleftBitmap, None);
+ }
+ XtSetValues(XtNameToWidget(menuBarWidget,
+ "menuOptions.ICS Alarm"), args, 1);
+}
+#endif
+
+void MoveSoundProc(w, event, prms, nprms)
+ Widget w;
+ XEvent *event;
+ String *prms;
+ Cardinal *nprms;
+{
+ Arg args[16];
+
+ appData.ringBellAfterMoves = !appData.ringBellAfterMoves;
+
+ if (appData.ringBellAfterMoves) {
+ XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
+ } else {
+ XtSetArg(args[0], XtNleftBitmap, None);
+ }
+ XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
+ args, 1);
+}
+
+void OneClickProc(w, event, prms, nprms)
+ Widget w;
+ XEvent *event;
+ String *prms;
+ Cardinal *nprms;
+{
+ Arg args[16];
+
+ appData.oneClick = !appData.oneClick;
+
+ if (appData.oneClick) {
+ XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
+ } else {
+ XtSetArg(args[0], XtNleftBitmap, None);
+ }
+ XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.OneClick"),
+ args, 1);
+}
+
+void PeriodicUpdatesProc(w, event, prms, nprms)
+ Widget w;
+ XEvent *event;
+ String *prms;
+ Cardinal *nprms;
+{
+ Arg args[16];
+
+ PeriodicUpdatesEvent(!appData.periodicUpdates);
+
+ if (appData.periodicUpdates) {
+ XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
+ } else {
+ XtSetArg(args[0], XtNleftBitmap, None);
+ }
+ XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Periodic Updates"),
+ args, 1);
+}
+
+void PopupExitMessageProc(w, event, prms, nprms)
+ Widget w;
+ XEvent *event;
+ String *prms;
+ Cardinal *nprms;
+{
+ Arg args[16];
+
+ appData.popupExitMessage = !appData.popupExitMessage;
+
+ if (appData.popupExitMessage) {
+ XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
+ } else {
+ XtSetArg(args[0], XtNleftBitmap, None);
+ }
+ XtSetValues(XtNameToWidget(menuBarWidget,
+ "menuOptions.Popup Exit Message"), args, 1);
+}
+
+void PopupMoveErrorsProc(w, event, prms, nprms)
+ Widget w;
+ XEvent *event;
+ String *prms;
+ Cardinal *nprms;
+{
+ Arg args[16];
+
+ appData.popupMoveErrors = !appData.popupMoveErrors;
+
+ if (appData.popupMoveErrors) {
+ XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
+ } else {
+ XtSetArg(args[0], XtNleftBitmap, None);
+ }
+ XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Popup Move Errors"),
+ args, 1);
+}
+
+#if 0
+void PremoveProc(w, event, prms, nprms)
+ Widget w;
+ XEvent *event;
+ String *prms;
+ Cardinal *nprms;
+{
+ Arg args[16];
+
+ appData.premove = !appData.premove;
+
+ if (appData.premove) {
+ XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
+ } else {
+ XtSetArg(args[0], XtNleftBitmap, None);
+ }
+ XtSetValues(XtNameToWidget(menuBarWidget,
+ "menuOptions.Premove"), args, 1);
+}
+#endif
+
+void ShowCoordsProc(w, event, prms, nprms)
+ Widget w;
+ XEvent *event;
+ String *prms;
+ Cardinal *nprms;
+{
+ Arg args[16];
+
+ appData.showCoords = !appData.showCoords;
+
+ if (appData.showCoords) {
+ XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
+ } else {
+ XtSetArg(args[0], XtNleftBitmap, None);
+ }
+ XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
+ args, 1);
+
+ DrawPosition(True, NULL);
+}
+
+void ShowThinkingProc(w, event, prms, nprms)
+ Widget w;
+ XEvent *event;
+ 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);
+}
+#endif
+
+void SaveOnExitProc(w, event, prms, nprms)
+ Widget w;
+ XEvent *event;
+ String *prms;
+ Cardinal *nprms;
+{
+ Arg args[16];
+
+ saveSettingsOnExit = !saveSettingsOnExit;
+
+ if (saveSettingsOnExit) {
+ XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
+ } else {
+ XtSetArg(args[0], XtNleftBitmap, None);
+ }
+ 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;
+ String *prms;
+ Cardinal *nprms;
+{
+ char buf[MSG_SIZ];
+ snprintf(buf, sizeof(buf), "xterm -e info --directory %s --directory . -f %s &",
+ INFODIR, INFOFILE);
+ system(buf);
+}
+
+void ManProc(w, event, prms, nprms)
+ Widget w;
+ XEvent *event;
+ String *prms;
+ Cardinal *nprms;
+{
+ char buf[MSG_SIZ];
+ String name;
+ if (nprms && *nprms > 0)
+ name = prms[0];
+ else
+ name = "xboard";
+ snprintf(buf, sizeof(buf), "xterm -e man %s &", name);
+ system(buf);
+}
+
+void HintProc(w, event, prms, nprms)
+ Widget w;
+ XEvent *event;
+ String *prms;
+ Cardinal *nprms;
+{
+ HintEvent();
+}
+
+void BookProc(w, event, prms, nprms)
+ Widget w;
+ XEvent *event;
+ String *prms;
+ Cardinal *nprms;
+{
+ BookEvent();
+}
+
+void AboutProc(w, event, prms, nprms)
+ Widget w;
+ XEvent *event;
+ String *prms;
+ Cardinal *nprms;
+{
+ char buf[MSG_SIZ];
+#if ZIPPY
+ char *zippy = " (with Zippy code)";
+#else
+ char *zippy = "";
+#endif
+ 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-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);
+}
+
+void DebugProc(w, event, prms, nprms)
+ Widget w;
+ XEvent *event;
+ String *prms;
+ Cardinal *nprms;
+{
+ appData.debugMode = !appData.debugMode;
+}
+
+void AboutGameProc(w, event, prms, nprms)
+ Widget w;
+ XEvent *event;
+ String *prms;
+ Cardinal *nprms;
+{
+ AboutGameEvent();
+}
+
+void NothingProc(w, event, prms, nprms)
+ Widget w;
+ XEvent *event;
+ String *prms;
+ Cardinal *nprms;
+{
+ return;
+}
+
+void Iconify(w, event, prms, nprms)
+ Widget w;
+ XEvent *event;
+ String *prms;
+ Cardinal *nprms;
+{
+ Arg args[16];
+
+ fromX = fromY = -1;
+ XtSetArg(args[0], XtNiconic, True);
+ XtSetValues(shellWidget, args, 1);
+}
+
+void DisplayMessage(message, extMessage)
+ char *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;
+ }
+ else
+ {
+ message = extMessage;
+ };
+ };
+
+ safeStrCpy(lastMsg, message, MSG_SIZ); // [HGM] make available
+
+ /* 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)
+ char *text;
+{
+ Arg args[16];
+ int i;
+ char title[MSG_SIZ];
+ char icon[MSG_SIZ];
+
+ if (text == NULL) text = "";
+
+ if (appData.titleInWindow) {
+ i = 0;
+ XtSetArg(args[i], XtNlabel, text); i++;
+ XtSetValues(titleWidget, args, i);
+ }
+
+ if (*text != NULLCHAR) {
+ safeStrCpy(icon, text, sizeof(icon)/sizeof(icon[0]) );
+ safeStrCpy(title, text, sizeof(title)/sizeof(title[0]) );
+ } else if (appData.icsActive) {
+ snprintf(icon, sizeof(icon), "%s", appData.icsHost);
+ snprintf(title, sizeof(title), "%s: %s", programName, appData.icsHost);
+ } else if (appData.cmailGameName[0] != NULLCHAR) {
+ 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) {
+ safeStrCpy(icon, programName, sizeof(icon)/sizeof(icon[0]) );
+ safeStrCpy(title, programName, sizeof(title)/sizeof(title[0]) );
+ } else {
+ 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++;
+ XtSetArg(args[i], XtNtitle, (XtArgVal) title); i++;
+ XtSetValues(shellWidget, args, i);
+}
+
+
+void
+DisplayError(message, error)
+ String message;
+ int error;
+{
+ char buf[MSG_SIZ];
+
+ if (error == 0) {
+ if (appData.debugMode || appData.matchMode) {
+ fprintf(stderr, "%s: %s\n", programName, message);
+ }
+ } else {
+ if (appData.debugMode || appData.matchMode) {
+ fprintf(stderr, "%s: %s: %s\n",
+ programName, message, strerror(error));
+ }
+ snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
+ message = buf;
+ }
+ ErrorPopUp(_("Error"), message, FALSE);
+}
+
+
+void DisplayMoveError(message)
+ String message;
+{
+ fromX = fromY = -1;
+ ClearHighlights();
+ DrawPosition(FALSE, NULL);
+ if (appData.debugMode || appData.matchMode) {
+ fprintf(stderr, "%s: %s\n", programName, message);
+ }
+ if (appData.popupMoveErrors) {
+ ErrorPopUp(_("Error"), message, FALSE);
+ } else {
+ DisplayMessage(message, "");
+ }
+}
+
+
+void DisplayFatalError(message, error, status)
+ String message;
+ int error, status;
+{
+ char buf[MSG_SIZ];
+
+ errorExitStatus = status;
+ if (error == 0) {
+ fprintf(stderr, "%s: %s\n", programName, message);
+ } else {
+ fprintf(stderr, "%s: %s: %s\n",
+ programName, message, strerror(error));
+ snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
+ message = buf;
+ }
+ if (appData.popupExitMessage && boardWidget && XtIsRealized(boardWidget)) {
+ ErrorPopUp(status ? _("Fatal Error") : _("Exiting"), message, TRUE);
+ } else {
+ ExitEvent(status);
+ }
+}
+
+void DisplayInformation(message)
+ String message;
+{
+ ErrorPopDown();
+ ErrorPopUp(_("Information"), message, TRUE);
+}
+
+void DisplayNote(message)
+ String message;
+{
+ ErrorPopDown();
+ ErrorPopUp(_("Note"), message, FALSE);
+}
+
+static int
+NullXErrorCheck(dpy, error_event)
+ Display *dpy;
+ XErrorEvent *error_event;
+{
+ return 0;
+}
+
+void DisplayIcsInteractionTitle(message)
+ String message;
+{
+ if (oldICSInteractionTitle == NULL) {
+ /* Magic to find the old window title, adapted from vim */
+ char *wina = getenv("WINDOWID");
+ if (wina != NULL) {
+ Window win = (Window) atoi(wina);
+ Window root, parent, *children;
+ unsigned int nchildren;
+ int (*oldHandler)() = XSetErrorHandler(NullXErrorCheck);
+ for (;;) {
+ if (XFetchName(xDisplay, win, &oldICSInteractionTitle)) break;
+ if (!XQueryTree(xDisplay, win, &root, &parent,
+ &children, &nchildren)) break;
+ if (children) XFree((void *)children);
+ if (parent == root || parent == 0) break;
+ win = parent;
+ }
+ XSetErrorHandler(oldHandler);
+ }
+ if (oldICSInteractionTitle == NULL) {
+ oldICSInteractionTitle = "xterm";
+ }
+ }
+ printf("\033]0;%s\007", message);
+ fflush(stdout);
+}
+
+char pendingReplyPrefix[MSG_SIZ];
+ProcRef pendingReplyPR;
+
+void AskQuestionProc(w, event, prms, nprms)
+ Widget w;
+ XEvent *event;
+ String *prms;
+ Cardinal *nprms;
+{
+ if (*nprms != 4) {
+ fprintf(stderr, _("AskQuestionProc needed 4 parameters, got %d\n"),
+ *nprms);
+ return;
+ }
+ AskQuestionEvent(prms[0], prms[1], prms[2], prms[3]);
+}
+
+void AskQuestionPopDown()
+{
+ if (!askQuestionUp) return;
+ XtPopdown(askQuestionShell);
+ XtDestroyWidget(askQuestionShell);
+ askQuestionUp = False;
+}
+
+void AskQuestionReplyAction(w, event, prms, nprms)
+ Widget w;
+ XEvent *event;
+ String *prms;
+ Cardinal *nprms;
+{
+ char buf[MSG_SIZ];
+ int err;
+ String reply;
+
+ reply = XawDialogGetValueString(w = XtParent(w));
+ 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();
+
+ if (err) DisplayFatalError(_("Error writing to chess program"), err, 0);
+}
+
+void AskQuestionCallback(w, client_data, call_data)
+ Widget w;
+ XtPointer client_data, call_data;
+{
+ String name;
+ Arg args[16];
+
+ XtSetArg(args[0], XtNlabel, &name);
+ XtGetValues(w, args, 1);
+
+ if (strcmp(name, _("cancel")) == 0) {
+ AskQuestionPopDown();
+ } else {
+ AskQuestionReplyAction(w, NULL, NULL, NULL);
+ }
+}
+
+void AskQuestion(title, question, replyPrefix, pr)
+ char *title, *question, *replyPrefix;
+ ProcRef pr;
+{
+ Arg args[16];
+ Widget popup, layout, dialog, edit;
+ Window root, child;
+ int x, y, i;
+ int win_x, win_y;
+ unsigned int mask;
+
+ 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,
+ (XtPointer) dialog);
+
+ XtRealizeWidget(popup);
+ CatchDeleteWindow(popup, "AskQuestionPopDown");
+
+ XQueryPointer(xDisplay, xBoardWindow, &root, &child,
+ &x, &y, &win_x, &win_y, &mask);
+
+ XtSetArg(args[0], XtNx, x - 10);
+ XtSetArg(args[1], XtNy, y - 30);
+ XtSetValues(popup, args, 2);
+
+ XtPopup(popup, XtGrabExclusive);
+ askQuestionUp = True;
+
+ edit = XtNameToWidget(dialog, "*value");
+ XtSetKeyboardFocus(popup, edit);
+}
+
+
+void
+PlaySound(name)
+ char *name;
+{
+ if (*name == NULLCHAR) {
+ return;
+ } else if (strcmp(name, "$") == 0) {
+ putc(BELLCHAR, stderr);
+ } else {
+ char buf[2048];
+ char *prefix = "", *sep = "";
+ if(!strchr(name, '/')) { prefix = appData.soundDirectory; sep = "/"; }
+ snprintf(buf, sizeof(buf), "%s '%s%s%s' &", appData.soundProgram, prefix, sep, name);
+ system(buf);
+ }
+}
+
+void
+RingBell()
+{
+ PlaySound(appData.soundMove);
+}
+
+void
+PlayIcsWinSound()
+{
+ PlaySound(appData.soundIcsWin);
+}
+
+void
+PlayIcsLossSound()
+{
+ PlaySound(appData.soundIcsLoss);
+}
+
+void
+PlayIcsDrawSound()
+{
+ PlaySound(appData.soundIcsDraw);
+}
+
+void
+PlayIcsUnfinishedSound()
+{
+ PlaySound(appData.soundIcsUnfinished);
+}
+
+void
+PlayAlarmSound()
+{
+ PlaySound(appData.soundIcsAlarm);
+}
+
+void
+PlayTellSound()
+{
+ PlaySound(appData.soundTell);
+}
+
+void
+EchoOn()
+{
+ system("stty echo");
+}
+
+void
+EchoOff()
+{
+ system("stty -echo");
+}
+
+void
+Colorize(cc, continuation)
+ ColorClass cc;
+ int continuation;
+{
+ char buf[MSG_SIZ];
+ int count, outCount, error;
+
+ if (textColors[(int)cc].bg > 0) {
+ if (textColors[(int)cc].fg > 0) {
+ snprintf(buf, MSG_SIZ, "\033[0;%d;%d;%dm", textColors[(int)cc].attr,
+ textColors[(int)cc].fg, textColors[(int)cc].bg);
+ } else {
+ snprintf(buf, MSG_SIZ, "\033[0;%d;%dm", textColors[(int)cc].attr,
+ textColors[(int)cc].bg);
+ }
+ } else {
+ if (textColors[(int)cc].fg > 0) {
+ snprintf(buf, MSG_SIZ, "\033[0;%d;%dm", textColors[(int)cc].attr,
+ textColors[(int)cc].fg);
+ } else {
+ snprintf(buf, MSG_SIZ, "\033[0;%dm", textColors[(int)cc].attr);
+ }
+ }
+ count = strlen(buf);
+ outCount = OutputToProcess(NoProc, buf, count, &error);
+ if (outCount < count) {
+ DisplayFatalError(_("Error writing to display"), error, 1);
+ }
+
+ if (continuation) return;
+ switch (cc) {
+ case ColorShout:
+ PlaySound(appData.soundShout);
+ break;
+ case ColorSShout:
+ PlaySound(appData.soundSShout);
+ break;
+ case ColorChannel1:
+ PlaySound(appData.soundChannel1);
+ break;
+ case ColorChannel:
+ PlaySound(appData.soundChannel);
+ break;
+ case ColorKibitz:
+ PlaySound(appData.soundKibitz);
+ break;
+ case ColorTell:
+ PlaySound(appData.soundTell);
+ break;
+ case ColorChallenge:
+ PlaySound(appData.soundChallenge);
+ break;
+ case ColorRequest:
+ PlaySound(appData.soundRequest);
+ break;
+ case ColorSeek:
+ PlaySound(appData.soundSeek);
+ break;
+ case ColorNormal:
+ case ColorNone:
+ default:
+ break;
+ }
+}
+
+char *UserName()
+{
+ return getpwuid(getuid())->pw_name;
+}
+
+static char *
+ExpandPathName(path)
+ char *path;
+{
+ static char static_buf[4*MSG_SIZ];
+ char *d, *s, buf[4*MSG_SIZ];
+ struct passwd *pwd;
+
+ s = path;
+ d = static_buf;
+
+ while (*s && isspace(*s))
+ ++s;
+
+ if (!*s) {
+ *d = 0;
+ return static_buf;
+ }
+
+ if (*s == '~') {
+ if (*(s+1) == '/') {
+ safeStrCpy(d, getpwuid(getuid())->pw_dir, 4*MSG_SIZ );
+ strcat(d, s+1);
+ }
+ else {
+ 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
+ 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;
+#else /* not HAVE_GETHOSTNAME */
+# if HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H
+ sysinfo(SI_HOSTNAME, host_name, MSG_SIZ);
+ return host_name;
+# else /* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
+ return "localhost";
+# endif/* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
+#endif /* not HAVE_GETHOSTNAME */
+}
+
+XtIntervalId delayedEventTimerXID = 0;
+DelayedEventCallback delayedEventCallback = 0;
+
+void
+FireDelayedEvent()
+{
+ delayedEventTimerXID = 0;
+ delayedEventCallback();
+}
+
+void
+ScheduleDelayedEvent(cb, millisec)
+ DelayedEventCallback cb; long millisec;
+{
+ if(delayedEventTimerXID && delayedEventCallback == cb)
+ // [HGM] alive: replace, rather than add or flush identical event
+ XtRemoveTimeOut(delayedEventTimerXID);
+ delayedEventCallback = cb;
+ delayedEventTimerXID =
+ XtAppAddTimeOut(appContext, millisec,
+ (XtTimerCallbackProc) FireDelayedEvent, (XtPointer) 0);
+}
+
+DelayedEventCallback
+GetDelayedEvent()
+{
+ if (delayedEventTimerXID) {
+ return delayedEventCallback;
+ } else {
+ return NULL;
+ }
+}
+
+void
+CancelDelayedEvent()
+{
+ if (delayedEventTimerXID) {
+ XtRemoveTimeOut(delayedEventTimerXID);
+ delayedEventTimerXID = 0;
+ }
+}
+
+XtIntervalId loadGameTimerXID = 0;
+
+int LoadGameTimerRunning()
+{
+ return loadGameTimerXID != 0;
+}
+
+int StopLoadGameTimer()
+{
+ if (loadGameTimerXID != 0) {
+ XtRemoveTimeOut(loadGameTimerXID);
+ loadGameTimerXID = 0;
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+void
+LoadGameTimerCallback(arg, id)
+ XtPointer arg;
+ XtIntervalId *id;
+{
+ loadGameTimerXID = 0;
+ AutoPlayGameLoop();
+}
+
+void
+StartLoadGameTimer(millisec)
+ long millisec;
+{
+ loadGameTimerXID =
+ XtAppAddTimeOut(appContext, millisec,
+ (XtTimerCallbackProc) LoadGameTimerCallback,
+ (XtPointer) 0);
+}
+
+XtIntervalId analysisClockXID = 0;
+
+void
+AnalysisClockCallback(arg, id)
+ XtPointer arg;
+ XtIntervalId *id;
+{
+ if (gameMode == AnalyzeMode || gameMode == AnalyzeFile
+ || appData.icsEngineAnalyze) { // [DM]
+ AnalysisPeriodicEvent(0);
+ StartAnalysisClock();
+ }
+}
+
+void
+StartAnalysisClock()
+{
+ analysisClockXID =
+ XtAppAddTimeOut(appContext, 2000,
+ (XtTimerCallbackProc) AnalysisClockCallback,
+ (XtPointer) 0);
+}
+
+XtIntervalId clockTimerXID = 0;
+
+int ClockTimerRunning()
+{
+ return clockTimerXID != 0;
+}
+
+int StopClockTimer()
+{
+ if (clockTimerXID != 0) {
+ XtRemoveTimeOut(clockTimerXID);
+ clockTimerXID = 0;
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+void
+ClockTimerCallback(arg, id)
+ XtPointer arg;
+ XtIntervalId *id;
+{
+ clockTimerXID = 0;
+ DecrementClocks();
+}
+
+void
+StartClockTimer(millisec)
+ long millisec;
+{
+ clockTimerXID =
+ XtAppAddTimeOut(appContext, millisec,
+ (XtTimerCallbackProc) ClockTimerCallback,
+ (XtPointer) 0);
+}
+
+void
+DisplayTimerLabel(w, color, timer, highlight)
+ Widget w;
+ char *color;
+ long timer;
+ int 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) {
+ snprintf(buf, MSG_SIZ, "%s: %s", color, TimeString(timer));
+ XtSetArg(args[0], XtNlabel, buf);
+ } else {
+ snprintf(buf, MSG_SIZ, "%s ", color);
+ XtSetArg(args[0], XtNlabel, buf);
+ }
+
+ if (highlight) {
+
+ XtSetArg(args[1], XtNbackground, foregroundOrWarningColor);
+ XtSetArg(args[2], XtNforeground, timerBackgroundPixel);
+ } else {
+ XtSetArg(args[1], XtNbackground, timerBackgroundPixel);
+ XtSetArg(args[2], XtNforeground, foregroundOrWarningColor);
+ }
+
+ XtSetValues(w, args, 3);
+}
+
+void
+DisplayWhiteClock(timeRemaining, highlight)
+ long timeRemaining;
+ int highlight;
+{
+ Arg args[16];
+
+ if(appData.noGUI) return;
+ DisplayTimerLabel(whiteTimerWidget, _("White"), timeRemaining, highlight);
+ if (highlight && iconPixmap == bIconPixmap) {
+ iconPixmap = wIconPixmap;
+ XtSetArg(args[0], XtNiconPixmap, iconPixmap);
+ XtSetValues(shellWidget, args, 1);
+ }
+}
+
+void
+DisplayBlackClock(timeRemaining, highlight)
+ long timeRemaining;
+ int highlight;
+{
+ Arg args[16];
+
+ if(appData.noGUI) return;
+ DisplayTimerLabel(blackTimerWidget, _("Black"), timeRemaining, highlight);
+ if (highlight && iconPixmap == wIconPixmap) {
+ iconPixmap = bIconPixmap;
+ XtSetArg(args[0], XtNiconPixmap, iconPixmap);
+ XtSetValues(shellWidget, args, 1);
+ }
+}
+
+#define CPNone 0
+#define CPReal 1
+#define CPComm 2
+#define CPSock 3
+#define CPLoop 4
+typedef int CPKind;
+
+typedef struct {
+ CPKind kind;
+ int pid;
+ int fdTo, fdFrom;
+} ChildProc;
+
+
+int StartChildProcess(cmdLine, dir, pr)
+ char *cmdLine;
+ char *dir;
+ ProcRef *pr;
+{
+ char *argv[64], *p;
+ int i, pid;
+ 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);
+ }
+
+ /* We do NOT feed the cmdLine to the shell; we just
+ parse it into blank-separated arguments in the
+ most simple-minded way possible.
+ */
+ i = 0;
+ safeStrCpy(buf, cmdLine, sizeof(buf)/sizeof(buf[0]) );
+ p = buf;
+ for (;;) {
+ while(*p == ' ') p++;
+ argv[i++] = p;
+ if(*p == '"' || *p == '\'')
+ p = strchr(++argv[i-1], *p);
+ else p = strchr(p, ' ');
+ if (p == NULL) break;
+ *p++ = NULLCHAR;
+ }
+ argv[i] = NULL;
+
+ SetUpChildIO(to_prog, from_prog);
+
+ if ((pid = fork()) == 0) {
+ /* Child process */
+ // [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]);
+ 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;
+ cp->fdFrom = from_prog[0];
+ cp->fdTo = to_prog[1];
+ *pr = (ProcRef) cp;
+ return 0;
+}
+
+// [HGM] kill: implement the 'hard killing' of AS's Winboard_x
+static RETSIGTYPE AlarmCallBack(int n)
+{
+ return;
+}
+
+void
+DestroyChildProcess(pr, signalType)
+ ProcRef pr;
+ int signalType;
+{
+ ChildProc *cp = (ChildProc *) pr;
+
+ if (cp->kind != CPReal) return;
+ cp->kind = CPNone;
+ 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);
+ }
+ close(cp->fdFrom);
+ close(cp->fdTo);
+}
+
+void
+InterruptChildProcess(pr)
+ ProcRef pr;
+{
+ ChildProc *cp = (ChildProc *) pr;
+
+ if (cp->kind != CPReal) return;
+ (void) kill(cp->pid, SIGINT); /* stop it thinking */
+}
+
+int OpenTelnet(host, port, pr)
+ char *host;
+ char *port;
+ ProcRef *pr;
+{
+ char cmdLine[MSG_SIZ];
+
+ if (port[0] == NULLCHAR) {
+ snprintf(cmdLine, sizeof(cmdLine), "%s %s", appData.telnetProgram, host);
+ } else {
+ snprintf(cmdLine, sizeof(cmdLine), "%s %s %s", appData.telnetProgram, host, port);
+ }
+ return StartChildProcess(cmdLine, "", pr);
+}
+
+int OpenTCP(host, port, pr)
+ char *host;
+ char *port;
+ ProcRef *pr;
+{
+#if OMIT_SOCKETS
+ DisplayFatalError(_("Socket support is not configured in"), 0, 2);
+#else /* !OMIT_SOCKETS */
+ struct addrinfo hints;
+ struct addrinfo *ais, *ai;
+ int error;
+ int s;
+ ChildProc *cp;
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+
+ error = getaddrinfo(host, port, &hints, &ais);
+ if (error != 0) {
+ /* a getaddrinfo error is not an errno, so can't return it */
+ fprintf(debugFP, "getaddrinfo(%s, %s): %s\n",
+ host, port, gai_strerror(error));
+ return ENOENT;
+ }
+
+ for (ai = ais; ai != NULL; ai = ai->ai_next) {
+ if ((s = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol)) < 0) {
+ error = errno;
+ continue;
+ }
+ if (connect(s, ai->ai_addr, ai->ai_addrlen) < 0) {
+ error = errno;
+ continue;
+ }
+ error = 0;
+ break;
+ }
+ freeaddrinfo(ais);
+
+ if (error != 0) {
+ return error;
+ }
+
+ cp = (ChildProc *) calloc(1, sizeof(ChildProc));
+ cp->kind = CPSock;
+ cp->pid = 0;
+ cp->fdFrom = s;
+ cp->fdTo = s;
+ *pr = (ProcRef) cp;
+#endif /* !OMIT_SOCKETS */
+
+ return 0;
+}
+
+int OpenCommPort(name, pr)
+ char *name;
+ ProcRef *pr;
+{
+ int fd;
+ ChildProc *cp;
+
+ fd = open(name, 2, 0);
+ if (fd < 0) return errno;
+
+ cp = (ChildProc *) calloc(1, sizeof(ChildProc));
+ cp->kind = CPComm;
+ cp->pid = 0;
+ cp->fdFrom = fd;
+ cp->fdTo = fd;
+ *pr = (ProcRef) cp;
+
+ return 0;
+}
+
+int OpenLoopback(pr)
+ ProcRef *pr;
+{
+ ChildProc *cp;
+ int to[2], from[2];
+
+ SetUpChildIO(to, from);
+
+ cp = (ChildProc *) calloc(1, sizeof(ChildProc));
+ cp->kind = CPLoop;
+ cp->pid = 0;
+ cp->fdFrom = to[0]; /* note not from[0]; we are doing a loopback */
+ cp->fdTo = to[1];
+ *pr = (ProcRef) cp;
+
+ return 0;
+}
+
+int OpenRcmd(host, user, cmd, pr)
+ char *host, *user, *cmd;
+ ProcRef *pr;
+{
+ DisplayFatalError(_("internal rcmd not implemented for Unix"), 0, 1);
+ return -1;
+}
+
+#define INPUT_SOURCE_BUF_SIZE 8192
+
+typedef struct {
+ CPKind kind;
+ int fd;
+ int lineByLine;
+ char *unused;
+ InputCallback func;
+ XtInputId xid;
+ char buf[INPUT_SOURCE_BUF_SIZE];
+ VOIDSTAR closure;
+} InputSource;
+
+void
+DoInputCallback(closure, source, xid)
+ caddr_t closure;
+ int *source;
+ XtInputId *xid;
+{
+ InputSource *is = (InputSource *) closure;
+ int count;
+ int error;
+ char *p, *q;
+
+ if (is->lineByLine) {
+ count = read(is->fd, is->unused,
+ INPUT_SOURCE_BUF_SIZE - (is->unused - is->buf));
+ if (count <= 0) {
+ (is->func)(is, is->closure, is->buf, count, count ? errno : 0);
+ return;
+ }
+ is->unused += count;
+ p = is->buf;
+ while (p < is->unused) {
+ q = memchr(p, '\n', is->unused - p);
+ if (q == NULL) break;
+ q++;
+ (is->func)(is, is->closure, p, q - p, 0);
+ p = q;
+ }
+ q = is->buf;
+ while (p < is->unused) {
+ *q++ = *p++;
+ }
+ is->unused = q;
+ } else {
+ count = read(is->fd, is->buf, INPUT_SOURCE_BUF_SIZE);
+ if (count == -1)
+ error = errno;
+ else
+ error = 0;
+ (is->func)(is, is->closure, is->buf, count, error);
+ }
+}
+
+InputSourceRef AddInputSource(pr, lineByLine, func, closure)
+ ProcRef pr;
+ int lineByLine;
+ InputCallback func;
+ VOIDSTAR closure;
+{
+ InputSource *is;
+ ChildProc *cp = (ChildProc *) pr;
+
+ is = (InputSource *) calloc(1, sizeof(InputSource));
+ is->lineByLine = lineByLine;
+ is->func = func;
+ if (pr == NoProc) {
+ is->kind = CPReal;
+ is->fd = fileno(stdin);
+ } else {
+ is->kind = cp->kind;
+ is->fd = cp->fdFrom;
+ }
+ if (lineByLine) {
+ is->unused = is->buf;
+ }
+
+ is->xid = XtAppAddInput(appContext, is->fd,
+ (XtPointer) (XtInputReadMask),
+ (XtInputCallbackProc) DoInputCallback,
+ (XtPointer) is);
+ is->closure = closure;
+ return (InputSourceRef) is;
+}
+
+void
+RemoveInputSource(isr)
+ InputSourceRef isr;
+{
+ InputSource *is = (InputSource *) isr;
+
+ if (is->xid == 0) return;
+ XtRemoveInput(is->xid);
+ is->xid = 0;
+}
+
+int OutputToProcess(pr, message, count, outError)
+ ProcRef pr;
+ char *message;
+ int count;
+ int *outError;
+{
+ static int line = 0;
+ ChildProc *cp = (ChildProc *) pr;
+ int outCount;
+
+ if (pr == NoProc)
+ {
+ 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);
+
+ if (outCount == -1)
+ *outError = errno;
+ else
+ *outError = 0;
+
+ return outCount;
+}
+
+/* Output message to process, with "ms" milliseconds of delay
+ between each character. This is needed when sending the logon
+ script to ICC, which for some reason doesn't like the
+ instantaneous send. */
+int OutputToProcessDelayed(pr, message, count, outError, msdelay)
+ ProcRef pr;
+ char *message;
+ int count;
+ int *outError;
+ long msdelay;
+{
+ ChildProc *cp = (ChildProc *) pr;
+ int outCount = 0;
+ int r;
+
+ while (count--) {
+ r = write(cp->fdTo, message++, 1);
+ if (r == -1) {
+ *outError = errno;
+ return outCount;
+ }
+ ++outCount;
+ if (msdelay >= 0)
+ TimeDelay(msdelay);
+ }
+
+ return outCount;
+}
+
+/**** Animation code by Hugh Fisher, DCS, ANU.
+
+ Known problem: if a window overlapping the board is
+ moved away while a piece is being animated underneath,
+ the newly exposed area won't be updated properly.
+ I can live with this.
+
+ Known problem: if you look carefully at the animation
+ of pieces in mono mode, they are being drawn as solid
+ shapes without interior detail while moving. Fixing
+ this would be a major complication for minimal return.
+****/
+
+/* Masks for XPM pieces. Black and white pieces can have
+ different shapes, but in the interest of retaining my
+ sanity pieces must have the same outline on both light
+ and dark squares, and all pieces must use the same
+ background square colors/images. */
+
+static int xpmDone = 0;
+
+static void
+CreateAnimMasks (pieceDepth)
+ int pieceDepth;
+{
+ ChessSquare piece;
+ Pixmap buf;
+ GC bufGC, maskGC;
+ int kind, n;
+ unsigned long plane;
+ XGCValues values;
+
+ /* Need a bitmap just to get a GC with right depth */
+ buf = XCreatePixmap(xDisplay, xBoardWindow,
+ 8, 8, 1);
+ values.foreground = 1;
+ values.background = 0;
+ /* Don't use XtGetGC, not read only */
+ maskGC = XCreateGC(xDisplay, buf,
+ GCForeground | GCBackground, &values);
+ XFreePixmap(xDisplay, buf);
+
+ buf = XCreatePixmap(xDisplay, xBoardWindow,
+ squareSize, squareSize, pieceDepth);
+ values.foreground = XBlackPixel(xDisplay, xScreen);
+ values.background = XWhitePixel(xDisplay, xScreen);
+ bufGC = XCreateGC(xDisplay, buf,
+ GCForeground | GCBackground, &values);
+
+ 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) % (int)BlackPawn],
+ buf, bufGC,
+ 0, 0, squareSize, squareSize, 0, 0);
+
+ /* XOR the background (light) over the piece */
+ XSetFunction(xDisplay, bufGC, GXxor);
+ if (useImageSqs)
+ XCopyArea(xDisplay, xpmLightSquare, buf, bufGC,
+ 0, 0, squareSize, squareSize, 0, 0);
+ else {
+ 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. */
+ XSetFunction(xDisplay, maskGC, GXor);
+ plane = 1;
+ /* Might be quicker to download an XImage and create bitmap
+ data from it rather than this N copies per piece, but it
+ only takes a fraction of a second and there is a much
+ longer delay for loading the pieces. */
+ for (n = 0; n < pieceDepth; n ++) {
+ XCopyPlane(xDisplay, buf, xpmMask[piece], maskGC,
+ 0, 0, squareSize, squareSize,
+ 0, 0, plane);
+ plane = plane << 1;
+ }
+ }
+ /* Clean up */
+ XFreePixmap(xDisplay, buf);
+ XFreeGC(xDisplay, bufGC);
+ XFreeGC(xDisplay, maskGC);
+}
+
+static void
+InitAnimState (anim, info)
+ AnimState * anim;
+ XWindowAttributes * info;
+{
+ XtGCMask mask;
+ XGCValues values;
+
+ /* Each buffer is square size, same depth as window */
+ anim->saveBuf = XCreatePixmap(xDisplay, xBoardWindow,
+ squareSize, squareSize, info->depth);
+ anim->newBuf = XCreatePixmap(xDisplay, xBoardWindow,
+ squareSize, squareSize, info->depth);
+
+ /* Create a plain GC for blitting */
+ mask = GCForeground | GCBackground | GCFunction |
+ GCPlaneMask | GCGraphicsExposures;
+ values.foreground = XBlackPixel(xDisplay, xScreen);
+ values.background = XWhitePixel(xDisplay, xScreen);
+ values.function = GXcopy;
+ values.plane_mask = AllPlanes;
+ values.graphics_exposures = False;
+ anim->blitGC = XCreateGC(xDisplay, xBoardWindow, mask, &values);
+
+ /* Piece will be copied from an existing context at
+ the start of each new animation/drag. */
+ anim->pieceGC = XCreateGC(xDisplay, xBoardWindow, 0, &values);
+
+ /* Outline will be a read-only copy of an existing */
+ anim->outlineGC = None;
+}
+
+static void
+CreateAnimVars ()
+{
+ XWindowAttributes info;
+
+ if (xpmDone && gameInfo.variant == oldVariant) return;
+ if(xpmDone) oldVariant = 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
+
+static Boolean frameWaiting;
+
+static RETSIGTYPE FrameAlarm (sig)
+ int sig;
+{
+ frameWaiting = False;
+ /* In case System-V style signals. Needed?? */
+ signal(SIGALRM, FrameAlarm);
+}
+
+static void
+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_value.tv_sec = time / 1000;
+ delay.it_interval.tv_usec =
+ delay.it_value.tv_usec = (time % 1000) * 1000;
+ setitimer(ITIMER_REAL, &delay, NULL);
+ while (frameWaiting) pause();
+ 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);
+ }
+}
+
+#else
+
+static void
+FrameDelay (time)
+ int time;
+{
+ XSync(xDisplay, False);
+ if (time > 0)
+ usleep(time * 1000);
+}
+
+#endif
+
+/* Convert board position to corner of screen rect and color */
+
+static void
+ScreenSquare(column, row, pt, color)
+ int column; int row; XPoint * pt; int * color;
+{
+ if (flipView) {
+ 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_HEIGHT-1)-row) * (squareSize + lineGap);
+ }
+ *color = SquareColor(row, column);
+}
+
+/* Convert window coords to square */
+
+static void
+BoardSquare(x, y, column, row)
+ int x; int y; int * column; int * row;
+{
+ *column = EventToSquare(x, BOARD_WIDTH);
+ if (flipView && *column >= 0)
+ *column = BOARD_WIDTH - 1 - *column;
+ *row = EventToSquare(y, BOARD_HEIGHT);
+ if (!flipView && *row >= 0)
+ *row = BOARD_HEIGHT - 1 - *row;
+}
+
+/* Utilities */
+
+#undef Max /* just in case */
+#undef Min
+#define Max(a, b) ((a) > (b) ? (a) : (b))
+#define Min(a, b) ((a) < (b) ? (a) : (b))
+
+static void
+SetRect(rect, x, y, width, height)
+ XRectangle * rect; int x; int y; int width; int height;
+{
+ rect->x = x;
+ rect->y = y;
+ rect->width = width;
+ rect->height = 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;
+ int size; XRectangle * area; XPoint * pt;
+{
+ if (old->x > new->x + size || new->x > old->x + size ||
+ old->y > new->y + size || new->y > old->y + size) {
+ return False;
+ } else {
+ SetRect(area, Max(new->x - old->x, 0), Max(new->y - old->y, 0),
+ size - abs(old->x - new->x), size - abs(old->y - new->y));
+ pt->x = Max(old->x - new->x, 0);
+ pt->y = Max(old->y - new->y, 0);
+ return True;
+ }
+}
+
+/* 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;
+ XRectangle update[]; int * nUpdates;
+{
+ int count;
+
+ /* If old = new (shouldn't happen) then nothing to draw */
+ if (old->x == new->x && old->y == new->y) {
+ *nUpdates = 0;
+ return;
+ }
+ /* Work out what bits overlap. Since we know the rects
+ are the same size we don't need a full intersect calc. */
+ count = 0;
+ /* Top or bottom edge? */
+ if (new->y > old->y) {
+ SetRect(&(update[count]), old->x, old->y, size, new->y - old->y);
+ count ++;
+ } else if (old->y > new->y) {
+ SetRect(&(update[count]), old->x, old->y + size - (old->y - new->y),
+ size, old->y - new->y);
+ count ++;
+ }
+ /* Left or right edge - don't overlap any update calculated above. */
+ if (new->x > old->x) {
+ SetRect(&(update[count]), old->x, Max(new->y, old->y),
+ new->x - old->x, size - abs(new->y - old->y));
+ count ++;
+ } else if (old->x > new->x) {
+ SetRect(&(update[count]), new->x + size, Max(new->y, old->y),
+ old->x - new->x, size - abs(new->y - old->y));
+ count ++;
+ }
+ /* Done */
+ *nUpdates = count;
+}
+
+/* Generate a series of frame coords from start->mid->finish.
+ The movement rate doubles until the half way point is
+ reached, then halves back down to the final destination,
+ which gives a nice slow in/out effect. The algorithmn
+ may seem to generate too many intermediates for short
+ moves, but remember that the purpose is to attract the
+ viewers attention to the piece about to be moved and
+ then to where it ends up. Too few frames would be less
+ noticeable. */
+
+static void
+Tween(start, mid, finish, factor, frames, nFrames)
+ XPoint * start; XPoint * mid;
+ XPoint * finish; int factor;
+ XPoint frames[]; int * nFrames;
+{
+ int fraction, n, count;
+
+ count = 0;
+
+ /* Slow in, stepping 1/16th, then 1/8th, ... */
+ fraction = 1;
+ for (n = 0; n < factor; n++)
+ fraction *= 2;
+ for (n = 0; n < factor; n++) {
+ frames[count].x = start->x + (mid->x - start->x) / fraction;
+ frames[count].y = start->y + (mid->y - start->y) / fraction;
+ count ++;
+ fraction = fraction / 2;
+ }
+
+ /* Midpoint */
+ frames[count] = *mid;
+ count ++;
+
+ /* Slow out, stepping 1/2, then 1/4, ... */
+ fraction = 2;
+ for (n = 0; n < factor; n++) {
+ frames[count].x = finish->x - (finish->x - mid->x) / fraction;
+ frames[count].y = finish->y - (finish->y - mid->y) / fraction;
+ count ++;
+ fraction = fraction * 2;
+ }
+ *nFrames = count;
+}
+
+/* Draw a piece on the screen without disturbing what's there */
+
+static void
+SelectGCMask(piece, clip, outline, mask)
+ ChessSquare piece; GC * clip; GC * outline; Pixmap * mask;
+{
+ GC source;
+
+ /* Bitmap for piece being moved. */
+ if (appData.monoMode) {
+ *mask = *pieceToSolid(piece);
+ } else if (useImages) {
+#if HAVE_LIBXPM
+ *mask = xpmMask[piece];
+#else
+ *mask = ximMaskPm[piece];
+#endif
+ } else {
+ *mask = *pieceToSolid(piece);
+ }
+
+ /* GC for piece being moved. Square color doesn't matter, but
+ since it gets modified we make a copy of the original. */
+ if (White(piece)) {
+ if (appData.monoMode)
+ source = bwPieceGC;
+ else
+ source = wlPieceGC;
+ } else {
+ if (appData.monoMode)
+ source = wbPieceGC;
+ else
+ source = blPieceGC;
+ }
+ XCopyGC(xDisplay, source, 0xFFFFFFFF, *clip);
+
+ /* Outline only used in mono mode and is not modified */
+ if (White(piece))
+ *outline = bwPieceGC;
+ else
+ *outline = wbPieceGC;
+}
+
+static void
+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,
+ 0, 0, squareSize, squareSize);
+ if (appData.monoMode)
+ /* Also draw outline in contrasting color for black
+ on black / white on white cases */
+ XCopyPlane(xDisplay, *pieceToOutline(piece), dest, outline,
+ 0, 0, squareSize, squareSize, 0, 0, 1);
+ } else {
+ /* Copy the piece */
+ if (White(piece))
+ kind = 0;
+ else
+ kind = 2;
+ if(appData.upsideDown && flipView) kind ^= 2;
+ XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
+ dest, clip,
+ 0, 0, squareSize, squareSize,
+ 0, 0);
+ }
+}
+
+/* Animate the movement of a single piece */
+
+static void
+BeginAnimation(anim, piece, startColor, start)
+ AnimState *anim;
+ ChessSquare piece;
+ int startColor;
+ XPoint * start;
+{
+ Pixmap mask;
+
+ if(appData.upsideDown && flipView) piece += piece < BlackPawn ? BlackPawn : -BlackPawn;
+ /* The old buffer is initialised with the start square (empty) */
+ 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);
+}
+
+static void
+AnimationFrame(anim, frame, piece)
+ AnimState *anim;
+ XPoint *frame;
+ ChessSquare piece;
+{
+ XRectangle updates[4];
+ 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,
+ the contents in newBuf are wrong. */
+ XCopyArea(xDisplay, anim->saveBuf, anim->newBuf, anim->blitGC,
+ overlap.x, overlap.y,
+ overlap.width, overlap.height,
+ pt.x, pt.y);
+ /* Repaint the areas in the old that don't overlap new */
+ CalcUpdateRects(&anim->prevFrame, frame, squareSize, updates, &count);
+ for (i = 0; i < count; i++)
+ XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
+ updates[i].x - anim->prevFrame.x,
+ updates[i].y - anim->prevFrame.y,
+ updates[i].width, updates[i].height,
+ updates[i].x, updates[i].y);
+ } else {
+ /* Easy when no overlap */
+ XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
+ 0, 0, squareSize, squareSize,
+ anim->prevFrame.x, anim->prevFrame.y);
+ }
+
+ /* Save this frame for next time round */
+ XCopyArea(xDisplay, anim->newBuf, anim->saveBuf, anim->blitGC,
+ 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);
+ XCopyArea(xDisplay, anim->newBuf, xBoardWindow, anim->blitGC,
+ 0, 0, squareSize, squareSize,
+ frame->x, frame->y);
+}
+
+static void
+EndAnimation (anim, finish)
+ AnimState *anim;
+ XPoint *finish;
+{
+ XRectangle updates[4];
+ XRectangle overlap;
+ XPoint pt;
+ int count, i;
+
+ /* The main code will redraw the final square, so we
+ only need to erase the bits that don't overlap. */
+ if (Intersect(&anim->prevFrame, finish, squareSize, &overlap, &pt)) {
+ CalcUpdateRects(&anim->prevFrame, finish, squareSize, updates, &count);
+ for (i = 0; i < count; i++)
+ XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
+ updates[i].x - anim->prevFrame.x,
+ updates[i].y - anim->prevFrame.y,
+ updates[i].width, updates[i].height,
+ updates[i].x, updates[i].y);
+ } else {
+ XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
+ 0, 0, squareSize, squareSize,
+ anim->prevFrame.x, anim->prevFrame.y);
+ }
+}
+
+static void
+FrameSequence(anim, piece, startColor, start, finish, frames, nFrames)
+ AnimState *anim;
+ ChessSquare piece; int startColor;
+ XPoint * start; XPoint * finish;
+ XPoint frames[]; int nFrames;
+{
+ int n;
+
+ BeginAnimation(anim, piece, startColor, start);
+ for (n = 0; n < nFrames; n++) {
+ AnimationFrame(anim, &(frames[n]), piece);
+ FrameDelay(appData.animSpeed);
+ }
+ 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
+AnimateMove(board, fromX, fromY, toX, toY)
+ Board board;
+ int fromX;
+ int fromY;
+ int toX;
+ int toY;
+{
+ ChessSquare piece;
+ int hop;
+ XPoint start, finish, mid;
+ XPoint frames[kFactor * 2 + 1];
+ int nFrames, startColor, endColor;
+
+ /* Are we animating? */
+ 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;
+
+#if DONT_HOP
+ hop = FALSE;
+#else
+ hop = abs(fromX-toX) == 1 && abs(fromY-toY) == 2 || abs(fromX-toX) == 2 && abs(fromY-toY) == 1;
+#endif
+
+ if (appData.debugMode) {
+ 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 straight movement then diagonal */
+ if (abs(toY - fromY) < abs(toX - fromX)) {
+ mid.x = start.x + (finish.x - start.x) / 2;
+ mid.y = start.y;
+ } else {
+ 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<BOARD_WIDTH; i++) for(j=0; j<BOARD_HEIGHT; j++)
+ if((i-toX)*(i-toX) + (j-toY)*(j-toY) < 6) damage[0][j][i] = True;
+ }
+
+ /* Be sure end square is redrawn */
+ damage[0][toY][toX] = True;
+}
+
+void
+DragPieceBegin(x, y)
+ int x; int y;
+{
+ int boardX, boardY, color;
+ XPoint corner;
+
+ /* Are we animating? */
+ if (!appData.animateDragging || appData.blindfold)
+ return;
+
+ /* Figure out which square we start in and the
+ mouse position relative to top left corner. */
+ BoardSquare(x, y, &boardX, &boardY);
+ player.startBoardX = boardX;
+ player.startBoardY = boardY;
+ ScreenSquare(boardX, boardY, &corner, &color);
+ player.startSquare = corner;
+ player.startColor = color;
+ /* As soon as we start dragging, the piece will jump slightly to
+ be centered over the mouse pointer. */
+ player.mouseDelta.x = squareSize/2;
+ player.mouseDelta.y = squareSize/2;
+ /* Initialise animation */
+ player.dragPiece = PieceForSquare(boardX, boardY);
+ /* Sanity check */
+ if (player.dragPiece >= 0 && player.dragPiece < EmptySquare) {
+ player.dragActive = True;
+ BeginAnimation(&player, player.dragPiece, color, &corner);
+ /* Mark this square as needing to be redrawn. Note that
+ we don't remove the piece though, since logically (ie
+ as seen by opponent) the move hasn't been made yet. */
+ if(boardX == BOARD_RGHT+1 && PieceForSquare(boardX-1, boardY) > 1 ||
+ boardX == BOARD_LEFT-2 && PieceForSquare(boardX+1, boardY) > 1)
+ XCopyArea(xDisplay, xBoardWindow, player.saveBuf, player.blitGC,
+ corner.x, corner.y, squareSize, squareSize,
+ 0, 0); // [HGM] zh: unstack in stead of grab
+ 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;
+ }
+}
+
+void
+ChangeDragPiece(ChessSquare piece)
+{
+ Pixmap mask;
+ player.dragPiece = piece;
+ /* The piece will be drawn using its own bitmap as a matte */
+ SelectGCMask(piece, &player.pieceGC, &player.outlineGC, &mask);
+ XSetClipMask(xDisplay, player.pieceGC, mask);
+}
+
+static void
+DragPieceMove(x, y)
+ int x; int y;
+{
+ XPoint corner;
+
+ /* Are we animating? */
+ if (!appData.animateDragging || appData.blindfold)
+ return;
+
+ /* Sanity check */
+ if (! player.dragActive)
+ return;
+ /* Move piece, maintaining same relative position
+ of mouse within square */
+ corner.x = x - player.mouseDelta.x;
+ corner.y = y - player.mouseDelta.y;
+ AnimationFrame(&player, &corner, player.dragPiece);
+#if HIGHDRAG*0
+ if (appData.highlightDragging) {
+ int boardX, boardY;
+ BoardSquare(x, y, &boardX, &boardY);
+ SetHighlights(fromX, fromY, boardX, boardY);
+ }
+#endif
+}
+
+void
+DragPieceEnd(x, y)
+ int x; int y;
+{
+ int boardX, boardY, color;
+ XPoint corner;
+
+ /* Are we animating? */
+ if (!appData.animateDragging || appData.blindfold)
+ return;
+
+ /* Sanity check */
+ if (! player.dragActive)
+ return;
+ /* Last frame in sequence is square piece is
+ placed on, which may not match mouse exactly. */
+ BoardSquare(x, y, &boardX, &boardY);
+ ScreenSquare(boardX, boardY, &corner, &color);
+ EndAnimation(&player, &corner);
+
+ /* Be sure end square is redrawn */
+ damage[0][boardY][boardX] = True;
+
+ /* This prevents weird things happening with fast successive
+ clicks which on my Sun at least can cause motion events
+ without corresponding press/release. */
+ player.dragActive = False;
+}
+
+/* Handle expose event while piece being dragged */
+
+static void
+DrawDragPiece ()
+{
+ if (!player.dragActive || appData.blindfold)
+ return;
+
+ /* What we're doing: logically, the move hasn't been made yet,
+ so the piece is still in it's original square. But visually
+ 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, 1);
+ AnimationFrame(&player, &player.prevFrame, player.dragPiece);
+ damage[0][player.startBoardY][player.startBoardX] = TRUE;
+}
+
+#include <sys/ioctl.h>
+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 );
+
+ 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);
+}
+
+void UpdateLogos(int displ)
+{
+ return; // no logos in XBoard yet
+}
+