2 * xboard.c -- X front end for XBoard
4 * Copyright 1991 by Digital Equipment Corporation, Maynard,
7 * Enhancements Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006,
8 * 2007, 2008, 2009 Free Software Foundation, Inc.
10 * The following terms apply to Digital Equipment Corporation's copyright
12 * ------------------------------------------------------------------------
15 * Permission to use, copy, modify, and distribute this software and its
16 * documentation for any purpose and without fee is hereby granted,
17 * provided that the above copyright notice appear in all copies and that
18 * both that copyright notice and this permission notice appear in
19 * supporting documentation, and that the name of Digital not be
20 * used in advertising or publicity pertaining to distribution of the
21 * software without specific, written prior permission.
23 * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
24 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
25 * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
26 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
27 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
28 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
30 * ------------------------------------------------------------------------
32 * The following terms apply to the enhanced version of XBoard
33 * distributed by the Free Software Foundation:
34 * ------------------------------------------------------------------------
36 * GNU XBoard is free software: you can redistribute it and/or modify
37 * it under the terms of the GNU General Public License as published by
38 * the Free Software Foundation, either version 3 of the License, or (at
39 * your option) any later version.
41 * GNU XBoard is distributed in the hope that it will be useful, but
42 * WITHOUT ANY WARRANTY; without even the implied warranty of
43 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
44 * General Public License for more details.
46 * You should have received a copy of the GNU General Public License
47 * along with this program. If not, see http://www.gnu.org/licenses/. *
49 *------------------------------------------------------------------------
50 ** See the file ChangeLog for a revision history. */
58 #include <sys/types.h>
63 # if HAVE_SYS_SOCKET_H
64 # include <sys/socket.h>
65 # include <netinet/in.h>
67 # else /* not HAVE_SYS_SOCKET_H */
68 # if HAVE_LAN_SOCKET_H
69 # include <lan/socket.h>
71 # include <lan/netdb.h>
72 # else /* not HAVE_LAN_SOCKET_H */
73 # define OMIT_SOCKETS 1
74 # endif /* not HAVE_LAN_SOCKET_H */
75 # endif /* not HAVE_SYS_SOCKET_H */
76 #endif /* !OMIT_SOCKETS */
81 #else /* not STDC_HEADERS */
82 extern char *getenv();
85 # else /* not HAVE_STRING_H */
87 # endif /* not HAVE_STRING_H */
88 #endif /* not STDC_HEADERS */
91 # include <sys/fcntl.h>
92 #else /* not HAVE_SYS_FCNTL_H */
95 # endif /* HAVE_FCNTL_H */
96 #endif /* not HAVE_SYS_FCNTL_H */
98 #if HAVE_SYS_SYSTEMINFO_H
99 # include <sys/systeminfo.h>
100 #endif /* HAVE_SYS_SYSTEMINFO_H */
102 #if TIME_WITH_SYS_TIME
103 # include <sys/time.h>
107 # include <sys/time.h>
118 # include <sys/wait.h>
123 # define NAMLEN(dirent) strlen((dirent)->d_name)
124 # define HAVE_DIR_STRUCT
126 # define dirent direct
127 # define NAMLEN(dirent) (dirent)->d_namlen
129 # include <sys/ndir.h>
130 # define HAVE_DIR_STRUCT
133 # include <sys/dir.h>
134 # define HAVE_DIR_STRUCT
138 # define HAVE_DIR_STRUCT
142 #include <X11/Intrinsic.h>
143 #include <X11/StringDefs.h>
144 #include <X11/Shell.h>
145 #include <X11/cursorfont.h>
146 #include <X11/Xatom.h>
148 #include <X11/Xaw3d/Dialog.h>
149 #include <X11/Xaw3d/Form.h>
150 #include <X11/Xaw3d/List.h>
151 #include <X11/Xaw3d/Label.h>
152 #include <X11/Xaw3d/SimpleMenu.h>
153 #include <X11/Xaw3d/SmeBSB.h>
154 #include <X11/Xaw3d/SmeLine.h>
155 #include <X11/Xaw3d/Box.h>
156 #include <X11/Xaw3d/MenuButton.h>
157 #include <X11/Xaw3d/Text.h>
158 #include <X11/Xaw3d/AsciiText.h>
160 #include <X11/Xaw/Dialog.h>
161 #include <X11/Xaw/Form.h>
162 #include <X11/Xaw/List.h>
163 #include <X11/Xaw/Label.h>
164 #include <X11/Xaw/SimpleMenu.h>
165 #include <X11/Xaw/SmeBSB.h>
166 #include <X11/Xaw/SmeLine.h>
167 #include <X11/Xaw/Box.h>
168 #include <X11/Xaw/MenuButton.h>
169 #include <X11/Xaw/Text.h>
170 #include <X11/Xaw/AsciiText.h>
173 // [HGM] bitmaps: put before incuding the bitmaps / pixmaps, to know how many piece types there are.
178 #include "pixmaps/pixmaps.h"
179 #define IMAGE_EXT "xpm"
181 #define IMAGE_EXT "xim"
182 #include "bitmaps/bitmaps.h"
187 #include <gdk-pixbuf/gdk-pixbuf.h>
189 #include "bitmaps/icon_white.bm"
190 #include "bitmaps/icon_black.bm"
191 #include "bitmaps/checkmark.bm"
193 #include "frontend.h"
198 #include "xgamelist.h"
199 #include "xhistory.h"
200 #include "xedittags.h"
202 #include "callback.h"
203 #include "interface.h"
205 // must be moved to xengineoutput.h
207 void EngineOutputProc P((Widget w, XEvent *event,
208 String *prms, Cardinal *nprms));
210 void EngineOutputPopDown();
217 #define usleep(t) _sleep2(((t)+500)/1000)
221 # define _(s) gettext (s)
222 # define N_(s) gettext_noop (s)
245 int main P((int argc, char **argv));
246 RETSIGTYPE CmailSigHandler P((int sig));
247 RETSIGTYPE IntSigHandler P((int sig));
248 void CreateGCs P((void));
249 void CreateXIMPieces P((void));
250 void CreateXPMPieces P((void));
251 void CreatePieces P((void));
252 void CreatePieceMenus P((void));
253 Widget CreateMenuBar P((Menu *mb));
254 Widget CreateButtonBar P ((MenuItem *mi));
255 char *FindFont P((char *pattern, int targetPxlSize));
256 void PieceMenuPopup P((Widget w, XEvent *event,
257 String *params, Cardinal *num_params));
258 static void PieceMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
259 static void DropMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
260 int EventToSquare P((int x, int limit));
261 void DrawSquare P((int row, int column, ChessSquare piece, int do_flash));
262 void HandleUserMove P((Widget w, XEvent *event,
263 String *prms, Cardinal *nprms));
264 void AnimateUserMove P((Widget w, XEvent * event,
265 String * params, Cardinal * nParams));
266 void WhiteClock P((Widget w, XEvent *event,
267 String *prms, Cardinal *nprms));
268 void BlackClock P((Widget w, XEvent *event,
269 String *prms, Cardinal *nprms));
270 void CommentPopUp P((char *title, char *label));
271 void CommentPopDown P((void));
272 void CommentCallback P((Widget w, XtPointer client_data,
273 XtPointer call_data));
274 void ICSInputBoxPopUp P((void));
275 void ICSInputBoxPopDown P((void));
276 void FileNamePopUp P((char *label, char *def,
277 FileProc proc, char *openMode));
278 void FileNamePopDown P((void));
279 void FileNameCallback P((Widget w, XtPointer client_data,
280 XtPointer call_data));
281 void FileNameAction P((Widget w, XEvent *event,
282 String *prms, Cardinal *nprms));
283 void AskQuestionReplyAction P((Widget w, XEvent *event,
284 String *prms, Cardinal *nprms));
285 void AskQuestionProc P((Widget w, XEvent *event,
286 String *prms, Cardinal *nprms));
287 void AskQuestionPopDown P((void));
288 void PromotionPopUp P((void));
289 void PromotionPopDown P((void));
290 void PromotionCallback P((Widget w, XtPointer client_data,
291 XtPointer call_data));
292 void EditCommentPopDown P((void));
293 void EditCommentCallback P((Widget w, XtPointer client_data,
294 XtPointer call_data));
295 void SelectCommand P((Widget w, XtPointer client_data, XtPointer call_data));
296 void LoadPositionProc P((Widget w, XEvent *event,
297 String *prms, Cardinal *nprms));
298 void LoadNextPositionProc P((Widget w, XEvent *event, String *prms,
300 void LoadPrevPositionProc P((Widget w, XEvent *event, String *prms,
302 void ReloadPositionProc P((Widget w, XEvent *event, String *prms,
304 void CopyPositionProc P((Widget w, XEvent *event, String *prms,
306 void PastePositionProc P((Widget w, XEvent *event, String *prms,
308 void CopyGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
309 void PasteGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
310 void SaveGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
311 void SavePositionProc P((Widget w, XEvent *event,
312 String *prms, Cardinal *nprms));
313 void MailMoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
314 void ReloadCmailMsgProc P((Widget w, XEvent *event, String *prms,
316 void AnalyzeModeProc P((Widget w, XEvent *event,
317 String *prms, Cardinal *nprms));
318 void AnalyzeFileProc P((Widget w, XEvent *event,
319 String *prms, Cardinal *nprms));
320 void IcsClientProc P((Widget w, XEvent *event, String *prms,
322 void EditGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
323 void EditPositionProc P((Widget w, XEvent *event,
324 String *prms, Cardinal *nprms));
325 void TrainingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
326 void EditCommentProc P((Widget w, XEvent *event,
327 String *prms, Cardinal *nprms));
328 void IcsInputBoxProc P((Widget w, XEvent *event,
329 String *prms, Cardinal *nprms));
330 void AdjuWhiteProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
331 void AdjuBlackProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
332 void AdjuDrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
333 void EnterKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
334 void StopObservingProc P((Widget w, XEvent *event, String *prms,
336 void StopExaminingProc P((Widget w, XEvent *event, String *prms,
338 void BackwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
339 void ForwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
340 void ToStartProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
341 void ToEndProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
342 void RevertProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
343 void TruncateGameProc P((Widget w, XEvent *event, String *prms,
345 void RetractMoveProc P((Widget w, XEvent *event, String *prms,
347 void AlwaysQueenProc P((Widget w, XEvent *event, String *prms,
349 void AnimateDraggingProc P((Widget w, XEvent *event, String *prms,
351 void AnimateMovingProc P((Widget w, XEvent *event, String *prms,
353 void AutocommProc P((Widget w, XEvent *event, String *prms,
355 void AutoflagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
356 void AutoflipProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
357 void AutobsProc P((Widget w, XEvent *event, String *prms,
359 void AutoraiseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
360 void AutosaveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
361 void BlindfoldProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
362 void FlashMovesProc P((Widget w, XEvent *event, String *prms,
364 void FlipViewProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
365 void GetMoveListProc P((Widget w, XEvent *event, String *prms,
367 void HighlightDraggingProc P((Widget w, XEvent *event, String *prms,
369 void HighlightLastMoveProc P((Widget w, XEvent *event, String *prms,
371 void MoveSoundProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
372 void IcsAlarmProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
373 void OldSaveStyleProc P((Widget w, XEvent *event, String *prms,
375 void PeriodicUpdatesProc P((Widget w, XEvent *event, String *prms,
377 void PonderNextMoveProc P((Widget w, XEvent *event, String *prms,
379 void PopupMoveErrorsProc P((Widget w, XEvent *event, String *prms,
381 void PopupExitMessageProc P((Widget w, XEvent *event, String *prms,
383 void PremoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
384 void QuietPlayProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
385 void ShowThinkingProc P((Widget w, XEvent *event, String *prms,
387 void HideThinkingProc P((Widget w, XEvent *event, String *prms,
389 void TestLegalityProc P((Widget w, XEvent *event, String *prms,
391 void InfoProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
392 void ManProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
393 void HintProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
394 void BookProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
395 void AboutGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
396 void DebugProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
397 void NothingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
398 void Iconify P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
399 void DisplayMove P((int moveNumber));
400 void DisplayTitle P((char *title));
401 void ICSInitScript P((void));
402 int LoadGamePopUp P((FILE *f, int gameNumber, char *title));
403 void ErrorPopUp P((char *title, char *text, int modal));
404 void ErrorPopDown P((void));
405 static char *ExpandPathName P((char *path));
406 static void CreateAnimVars P((void));
407 void DragPieceBegin P((int x, int y));
408 static void DragPieceMove P((int x, int y));
409 void DragPieceEnd P((int x, int y));
410 static void DrawDragPiece P((void));
411 char *ModeToWidgetName P((GameMode mode));
412 void EngineOutputUpdate( FrontEndProgramStats * stats );
413 void ShuffleMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
414 void EngineMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
415 void UciMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
416 void TimeControlProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
417 void NewVariantProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
418 void FirstSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
419 void SecondSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
420 void ShufflePopDown P(());
421 void EnginePopDown P(());
422 void UciPopDown P(());
423 void TimeControlPopDown P(());
424 void NewVariantPopDown P(());
425 void SettingsPopDown P(());
426 void SetMenuEnables P((Enables *enab));
429 * XBoard depends on Xt R4 or higher
431 int xtVersion = XtSpecificationRelease;
436 Pixel lightSquareColor, darkSquareColor, whitePieceColor, blackPieceColor,
437 jailSquareColor, highlightSquareColor, premoveHighlightColor;
438 Pixel lowTimeWarningColor;
440 #define LINE_TYPE_NORMAL 0
441 #define LINE_TYPE_HIGHLIGHT 1
442 #define LINE_TYPE_PRE 2
445 GC lightSquareGC, darkSquareGC, jailSquareGC, wdPieceGC, wlPieceGC,
446 bdPieceGC, blPieceGC, wbPieceGC, bwPieceGC, coordGC,
447 wjPieceGC, bjPieceGC;
448 Pixmap iconPixmap, wIconPixmap, bIconPixmap, xMarkPixmap;
449 Widget shellWidget, layoutWidget, formWidget, boardWidget, messageWidget,
450 whiteTimerWidget, blackTimerWidget, titleWidget, widgetList[16],
451 commentShell, promotionShell, whitePieceMenu, blackPieceMenu, dropMenu,
452 menuBarWidget, buttonBarWidget, editShell, errorShell, analysisShell,
453 ICSInputShell, fileNameShell, askQuestionShell;
454 Font clockFontID, coordFontID, countFontID;
455 XFontStruct *clockFontStruct, *coordFontStruct, *countFontStruct;
456 XtAppContext appContext;
458 char *oldICSInteractionTitle;
462 char installDir[] = "."; // [HGM] UCI: needed for UCI; probably needs run-time initializtion
464 Position commentX = -1, commentY = -1;
465 Dimension commentW, commentH;
467 int squareSize, smallLayout = 0, tinyLayout = 0,
468 marginW, marginH, // [HGM] for run-time resizing
469 fromX = -1, fromY = -1, toX, toY, commentUp = False, analysisUp = False,
470 ICSInputBoxUp = False, askQuestionUp = False,
471 filenameUp = False, promotionUp = False, pmFromX = -1, pmFromY = -1,
472 editUp = False, errorUp = False, errorExitStatus = -1, lineGap;
473 Pixel timerForegroundPixel, timerBackgroundPixel;
474 Pixel buttonForegroundPixel, buttonBackgroundPixel;
475 char *chessDir, *programName, *programVersion,
476 *gameCopyFilename, *gamePasteFilename;
480 Pixmap pieceBitmap[2][(int)BlackPawn];
481 Pixmap pieceBitmap2[2][(int)BlackPawn+4]; /* [HGM] pieces */
482 Pixmap xpmPieceBitmap[4][(int)BlackPawn]; /* LL, LD, DL, DD actually used*/
483 Pixmap xpmPieceBitmap2[4][(int)BlackPawn+4]; /* LL, LD, DL, DD set to select from */
484 Pixmap xpmLightSquare, xpmDarkSquare, xpmJailSquare;
485 int useImages=0, useImageSqs;
486 XImage *ximPieceBitmap[4][(int)BlackPawn+4]; /* LL, LD, DL, DD */
487 Pixmap ximMaskPm[(int)BlackPawn]; /* clipmasks, used for XIM pieces */
488 Pixmap ximMaskPm2[(int)BlackPawn+4]; /* clipmasks, used for XIM pieces */
489 XImage *ximLightSquare, *ximDarkSquare;
492 #define pieceToSolid(piece) &pieceBitmap[SOLID][(piece) % (int)BlackPawn]
493 #define pieceToOutline(piece) &pieceBitmap[OUTLINE][(piece) % (int)BlackPawn]
495 #define White(piece) ((int)(piece) < (int)BlackPawn)
497 /* Variables for doing smooth animation. This whole thing
498 would be much easier if the board was double-buffered,
499 but that would require a fairly major rewrite. */
504 GC blitGC, pieceGC, outlineGC;
505 XPoint startSquare, prevFrame, mouseDelta;
509 int startBoardX, startBoardY;
512 /* There can be two pieces being animated at once: a player
513 can begin dragging a piece before the remote opponent has moved. */
515 static AnimState game, player;
517 /* Bitmaps for use as masks when drawing XPM pieces.
518 Need one for each black and white piece. */
519 static Pixmap xpmMask[BlackKing + 1];
521 /* This magic number is the number of intermediate frames used
522 in each half of the animation. For short moves it's reduced
523 by 1. The total number of frames will be factor * 2 + 1. */
526 SizeDefaults sizeDefaults[] = SIZE_DEFAULTS;
528 Enables icsEnables[] = {
529 { "menuFile.Mail Move", False },
530 { "menuFile.Reload CMail Message", False },
531 { "menuMode.Machine Black", False },
532 { "menuMode.Machine White", False },
533 { "menuMode.Analysis Mode", False },
534 { "menuMode.Analyze File", False },
535 { "menuMode.Two Machines", False },
537 { "menuHelp.Hint", False },
538 { "menuHelp.Book", False },
539 { "menuStep.Move Now", False },
540 { "menuOptions.Periodic Updates", False },
541 { "menuOptions.Hide Thinking", False },
542 { "menuOptions.Ponder Next Move", False },
547 Enables ncpEnables[] = {
548 { "menuFile.Mail Move", False },
549 { "menuFile.Reload CMail Message", False },
550 { "menuMode.Machine White", False },
551 { "menuMode.Machine Black", False },
552 { "menuMode.Analysis Mode", False },
553 { "menuMode.Analyze File", False },
554 { "menuMode.Two Machines", False },
555 { "menuMode.ICS Client", False },
556 { "menuMode.ICS Input Box", False },
558 { "menuStep.Revert", False },
559 { "menuStep.Move Now", False },
560 { "menuStep.Retract Move", False },
561 { "menuOptions.Auto Comment", False },
562 { "menuOptions.Auto Flag", False },
563 { "menuOptions.Auto Flip View", False },
564 { "menuOptions.Auto Observe", False },
565 { "menuOptions.Auto Raise Board", False },
566 { "menuOptions.Get Move List", False },
567 { "menuOptions.ICS Alarm", False },
568 { "menuOptions.Move Sound", False },
569 { "menuOptions.Quiet Play", False },
570 { "menuOptions.Hide Thinking", False },
571 { "menuOptions.Periodic Updates", False },
572 { "menuOptions.Ponder Next Move", False },
573 { "menuHelp.Hint", False },
574 { "menuHelp.Book", False },
578 Enables gnuEnables[] = {
579 { "menuMode.ICS Client", False },
580 { "menuMode.ICS Input Box", False },
581 { "menuAction.Accept", False },
582 { "menuAction.Decline", False },
583 { "menuAction.Rematch", False },
584 { "menuAction.Adjourn", False },
585 { "menuAction.Stop Examining", False },
586 { "menuAction.Stop Observing", False },
587 { "menuStep.Revert", False },
588 { "menuOptions.Auto Comment", False },
589 { "menuOptions.Auto Observe", False },
590 { "menuOptions.Auto Raise Board", False },
591 { "menuOptions.Get Move List", False },
592 { "menuOptions.Premove", False },
593 { "menuOptions.Quiet Play", False },
595 /* The next two options rely on SetCmailMode being called *after* */
596 /* SetGNUMode so that when GNU is being used to give hints these */
597 /* menu options are still available */
599 { "menuFile.Mail Move", False },
600 { "menuFile.Reload CMail Message", False },
604 Enables cmailEnables[] = {
606 { "menuAction.Call Flag", False },
607 { "menuAction.Draw", True },
608 { "menuAction.Adjourn", False },
609 { "menuAction.Abort", False },
610 { "menuAction.Stop Observing", False },
611 { "menuAction.Stop Examining", False },
612 { "menuFile.Mail Move", True },
613 { "menuFile.Reload CMail Message", True },
617 Enables trainingOnEnables[] = {
618 { "menuMode.Edit Comment", False },
619 { "menuMode.Pause", False },
620 { "menuStep.Forward", False },
621 { "menuStep.Backward", False },
622 { "menuStep.Forward to End", False },
623 { "menuStep.Back to Start", False },
624 { "menuStep.Move Now", False },
625 { "menuStep.Truncate Game", False },
629 Enables trainingOffEnables[] = {
630 { "menuMode.Edit Comment", True },
631 { "menuMode.Pause", True },
632 { "menuStep.Forward", True },
633 { "menuStep.Backward", True },
634 { "menuStep.Forward to End", True },
635 { "menuStep.Back to Start", True },
636 { "menuStep.Move Now", True },
637 { "menuStep.Truncate Game", True },
641 Enables machineThinkingEnables[] = {
642 { "menuFile.Load Game", False },
643 { "menuFile.Load Next Game", False },
644 { "menuFile.Load Previous Game", False },
645 { "menuFile.Reload Same Game", False },
646 { "menuFile.Paste Game", False },
647 { "menuFile.Load Position", False },
648 { "menuFile.Load Next Position", False },
649 { "menuFile.Load Previous Position", False },
650 { "menuFile.Reload Same Position", False },
651 { "menuFile.Paste Position", False },
652 { "menuMode.Machine White", False },
653 { "menuMode.Machine Black", False },
654 { "menuMode.Two Machines", False },
655 { "menuStep.Retract Move", False },
659 Enables userThinkingEnables[] = {
660 { "menuFile.Load Game", True },
661 { "menuFile.Load Next Game", True },
662 { "menuFile.Load Previous Game", True },
663 { "menuFile.Reload Same Game", True },
664 { "menuFile.Paste Game", True },
665 { "menuFile.Load Position", True },
666 { "menuFile.Load Next Position", True },
667 { "menuFile.Load Previous Position", True },
668 { "menuFile.Reload Same Position", True },
669 { "menuFile.Paste Position", True },
670 { "menuMode.Machine White", True },
671 { "menuMode.Machine Black", True },
672 { "menuMode.Two Machines", True },
673 { "menuStep.Retract Move", True },
679 MenuItem fileMenu[] = {
680 {N_("New Shuffle Game ..."), ShuffleMenuProc},
681 {N_("New Variant ..."), NewVariantProc}, // [HGM] variant: not functional yet
682 {"----", NothingProc},
683 {N_("Save Game"), SaveGameProc},
684 {"----", NothingProc},
685 {N_("Copy Game"), CopyGameProc},
686 {N_("Paste Game"), PasteGameProc},
687 {"----", NothingProc},
688 {N_("Load Position"), LoadPositionProc},
689 {N_("Load Next Position"), LoadNextPositionProc},
690 {N_("Load Previous Position"), LoadPrevPositionProc},
691 {N_("Reload Same Position"), ReloadPositionProc},
692 {N_("Save Position"), SavePositionProc},
693 {"----", NothingProc},
694 {N_("Copy Position"), CopyPositionProc},
695 {N_("Paste Position"), PastePositionProc},
696 {"----", NothingProc},
697 {N_("Mail Move"), MailMoveProc},
698 {N_("Reload CMail Message"), ReloadCmailMsgProc},
699 {"----", NothingProc},
703 MenuItem modeMenu[] = {
704 // {N_("Machine White"), MachineWhiteProc},
705 // {N_("Machine Black"), MachineBlackProc},
706 // {N_("Two Machines"), TwoMachinesProc},
707 {N_("Analysis Mode"), AnalyzeModeProc},
708 {N_("Analyze File"), AnalyzeFileProc },
709 {N_("ICS Client"), IcsClientProc},
710 {N_("Edit Game"), EditGameProc},
711 {N_("Edit Position"), EditPositionProc},
712 {N_("Training"), TrainingProc},
713 {"----", NothingProc},
714 {N_("Show Engine Output"), EngineOutputProc},
715 {N_("Show Evaluation Graph"), NothingProc}, // [HGM] evalgr: not functional yet
716 {N_("Show Game List"), ShowGameListProc},
717 {"Show Move History", HistoryShowProc}, // [HGM] hist: activate 4.2.7 code
718 {"----", NothingProc},
719 {N_("Edit Tags"), EditTagsProc},
720 {N_("Edit Comment"), EditCommentProc},
721 {N_("ICS Input Box"), IcsInputBoxProc},
725 MenuItem actionMenu[] = {
726 // {N_("Accept"), AcceptProc},
727 // {N_("Decline"), DeclineProc},
728 // {N_("Rematch"), RematchProc},
729 // {"----", NothingProc},
730 // {N_("Call Flag"), CallFlagProc},
731 // {N_("Draw"), DrawProc},
732 // {N_("Adjourn"), AdjournProc},
733 // {N_("Abort"), AbortProc},
734 // {N_("Resign"), ResignProc},
735 {"----", NothingProc},
736 {N_("Stop Observing"), StopObservingProc},
737 {N_("Stop Examining"), StopExaminingProc},
738 {"----", NothingProc},
739 {N_("Adjudicate to White"), AdjuWhiteProc},
740 {N_("Adjudicate to Black"), AdjuBlackProc},
741 {N_("Adjudicate Draw"), AdjuDrawProc},
745 MenuItem stepMenu[] = {
746 {N_("Backward"), BackwardProc},
747 {N_("Forward"), ForwardProc},
748 {N_("Back to Start"), ToStartProc},
749 {N_("Forward to End"), ToEndProc},
750 {N_("Revert"), RevertProc},
751 {N_("Truncate Game"), TruncateGameProc},
752 {"----", NothingProc},
753 // {N_("Move Now"), MoveNowProc},
754 {N_("Retract Move"), RetractMoveProc},
758 MenuItem optionsMenu[] = {
759 {N_("Flip View"), FlipViewProc},
760 {"----", NothingProc},
761 {N_("Adjudications ..."), EngineMenuProc},
762 {N_("General Settings ..."), UciMenuProc},
763 {N_("Engine #1 Settings ..."), FirstSettingsProc},
764 {N_("Engine #2 Settings ..."), SecondSettingsProc},
765 {N_("Time Control ..."), TimeControlProc},
766 {"----", NothingProc},
767 {N_("Always Queen"), AlwaysQueenProc},
768 {N_("Animate Dragging"), AnimateDraggingProc},
769 {N_("Animate Moving"), AnimateMovingProc},
770 {N_("Auto Comment"), AutocommProc},
771 {N_("Auto Flag"), AutoflagProc},
772 {N_("Auto Flip View"), AutoflipProc},
773 {N_("Auto Observe"), AutobsProc},
774 {N_("Auto Raise Board"), AutoraiseProc},
775 {N_("Auto Save"), AutosaveProc},
776 {N_("Blindfold"), BlindfoldProc},
777 {N_("Flash Moves"), FlashMovesProc},
778 {N_("Get Move List"), GetMoveListProc},
780 {N_("Highlight Dragging"), HighlightDraggingProc},
782 {N_("Highlight Last Move"), HighlightLastMoveProc},
783 {N_("Move Sound"), MoveSoundProc},
784 {N_("ICS Alarm"), IcsAlarmProc},
785 {N_("Old Save Style"), OldSaveStyleProc},
786 {N_("Periodic Updates"), PeriodicUpdatesProc},
787 {N_("Ponder Next Move"), PonderNextMoveProc},
788 {N_("Popup Exit Message"), PopupExitMessageProc},
789 {N_("Popup Move Errors"), PopupMoveErrorsProc},
790 {N_("Premove"), PremoveProc},
791 {N_("Quiet Play"), QuietPlayProc},
792 {N_("Hide Thinking"), HideThinkingProc},
793 {N_("Test Legality"), TestLegalityProc},
797 MenuItem helpMenu[] = {
798 {N_("Info XBoard"), InfoProc},
799 {N_("Man XBoard"), ManProc},
800 {"----", NothingProc},
801 {N_("Hint"), HintProc},
802 {N_("Book"), BookProc},
803 {"----", NothingProc},
808 {N_("File"), fileMenu},
809 {N_("Mode"), modeMenu},
810 {N_("Action"), actionMenu},
811 {N_("Step"), stepMenu},
812 {N_("Options"), optionsMenu},
813 {N_("Help"), helpMenu},
817 #define PAUSE_BUTTON N_("P")
818 MenuItem buttonBar[] = {
821 // {PAUSE_BUTTON, PauseProc},
827 #define PIECE_MENU_SIZE 18
828 String pieceMenuStrings[2][PIECE_MENU_SIZE] = {
829 { N_("White"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
830 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
831 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
832 N_("Empty square"), N_("Clear board") },
833 { N_("Black"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
834 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
835 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
836 N_("Empty square"), N_("Clear board") }
838 /* must be in same order as PieceMenuStrings! */
839 ChessSquare pieceMenuTranslation[2][PIECE_MENU_SIZE] = {
840 { WhitePlay, (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
841 WhiteRook, WhiteQueen, WhiteKing, (ChessSquare) 0, WhiteAlfil,
842 WhiteCannon, WhiteAngel, WhiteMarshall, (ChessSquare) 0,
843 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
844 { BlackPlay, (ChessSquare) 0, BlackPawn, BlackKnight, BlackBishop,
845 BlackRook, BlackQueen, BlackKing, (ChessSquare) 0, BlackAlfil,
846 BlackCannon, BlackAngel, BlackMarshall, (ChessSquare) 0,
847 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
850 #define DROP_MENU_SIZE 6
851 String dropMenuStrings[DROP_MENU_SIZE] = {
852 "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"), N_("Queen")
854 /* must be in same order as PieceMenuStrings! */
855 ChessSquare dropMenuTranslation[DROP_MENU_SIZE] = {
856 (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
857 WhiteRook, WhiteQueen
865 DropMenuEnables dmEnables[] = {
883 { XtNborderWidth, 0 },
884 { XtNdefaultDistance, 0 },
888 { XtNborderWidth, 0 },
889 { XtNresizable, (XtArgVal) True },
893 { XtNborderWidth, 0 },
899 { XtNjustify, (XtArgVal) XtJustifyRight },
900 { XtNlabel, (XtArgVal) "..." },
901 { XtNresizable, (XtArgVal) True },
902 { XtNresize, (XtArgVal) False }
905 Arg messageArgs[] = {
906 { XtNjustify, (XtArgVal) XtJustifyLeft },
907 { XtNlabel, (XtArgVal) "..." },
908 { XtNresizable, (XtArgVal) True },
909 { XtNresize, (XtArgVal) False }
913 { XtNborderWidth, 0 },
914 { XtNjustify, (XtArgVal) XtJustifyLeft }
917 XtResource clientResources[] = {
918 { "whitePieceColor", "whitePieceColor", XtRString, sizeof(String),
919 XtOffset(AppDataPtr, whitePieceColor), XtRString,
921 { "blackPieceColor", "blackPieceColor", XtRString, sizeof(String),
922 XtOffset(AppDataPtr, blackPieceColor), XtRString,
924 { "lightSquareColor", "lightSquareColor", XtRString,
925 sizeof(String), XtOffset(AppDataPtr, lightSquareColor),
926 XtRString, LIGHT_SQUARE_COLOR },
927 { "darkSquareColor", "darkSquareColor", XtRString, sizeof(String),
928 XtOffset(AppDataPtr, darkSquareColor), XtRString,
930 { "highlightSquareColor", "highlightSquareColor", XtRString,
931 sizeof(String), XtOffset(AppDataPtr, highlightSquareColor),
932 XtRString, HIGHLIGHT_SQUARE_COLOR },
933 { "premoveHighlightColor", "premoveHighlightColor", XtRString,
934 sizeof(String), XtOffset(AppDataPtr, premoveHighlightColor),
935 XtRString, PREMOVE_HIGHLIGHT_COLOR },
936 { "movesPerSession", "movesPerSession", XtRInt, sizeof(int),
937 XtOffset(AppDataPtr, movesPerSession), XtRImmediate,
938 (XtPointer) MOVES_PER_SESSION },
939 { "timeIncrement", "timeIncrement", XtRInt, sizeof(int),
940 XtOffset(AppDataPtr, timeIncrement), XtRImmediate,
941 (XtPointer) TIME_INCREMENT },
942 { "initString", "initString", XtRString, sizeof(String),
943 XtOffset(AppDataPtr, initString), XtRString, INIT_STRING },
944 { "secondInitString", "secondInitString", XtRString, sizeof(String),
945 XtOffset(AppDataPtr, secondInitString), XtRString, INIT_STRING },
946 { "firstComputerString", "firstComputerString", XtRString,
947 sizeof(String), XtOffset(AppDataPtr, firstComputerString), XtRString,
949 { "secondComputerString", "secondComputerString", XtRString,
950 sizeof(String), XtOffset(AppDataPtr, secondComputerString), XtRString,
952 { "firstChessProgram", "firstChessProgram", XtRString,
953 sizeof(String), XtOffset(AppDataPtr, firstChessProgram),
954 XtRString, FIRST_CHESS_PROGRAM },
955 { "secondChessProgram", "secondChessProgram", XtRString,
956 sizeof(String), XtOffset(AppDataPtr, secondChessProgram),
957 XtRString, SECOND_CHESS_PROGRAM },
958 { "firstPlaysBlack", "firstPlaysBlack", XtRBoolean,
959 sizeof(Boolean), XtOffset(AppDataPtr, firstPlaysBlack),
960 XtRImmediate, (XtPointer) False },
961 { "noChessProgram", "noChessProgram", XtRBoolean,
962 sizeof(Boolean), XtOffset(AppDataPtr, noChessProgram),
963 XtRImmediate, (XtPointer) False },
964 { "firstHost", "firstHost", XtRString, sizeof(String),
965 XtOffset(AppDataPtr, firstHost), XtRString, FIRST_HOST },
966 { "secondHost", "secondHost", XtRString, sizeof(String),
967 XtOffset(AppDataPtr, secondHost), XtRString, SECOND_HOST },
968 { "firstDirectory", "firstDirectory", XtRString, sizeof(String),
969 XtOffset(AppDataPtr, firstDirectory), XtRString, "." },
970 { "secondDirectory", "secondDirectory", XtRString, sizeof(String),
971 XtOffset(AppDataPtr, secondDirectory), XtRString, "." },
972 { "bitmapDirectory", "bitmapDirectory", XtRString,
973 sizeof(String), XtOffset(AppDataPtr, bitmapDirectory),
975 { "remoteShell", "remoteShell", XtRString, sizeof(String),
976 XtOffset(AppDataPtr, remoteShell), XtRString, REMOTE_SHELL },
977 { "remoteUser", "remoteUser", XtRString, sizeof(String),
978 XtOffset(AppDataPtr, remoteUser), XtRString, "" },
979 { "timeDelay", "timeDelay", XtRFloat, sizeof(float),
980 XtOffset(AppDataPtr, timeDelay), XtRString,
981 (XtPointer) TIME_DELAY_QUOTE },
982 { "timeControl", "timeControl", XtRString, sizeof(String),
983 XtOffset(AppDataPtr, timeControl), XtRString,
984 (XtPointer) TIME_CONTROL },
985 { "internetChessServerMode", "internetChessServerMode",
986 XtRBoolean, sizeof(Boolean),
987 XtOffset(AppDataPtr, icsActive), XtRImmediate,
989 { "internetChessServerHost", "internetChessServerHost",
990 XtRString, sizeof(String),
991 XtOffset(AppDataPtr, icsHost),
992 XtRString, (XtPointer) ICS_HOST },
993 { "internetChessServerPort", "internetChessServerPort",
994 XtRString, sizeof(String),
995 XtOffset(AppDataPtr, icsPort), XtRString,
996 (XtPointer) ICS_PORT },
997 { "internetChessServerCommPort", "internetChessServerCommPort",
998 XtRString, sizeof(String),
999 XtOffset(AppDataPtr, icsCommPort), XtRString,
1001 { "internetChessServerLogonScript", "internetChessServerLogonScript",
1002 XtRString, sizeof(String),
1003 XtOffset(AppDataPtr, icsLogon), XtRString,
1005 { "internetChessServerHelper", "internetChessServerHelper",
1006 XtRString, sizeof(String),
1007 XtOffset(AppDataPtr, icsHelper), XtRString, "" },
1008 { "internetChessServerInputBox", "internetChessServerInputBox",
1009 XtRBoolean, sizeof(Boolean),
1010 XtOffset(AppDataPtr, icsInputBox), XtRImmediate,
1011 (XtPointer) False },
1012 { "icsAlarm", "icsAlarm",
1013 XtRBoolean, sizeof(Boolean),
1014 XtOffset(AppDataPtr, icsAlarm), XtRImmediate,
1016 { "icsAlarmTime", "icsAlarmTime",
1017 XtRInt, sizeof(int),
1018 XtOffset(AppDataPtr, icsAlarmTime), XtRImmediate,
1020 { "useTelnet", "useTelnet", XtRBoolean, sizeof(Boolean),
1021 XtOffset(AppDataPtr, useTelnet), XtRImmediate,
1022 (XtPointer) False },
1023 { "telnetProgram", "telnetProgram", XtRString, sizeof(String),
1024 XtOffset(AppDataPtr, telnetProgram), XtRString, TELNET_PROGRAM },
1025 { "gateway", "gateway", XtRString, sizeof(String),
1026 XtOffset(AppDataPtr, gateway), XtRString, "" },
1027 { "loadGameFile", "loadGameFile", XtRString, sizeof(String),
1028 XtOffset(AppDataPtr, loadGameFile), XtRString, "" },
1029 { "loadGameIndex", "loadGameIndex",
1030 XtRInt, sizeof(int),
1031 XtOffset(AppDataPtr, loadGameIndex), XtRImmediate,
1033 { "saveGameFile", "saveGameFile", XtRString, sizeof(String),
1034 XtOffset(AppDataPtr, saveGameFile), XtRString, "" },
1035 { "autoRaiseBoard", "autoRaiseBoard", XtRBoolean,
1036 sizeof(Boolean), XtOffset(AppDataPtr, autoRaiseBoard),
1037 XtRImmediate, (XtPointer) True },
1038 { "autoSaveGames", "autoSaveGames", XtRBoolean,
1039 sizeof(Boolean), XtOffset(AppDataPtr, autoSaveGames),
1040 XtRImmediate, (XtPointer) False },
1041 { "blindfold", "blindfold", XtRBoolean,
1042 sizeof(Boolean), XtOffset(AppDataPtr, blindfold),
1043 XtRImmediate, (XtPointer) False },
1044 { "loadPositionFile", "loadPositionFile", XtRString,
1045 sizeof(String), XtOffset(AppDataPtr, loadPositionFile),
1047 { "loadPositionIndex", "loadPositionIndex",
1048 XtRInt, sizeof(int),
1049 XtOffset(AppDataPtr, loadPositionIndex), XtRImmediate,
1051 { "savePositionFile", "savePositionFile", XtRString,
1052 sizeof(String), XtOffset(AppDataPtr, savePositionFile),
1054 { "matchMode", "matchMode", XtRBoolean, sizeof(Boolean),
1055 XtOffset(AppDataPtr, matchMode), XtRImmediate, (XtPointer) False },
1056 { "matchGames", "matchGames", XtRInt, sizeof(int),
1057 XtOffset(AppDataPtr, matchGames), XtRImmediate,
1059 { "monoMode", "monoMode", XtRBoolean, sizeof(Boolean),
1060 XtOffset(AppDataPtr, monoMode), XtRImmediate,
1061 (XtPointer) False },
1062 { "debugMode", "debugMode", XtRBoolean, sizeof(Boolean),
1063 XtOffset(AppDataPtr, debugMode), XtRImmediate,
1064 (XtPointer) False },
1065 { "clockMode", "clockMode", XtRBoolean, sizeof(Boolean),
1066 XtOffset(AppDataPtr, clockMode), XtRImmediate,
1068 { "boardSize", "boardSize", XtRString, sizeof(String),
1069 XtOffset(AppDataPtr, boardSize), XtRString, "" },
1070 { "searchTime", "searchTime", XtRString, sizeof(String),
1071 XtOffset(AppDataPtr, searchTime), XtRString,
1073 { "searchDepth", "searchDepth", XtRInt, sizeof(int),
1074 XtOffset(AppDataPtr, searchDepth), XtRImmediate,
1076 { "showCoords", "showCoords", XtRBoolean, sizeof(Boolean),
1077 XtOffset(AppDataPtr, showCoords), XtRImmediate,
1078 (XtPointer) False },
1079 { "showJail", "showJail", XtRInt, sizeof(int),
1080 XtOffset(AppDataPtr, showJail), XtRImmediate,
1082 { "showThinking", "showThinking", XtRBoolean, sizeof(Boolean),
1083 XtOffset(AppDataPtr, showThinking), XtRImmediate,
1085 { "ponderNextMove", "ponderNextMove", XtRBoolean, sizeof(Boolean),
1086 XtOffset(AppDataPtr, ponderNextMove), XtRImmediate,
1088 { "periodicUpdates", "periodicUpdates", XtRBoolean, sizeof(Boolean),
1089 XtOffset(AppDataPtr, periodicUpdates), XtRImmediate,
1091 { "clockFont", "clockFont", XtRString, sizeof(String),
1092 XtOffset(AppDataPtr, clockFont), XtRString, CLOCK_FONT },
1093 { "coordFont", "coordFont", XtRString, sizeof(String),
1094 XtOffset(AppDataPtr, coordFont), XtRString, COORD_FONT },
1095 { "font", "font", XtRString, sizeof(String),
1096 XtOffset(AppDataPtr, font), XtRString, DEFAULT_FONT },
1097 { "ringBellAfterMoves", "ringBellAfterMoves",
1098 XtRBoolean, sizeof(Boolean),
1099 XtOffset(AppDataPtr, ringBellAfterMoves),
1100 XtRImmediate, (XtPointer) False },
1101 { "autoCallFlag", "autoCallFlag", XtRBoolean,
1102 sizeof(Boolean), XtOffset(AppDataPtr, autoCallFlag),
1103 XtRImmediate, (XtPointer) False },
1104 { "autoFlipView", "autoFlipView", XtRBoolean,
1105 sizeof(Boolean), XtOffset(AppDataPtr, autoFlipView),
1106 XtRImmediate, (XtPointer) True },
1107 { "autoObserve", "autoObserve", XtRBoolean,
1108 sizeof(Boolean), XtOffset(AppDataPtr, autoObserve),
1109 XtRImmediate, (XtPointer) False },
1110 { "autoComment", "autoComment", XtRBoolean,
1111 sizeof(Boolean), XtOffset(AppDataPtr, autoComment),
1112 XtRImmediate, (XtPointer) False },
1113 { "getMoveList", "getMoveList", XtRBoolean,
1114 sizeof(Boolean), XtOffset(AppDataPtr, getMoveList),
1115 XtRImmediate, (XtPointer) True },
1117 { "highlightDragging", "highlightDragging", XtRBoolean,
1118 sizeof(Boolean), XtOffset(AppDataPtr, highlightDragging),
1119 XtRImmediate, (XtPointer) False },
1121 { "highlightLastMove", "highlightLastMove", XtRBoolean,
1122 sizeof(Boolean), XtOffset(AppDataPtr, highlightLastMove),
1123 XtRImmediate, (XtPointer) False },
1124 { "premove", "premove", XtRBoolean,
1125 sizeof(Boolean), XtOffset(AppDataPtr, premove),
1126 XtRImmediate, (XtPointer) True },
1127 { "testLegality", "testLegality", XtRBoolean,
1128 sizeof(Boolean), XtOffset(AppDataPtr, testLegality),
1129 XtRImmediate, (XtPointer) True },
1130 { "flipView", "flipView", XtRBoolean,
1131 sizeof(Boolean), XtOffset(AppDataPtr, flipView),
1132 XtRImmediate, (XtPointer) False },
1133 { "cmail", "cmailGameName", XtRString, sizeof(String),
1134 XtOffset(AppDataPtr, cmailGameName), XtRString, "" },
1135 { "alwaysPromoteToQueen", "alwaysPromoteToQueen", XtRBoolean,
1136 sizeof(Boolean), XtOffset(AppDataPtr, alwaysPromoteToQueen),
1137 XtRImmediate, (XtPointer) False },
1138 { "oldSaveStyle", "oldSaveStyle", XtRBoolean,
1139 sizeof(Boolean), XtOffset(AppDataPtr, oldSaveStyle),
1140 XtRImmediate, (XtPointer) False },
1141 { "quietPlay", "quietPlay", XtRBoolean,
1142 sizeof(Boolean), XtOffset(AppDataPtr, quietPlay),
1143 XtRImmediate, (XtPointer) False },
1144 { "titleInWindow", "titleInWindow", XtRBoolean,
1145 sizeof(Boolean), XtOffset(AppDataPtr, titleInWindow),
1146 XtRImmediate, (XtPointer) False },
1147 { "localLineEditing", "localLineEditing", XtRBoolean,
1148 sizeof(Boolean), XtOffset(AppDataPtr, localLineEditing),
1149 XtRImmediate, (XtPointer) True }, /* not implemented, must be True */
1151 { "zippyTalk", "zippyTalk", XtRBoolean,
1152 sizeof(Boolean), XtOffset(AppDataPtr, zippyTalk),
1153 XtRImmediate, (XtPointer) ZIPPY_TALK },
1154 { "zippyPlay", "zippyPlay", XtRBoolean,
1155 sizeof(Boolean), XtOffset(AppDataPtr, zippyPlay),
1156 XtRImmediate, (XtPointer) ZIPPY_PLAY },
1157 { "zippyLines", "zippyLines", XtRString, sizeof(String),
1158 XtOffset(AppDataPtr, zippyLines), XtRString, ZIPPY_LINES },
1159 { "zippyPinhead", "zippyPinhead", XtRString, sizeof(String),
1160 XtOffset(AppDataPtr, zippyPinhead), XtRString, ZIPPY_PINHEAD },
1161 { "zippyPassword", "zippyPassword", XtRString, sizeof(String),
1162 XtOffset(AppDataPtr, zippyPassword), XtRString, ZIPPY_PASSWORD },
1163 { "zippyPassword2", "zippyPassword2", XtRString, sizeof(String),
1164 XtOffset(AppDataPtr, zippyPassword2), XtRString, ZIPPY_PASSWORD2 },
1165 { "zippyWrongPassword", "zippyWrongPassword", XtRString, sizeof(String),
1166 XtOffset(AppDataPtr, zippyWrongPassword), XtRString,
1167 ZIPPY_WRONG_PASSWORD },
1168 { "zippyAcceptOnly", "zippyAcceptOnly", XtRString, sizeof(String),
1169 XtOffset(AppDataPtr, zippyAcceptOnly), XtRString, ZIPPY_ACCEPT_ONLY },
1170 { "zippyUseI", "zippyUseI", XtRBoolean,
1171 sizeof(Boolean), XtOffset(AppDataPtr, zippyUseI),
1172 XtRImmediate, (XtPointer) ZIPPY_USE_I },
1173 { "zippyBughouse", "zippyBughouse", XtRInt,
1174 sizeof(int), XtOffset(AppDataPtr, zippyBughouse),
1175 XtRImmediate, (XtPointer) ZIPPY_BUGHOUSE },
1176 { "zippyNoplayCrafty", "zippyNoplayCrafty", XtRBoolean,
1177 sizeof(Boolean), XtOffset(AppDataPtr, zippyNoplayCrafty),
1178 XtRImmediate, (XtPointer) ZIPPY_NOPLAY_CRAFTY },
1179 { "zippyGameEnd", "zippyGameEnd", XtRString, sizeof(String),
1180 XtOffset(AppDataPtr, zippyGameEnd), XtRString, ZIPPY_GAME_END },
1181 { "zippyGameStart", "zippyGameStart", XtRString, sizeof(String),
1182 XtOffset(AppDataPtr, zippyGameStart), XtRString, ZIPPY_GAME_START },
1183 { "zippyAdjourn", "zippyAdjourn", XtRBoolean,
1184 sizeof(Boolean), XtOffset(AppDataPtr, zippyAdjourn),
1185 XtRImmediate, (XtPointer) ZIPPY_ADJOURN },
1186 { "zippyAbort", "zippyAbort", XtRBoolean,
1187 sizeof(Boolean), XtOffset(AppDataPtr, zippyAbort),
1188 XtRImmediate, (XtPointer) ZIPPY_ABORT },
1189 { "zippyVariants", "zippyVariants", XtRString, sizeof(String),
1190 XtOffset(AppDataPtr, zippyVariants), XtRString, ZIPPY_VARIANTS },
1191 { "zippyMaxGames", "zippyMaxGames", XtRInt, sizeof(int),
1192 XtOffset(AppDataPtr, zippyMaxGames), XtRImmediate,
1193 (XtPointer) ZIPPY_MAX_GAMES },
1194 { "zippyReplayTimeout", "zippyReplayTimeout", XtRInt, sizeof(int),
1195 XtOffset(AppDataPtr, zippyReplayTimeout), XtRImmediate,
1196 (XtPointer) ZIPPY_REPLAY_TIMEOUT },
1197 { "zippyShortGame", "zippyShortGame", XtRInt, sizeof(int),
1198 XtOffset(AppDataPtr, zippyShortGame), XtRImmediate,
1201 { "flashCount", "flashCount", XtRInt, sizeof(int),
1202 XtOffset(AppDataPtr, flashCount), XtRImmediate,
1203 (XtPointer) FLASH_COUNT },
1204 { "flashRate", "flashRate", XtRInt, sizeof(int),
1205 XtOffset(AppDataPtr, flashRate), XtRImmediate,
1206 (XtPointer) FLASH_RATE },
1207 { "pixmapDirectory", "pixmapDirectory", XtRString,
1208 sizeof(String), XtOffset(AppDataPtr, pixmapDirectory),
1210 { "msLoginDelay", "msLoginDelay", XtRInt, sizeof(int),
1211 XtOffset(AppDataPtr, msLoginDelay), XtRImmediate,
1212 (XtPointer) MS_LOGIN_DELAY },
1213 { "colorizeMessages", "colorizeMessages", XtRBoolean,
1214 sizeof(Boolean), XtOffset(AppDataPtr, colorize),
1215 XtRImmediate, (XtPointer) False },
1216 { "colorShout", "colorShout", XtRString,
1217 sizeof(String), XtOffset(AppDataPtr, colorShout),
1218 XtRString, COLOR_SHOUT },
1219 { "colorSShout", "colorSShout", XtRString,
1220 sizeof(String), XtOffset(AppDataPtr, colorSShout),
1221 XtRString, COLOR_SSHOUT },
1222 { "colorChannel1", "colorChannel1", XtRString,
1223 sizeof(String), XtOffset(AppDataPtr, colorChannel1),
1224 XtRString, COLOR_CHANNEL1 },
1225 { "colorChannel", "colorChannel", XtRString,
1226 sizeof(String), XtOffset(AppDataPtr, colorChannel),
1227 XtRString, COLOR_CHANNEL },
1228 { "colorKibitz", "colorKibitz", XtRString,
1229 sizeof(String), XtOffset(AppDataPtr, colorKibitz),
1230 XtRString, COLOR_KIBITZ },
1231 { "colorTell", "colorTell", XtRString,
1232 sizeof(String), XtOffset(AppDataPtr, colorTell),
1233 XtRString, COLOR_TELL },
1234 { "colorChallenge", "colorChallenge", XtRString,
1235 sizeof(String), XtOffset(AppDataPtr, colorChallenge),
1236 XtRString, COLOR_CHALLENGE },
1237 { "colorRequest", "colorRequest", XtRString,
1238 sizeof(String), XtOffset(AppDataPtr, colorRequest),
1239 XtRString, COLOR_REQUEST },
1240 { "colorSeek", "colorSeek", XtRString,
1241 sizeof(String), XtOffset(AppDataPtr, colorSeek),
1242 XtRString, COLOR_SEEK },
1243 { "colorNormal", "colorNormal", XtRString,
1244 sizeof(String), XtOffset(AppDataPtr, colorNormal),
1245 XtRString, COLOR_NORMAL },
1246 { "soundProgram", "soundProgram", XtRString,
1247 sizeof(String), XtOffset(AppDataPtr, soundProgram),
1248 XtRString, "play" },
1249 { "soundShout", "soundShout", XtRString,
1250 sizeof(String), XtOffset(AppDataPtr, soundShout),
1252 { "soundSShout", "soundSShout", XtRString,
1253 sizeof(String), XtOffset(AppDataPtr, soundSShout),
1255 { "soundChannel1", "soundChannel1", XtRString,
1256 sizeof(String), XtOffset(AppDataPtr, soundChannel1),
1258 { "soundChannel", "soundChannel", XtRString,
1259 sizeof(String), XtOffset(AppDataPtr, soundChannel),
1261 { "soundKibitz", "soundKibitz", XtRString,
1262 sizeof(String), XtOffset(AppDataPtr, soundKibitz),
1264 { "soundTell", "soundTell", XtRString,
1265 sizeof(String), XtOffset(AppDataPtr, soundTell),
1267 { "soundChallenge", "soundChallenge", XtRString,
1268 sizeof(String), XtOffset(AppDataPtr, soundChallenge),
1270 { "soundRequest", "soundRequest", XtRString,
1271 sizeof(String), XtOffset(AppDataPtr, soundRequest),
1273 { "soundSeek", "soundSeek", XtRString,
1274 sizeof(String), XtOffset(AppDataPtr, soundSeek),
1276 { "soundMove", "soundMove", XtRString,
1277 sizeof(String), XtOffset(AppDataPtr, soundMove),
1279 { "soundIcsWin", "soundIcsWin", XtRString,
1280 sizeof(String), XtOffset(AppDataPtr, soundIcsWin),
1282 { "soundIcsLoss", "soundIcsLoss", XtRString,
1283 sizeof(String), XtOffset(AppDataPtr, soundIcsLoss),
1285 { "soundIcsDraw", "soundIcsDraw", XtRString,
1286 sizeof(String), XtOffset(AppDataPtr, soundIcsDraw),
1288 { "soundIcsUnfinished", "soundIcsUnfinished", XtRString,
1289 sizeof(String), XtOffset(AppDataPtr, soundIcsUnfinished),
1291 { "soundIcsAlarm", "soundIcsAlarm", XtRString,
1292 sizeof(String), XtOffset(AppDataPtr, soundIcsAlarm),
1294 { "reuseFirst", "reuseFirst", XtRBoolean,
1295 sizeof(Boolean), XtOffset(AppDataPtr, reuseFirst),
1296 XtRImmediate, (XtPointer) True },
1297 { "reuseSecond", "reuseSecond", XtRBoolean,
1298 sizeof(Boolean), XtOffset(AppDataPtr, reuseSecond),
1299 XtRImmediate, (XtPointer) True },
1300 { "animateDragging", "animateDragging", XtRBoolean,
1301 sizeof(Boolean), XtOffset(AppDataPtr, animateDragging),
1302 XtRImmediate, (XtPointer) True },
1303 { "animateMoving", "animateMoving", XtRBoolean,
1304 sizeof(Boolean), XtOffset(AppDataPtr, animate),
1305 XtRImmediate, (XtPointer) True },
1306 { "animateSpeed", "animateSpeed", XtRInt,
1307 sizeof(int), XtOffset(AppDataPtr, animSpeed),
1308 XtRImmediate, (XtPointer)10 },
1309 { "popupExitMessage", "popupExitMessage", XtRBoolean,
1310 sizeof(Boolean), XtOffset(AppDataPtr, popupExitMessage),
1311 XtRImmediate, (XtPointer) True },
1312 { "popupMoveErrors", "popupMoveErrors", XtRBoolean,
1313 sizeof(Boolean), XtOffset(AppDataPtr, popupMoveErrors),
1314 XtRImmediate, (XtPointer) False },
1315 { "fontSizeTolerance", "fontSizeTolerance", XtRInt,
1316 sizeof(int), XtOffset(AppDataPtr, fontSizeTolerance),
1317 XtRImmediate, (XtPointer)4 },
1318 { "initialMode", "initialMode", XtRString,
1319 sizeof(String), XtOffset(AppDataPtr, initialMode),
1320 XtRImmediate, (XtPointer) "" },
1321 { "variant", "variant", XtRString,
1322 sizeof(String), XtOffset(AppDataPtr, variant),
1323 XtRImmediate, (XtPointer) "normal" },
1324 { "firstProtocolVersion", "firstProtocolVersion", XtRInt,
1325 sizeof(int), XtOffset(AppDataPtr, firstProtocolVersion),
1326 XtRImmediate, (XtPointer)PROTOVER },
1327 { "secondProtocolVersion", "secondProtocolVersion", XtRInt,
1328 sizeof(int), XtOffset(AppDataPtr, secondProtocolVersion),
1329 XtRImmediate, (XtPointer)PROTOVER },
1330 { "showButtonBar", "showButtonBar", XtRBoolean,
1331 sizeof(Boolean), XtOffset(AppDataPtr, showButtonBar),
1332 XtRImmediate, (XtPointer) True },
1333 { "lowTimeWarningColor", "lowTimeWarningColor", XtRString,
1334 sizeof(String), XtOffset(AppDataPtr, lowTimeWarningColor),
1335 XtRString, COLOR_LOWTIMEWARNING },
1336 { "lowTimeWarning", "lowTimeWarning", XtRBoolean,
1337 sizeof(Boolean), XtOffset(AppDataPtr, lowTimeWarning),
1338 XtRImmediate, (XtPointer) False },
1339 {"icsEngineAnalyze", "icsEngineAnalyze", XtRBoolean, /* [DM] icsEngineAnalyze */
1340 sizeof(Boolean), XtOffset(AppDataPtr, icsEngineAnalyze),
1341 XtRImmediate, (XtPointer) False },
1342 { "firstScoreAbs", "firstScoreAbs", XtRBoolean,
1343 sizeof(Boolean), XtOffset(AppDataPtr, firstScoreIsAbsolute),
1344 XtRImmediate, (XtPointer) False },
1345 { "secondScoreAbs", "secondScoreAbs", XtRBoolean,
1346 sizeof(Boolean), XtOffset(AppDataPtr, secondScoreIsAbsolute),
1347 XtRImmediate, (XtPointer) False },
1348 { "pgnExtendedInfo", "pgnExtendedInfo", XtRBoolean,
1349 sizeof(Boolean), XtOffset(AppDataPtr, saveExtendedInfoInPGN),
1350 XtRImmediate, (XtPointer) False },
1351 { "hideThinkingFromHuman", "hideThinkingFromHuman", XtRBoolean,
1352 sizeof(Boolean), XtOffset(AppDataPtr, hideThinkingFromHuman),
1353 XtRImmediate, (XtPointer) True },
1354 { "adjudicateLossThreshold", "adjudicateLossThreshold", XtRInt,
1355 sizeof(int), XtOffset(AppDataPtr, adjudicateLossThreshold),
1356 XtRImmediate, (XtPointer) 0},
1357 { "pgnEventHeader", "pgnEventHeader", XtRString,
1358 sizeof(String), XtOffset(AppDataPtr, pgnEventHeader),
1359 XtRImmediate, (XtPointer) "Computer Chess Game" },
1360 { "defaultFrcPosition", "defaultFrcPositon", XtRInt,
1361 sizeof(int), XtOffset(AppDataPtr, defaultFrcPosition),
1362 XtRImmediate, (XtPointer) -1},
1363 { "gameListTags", "gameListTags", XtRString,
1364 sizeof(String), XtOffset(AppDataPtr, gameListTags),
1365 XtRImmediate, (XtPointer) GLT_DEFAULT_TAGS },
1367 // [HGM] 4.3.xx options
1368 { "boardWidth", "boardWidth", XtRInt,
1369 sizeof(int), XtOffset(AppDataPtr, NrFiles),
1370 XtRImmediate, (XtPointer) -1},
1371 { "boardHeight", "boardHeight", XtRInt,
1372 sizeof(int), XtOffset(AppDataPtr, NrRanks),
1373 XtRImmediate, (XtPointer) -1},
1374 { "matchPause", "matchPause", XtRInt,
1375 sizeof(int), XtOffset(AppDataPtr, matchPause),
1376 XtRImmediate, (XtPointer) 10000},
1377 { "holdingsSize", "holdingsSize", XtRInt,
1378 sizeof(int), XtOffset(AppDataPtr, holdingsSize),
1379 XtRImmediate, (XtPointer) -1},
1380 { "flipBlack", "flipBlack", XtRBoolean,
1381 sizeof(Boolean), XtOffset(AppDataPtr, upsideDown),
1382 XtRImmediate, (XtPointer) False},
1383 { "allWhite", "allWhite", XtRBoolean,
1384 sizeof(Boolean), XtOffset(AppDataPtr, allWhite),
1385 XtRImmediate, (XtPointer) False},
1386 { "pieceToCharTable", "pieceToCharTable", XtRString,
1387 sizeof(String), XtOffset(AppDataPtr, pieceToCharTable),
1388 XtRImmediate, (XtPointer) 0},
1389 { "alphaRank", "alphaRank", XtRBoolean,
1390 sizeof(Boolean), XtOffset(AppDataPtr, alphaRank),
1391 XtRImmediate, (XtPointer) False},
1392 { "testClaims", "testClaims", XtRBoolean,
1393 sizeof(Boolean), XtOffset(AppDataPtr, testClaims),
1394 XtRImmediate, (XtPointer) True},
1395 { "checkMates", "checkMates", XtRBoolean,
1396 sizeof(Boolean), XtOffset(AppDataPtr, checkMates),
1397 XtRImmediate, (XtPointer) True},
1398 { "materialDraws", "materialDraws", XtRBoolean,
1399 sizeof(Boolean), XtOffset(AppDataPtr, materialDraws),
1400 XtRImmediate, (XtPointer) True},
1401 { "trivialDraws", "trivialDraws", XtRBoolean,
1402 sizeof(Boolean), XtOffset(AppDataPtr, trivialDraws),
1403 XtRImmediate, (XtPointer) False},
1404 { "ruleMoves", "ruleMoves", XtRInt,
1405 sizeof(int), XtOffset(AppDataPtr, ruleMoves),
1406 XtRImmediate, (XtPointer) 51},
1407 { "repeatsToDraw", "repeatsToDraw", XtRInt,
1408 sizeof(int), XtOffset(AppDataPtr, drawRepeats),
1409 XtRImmediate, (XtPointer) 6},
1410 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1411 sizeof(int), XtOffset(AppDataPtr, engineComments),
1412 XtRImmediate, (XtPointer) 1},
1413 { "userName", "userName", XtRString,
1414 sizeof(int), XtOffset(AppDataPtr, userName),
1415 XtRImmediate, (XtPointer) 0},
1416 { "autoKibitz", "autoKibitz", XtRBoolean,
1417 sizeof(Boolean), XtOffset(AppDataPtr, autoKibitz),
1418 XtRImmediate, (XtPointer) False},
1419 { "firstTimeOdds", "firstTimeOdds", XtRInt,
1420 sizeof(int), XtOffset(AppDataPtr, firstTimeOdds),
1421 XtRImmediate, (XtPointer) 1},
1422 { "secondTimeOdds", "secondTimeOdds", XtRInt,
1423 sizeof(int), XtOffset(AppDataPtr, secondTimeOdds),
1424 XtRImmediate, (XtPointer) 1},
1425 { "timeOddsMode", "timeOddsMode", XtRInt,
1426 sizeof(int), XtOffset(AppDataPtr, timeOddsMode),
1427 XtRImmediate, (XtPointer) 0},
1428 { "firstAccumulateTC", "firstAccumulateTC", XtRInt,
1429 sizeof(int), XtOffset(AppDataPtr, firstAccumulateTC),
1430 XtRImmediate, (XtPointer) 1},
1431 { "secondAccumulateTC", "secondAccumulateTC", XtRInt,
1432 sizeof(int), XtOffset(AppDataPtr, secondAccumulateTC),
1433 XtRImmediate, (XtPointer) 1},
1434 { "firstNPS", "firstNPS", XtRInt,
1435 sizeof(int), XtOffset(AppDataPtr, firstNPS),
1436 XtRImmediate, (XtPointer) -1},
1437 { "secondNPS", "secondNPS", XtRInt,
1438 sizeof(int), XtOffset(AppDataPtr, secondNPS),
1439 XtRImmediate, (XtPointer) -1},
1440 { "serverMoves", "serverMoves", XtRString,
1441 sizeof(String), XtOffset(AppDataPtr, serverMovesName),
1442 XtRImmediate, (XtPointer) 0},
1443 { "serverPause", "serverPause", XtRInt,
1444 sizeof(int), XtOffset(AppDataPtr, serverPause),
1445 XtRImmediate, (XtPointer) 0},
1446 { "suppressLoadMoves", "suppressLoadMoves", XtRBoolean,
1447 sizeof(Boolean), XtOffset(AppDataPtr, suppressLoadMoves),
1448 XtRImmediate, (XtPointer) False},
1449 { "userName", "userName", XtRString,
1450 sizeof(String), XtOffset(AppDataPtr, userName),
1451 XtRImmediate, (XtPointer) 0},
1452 { "egtFormats", "egtFormats", XtRString,
1453 sizeof(String), XtOffset(AppDataPtr, egtFormats),
1454 XtRImmediate, (XtPointer) 0},
1455 { "rewindIndex", "rewindIndex", XtRInt,
1456 sizeof(int), XtOffset(AppDataPtr, rewindIndex),
1457 XtRImmediate, (XtPointer) 0},
1458 { "sameColorGames", "sameColorGames", XtRInt,
1459 sizeof(int), XtOffset(AppDataPtr, sameColorGames),
1460 XtRImmediate, (XtPointer) 0},
1461 { "smpCores", "smpCores", XtRInt,
1462 sizeof(int), XtOffset(AppDataPtr, smpCores),
1463 XtRImmediate, (XtPointer) 1},
1464 { "niceEngines", "niceEngines", XtRInt,
1465 sizeof(int), XtOffset(AppDataPtr, niceEngines),
1466 XtRImmediate, (XtPointer) 0},
1467 { "nameOfDebugFile", "nameOfDebugFile", XtRString,
1468 sizeof(String), XtOffset(AppDataPtr, nameOfDebugFile),
1469 XtRImmediate, (XtPointer) "xboard.debug"},
1470 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1471 sizeof(int), XtOffset(AppDataPtr, engineComments),
1472 XtRImmediate, (XtPointer) 0},
1473 { "noGUI", "noGUI", XtRBoolean,
1474 sizeof(Boolean), XtOffset(AppDataPtr, noGUI),
1475 XtRImmediate, (XtPointer) 0},
1476 { "firstOptions", "firstOptions", XtRString,
1477 sizeof(String), XtOffset(AppDataPtr, firstOptions),
1478 XtRImmediate, (XtPointer) "" },
1479 { "secondOptions", "secondOptions", XtRString,
1480 sizeof(String), XtOffset(AppDataPtr, secondOptions),
1481 XtRImmediate, (XtPointer) "" },
1482 { "firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XtRString,
1483 sizeof(String), XtOffset(AppDataPtr, fenOverride1),
1484 XtRImmediate, (XtPointer) 0 },
1485 { "secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XtRString,
1486 sizeof(String), XtOffset(AppDataPtr, fenOverride2),
1487 XtRImmediate, (XtPointer) 0 },
1489 // [HGM] Winboard_x UCI options
1490 { "firstIsUCI", "firstIsUCI", XtRBoolean,
1491 sizeof(Boolean), XtOffset(AppDataPtr, firstIsUCI),
1492 XtRImmediate, (XtPointer) False},
1493 { "secondIsUCI", "secondIsUCI", XtRBoolean,
1494 sizeof(Boolean), XtOffset(AppDataPtr, secondIsUCI),
1495 XtRImmediate, (XtPointer) False},
1496 { "firstHasOwnBookUCI", "firstHasOwnBookUCI", XtRBoolean,
1497 sizeof(Boolean), XtOffset(AppDataPtr, firstHasOwnBookUCI),
1498 XtRImmediate, (XtPointer) True},
1499 { "secondHasOwnBookUCI", "secondHasOwnBookUCI", XtRBoolean,
1500 sizeof(Boolean), XtOffset(AppDataPtr, secondHasOwnBookUCI),
1501 XtRImmediate, (XtPointer) True},
1502 { "usePolyglotBook", "usePolyglotBook", XtRBoolean,
1503 sizeof(Boolean), XtOffset(AppDataPtr, usePolyglotBook),
1504 XtRImmediate, (XtPointer) False},
1505 { "defaultHashSize", "defaultHashSize", XtRInt,
1506 sizeof(int), XtOffset(AppDataPtr, defaultHashSize),
1507 XtRImmediate, (XtPointer) 64},
1508 { "defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XtRInt,
1509 sizeof(int), XtOffset(AppDataPtr, defaultCacheSizeEGTB),
1510 XtRImmediate, (XtPointer) 4},
1511 { "polyglotDir", "polyglotDir", XtRString,
1512 sizeof(String), XtOffset(AppDataPtr, polyglotDir),
1513 XtRImmediate, (XtPointer) "." },
1514 { "polyglotBook", "polyglotBook", XtRString,
1515 sizeof(String), XtOffset(AppDataPtr, polyglotBook),
1516 XtRImmediate, (XtPointer) "" },
1517 { "defaultPathEGTB", "defaultPathEGTB", XtRString,
1518 sizeof(String), XtOffset(AppDataPtr, defaultPathEGTB),
1519 XtRImmediate, (XtPointer) "/usr/local/share/egtb"},
1520 { "delayBeforeQuit", "delayBeforeQuit", XtRInt,
1521 sizeof(int), XtOffset(AppDataPtr, delayBeforeQuit),
1522 XtRImmediate, (XtPointer) 0},
1523 { "delayAfterQuit", "delayAfterQuit", XtRInt,
1524 sizeof(int), XtOffset(AppDataPtr, delayAfterQuit),
1525 XtRImmediate, (XtPointer) 0},
1528 XrmOptionDescRec shellOptions[] = {
1529 { "-whitePieceColor", "whitePieceColor", XrmoptionSepArg, NULL },
1530 { "-blackPieceColor", "blackPieceColor", XrmoptionSepArg, NULL },
1531 { "-lightSquareColor", "lightSquareColor", XrmoptionSepArg, NULL },
1532 { "-darkSquareColor", "darkSquareColor", XrmoptionSepArg, NULL },
1533 { "-highlightSquareColor", "highlightSquareColor", XrmoptionSepArg, NULL },
1534 { "-premoveHighlightColor", "premoveHighlightColor", XrmoptionSepArg,NULL},
1535 { "-movesPerSession", "movesPerSession", XrmoptionSepArg, NULL },
1536 { "-mps", "movesPerSession", XrmoptionSepArg, NULL },
1537 { "-timeIncrement", "timeIncrement", XrmoptionSepArg, NULL },
1538 { "-inc", "timeIncrement", XrmoptionSepArg, NULL },
1539 { "-initString", "initString", XrmoptionSepArg, NULL },
1540 { "-firstInitString", "initString", XrmoptionSepArg, NULL },
1541 { "-secondInitString", "secondInitString", XrmoptionSepArg, NULL },
1542 { "-firstComputerString", "firstComputerString", XrmoptionSepArg, NULL },
1543 { "-secondComputerString", "secondComputerString", XrmoptionSepArg, NULL },
1544 { "-firstChessProgram", "firstChessProgram", XrmoptionSepArg, NULL },
1545 { "-fcp", "firstChessProgram", XrmoptionSepArg, NULL },
1546 { "-secondChessProgram", "secondChessProgram", XrmoptionSepArg, NULL },
1547 { "-scp", "secondChessProgram", XrmoptionSepArg, NULL },
1548 { "-firstPlaysBlack", "firstPlaysBlack", XrmoptionSepArg, NULL },
1549 { "-fb", "firstPlaysBlack", XrmoptionNoArg, "True" },
1550 { "-xfb", "firstPlaysBlack", XrmoptionNoArg, "False" },
1551 { "-noChessProgram", "noChessProgram", XrmoptionSepArg, NULL },
1552 { "-ncp", "noChessProgram", XrmoptionNoArg, "True" },
1553 { "-xncp", "noChessProgram", XrmoptionNoArg, "False" },
1554 { "-firstHost", "firstHost", XrmoptionSepArg, NULL },
1555 { "-fh", "firstHost", XrmoptionSepArg, NULL },
1556 { "-secondHost", "secondHost", XrmoptionSepArg, NULL },
1557 { "-sh", "secondHost", XrmoptionSepArg, NULL },
1558 { "-firstDirectory", "firstDirectory", XrmoptionSepArg, NULL },
1559 { "-fd", "firstDirectory", XrmoptionSepArg, NULL },
1560 { "-secondDirectory", "secondDirectory", XrmoptionSepArg, NULL },
1561 { "-sd", "secondDirectory", XrmoptionSepArg, NULL },
1562 { "-bitmapDirectory", "bitmapDirectory", XrmoptionSepArg, NULL },
1563 { "-bm", "bitmapDirectory", XrmoptionSepArg, NULL },
1564 { "-remoteShell", "remoteShell", XrmoptionSepArg, NULL },
1565 { "-rsh", "remoteShell", XrmoptionSepArg, NULL },
1566 { "-remoteUser", "remoteUser", XrmoptionSepArg, NULL },
1567 { "-ruser", "remoteUser", XrmoptionSepArg, NULL },
1568 { "-timeDelay", "timeDelay", XrmoptionSepArg, NULL },
1569 { "-td", "timeDelay", XrmoptionSepArg, NULL },
1570 { "-timeControl", "timeControl", XrmoptionSepArg, NULL },
1571 { "-tc", "timeControl", XrmoptionSepArg, NULL },
1572 { "-internetChessServerMode", "internetChessServerMode",
1573 XrmoptionSepArg, NULL },
1574 { "-ics", "internetChessServerMode", XrmoptionNoArg, "True" },
1575 { "-xics", "internetChessServerMode", XrmoptionNoArg, "False" },
1576 { "-internetChessServerHost", "internetChessServerHost",
1577 XrmoptionSepArg, NULL },
1578 { "-icshost", "internetChessServerHost", XrmoptionSepArg, NULL },
1579 { "-internetChessServerPort", "internetChessServerPort",
1580 XrmoptionSepArg, NULL },
1581 { "-icsport", "internetChessServerPort", XrmoptionSepArg, NULL },
1582 { "-internetChessServerCommPort", "internetChessServerCommPort",
1583 XrmoptionSepArg, NULL },
1584 { "-icscomm", "internetChessServerCommPort", XrmoptionSepArg, NULL },
1585 { "-internetChessServerLogonScript", "internetChessServerLogonScript",
1586 XrmoptionSepArg, NULL },
1587 { "-icslogon", "internetChessServerLogonScript", XrmoptionSepArg, NULL },
1588 { "-internetChessServerHelper", "internetChessServerHelper",
1589 XrmoptionSepArg, NULL },
1590 { "-icshelper", "internetChessServerHelper", XrmoptionSepArg, NULL },
1591 { "-internetChessServerInputBox", "internetChessServerInputBox",
1592 XrmoptionSepArg, NULL },
1593 { "-icsinput", "internetChessServerInputBox", XrmoptionNoArg, "True" },
1594 { "-xicsinput", "internetChessServerInputBox", XrmoptionNoArg, "False" },
1595 { "-icsAlarm", "icsAlarm", XrmoptionSepArg, NULL },
1596 { "-alarm", "icsAlarm", XrmoptionNoArg, "True" },
1597 { "-xalarm", "icsAlarm", XrmoptionNoArg, "False" },
1598 { "-icsAlarmTime", "icsAlarmTime", XrmoptionSepArg, NULL },
1599 { "-useTelnet", "useTelnet", XrmoptionSepArg, NULL },
1600 { "-telnet", "useTelnet", XrmoptionNoArg, "True" },
1601 { "-xtelnet", "useTelnet", XrmoptionNoArg, "False" },
1602 { "-telnetProgram", "telnetProgram", XrmoptionSepArg, NULL },
1603 { "-gateway", "gateway", XrmoptionSepArg, NULL },
1604 { "-loadGameFile", "loadGameFile", XrmoptionSepArg, NULL },
1605 { "-lgf", "loadGameFile", XrmoptionSepArg, NULL },
1606 { "-loadGameIndex", "loadGameIndex", XrmoptionSepArg, NULL },
1607 { "-lgi", "loadGameIndex", XrmoptionSepArg, NULL },
1608 { "-saveGameFile", "saveGameFile", XrmoptionSepArg, NULL },
1609 { "-sgf", "saveGameFile", XrmoptionSepArg, NULL },
1610 { "-autoSaveGames", "autoSaveGames", XrmoptionSepArg, NULL },
1611 { "-autosave", "autoSaveGames", XrmoptionNoArg, "True" },
1612 { "-xautosave", "autoSaveGames", XrmoptionNoArg, "False" },
1613 { "-autoRaiseBoard", "autoRaiseBoard", XrmoptionSepArg, NULL },
1614 { "-autoraise", "autoRaiseBoard", XrmoptionNoArg, "True" },
1615 { "-xautoraise", "autoRaiseBoard", XrmoptionNoArg, "False" },
1616 { "-blindfold", "blindfold", XrmoptionSepArg, NULL },
1617 { "-blind", "blindfold", XrmoptionNoArg, "True" },
1618 { "-xblind", "blindfold", XrmoptionNoArg, "False" },
1619 { "-loadPositionFile", "loadPositionFile", XrmoptionSepArg, NULL },
1620 { "-lpf", "loadPositionFile", XrmoptionSepArg, NULL },
1621 { "-loadPositionIndex", "loadPositionIndex", XrmoptionSepArg, NULL },
1622 { "-lpi", "loadPositionIndex", XrmoptionSepArg, NULL },
1623 { "-savePositionFile", "savePositionFile", XrmoptionSepArg, NULL },
1624 { "-spf", "savePositionFile", XrmoptionSepArg, NULL },
1625 { "-matchMode", "matchMode", XrmoptionSepArg, NULL },
1626 { "-mm", "matchMode", XrmoptionNoArg, "True" },
1627 { "-xmm", "matchMode", XrmoptionNoArg, "False" },
1628 { "-matchGames", "matchGames", XrmoptionSepArg, NULL },
1629 { "-mg", "matchGames", XrmoptionSepArg, NULL },
1630 { "-monoMode", "monoMode", XrmoptionSepArg, NULL },
1631 { "-mono", "monoMode", XrmoptionNoArg, "True" },
1632 { "-xmono", "monoMode", XrmoptionNoArg, "False" },
1633 { "-debugMode", "debugMode", XrmoptionSepArg, NULL },
1634 { "-debug", "debugMode", XrmoptionNoArg, "True" },
1635 { "-xdebug", "debugMode", XrmoptionNoArg, "False" },
1636 { "-clockMode", "clockMode", XrmoptionSepArg, NULL },
1637 { "-clock", "clockMode", XrmoptionNoArg, "True" },
1638 { "-xclock", "clockMode", XrmoptionNoArg, "False" },
1639 { "-boardSize", "boardSize", XrmoptionSepArg, NULL },
1640 { "-size", "boardSize", XrmoptionSepArg, NULL },
1641 { "-searchTime", "searchTime", XrmoptionSepArg, NULL },
1642 { "-st", "searchTime", XrmoptionSepArg, NULL },
1643 { "-searchDepth", "searchDepth", XrmoptionSepArg, NULL },
1644 { "-depth", "searchDepth", XrmoptionSepArg, NULL },
1645 { "-showCoords", "showCoords", XrmoptionSepArg, NULL },
1646 { "-coords", "showCoords", XrmoptionNoArg, "True" },
1647 { "-xcoords", "showCoords", XrmoptionNoArg, "False" },
1649 { "-showJail", "showJail", XrmoptionSepArg, NULL },
1650 { "-jail", "showJail", XrmoptionNoArg, "1" },
1651 { "-sidejail", "showJail", XrmoptionNoArg, "2" },
1652 { "-xjail", "showJail", XrmoptionNoArg, "0" },
1654 { "-showThinking", "showThinking", XrmoptionSepArg, NULL },
1655 { "-thinking", "showThinking", XrmoptionNoArg, "True" },
1656 { "-xthinking", "showThinking", XrmoptionNoArg, "False" },
1657 { "-ponderNextMove", "ponderNextMove", XrmoptionSepArg, NULL },
1658 { "-ponder", "ponderNextMove", XrmoptionNoArg, "True" },
1659 { "-xponder", "ponderNextMove", XrmoptionNoArg, "False" },
1660 { "-periodicUpdates", "periodicUpdates", XrmoptionSepArg, NULL },
1661 { "-periodic", "periodicUpdates", XrmoptionNoArg, "True" },
1662 { "-xperiodic", "periodicUpdates", XrmoptionNoArg, "False" },
1663 { "-clockFont", "clockFont", XrmoptionSepArg, NULL },
1664 { "-coordFont", "coordFont", XrmoptionSepArg, NULL },
1665 { "-font", "font", XrmoptionSepArg, NULL },
1666 { "-ringBellAfterMoves", "ringBellAfterMoves", XrmoptionSepArg, NULL },
1667 { "-bell", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1668 { "-xbell", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1669 { "-movesound", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1670 { "-xmovesound", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1671 { "-autoCallFlag", "autoCallFlag", XrmoptionSepArg, NULL },
1672 { "-autoflag", "autoCallFlag", XrmoptionNoArg, "True" },
1673 { "-xautoflag", "autoCallFlag", XrmoptionNoArg, "False" },
1674 { "-autoFlipView", "autoFlipView", XrmoptionSepArg, NULL },
1675 { "-autoflip", "autoFlipView", XrmoptionNoArg, "True" },
1676 { "-xautoflip", "autoFlipView", XrmoptionNoArg, "False" },
1677 { "-autoObserve", "autoObserve", XrmoptionSepArg, NULL },
1678 { "-autobs", "autoObserve", XrmoptionNoArg, "True" },
1679 { "-xautobs", "autoObserve", XrmoptionNoArg, "False" },
1680 { "-autoComment", "autoComment", XrmoptionSepArg, NULL },
1681 { "-autocomm", "autoComment", XrmoptionNoArg, "True" },
1682 { "-xautocomm", "autoComment", XrmoptionNoArg, "False" },
1683 { "-getMoveList", "getMoveList", XrmoptionSepArg, NULL },
1684 { "-moves", "getMoveList", XrmoptionNoArg, "True" },
1685 { "-xmoves", "getMoveList", XrmoptionNoArg, "False" },
1687 { "-highlightDragging", "highlightDragging", XrmoptionSepArg, NULL },
1688 { "-highdrag", "highlightDragging", XrmoptionNoArg, "True" },
1689 { "-xhighdrag", "highlightDragging", XrmoptionNoArg, "False" },
1691 { "-highlightLastMove", "highlightLastMove", XrmoptionSepArg, NULL },
1692 { "-highlight", "highlightLastMove", XrmoptionNoArg, "True" },
1693 { "-xhighlight", "highlightLastMove", XrmoptionNoArg, "False" },
1694 { "-premove", "premove", XrmoptionSepArg, NULL },
1695 { "-pre", "premove", XrmoptionNoArg, "True" },
1696 { "-xpre", "premove", XrmoptionNoArg, "False" },
1697 { "-testLegality", "testLegality", XrmoptionSepArg, NULL },
1698 { "-legal", "testLegality", XrmoptionNoArg, "True" },
1699 { "-xlegal", "testLegality", XrmoptionNoArg, "False" },
1700 { "-flipView", "flipView", XrmoptionSepArg, NULL },
1701 { "-flip", "flipView", XrmoptionNoArg, "True" },
1702 { "-xflip", "flipView", XrmoptionNoArg, "False" },
1703 { "-cmail", "cmailGameName", XrmoptionSepArg, NULL },
1704 { "-alwaysPromoteToQueen", "alwaysPromoteToQueen",
1705 XrmoptionSepArg, NULL },
1706 { "-queen", "alwaysPromoteToQueen", XrmoptionNoArg, "True" },
1707 { "-xqueen", "alwaysPromoteToQueen", XrmoptionNoArg, "False" },
1708 { "-oldSaveStyle", "oldSaveStyle", XrmoptionSepArg, NULL },
1709 { "-oldsave", "oldSaveStyle", XrmoptionNoArg, "True" },
1710 { "-xoldsave", "oldSaveStyle", XrmoptionNoArg, "False" },
1711 { "-quietPlay", "quietPlay", XrmoptionSepArg, NULL },
1712 { "-quiet", "quietPlay", XrmoptionNoArg, "True" },
1713 { "-xquiet", "quietPlay", XrmoptionNoArg, "False" },
1714 { "-titleInWindow", "titleInWindow", XrmoptionSepArg, NULL },
1715 { "-title", "titleInWindow", XrmoptionNoArg, "True" },
1716 { "-xtitle", "titleInWindow", XrmoptionNoArg, "False" },
1718 { "-zippyTalk", "zippyTalk", XrmoptionSepArg, NULL },
1719 { "-zt", "zippyTalk", XrmoptionNoArg, "True" },
1720 { "-xzt", "zippyTalk", XrmoptionNoArg, "False" },
1721 { "-zippyPlay", "zippyPlay", XrmoptionSepArg, NULL },
1722 { "-zp", "zippyPlay", XrmoptionNoArg, "True" },
1723 { "-xzp", "zippyPlay", XrmoptionNoArg, "False" },
1724 { "-zippyLines", "zippyLines", XrmoptionSepArg, NULL },
1725 { "-zippyPinhead", "zippyPinhead", XrmoptionSepArg, NULL },
1726 { "-zippyPassword", "zippyPassword", XrmoptionSepArg, NULL },
1727 { "-zippyPassword2", "zippyPassword2", XrmoptionSepArg, NULL },
1728 { "-zippyWrongPassword", "zippyWrongPassword", XrmoptionSepArg, NULL },
1729 { "-zippyAcceptOnly", "zippyAcceptOnly", XrmoptionSepArg, NULL },
1730 { "-zippyUseI", "zippyUseI", XrmoptionSepArg, NULL },
1731 { "-zui", "zippyUseI", XrmoptionNoArg, "True" },
1732 { "-xzui", "zippyUseI", XrmoptionNoArg, "False" },
1733 { "-zippyBughouse", "zippyBughouse", XrmoptionSepArg, NULL },
1734 { "-zippyNoplayCrafty", "zippyNoplayCrafty", XrmoptionSepArg, NULL },
1735 { "-znc", "zippyNoplayCrafty", XrmoptionNoArg, "True" },
1736 { "-xznc", "zippyNoplayCrafty", XrmoptionNoArg, "False" },
1737 { "-zippyGameEnd", "zippyGameEnd", XrmoptionSepArg, NULL },
1738 { "-zippyGameStart", "zippyGameStart", XrmoptionSepArg, NULL },
1739 { "-zippyAdjourn", "zippyAdjourn", XrmoptionSepArg, NULL },
1740 { "-zadj", "zippyAdjourn", XrmoptionNoArg, "True" },
1741 { "-xzadj", "zippyAdjourn", XrmoptionNoArg, "False" },
1742 { "-zippyAbort", "zippyAbort", XrmoptionSepArg, NULL },
1743 { "-zab", "zippyAbort", XrmoptionNoArg, "True" },
1744 { "-xzab", "zippyAbort", XrmoptionNoArg, "False" },
1745 { "-zippyVariants", "zippyVariants", XrmoptionSepArg, NULL },
1746 { "-zippyMaxGames", "zippyMaxGames", XrmoptionSepArg, NULL },
1747 { "-zippyReplayTimeout", "zippyReplayTimeout", XrmoptionSepArg, NULL },
1748 { "-zippyShortGame", "zippyShortGame", XrmoptionSepArg, NULL },
1750 { "-flashCount", "flashCount", XrmoptionSepArg, NULL },
1751 { "-flash", "flashCount", XrmoptionNoArg, "3" },
1752 { "-xflash", "flashCount", XrmoptionNoArg, "0" },
1753 { "-flashRate", "flashRate", XrmoptionSepArg, NULL },
1754 { "-pixmapDirectory", "pixmapDirectory", XrmoptionSepArg, NULL },
1755 { "-msLoginDelay", "msLoginDelay", XrmoptionSepArg, NULL },
1756 { "-pixmap", "pixmapDirectory", XrmoptionSepArg, NULL },
1757 { "-colorizeMessages", "colorizeMessages", XrmoptionSepArg, NULL },
1758 { "-colorize", "colorizeMessages", XrmoptionNoArg, "True" },
1759 { "-xcolorize", "colorizeMessages", XrmoptionNoArg, "False" },
1760 { "-colorShout", "colorShout", XrmoptionSepArg, NULL },
1761 { "-colorSShout", "colorSShout", XrmoptionSepArg, NULL },
1762 { "-colorCShout", "colorSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1763 { "-colorChannel1", "colorChannel1", XrmoptionSepArg, NULL },
1764 { "-colorChannel", "colorChannel", XrmoptionSepArg, NULL },
1765 { "-colorKibitz", "colorKibitz", XrmoptionSepArg, NULL },
1766 { "-colorTell", "colorTell", XrmoptionSepArg, NULL },
1767 { "-colorChallenge", "colorChallenge", XrmoptionSepArg, NULL },
1768 { "-colorRequest", "colorRequest", XrmoptionSepArg, NULL },
1769 { "-colorSeek", "colorSeek", XrmoptionSepArg, NULL },
1770 { "-colorNormal", "colorNormal", XrmoptionSepArg, NULL },
1771 { "-soundProgram", "soundProgram", XrmoptionSepArg, NULL },
1772 { "-soundShout", "soundShout", XrmoptionSepArg, NULL },
1773 { "-soundSShout", "soundSShout", XrmoptionSepArg, NULL },
1774 { "-soundCShout", "soundSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1775 { "-soundChannel1", "soundChannel1", XrmoptionSepArg, NULL },
1776 { "-soundChannel", "soundChannel", XrmoptionSepArg, NULL },
1777 { "-soundKibitz", "soundKibitz", XrmoptionSepArg, NULL },
1778 { "-soundTell", "soundTell", XrmoptionSepArg, NULL },
1779 { "-soundChallenge", "soundChallenge", XrmoptionSepArg, NULL },
1780 { "-soundRequest", "soundRequest", XrmoptionSepArg, NULL },
1781 { "-soundSeek", "soundSeek", XrmoptionSepArg, NULL },
1782 { "-soundMove", "soundMove", XrmoptionSepArg, NULL },
1783 { "-soundIcsWin", "soundIcsWin", XrmoptionSepArg, NULL },
1784 { "-soundIcsLoss", "soundIcsLoss", XrmoptionSepArg, NULL },
1785 { "-soundIcsDraw", "soundIcsDraw", XrmoptionSepArg, NULL },
1786 { "-soundIcsUnfinished", "soundIcsUnfinished", XrmoptionSepArg, NULL },
1787 { "-soundIcsAlarm", "soundIcsAlarm", XrmoptionSepArg, NULL },
1788 { "-reuseFirst", "reuseFirst", XrmoptionSepArg, NULL },
1789 { "-reuseChessPrograms", "reuseFirst", XrmoptionSepArg, NULL }, /*compat*/
1790 { "-reuse", "reuseFirst", XrmoptionNoArg, "True" },
1791 { "-xreuse", "reuseFirst", XrmoptionNoArg, "False" },
1792 { "-reuseSecond", "reuseSecond", XrmoptionSepArg, NULL },
1793 { "-reuse2", "reuseSecond", XrmoptionNoArg, "True" },
1794 { "-xreuse2", "reuseSecond", XrmoptionNoArg, "False" },
1795 { "-animateMoving", "animateMoving", XrmoptionSepArg, NULL },
1796 { "-animate", "animateMoving", XrmoptionNoArg, "True" },
1797 { "-xanimate", "animateMoving", XrmoptionNoArg, "False" },
1798 { "-animateDragging", "animateDragging", XrmoptionSepArg, NULL },
1799 { "-drag", "animateDragging", XrmoptionNoArg, "True" },
1800 { "-xdrag", "animateDragging", XrmoptionNoArg, "False" },
1801 { "-animateSpeed", "animateSpeed", XrmoptionSepArg, NULL },
1802 { "-popupExitMessage", "popupExitMessage", XrmoptionSepArg, NULL },
1803 { "-exit", "popupExitMessage", XrmoptionNoArg, "True" },
1804 { "-xexit", "popupExitMessage", XrmoptionNoArg, "False" },
1805 { "-popupMoveErrors", "popupMoveErrors", XrmoptionSepArg, NULL },
1806 { "-popup", "popupMoveErrors", XrmoptionNoArg, "True" },
1807 { "-xpopup", "popupMoveErrors", XrmoptionNoArg, "False" },
1808 { "-fontSizeTolerance", "fontSizeTolerance", XrmoptionSepArg, NULL },
1809 { "-initialMode", "initialMode", XrmoptionSepArg, NULL },
1810 { "-mode", "initialMode", XrmoptionSepArg, NULL },
1811 { "-variant", "variant", XrmoptionSepArg, NULL },
1812 { "-firstProtocolVersion", "firstProtocolVersion", XrmoptionSepArg, NULL },
1813 { "-secondProtocolVersion","secondProtocolVersion",XrmoptionSepArg, NULL },
1814 { "-showButtonBar", "showButtonBar", XrmoptionSepArg, NULL },
1815 { "-buttons", "showButtonBar", XrmoptionNoArg, "True" },
1816 { "-xbuttons", "showButtonBar", XrmoptionNoArg, "False" },
1817 { "-lowTimeWarningColor", "lowTimeWarningColor", XrmoptionSepArg, NULL },
1818 { "-lowTimeWarning", "lowTimeWarning", XrmoptionSepArg, NULL },
1819 /* [AS,HR] New features */
1820 { "-firstScoreAbs", "firstScoreAbs", XrmoptionSepArg, NULL },
1821 { "-secondScoreAbs", "secondScoreAbs", XrmoptionSepArg, NULL },
1822 { "-pgnExtendedInfo", "pgnExtendedInfo", XrmoptionSepArg, NULL },
1823 { "-hideThinkingFromHuman", "hideThinkingFromHuman", XrmoptionSepArg, NULL },
1824 { "-adjudicateLossThreshold", "adjudicateLossThreshold", XrmoptionSepArg, NULL },
1825 { "-pgnEventHeader", "pgnEventHeader", XrmoptionSepArg, NULL },
1826 { "-firstIsUCI", "firstIsUCI", XrmoptionSepArg, NULL },
1827 { "-secondIsUCI", "secondIsUCI", XrmoptionSepArg, NULL },
1828 { "-fUCI", "firstIsUCI", XrmoptionNoArg, "True" },
1829 { "-sUCI", "secondIsUCI", XrmoptionNoArg, "True" },
1830 { "-firstHasOwnBookUCI", "firstHasOwnBookUCI", XrmoptionSepArg, NULL },
1831 { "-secondHasOwnBookUCI", "secondHasOwnBookUCI", XrmoptionSepArg, NULL },
1832 { "-fNoOwnBookUCI", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1833 { "-sNoOwnBookUCI", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1834 { "-firstXBook", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1835 { "-secondXBook", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1836 { "-polyglotDir", "polyglotDir", XrmoptionSepArg, NULL },
1837 { "-usePolyglotBook", "usePolyglotBook", XrmoptionSepArg, NULL },
1838 { "-polyglotBook", "polyglotBook", XrmoptionSepArg, NULL },
1839 { "-defaultHashSize", "defaultHashSize", XrmoptionSepArg, NULL },
1840 { "-defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XrmoptionSepArg, NULL },
1841 { "-defaultPathEGTB", "defaultPathEGTB", XrmoptionSepArg, NULL },
1842 { "-defaultFrcPosition", "defaultFrcPosition", XrmoptionSepArg, NULL },
1843 { "-gameListTags", "gameListTags", XrmoptionSepArg, NULL },
1844 // [HGM] I am sure AS added many more options, but we have to fish them out, from the list in winboard.c
1846 /* [HGM,HR] User-selectable board size */
1847 { "-boardWidth", "boardWidth", XrmoptionSepArg, NULL },
1848 { "-boardHeight", "boardHeight", XrmoptionSepArg, NULL },
1849 { "-matchPause", "matchPause", XrmoptionSepArg, NULL },
1851 /* [HGM] new arguments of 4.3.xx. All except first three are back-end options, which should work immediately */
1852 { "-holdingsSize", "holdingsSize", XrmoptionSepArg, NULL }, // requires extensive front-end changes to work
1853 { "-flipBlack", "flipBlack", XrmoptionSepArg, NULL }, // requires front-end changes to work
1854 { "-allWhite", "allWhite", XrmoptionSepArg, NULL }, // requires front-end changes to work
1855 { "-pieceToCharTable", "pieceToCharTable", XrmoptionSepArg, NULL },
1856 { "-alphaRank", "alphaRank", XrmoptionSepArg, NULL },
1857 { "-testClaims", "testClaims", XrmoptionSepArg, NULL },
1858 { "-checkMates", "checkMates", XrmoptionSepArg, NULL },
1859 { "-materialDraws", "materialDraws", XrmoptionSepArg, NULL },
1860 { "-trivialDraws", "trivialDraws", XrmoptionSepArg, NULL },
1861 { "-ruleMoves", "ruleMoves", XrmoptionSepArg, NULL },
1862 { "-repeatsToDraw", "repeatsToDraw", XrmoptionSepArg, NULL },
1863 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1864 { "-userName", "userName", XrmoptionSepArg, NULL },
1865 { "-autoKibitz", "autoKibitz", XrmoptionNoArg, "True" },
1866 { "-firstTimeOdds", "firstTimeOdds", XrmoptionSepArg, NULL },
1867 { "-secondTimeOdds", "secondTimeOdds", XrmoptionSepArg, NULL },
1868 { "-timeOddsMode", "timeOddsMode", XrmoptionSepArg, NULL },
1869 { "-firstAccumulateTC", "firstAccumulateTC", XrmoptionSepArg, NULL },
1870 { "-secondAccumulateTC", "secondAccumulateTC", XrmoptionSepArg, NULL },
1871 { "-firstNPS", "firstNPS", XrmoptionSepArg, NULL },
1872 { "-secondNPS", "secondNPS", XrmoptionSepArg, NULL },
1873 { "-serverMoves", "serverMoves", XrmoptionSepArg, NULL },
1874 { "-serverPause", "serverPause", XrmoptionSepArg, NULL },
1875 { "-suppressLoadMoves", "suppressLoadMoves", XrmoptionSepArg, NULL },
1876 { "-egtFormats", "egtFormats", XrmoptionSepArg, NULL },
1877 { "-userName", "userName", XrmoptionSepArg, NULL },
1878 { "-smpCores", "smpCores", XrmoptionSepArg, NULL },
1879 { "-sameColorGames", "sameColorGames", XrmoptionSepArg, NULL },
1880 { "-rewindIndex", "rewindIndex", XrmoptionSepArg, NULL },
1881 { "-niceEngines", "niceEngines", XrmoptionSepArg, NULL },
1882 { "-delayBeforeQuit", "delayBeforeQuit", XrmoptionSepArg, NULL },
1883 { "-delayAfterQuit", "delayAfterQuit", XrmoptionSepArg, NULL },
1884 { "-nameOfDebugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1885 { "-debugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1886 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1887 { "-noGUI", "noGUI", XrmoptionNoArg, "True" },
1888 { "-firstOptions", "firstOptions", XrmoptionSepArg, NULL },
1889 { "-secondOptions", "secondOptions", XrmoptionSepArg, NULL },
1890 { "-firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1891 { "-secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1895 XtActionsRec boardActions[] = {
1896 { "HandleUserMove", HandleUserMove },
1897 { "AnimateUserMove", AnimateUserMove },
1898 { "FileNameAction", FileNameAction },
1899 { "AskQuestionProc", AskQuestionProc },
1900 { "AskQuestionReplyAction", AskQuestionReplyAction },
1901 { "PieceMenuPopup", PieceMenuPopup },
1902 { "WhiteClock", WhiteClock },
1903 { "BlackClock", BlackClock },
1904 { "Iconify", Iconify },
1905 { "LoadSelectedProc", LoadSelectedProc },
1906 { "LoadPositionProc", LoadPositionProc },
1907 { "LoadNextPositionProc", LoadNextPositionProc },
1908 { "LoadPrevPositionProc", LoadPrevPositionProc },
1909 { "ReloadPositionProc", ReloadPositionProc },
1910 { "CopyPositionProc", CopyPositionProc },
1911 { "PastePositionProc", PastePositionProc },
1912 { "CopyGameProc", CopyGameProc },
1913 { "PasteGameProc", PasteGameProc },
1914 { "SaveGameProc", SaveGameProc },
1915 { "SavePositionProc", SavePositionProc },
1916 { "MailMoveProc", MailMoveProc },
1917 { "ReloadCmailMsgProc", ReloadCmailMsgProc },
1918 // { "MachineWhiteProc", MachineWhiteProc },
1919 // { "MachineBlackProc", MachineBlackProc },
1920 { "AnalysisModeProc", AnalyzeModeProc },
1921 { "AnalyzeFileProc", AnalyzeFileProc },
1922 // { "TwoMachinesProc", TwoMachinesProc },
1923 { "IcsClientProc", IcsClientProc },
1924 { "EditGameProc", EditGameProc },
1925 { "EditPositionProc", EditPositionProc },
1926 { "TrainingProc", EditPositionProc },
1927 { "EngineOutputProc", EngineOutputProc}, // [HGM] Winboard_x engine-output window
1928 { "ShowGameListProc", ShowGameListProc },
1929 { "ShowMoveListProc", HistoryShowProc},
1930 { "EditTagsProc", EditCommentProc },
1931 { "EditCommentProc", EditCommentProc },
1932 { "IcsAlarmProc", IcsAlarmProc },
1933 { "IcsInputBoxProc", IcsInputBoxProc },
1934 // { "AcceptProc", AcceptProc },
1935 // { "DeclineProc", DeclineProc },
1936 // { "RematchProc", RematchProc },
1937 // { "CallFlagProc", CallFlagProc },
1938 // { "DrawProc", DrawProc },
1939 // { "AdjournProc", AdjournProc },
1940 // { "AbortProc", AbortProc },
1941 // { "ResignProc", ResignProc },
1942 { "AdjuWhiteProc", AdjuWhiteProc },
1943 { "AdjuBlackProc", AdjuBlackProc },
1944 { "AdjuDrawProc", AdjuDrawProc },
1945 { "EnterKeyProc", EnterKeyProc },
1946 { "StopObservingProc", StopObservingProc },
1947 { "StopExaminingProc", StopExaminingProc },
1948 { "BackwardProc", BackwardProc },
1949 { "ForwardProc", ForwardProc },
1950 { "ToStartProc", ToStartProc },
1951 { "ToEndProc", ToEndProc },
1952 { "RevertProc", RevertProc },
1953 { "TruncateGameProc", TruncateGameProc },
1954 // { "MoveNowProc", MoveNowProc },
1955 { "RetractMoveProc", RetractMoveProc },
1956 { "AlwaysQueenProc", AlwaysQueenProc },
1957 { "AnimateDraggingProc", AnimateDraggingProc },
1958 { "AnimateMovingProc", AnimateMovingProc },
1959 { "AutoflagProc", AutoflagProc },
1960 { "AutoflipProc", AutoflipProc },
1961 { "AutobsProc", AutobsProc },
1962 { "AutoraiseProc", AutoraiseProc },
1963 { "AutosaveProc", AutosaveProc },
1964 { "BlindfoldProc", BlindfoldProc },
1965 { "FlashMovesProc", FlashMovesProc },
1966 { "FlipViewProc", FlipViewProc },
1967 { "GetMoveListProc", GetMoveListProc },
1969 { "HighlightDraggingProc", HighlightDraggingProc },
1971 { "HighlightLastMoveProc", HighlightLastMoveProc },
1972 { "IcsAlarmProc", IcsAlarmProc },
1973 { "MoveSoundProc", MoveSoundProc },
1974 { "OldSaveStyleProc", OldSaveStyleProc },
1975 { "PeriodicUpdatesProc", PeriodicUpdatesProc },
1976 { "PonderNextMoveProc", PonderNextMoveProc },
1977 { "PopupExitMessageProc", PopupExitMessageProc },
1978 { "PopupMoveErrorsProc", PopupMoveErrorsProc },
1979 { "PremoveProc", PremoveProc },
1980 { "QuietPlayProc", QuietPlayProc },
1981 { "ShowThinkingProc", ShowThinkingProc },
1982 { "HideThinkingProc", HideThinkingProc },
1983 { "TestLegalityProc", TestLegalityProc },
1984 { "InfoProc", InfoProc },
1985 { "ManProc", ManProc },
1986 { "HintProc", HintProc },
1987 { "BookProc", BookProc },
1988 { "AboutGameProc", AboutGameProc },
1989 { "DebugProc", DebugProc },
1990 { "NothingProc", NothingProc },
1991 { "CommentPopDown", (XtActionProc) CommentPopDown },
1992 { "EditCommentPopDown", (XtActionProc) EditCommentPopDown },
1993 { "TagsPopDown", (XtActionProc) TagsPopDown },
1994 { "ErrorPopDown", (XtActionProc) ErrorPopDown },
1995 { "ICSInputBoxPopDown", (XtActionProc) ICSInputBoxPopDown },
1996 { "AnalysisPopDown", (XtActionProc) AnalysisPopDown },
1997 { "FileNamePopDown", (XtActionProc) FileNamePopDown },
1998 { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown },
1999 { "GameListPopDown", (XtActionProc) GameListPopDown },
2000 { "PromotionPopDown", (XtActionProc) PromotionPopDown },
2001 { "HistoryPopDown", (XtActionProc) HistoryPopDown },
2002 { "EngineOutputPopDown", (XtActionProc) EngineOutputPopDown },
2003 { "ShufflePopDown", (XtActionProc) ShufflePopDown },
2004 { "EnginePopDown", (XtActionProc) EnginePopDown },
2005 { "UciPopDown", (XtActionProc) UciPopDown },
2006 { "TimeControlPopDown", (XtActionProc) TimeControlPopDown },
2007 { "NewVariantPopDown", (XtActionProc) NewVariantPopDown },
2008 { "SettingsPopDown", (XtActionProc) SettingsPopDown },
2012 char ICSInputTranslations[] =
2013 "<Key>Return: EnterKeyProc() \n";
2015 String xboardResources[] = {
2016 "*fileName*value.translations: #override\\n <Key>Return: FileNameAction()",
2017 "*question*value.translations: #override\\n <Key>Return: AskQuestionReplyAction()",
2018 "*errorpopup*translations: #override\\n <Key>Return: ErrorPopDown()",
2022 static char *cnames[9] = { "black", "red", "green", "yellow", "blue",
2023 "magenta", "cyan", "white" };
2027 TextColors textColors[(int)NColorClasses];
2029 /* String is: "fg, bg, attr". Which is 0, 1, 2 */
2031 parse_color(str, which)
2035 char *p, buf[100], *d;
2038 if (strlen(str) > 99) /* watch bounds on buf */
2043 for (i=0; i<which; ++i) {
2050 /* Could be looking at something like:
2052 .. in which case we want to stop on a comma also */
2053 while (*p && *p != ',' && !isalpha(*p) && !isdigit(*p))
2057 return -1; /* Use default for empty field */
2060 if (which == 2 || isdigit(*p))
2063 while (*p && isalpha(*p))
2068 for (i=0; i<8; ++i) {
2069 if (!StrCaseCmp(buf, cnames[i]))
2070 return which? (i+40) : (i+30);
2072 if (!StrCaseCmp(buf, "default")) return -1;
2074 fprintf(stderr, _("%s: unrecognized color %s\n"), programName, buf);
2079 parse_cpair(cc, str)
2083 if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {
2084 fprintf(stderr, _("%s: can't parse foreground color in `%s'\n"),
2089 /* bg and attr are optional */
2090 textColors[(int)cc].bg = parse_color(str, 1);
2091 if ((textColors[(int)cc].attr = parse_color(str, 2)) < 0) {
2092 textColors[(int)cc].attr = 0;
2098 /* Arrange to catch delete-window events */
2099 Atom wm_delete_window;
2101 CatchDeleteWindow(Widget w, String procname)
2104 XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
2105 snprintf(buf, sizeof(buf), "<Message>WM_PROTOCOLS: %s() \n", procname);
2106 XtAugmentTranslations(w, XtParseTranslationTable(buf));
2112 /* this should raise the board to the top */
2113 gtk_window_present(GTK_WINDOW(GUI_Window));
2118 // eventually, all layout determining code should go into a subroutine, but until then IDSIZE remains undefined
2120 #define BoardSize int
2121 void InitDrawingSizes(BoardSize boardSize, int flags)
2122 { // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
2123 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2125 XtGeometryResult gres;
2128 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2129 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2131 timerWidth = (boardWidth - sep) / 2;
2133 if (appData.titleInWindow)
2138 w = boardWidth - 2*bor;
2142 w = boardWidth - w - sep - 2*bor - 2; // WIDTH_FUDGE
2146 if(!formWidget) return;
2149 * Inhibit shell resizing.
2152 // [HGM] pieces: tailor piece bitmaps to needs of specific variant
2155 for(i=0; i<4; i++) {
2157 for(p=0; p<=(int)WhiteKing; p++)
2158 xpmPieceBitmap[i][p] = xpmPieceBitmap2[i][p]; // defaults
2159 if(gameInfo.variant == VariantShogi) {
2160 xpmPieceBitmap[i][(int)WhiteCannon] = xpmPieceBitmap2[i][(int)WhiteKing+1];
2161 xpmPieceBitmap[i][(int)WhiteNightrider] = xpmPieceBitmap2[i][(int)WhiteKing+2];
2162 xpmPieceBitmap[i][(int)WhiteSilver] = xpmPieceBitmap2[i][(int)WhiteKing+3];
2163 xpmPieceBitmap[i][(int)WhiteGrasshopper] = xpmPieceBitmap2[i][(int)WhiteKing+4];
2164 xpmPieceBitmap[i][(int)WhiteQueen] = xpmPieceBitmap2[i][(int)WhiteLance];
2167 if(gameInfo.variant == VariantGothic) {
2168 xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteSilver];
2172 // [HGM] why are thee ximMasks used at all? the ximPieceBitmaps seem to be never used!
2173 for(p=0; p<=(int)WhiteKing; p++)
2174 ximMaskPm[p] = ximMaskPm2[p]; // defaults
2175 if(gameInfo.variant == VariantShogi) {
2176 ximMaskPm[(int)WhiteCannon] = ximMaskPm2[(int)WhiteKing+1];
2177 ximMaskPm[(int)WhiteNightrider] = ximMaskPm2[(int)WhiteKing+2];
2178 ximMaskPm[(int)WhiteSilver] = ximMaskPm2[(int)WhiteKing+3];
2179 ximMaskPm[(int)WhiteGrasshopper] = ximMaskPm2[(int)WhiteKing+4];
2180 ximMaskPm[(int)WhiteQueen] = ximMaskPm2[(int)WhiteLance];
2183 if(gameInfo.variant == VariantGothic) {
2184 ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[i][(int)WhiteSilver];
2190 for(i=0; i<2; i++) {
2192 for(p=0; p<=(int)WhiteKing; p++)
2193 pieceBitmap[i][p] = pieceBitmap2[i][p]; // defaults
2194 if(gameInfo.variant == VariantShogi) {
2195 pieceBitmap[i][(int)WhiteCannon] = pieceBitmap2[i][(int)WhiteKing+1];
2196 pieceBitmap[i][(int)WhiteNightrider] = pieceBitmap2[i][(int)WhiteKing+2];
2197 pieceBitmap[i][(int)WhiteSilver] = pieceBitmap2[i][(int)WhiteKing+3];
2198 pieceBitmap[i][(int)WhiteGrasshopper] = pieceBitmap2[i][(int)WhiteKing+4];
2199 pieceBitmap[i][(int)WhiteQueen] = pieceBitmap2[i][(int)WhiteLance];
2202 if(gameInfo.variant == VariantGothic) {
2203 pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteSilver];
2219 int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
2220 XSetWindowAttributes window_attributes;
2222 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2223 XrmValue vFrom, vTo;
2224 XtGeometryResult gres;
2227 int forceMono = False;
2231 // [HGM] before anything else, expand any indirection files amongst options
2232 char *argvCopy[1000]; // 1000 seems enough
2233 char newArgs[10000]; // holds actual characters
2236 srandom(time(0)); // [HGM] book: make random truly random
2239 for(i=0; i<argc; i++) {
2240 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2241 //fprintf(stderr, "arg %s\n", argv[i]);
2242 if(argv[i][0] != '@') argvCopy[j++] = argv[i]; else {
2244 FILE *f = fopen(argv[i]+1, "rb");
2245 if(f == NULL) { fprintf(stderr, _("ignore %s\n"), argv[i]); continue; } // do not expand non-existing
2246 argvCopy[j++] = newArgs + k; // get ready for first argument from file
2247 while((c = fgetc(f)) != EOF) { // each line of file inserts 1 argument in the list
2249 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2250 newArgs[k++] = 0; // terminate current arg
2251 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2252 argvCopy[j++] = newArgs + k; // get ready for next
2254 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2267 if(appData.debugMode,1) { // OK, appData is not initialized here yet...
2268 for(i=0; i<argc; i++) fprintf(stderr, "argv[%2d] = '%s'\n", i, argv[i]);
2274 setbuf(stdout, NULL);
2275 setbuf(stderr, NULL);
2278 programName = strrchr(argv[0], '/');
2279 if (programName == NULL)
2280 programName = argv[0];
2285 XtSetLanguageProc(NULL, NULL, NULL);
2286 bindtextdomain(PACKAGE, LOCALEDIR);
2287 textdomain(PACKAGE);
2291 XtAppInitialize(&appContext, "XBoard", shellOptions,
2292 XtNumber(shellOptions),
2293 &argc, argv, xboardResources, NULL, 0);
2297 gtk_init (&argc, &argv);
2299 /* parse glade file to build widgets */
2301 builder = gtk_builder_new ();
2302 gtk_builder_add_from_file (builder, "gtk-interface.xml", NULL);
2304 /* test if everything worked ok */
2306 GUI_Window = GTK_WIDGET (gtk_builder_get_object (builder, "MainWindow"));
2307 if(!GUI_Window) printf("Error: gtk_builder didn't work!\n");
2308 GUI_Board = GTK_WIDGET (gtk_builder_get_object (builder, "Board"));
2309 if(!GUI_Board) printf("Error: gtk_builder didn't work!\n");
2310 GUI_Whiteclock = GTK_WIDGET (gtk_builder_get_object (builder, "WhiteClock"));
2311 if(!GUI_Whiteclock) printf("Error: gtk_builder didn't work!\n");
2312 GUI_Blackclock = GTK_WIDGET (gtk_builder_get_object (builder, "BlackClock"));
2313 if(!GUI_Blackclock) printf("Error: gtk_builder didn't work!\n");
2315 gtk_builder_connect_signals (builder, NULL);
2317 // don't unref the builder, since we use it to get references to widgets
2318 // g_object_unref (G_OBJECT (builder));
2320 /* end parse glade file */
2324 fprintf(stderr, _("%s: unrecognized argument %s\n"),
2325 programName, argv[1]);
2326 fprintf(stderr, "Recognized options:\n");
2327 for(i = 0; i < XtNumber(shellOptions); i++)
2329 j = fprintf(stderr, " %s%s", shellOptions[i].option,
2330 (shellOptions[i].argKind == XrmoptionSepArg
2332 if (i++ < XtNumber(shellOptions))
2334 fprintf(stderr, "%*c%s%s\n", 40 - j, ' ',
2335 shellOptions[i].option,
2336 (shellOptions[i].argKind == XrmoptionSepArg
2341 fprintf(stderr, "\n");
2347 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL)
2353 if (chdir(chessDir) != 0)
2355 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
2362 if (p == NULL) p = "/tmp";
2363 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
2364 gameCopyFilename = (char*) malloc(i);
2365 gamePasteFilename = (char*) malloc(i);
2366 snprintf(gameCopyFilename,i, "%s/.xboard%05uc.pgn", p, getpid());
2367 snprintf(gamePasteFilename,i, "%s/.xboard%05up.pgn", p, getpid());
2369 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
2370 clientResources, XtNumber(clientResources),
2373 if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) {
2374 /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */
2375 if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL) {
2376 printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile);
2379 setbuf(debugFP, NULL);
2382 /* [HGM,HR] make sure board size is acceptable */
2383 if(appData.NrFiles > BOARD_SIZE ||
2384 appData.NrRanks > BOARD_SIZE )
2385 DisplayFatalError(_("Recompile with BOARD_SIZE > 12, to support this size"), 0, 2);
2388 /* This feature does not work; animation needs a rewrite */
2389 appData.highlightDragging = FALSE;
2393 xDisplay = XtDisplay(shellWidget);
2394 xScreen = DefaultScreen(xDisplay);
2395 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
2397 gameInfo.variant = StringToVariant(appData.variant);
2398 InitPosition(FALSE);
2402 * Determine boardSize
2404 gameInfo.boardWidth = gameInfo.boardHeight = 8; // [HGM] boardsize: make sure we start as 8x8
2407 // [HGM] as long as we have not created the possibility to change size while running, start with requested size
2408 gameInfo.boardWidth = appData.NrFiles > 0 ? appData.NrFiles : 8;
2409 gameInfo.boardHeight = appData.NrRanks > 0 ? appData.NrRanks : 8;
2410 gameInfo.holdingsWidth = appData.holdingsSize > 0 ? 2 : 0;
2415 InitDrawingSizes(-1, 0); // [HGM] initsize: make this into a subroutine
2417 if (isdigit(appData.boardSize[0])) {
2418 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
2419 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
2420 &fontPxlSize, &smallLayout, &tinyLayout);
2422 fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
2423 programName, appData.boardSize);
2427 /* Find some defaults; use the nearest known size */
2428 SizeDefaults *szd, *nearest;
2429 int distance = 99999;
2430 nearest = szd = sizeDefaults;
2431 while (szd->name != NULL) {
2432 if (abs(szd->squareSize - squareSize) < distance) {
2434 distance = abs(szd->squareSize - squareSize);
2435 if (distance == 0) break;
2439 if (i < 2) lineGap = nearest->lineGap;
2440 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
2441 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
2442 if (i < 5) fontPxlSize = nearest->fontPxlSize;
2443 if (i < 6) smallLayout = nearest->smallLayout;
2444 if (i < 7) tinyLayout = nearest->tinyLayout;
2447 SizeDefaults *szd = sizeDefaults;
2448 if (*appData.boardSize == NULLCHAR) {
2449 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize ||
2450 DisplayHeight(xDisplay, xScreen) < szd->minScreenSize) {
2453 if (szd->name == NULL) szd--;
2455 while (szd->name != NULL &&
2456 StrCaseCmp(szd->name, appData.boardSize) != 0) szd++;
2457 if (szd->name == NULL) {
2458 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
2459 programName, appData.boardSize);
2463 squareSize = szd->squareSize;
2464 lineGap = szd->lineGap;
2465 clockFontPxlSize = szd->clockFontPxlSize;
2466 coordFontPxlSize = szd->coordFontPxlSize;
2467 fontPxlSize = szd->fontPxlSize;
2468 smallLayout = szd->smallLayout;
2469 tinyLayout = szd->tinyLayout;
2472 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2473 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2474 if (appData.showJail == 1) {
2475 /* Jail on top and bottom */
2476 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2477 XtSetArg(boardArgs[2], XtNheight,
2478 boardHeight + 2*(lineGap + squareSize));
2479 } else if (appData.showJail == 2) {
2481 XtSetArg(boardArgs[1], XtNwidth,
2482 boardWidth + 2*(lineGap + squareSize));
2483 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2486 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2487 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2491 * Determine what fonts to use.
2493 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
2494 clockFontID = XLoadFont(xDisplay, appData.clockFont);
2495 clockFontStruct = XQueryFont(xDisplay, clockFontID);
2496 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
2497 coordFontID = XLoadFont(xDisplay, appData.coordFont);
2498 coordFontStruct = XQueryFont(xDisplay, coordFontID);
2499 appData.font = FindFont(appData.font, fontPxlSize);
2500 countFontID = XLoadFont(xDisplay, appData.coordFont); // [HGM] holdings
2501 countFontStruct = XQueryFont(xDisplay, countFontID);
2502 // appData.font = FindFont(appData.font, fontPxlSize);
2504 xdb = XtDatabase(xDisplay);
2505 XrmPutStringResource(&xdb, "*font", appData.font);
2508 * Detect if there are not enough colors available and adapt.
2510 if (DefaultDepth(xDisplay, xScreen) <= 2) {
2511 appData.monoMode = True;
2514 if (!appData.monoMode) {
2515 vFrom.addr = (caddr_t) appData.lightSquareColor;
2516 vFrom.size = strlen(appData.lightSquareColor);
2517 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2518 if (vTo.addr == NULL) {
2519 appData.monoMode = True;
2522 lightSquareColor = *(Pixel *) vTo.addr;
2525 if (!appData.monoMode) {
2526 vFrom.addr = (caddr_t) appData.darkSquareColor;
2527 vFrom.size = strlen(appData.darkSquareColor);
2528 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2529 if (vTo.addr == NULL) {
2530 appData.monoMode = True;
2533 darkSquareColor = *(Pixel *) vTo.addr;
2536 if (!appData.monoMode) {
2537 vFrom.addr = (caddr_t) appData.whitePieceColor;
2538 vFrom.size = strlen(appData.whitePieceColor);
2539 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2540 if (vTo.addr == NULL) {
2541 appData.monoMode = True;
2544 whitePieceColor = *(Pixel *) vTo.addr;
2547 if (!appData.monoMode) {
2548 vFrom.addr = (caddr_t) appData.blackPieceColor;
2549 vFrom.size = strlen(appData.blackPieceColor);
2550 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2551 if (vTo.addr == NULL) {
2552 appData.monoMode = True;
2555 blackPieceColor = *(Pixel *) vTo.addr;
2559 if (!appData.monoMode) {
2560 vFrom.addr = (caddr_t) appData.highlightSquareColor;
2561 vFrom.size = strlen(appData.highlightSquareColor);
2562 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2563 if (vTo.addr == NULL) {
2564 appData.monoMode = True;
2567 highlightSquareColor = *(Pixel *) vTo.addr;
2571 if (!appData.monoMode) {
2572 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
2573 vFrom.size = strlen(appData.premoveHighlightColor);
2574 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2575 if (vTo.addr == NULL) {
2576 appData.monoMode = True;
2579 premoveHighlightColor = *(Pixel *) vTo.addr;
2584 fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2587 if (appData.bitmapDirectory == NULL ||
2588 appData.bitmapDirectory[0] == NULLCHAR)
2589 appData.bitmapDirectory = DEF_BITMAP_DIR;
2592 if (appData.lowTimeWarning && !appData.monoMode) {
2593 vFrom.addr = (caddr_t) appData.lowTimeWarningColor;
2594 vFrom.size = strlen(appData.lowTimeWarningColor);
2595 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2596 if (vTo.addr == NULL)
2597 appData.monoMode = True;
2599 lowTimeWarningColor = *(Pixel *) vTo.addr;
2602 if (appData.monoMode && appData.debugMode) {
2603 fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2604 (unsigned long) XWhitePixel(xDisplay, xScreen),
2605 (unsigned long) XBlackPixel(xDisplay, xScreen));
2608 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
2609 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
2610 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
2611 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
2612 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
2613 parse_cpair(ColorTell, appData.colorTell) < 0 ||
2614 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
2615 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
2616 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
2617 parse_cpair(ColorNormal, appData.colorNormal) < 0)
2619 if (appData.colorize) {
2621 _("%s: can't parse color names; disabling colorization\n"),
2624 appData.colorize = FALSE;
2626 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2627 textColors[ColorNone].attr = 0;
2629 // XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2635 layoutName = "tinyLayout";
2636 } else if (smallLayout) {
2637 layoutName = "smallLayout";
2639 layoutName = "normalLayout";
2642 if (appData.titleInWindow) {
2643 /* todo check what this appdata does */
2646 if (appData.showButtonBar) {
2647 /* TODO hide button bar if requested */
2651 * gtk set properties of widgets
2654 /* set board size */
2655 gtk_widget_set_size_request(GTK_WIDGET(GUI_Board),
2656 boardWidth,boardHeight);
2658 /* end gtk set properties of widgets */
2660 if (appData.titleInWindow)
2665 if (appData.showButtonBar)
2672 if (appData.showButtonBar)
2681 // [HGM] it seems the layout code ends here, but perhaps the color stuff is size independent and would
2682 // not need to go into InitDrawingSizes().
2685 /* set some checkboxes in the menu according to appData */
2687 if (appData.alwaysPromoteToQueen)
2688 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Always Queen")),TRUE);
2690 if (appData.animateDragging)
2691 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Animate Dragging")),TRUE);
2693 if (appData.animate)
2694 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Animate Moving")),TRUE);
2696 if (appData.autoComment)
2697 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Comment")),TRUE);
2699 if (appData.autoCallFlag)
2700 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Flag")),TRUE);
2702 if (appData.autoFlipView)
2703 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Flip View")),TRUE);
2705 if (appData.autoObserve)
2706 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Observe")),TRUE);
2708 if (appData.autoRaiseBoard)
2709 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Raise Board")),TRUE);
2711 if (appData.autoSaveGames)
2712 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Save")),TRUE);
2714 if (appData.saveGameFile[0] != NULLCHAR)
2716 /* Can't turn this off from menu */
2717 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Save")),TRUE);
2718 gtk_action_set_sensitive(GTK_ACTION (gtk_builder_get_object (builder, "menuOptions.Auto Save")),FALSE);
2721 if (appData.blindfold)
2722 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Blindfold")),TRUE);
2724 if (appData.flashCount > 0)
2725 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Flash Moves")),TRUE);
2727 if (appData.getMoveList)
2728 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Get Move List")),TRUE);
2731 if (appData.highlightDragging)
2732 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Highlight Dragging")),TRUE);
2735 if (appData.highlightLastMove)
2736 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Highlight Last Move")),TRUE);
2738 if (appData.icsAlarm)
2739 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.ICS Alarm")),TRUE);
2741 if (appData.ringBellAfterMoves)
2742 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Move Sound")),TRUE);
2744 if (appData.oldSaveStyle)
2745 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Old Save Style")),TRUE);
2747 if (appData.periodicUpdates)
2748 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Periodic Updates")),TRUE);
2750 if (appData.ponderNextMove)
2751 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Ponder Next Move")),TRUE);
2753 if (appData.popupExitMessage)
2754 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Popup Exit Message")),TRUE);
2756 if (appData.popupMoveErrors)
2757 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Popup Move Errors")),TRUE);
2759 if (appData.premove)
2760 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Premove")),TRUE);
2762 if (appData.quietPlay)
2763 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Quit Play")),TRUE);
2765 if (appData.showCoords)
2766 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Show Coords")),TRUE);
2768 if (appData.showThinking)
2769 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Show Thinking")),TRUE);
2771 if (appData.testLegality)
2772 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Test Legality")),TRUE);
2774 /* end setting check boxes */
2777 /* load square colors */
2778 SVGLightSquare = load_pixbuf("svg/LightSquare.svg",squareSize);
2779 SVGDarkSquare = load_pixbuf("svg/DarkSquare.svg",squareSize);
2780 SVGNeutralSquare = load_pixbuf("svg/NeutralSquare.svg",squareSize);
2782 /* use two icons to indicate if it is white's or black's turn */
2783 WhiteIcon = load_pixbuf("svg/icon_white.svg",0);
2784 BlackIcon = load_pixbuf("svg/icon_black.svg",0);
2785 WindowIcon = WhiteIcon;
2786 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
2788 /* do resizing to a fixed aspect ratio */
2793 GUI_SetAspectRatio(0.7);
2795 /* realize window */
2796 gtk_widget_show (GUI_Window);
2802 if (appData.animate || appData.animateDragging)
2807 if (errorExitStatus == -1) {
2808 if (appData.icsActive) {
2809 /* We now wait until we see "login:" from the ICS before
2810 sending the logon script (problems with timestamp otherwise) */
2811 /*ICSInitScript();*/
2812 if (appData.icsInputBox) ICSInputBoxPopUp();
2815 signal(SIGINT, IntSigHandler);
2816 signal(SIGTERM, IntSigHandler);
2817 if (*appData.cmailGameName != NULLCHAR) {
2818 signal(SIGUSR1, CmailSigHandler);
2821 gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes()
2825 * Create a cursor for the board widget.
2826 * (This needs to be called after the window has been created to have access to board-window)
2829 BoardCursor = gdk_cursor_new(GDK_HAND2);
2830 gdk_window_set_cursor(GUI_Board->window, BoardCursor);
2831 gdk_cursor_destroy(BoardCursor);
2836 if (appData.debugMode) fclose(debugFP); // [DM] debug
2843 if (appData.icsActive && oldICSInteractionTitle != NULL) {
2844 DisplayIcsInteractionTitle(oldICSInteractionTitle);
2846 unlink(gameCopyFilename);
2847 unlink(gamePasteFilename);
2858 CmailSigHandler(sig)
2864 signal(SIGUSR1, SIG_IGN); /* suspend handler */
2866 /* Activate call-back function CmailSigHandlerCallBack() */
2867 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
2869 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
2873 CmailSigHandlerCallBack(isr, closure, message, count, error)
2881 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
2883 /**** end signal code ****/
2893 f = fopen(appData.icsLogon, "r");
2899 strcat(buf, appData.icsLogon);
2900 f = fopen(buf, "r");
2904 ProcessICSInitScript(f);
2911 EditCommentPopDown();
2917 SetMenuEnables(enab)
2922 if (!builder) return;
2923 while (enab->name != NULL) {
2924 o = gtk_builder_get_object(builder, enab->name);
2925 if(GTK_IS_WIDGET(o))
2926 gtk_widget_set_sensitive(GTK_WIDGET (o),enab->value);
2929 if(GTK_IS_ACTION(o))
2930 gtk_action_set_sensitive(GTK_ACTION (o),enab->value);
2932 DisplayError(enab->name, 0);
2940 SetMenuEnables(icsEnables);
2943 if (appData.zippyPlay && !appData.noChessProgram) /* [DM] icsEngineAnalyze */
2944 {}; // XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
2951 SetMenuEnables(ncpEnables);
2957 SetMenuEnables(gnuEnables);
2963 SetMenuEnables(cmailEnables);
2969 SetMenuEnables(trainingOnEnables);
2970 if (appData.showButtonBar) {
2971 // XtSetSensitive(buttonBarWidget, False);
2977 SetTrainingModeOff()
2979 SetMenuEnables(trainingOffEnables);
2980 if (appData.showButtonBar) {
2981 // XtSetSensitive(buttonBarWidget, True);
2986 SetUserThinkingEnables()
2988 if (appData.noChessProgram) return;
2989 SetMenuEnables(userThinkingEnables);
2993 SetMachineThinkingEnables()
2995 if (appData.noChessProgram) return;
2996 SetMenuEnables(machineThinkingEnables);
2998 case MachinePlaysBlack:
2999 case MachinePlaysWhite:
3000 case TwoMachinesPlay:
3001 // XtSetSensitive(XtNameToWidget(menuBarWidget,
3002 // ModeToWidgetName(gameMode)), True);
3009 #define Abs(n) ((n)<0 ? -(n) : (n))
3012 * Find a font that matches "pattern" that is as close as
3013 * possible to the targetPxlSize. Prefer fonts that are k
3014 * pixels smaller to fonts that are k pixels larger. The
3015 * pattern must be in the X Consortium standard format,
3016 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
3017 * The return value should be freed with XtFree when no
3020 char *FindFont(pattern, targetPxlSize)
3024 char **fonts, *p, *best, *scalable, *scalableTail;
3025 int i, j, nfonts, minerr, err, pxlSize;
3028 char **missing_list;
3030 char *def_string, *base_fnt_lst, strInt[3];
3032 XFontStruct **fnt_list;
3034 base_fnt_lst = calloc(1, strlen(pattern) + 3);
3035 sprintf(strInt, "%d", targetPxlSize);
3036 p = strstr(pattern, "--");
3037 strncpy(base_fnt_lst, pattern, p - pattern + 2);
3038 strcat(base_fnt_lst, strInt);
3039 strcat(base_fnt_lst, strchr(p + 2, '-'));
3041 if ((fntSet = XCreateFontSet(xDisplay,
3045 &def_string)) == NULL) {
3047 fprintf(stderr, _("Unable to create font set.\n"));
3051 nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
3053 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
3055 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
3056 programName, pattern);
3064 for (i=0; i<nfonts; i++) {
3067 if (*p != '-') continue;
3069 if (*p == NULLCHAR) break;
3070 if (*p++ == '-') j++;
3072 if (j < 7) continue;
3075 scalable = fonts[i];
3078 err = pxlSize - targetPxlSize;
3079 if (Abs(err) < Abs(minerr) ||
3080 (minerr > 0 && err < 0 && -err == minerr)) {
3086 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
3087 /* If the error is too big and there is a scalable font,
3088 use the scalable font. */
3089 int headlen = scalableTail - scalable;
3090 p = (char *) XtMalloc(strlen(scalable) + 10);
3091 while (isdigit(*scalableTail)) scalableTail++;
3092 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
3094 p = (char *) XtMalloc(strlen(best) + 1);
3097 if (appData.debugMode) {
3098 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
3099 pattern, targetPxlSize, p);
3102 if (missing_count > 0)
3103 XFreeStringList(missing_list);
3104 XFreeFontSet(xDisplay, fntSet);
3106 XFreeFontNames(fonts);
3113 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
3114 | GCBackground | GCFunction | GCPlaneMask;
3115 XGCValues gc_values;
3118 gc_values.plane_mask = AllPlanes;
3119 gc_values.line_width = lineGap;
3120 gc_values.line_style = LineSolid;
3121 gc_values.function = GXcopy;
3123 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3124 gc_values.background = XWhitePixel(xDisplay, xScreen);
3125 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
3126 XSetFont(xDisplay, coordGC, coordFontID);
3128 if (appData.monoMode) {
3129 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3130 gc_values.background = XBlackPixel(xDisplay, xScreen);
3131 lightSquareGC = wbPieceGC
3132 = XtGetGC(shellWidget, value_mask, &gc_values);
3134 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3135 gc_values.background = XWhitePixel(xDisplay, xScreen);
3136 darkSquareGC = bwPieceGC
3137 = XtGetGC(shellWidget, value_mask, &gc_values);
3139 if (DefaultDepth(xDisplay, xScreen) == 1) {
3140 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3141 gc_values.function = GXcopyInverted;
3142 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3143 gc_values.function = GXcopy;
3144 if (XBlackPixel(xDisplay, xScreen) == 1) {
3145 bwPieceGC = darkSquareGC;
3146 wbPieceGC = copyInvertedGC;
3148 bwPieceGC = copyInvertedGC;
3149 wbPieceGC = lightSquareGC;
3153 gc_values.foreground = lightSquareColor;
3154 gc_values.background = darkSquareColor;
3155 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3157 gc_values.foreground = darkSquareColor;
3158 gc_values.background = lightSquareColor;
3159 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3161 gc_values.foreground = jailSquareColor;
3162 gc_values.background = jailSquareColor;
3163 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3165 gc_values.foreground = whitePieceColor;
3166 gc_values.background = darkSquareColor;
3167 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3169 gc_values.foreground = whitePieceColor;
3170 gc_values.background = lightSquareColor;
3171 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3173 gc_values.foreground = whitePieceColor;
3174 gc_values.background = jailSquareColor;
3175 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3177 gc_values.foreground = blackPieceColor;
3178 gc_values.background = darkSquareColor;
3179 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3181 gc_values.foreground = blackPieceColor;
3182 gc_values.background = lightSquareColor;
3183 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3185 gc_values.foreground = blackPieceColor;
3186 gc_values.background = jailSquareColor;
3187 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3194 WhitePawn, WhiteKnight, WhiteBishop, WhiteRook, WhiteQueen, WhiteKing,
3195 BlackPawn, BlackKnight, BlackBishop, BlackRook, BlackQueen, BlackKing,
3199 /* get some defaults going */
3200 for(i=WhitePawn; i<DemotePiece+1; i++)
3201 SVGpieces[i] = load_pixbuf("svg/NeutralSquare.svg",squareSize);
3204 SVGpieces[WhitePawn] = load_pixbuf("svg/WhitePawn.svg",squareSize);
3205 SVGpieces[WhiteKnight] = load_pixbuf("svg/WhiteKnight.svg",squareSize);
3206 SVGpieces[WhiteBishop] = load_pixbuf("svg/WhiteBishop.svg",squareSize);
3207 SVGpieces[WhiteRook] = load_pixbuf("svg/WhiteRook.svg",squareSize);
3208 SVGpieces[WhiteQueen] = load_pixbuf("svg/WhiteQueen.svg",squareSize);
3209 SVGpieces[WhiteKing] = load_pixbuf("svg/WhiteKing.svg",squareSize);
3211 SVGpieces[BlackPawn] = load_pixbuf("svg/BlackPawn.svg",squareSize);
3212 SVGpieces[BlackKnight] = load_pixbuf("svg/BlackKnight.svg",squareSize);
3213 SVGpieces[BlackBishop] = load_pixbuf("svg/BlackBishop.svg",squareSize);
3214 SVGpieces[BlackRook] = load_pixbuf("svg/BlackRook.svg",squareSize);
3215 SVGpieces[BlackQueen] = load_pixbuf("svg/BlackQueen.svg",squareSize);
3216 SVGpieces[BlackKing] = load_pixbuf("svg/BlackKing.svg",squareSize);
3222 static void MenuBarSelect(w, addr, index)
3227 XtActionProc proc = (XtActionProc) addr;
3229 (proc)(NULL, NULL, NULL, NULL);
3232 void CreateMenuBarPopup(parent, name, mb)
3242 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3245 XtSetArg(args[j], XtNleftMargin, 20); j++;
3246 XtSetArg(args[j], XtNrightMargin, 20); j++;
3248 while (mi->string != NULL) {
3249 if (strcmp(mi->string, "----") == 0) {
3250 entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
3253 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string)));
3254 entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass,
3256 XtAddCallback(entry, XtNcallback,
3257 (XtCallbackProc) MenuBarSelect,
3258 (caddr_t) mi->proc);
3264 Widget CreateMenuBar(mb)
3268 Widget anchor, menuBar;
3270 char menuName[MSG_SIZ];
3273 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3274 XtSetArg(args[j], XtNvSpace, 0); j++;
3275 XtSetArg(args[j], XtNborderWidth, 0); j++;
3276 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
3277 formWidget, args, j);
3279 while (mb->name != NULL) {
3280 strcpy(menuName, "menu");
3281 strcat(menuName, mb->name);
3283 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
3286 shortName[0] = _(mb->name)[0];
3287 shortName[1] = NULLCHAR;
3288 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
3291 XtSetArg(args[j], XtNlabel, XtNewString(_(mb->name))); j++;
3294 XtSetArg(args[j], XtNborderWidth, 0); j++;
3295 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
3297 CreateMenuBarPopup(menuBar, menuName, mb);
3303 Widget CreateButtonBar(mi)
3307 Widget button, buttonBar;
3311 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3313 XtSetArg(args[j], XtNhSpace, 0); j++;
3315 XtSetArg(args[j], XtNborderWidth, 0); j++;
3316 XtSetArg(args[j], XtNvSpace, 0); j++;
3317 buttonBar = XtCreateWidget("buttonBar", boxWidgetClass,
3318 formWidget, args, j);
3320 while (mi->string != NULL) {
3323 XtSetArg(args[j], XtNinternalWidth, 2); j++;
3324 XtSetArg(args[j], XtNborderWidth, 0); j++;
3326 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string))); j++;
3327 button = XtCreateManagedWidget(mi->string, commandWidgetClass,
3328 buttonBar, args, j);
3329 XtAddCallback(button, XtNcallback,
3330 (XtCallbackProc) MenuBarSelect,
3331 (caddr_t) mi->proc);
3338 CreatePieceMenu(name, color)
3345 ChessSquare selection;
3347 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3348 boardWidget, args, 0);
3350 for (i = 0; i < PIECE_MENU_SIZE; i++) {
3351 String item = pieceMenuStrings[color][i];
3353 if (strcmp(item, "----") == 0) {
3354 entry = XtCreateManagedWidget(item, smeLineObjectClass,
3357 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3358 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3360 selection = pieceMenuTranslation[color][i];
3361 XtAddCallback(entry, XtNcallback,
3362 (XtCallbackProc) PieceMenuSelect,
3363 (caddr_t) selection);
3364 if (selection == WhitePawn || selection == BlackPawn) {
3365 XtSetArg(args[0], XtNpopupOnEntry, entry);
3366 XtSetValues(menu, args, 1);
3379 ChessSquare selection;
3381 // whitePieceMenu = CreatePieceMenu("menuW", 0);
3382 // blackPieceMenu = CreatePieceMenu("menuB", 1);
3384 // XtRegisterGrabAction(PieceMenuPopup, True,
3385 // (unsigned)(ButtonPressMask|ButtonReleaseMask),
3386 // GrabModeAsync, GrabModeAsync);
3388 // XtSetArg(args[0], XtNlabel, _("Drop"));
3389 // dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
3390 // boardWidget, args, 1);
3391 // for (i = 0; i < DROP_MENU_SIZE; i++) {
3392 // String item = dropMenuStrings[i];
3394 // if (strcmp(item, "----") == 0) {
3395 // entry = XtCreateManagedWidget(item, smeLineObjectClass,
3396 // dropMenu, NULL, 0);
3398 // XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3399 // entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3400 // dropMenu, args, 1);
3401 // selection = dropMenuTranslation[i];
3402 // XtAddCallback(entry, XtNcallback,
3403 // (XtCallbackProc) DropMenuSelect,
3404 // (caddr_t) selection);
3409 void SetupDropMenu()
3417 for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
3418 entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
3419 p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
3420 dmEnables[i].piece);
3421 XtSetSensitive(entry, p != NULL || !appData.testLegality
3422 /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
3423 && !appData.icsActive));
3425 while (p && *p++ == dmEnables[i].piece) count++;
3426 snprintf(label, sizeof(label), "%s %d", dmEnables[i].widget, count);
3428 XtSetArg(args[j], XtNlabel, label); j++;
3429 XtSetValues(entry, args, j);
3433 void PieceMenuPopup(w, event, params, num_params)
3437 Cardinal *num_params;
3440 if (event->type != ButtonPress) return;
3441 if (errorUp) ErrorPopDown();
3445 whichMenu = params[0];
3447 case IcsPlayingWhite:
3448 case IcsPlayingBlack:
3450 case MachinePlaysWhite:
3451 case MachinePlaysBlack:
3452 if (appData.testLegality &&
3453 gameInfo.variant != VariantBughouse &&
3454 gameInfo.variant != VariantCrazyhouse) return;
3456 whichMenu = "menuD";
3462 if (((pmFromX = EventToSquare(event->xbutton.x, BOARD_WIDTH)) < 0) ||
3463 ((pmFromY = EventToSquare(event->xbutton.y, BOARD_HEIGHT)) < 0)) {
3464 pmFromX = pmFromY = -1;
3468 pmFromX = BOARD_WIDTH - 1 - pmFromX;
3470 pmFromY = BOARD_HEIGHT - 1 - pmFromY;
3472 XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
3475 static void PieceMenuSelect(w, piece, junk)
3480 if (pmFromX < 0 || pmFromY < 0) return;
3481 EditPositionMenuEvent(piece, pmFromX, pmFromY);
3484 static void DropMenuSelect(w, piece, junk)
3489 if (pmFromX < 0 || pmFromY < 0) return;
3490 DropMenuEvent(piece, pmFromX, pmFromY);
3493 void WhiteClock(w, event, prms, nprms)
3499 if (gameMode == EditPosition || gameMode == IcsExamining) {
3500 SetWhiteToPlayEvent();
3501 } else if (gameMode == IcsPlayingBlack || gameMode == MachinePlaysWhite) {
3506 void BlackClock(w, event, prms, nprms)
3512 if (gameMode == EditPosition || gameMode == IcsExamining) {
3513 SetBlackToPlayEvent();
3514 } else if (gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) {
3521 * If the user selects on a border boundary, return -1; if off the board,
3522 * return -2. Otherwise map the event coordinate to the square.
3524 int EventToSquare(x, limit)
3532 if ((x % (squareSize + lineGap)) >= squareSize)
3534 x /= (squareSize + lineGap);
3540 static void do_flash_delay(msec)
3546 static void drawHighlight(file, rank, line_type)
3547 int file, rank, line_type;
3552 if (lineGap == 0 || appData.blindfold) return;
3556 x = lineGap/2 + ((BOARD_WIDTH-1)-file) *
3557 (squareSize + lineGap);
3558 y = lineGap/2 + rank * (squareSize + lineGap);
3562 x = lineGap/2 + file * (squareSize + lineGap);
3563 y = lineGap/2 + ((BOARD_HEIGHT-1)-rank) *
3564 (squareSize + lineGap);
3568 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3570 /* draw the highlight */
3571 cairo_move_to (cr, x, y);
3572 cairo_rel_line_to (cr, 0,squareSize+lineGap);
3573 cairo_rel_line_to (cr, squareSize+lineGap,0);
3574 cairo_rel_line_to (cr, 0,-squareSize-lineGap);
3575 cairo_close_path (cr);
3577 cairo_set_line_width (cr, lineGap);
3580 /* TODO: use appdata colors */
3581 case LINE_TYPE_HIGHLIGHT:
3582 cairo_set_source_rgba (cr, 1, 1, 0, 1.0);
3585 cairo_set_source_rgba (cr, 1, 0, 0, 1.0);
3587 case LINE_TYPE_NORMAL:
3589 cairo_set_source_rgba (cr, 0, 1, 0, 1.0);
3600 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
3601 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
3604 SetHighlights(fromX, fromY, toX, toY)
3605 int fromX, fromY, toX, toY;
3607 if (hi1X != fromX || hi1Y != fromY)
3609 if (hi1X >= 0 && hi1Y >= 0)
3611 drawHighlight(hi1X, hi1Y, LINE_TYPE_NORMAL);
3613 if (fromX >= 0 && fromY >= 0)
3615 drawHighlight(fromX, fromY, LINE_TYPE_HIGHLIGHT);
3618 if (hi2X != toX || hi2Y != toY)
3620 if (hi2X >= 0 && hi2Y >= 0)
3622 drawHighlight(hi2X, hi2Y, LINE_TYPE_NORMAL);
3624 if (toX >= 0 && toY >= 0)
3626 drawHighlight(toX, toY, LINE_TYPE_HIGHLIGHT);
3640 SetHighlights(-1, -1, -1, -1);
3645 SetPremoveHighlights(fromX, fromY, toX, toY)
3646 int fromX, fromY, toX, toY;
3648 if (pm1X != fromX || pm1Y != fromY)
3650 if (pm1X >= 0 && pm1Y >= 0)
3652 drawHighlight(pm1X, pm1Y, LINE_TYPE_NORMAL);
3654 if (fromX >= 0 && fromY >= 0)
3656 drawHighlight(fromX, fromY, LINE_TYPE_PRE);
3659 if (pm2X != toX || pm2Y != toY)
3661 if (pm2X >= 0 && pm2Y >= 0)
3663 drawHighlight(pm2X, pm2Y, LINE_TYPE_NORMAL);
3665 if (toX >= 0 && toY >= 0)
3667 drawHighlight(toX, toY, LINE_TYPE_PRE);
3680 ClearPremoveHighlights()
3682 SetPremoveHighlights(-1, -1, -1, -1);
3685 static void BlankSquare(x, y, color, piece, dest)
3698 pb = SVGLightSquare;
3700 case 2: /* neutral */
3702 pb = SVGNeutralSquare;
3705 gdk_draw_pixbuf(GDK_WINDOW(GUI_Board->window),NULL,pb,0,0,x,y,-1,-1, GDK_RGB_DITHER_NORMAL, 0, 0);
3709 static void DrawPiece(piece, square_color, x, y, dest)
3711 int square_color, x, y;
3714 gdk_draw_pixbuf(GDK_WINDOW(GUI_Board->window),NULL,
3715 GDK_PIXBUF(SVGpieces[piece]),0,0,x,y,-1,-1,
3716 GDK_RGB_DITHER_NORMAL, 0, 0);
3720 /* [HR] determine square color depending on chess variant. */
3721 static int SquareColor(row, column)
3726 if (gameInfo.variant == VariantXiangqi) {
3727 if (column >= 3 && column <= 5 && row >= 0 && row <= 2) {
3729 } else if (column >= 3 && column <= 5 && row >= 7 && row <= 9) {
3731 } else if (row <= 4) {
3737 square_color = ((column + row) % 2) == 1;
3740 /* [hgm] holdings: next line makes all holdings squares light */
3741 if(column < BOARD_LEFT || column >= BOARD_RGHT) square_color = 1;
3743 return square_color;
3746 void DrawSquare(row, column, piece, do_flash)
3747 int row, column, do_flash;
3750 int square_color, x, y;
3755 /* Calculate delay in milliseconds (2-delays per complete flash) */
3756 flash_delay = 500 / appData.flashRate;
3758 /* calculate x and y coordinates from row and column */
3761 x = lineGap + ((BOARD_WIDTH-1)-column) *
3762 (squareSize + lineGap);
3763 y = lineGap + row * (squareSize + lineGap);
3767 x = lineGap + column * (squareSize + lineGap);
3768 y = lineGap + ((BOARD_HEIGHT-1)-row) *
3769 (squareSize + lineGap);
3772 square_color = SquareColor(row, column);
3774 // [HGM] holdings: blank out area between board and holdings
3775 if ( column == BOARD_LEFT-1 || column == BOARD_RGHT
3776 || (column == BOARD_LEFT-2 && row < BOARD_HEIGHT-gameInfo.holdingsSize)
3777 || (column == BOARD_RGHT+1 && row >= gameInfo.holdingsSize) )
3779 BlankSquare(x, y, 2, EmptySquare, xBoardWindow);
3781 // [HGM] print piece counts next to holdings
3782 string[1] = NULLCHAR;
3785 cairo_text_extents_t extents;
3790 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3792 string[0] = '0' + piece;
3794 /* TODO this has to go into the font-selection */
3795 cairo_select_font_face (cr, "Sans",
3796 CAIRO_FONT_SLANT_NORMAL,
3797 CAIRO_FONT_WEIGHT_NORMAL);
3799 cairo_set_font_size (cr, 12.0);
3800 cairo_text_extents (cr, string, &extents);
3802 if (column == (flipView ? BOARD_LEFT-1 : BOARD_RGHT) )
3804 xpos= x + squareSize - extents.width - 2;
3805 ypos= y + extents.y_bearing + 1;
3807 if (column == (flipView ? BOARD_RGHT : BOARD_LEFT-1) && piece > 1)
3810 ypos = y + extents.y_bearing + 1;
3813 /* TODO mono mode? */
3814 cairo_move_to (cr, xpos, ypos);
3815 cairo_text_path (cr, string);
3816 cairo_set_source_rgb (cr, 1.0, 1.0, 1);
3817 cairo_fill_preserve (cr);
3818 cairo_set_source_rgb (cr, 0, 0, 0);
3819 cairo_set_line_width (cr, 0.1);
3828 /* square on the board */
3829 if (piece == EmptySquare || appData.blindfold)
3831 BlankSquare(x, y, square_color, piece, xBoardWindow);
3835 if (do_flash && appData.flashCount > 0)
3837 for (i=0; i<appData.flashCount; ++i)
3840 DrawPiece(piece, square_color, x, y, xBoardWindow);
3841 do_flash_delay(flash_delay);
3843 BlankSquare(x, y, square_color, piece, xBoardWindow);
3844 do_flash_delay(flash_delay);
3847 DrawPiece(piece, square_color, x, y, xBoardWindow);
3851 /* show coordinates if necessary */
3852 if(appData.showCoords)
3854 cairo_text_extents_t extents;
3858 /* TODO this has to go into the font-selection */
3859 cairo_select_font_face (cr, "Sans",
3860 CAIRO_FONT_SLANT_NORMAL,
3861 CAIRO_FONT_WEIGHT_NORMAL);
3862 cairo_set_font_size (cr, 12.0);
3864 string[1] = NULLCHAR;
3867 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3869 if (row == (flipView ? BOARD_HEIGHT-1 : 0) &&
3870 column >= BOARD_LEFT && column < BOARD_RGHT)
3872 string[0] = 'a' + column - BOARD_LEFT;
3873 cairo_text_extents (cr, string, &extents);
3875 xpos = x + squareSize - extents.width - 2;
3876 ypos = y + squareSize - extents.height - extents.y_bearing - 1;
3878 if (appData.monoMode)
3885 cairo_move_to (cr, xpos, ypos);
3886 cairo_text_path (cr, string);
3887 cairo_set_source_rgb (cr, 0.0, 0.0, 0);
3888 cairo_fill_preserve (cr);
3889 cairo_set_source_rgb (cr, 0, 1.0, 0);
3890 cairo_set_line_width (cr, 0.1);
3893 if ( column == (flipView ? BOARD_RGHT-1 : BOARD_LEFT))
3896 string[0] = ONE + row;
3897 cairo_text_extents (cr, string, &extents);
3900 ypos = y + extents.height + 1;
3902 if (appData.monoMode)
3909 cairo_move_to (cr, xpos, ypos);
3910 cairo_text_path (cr, string);
3911 cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
3912 cairo_fill_preserve (cr);
3913 cairo_set_source_rgb (cr, 0, 0, 1.0);
3914 cairo_set_line_width (cr, 0.1);
3926 /* Returns 1 if there are "too many" differences between b1 and b2
3927 (i.e. more than 1 move was made) */
3928 static int too_many_diffs(b1, b2)
3934 for (i=0; i<BOARD_HEIGHT; ++i) {
3935 for (j=0; j<BOARD_WIDTH; ++j) {
3936 if (b1[i][j] != b2[i][j]) {
3937 if (++c > 4) /* Castling causes 4 diffs */
3946 /* Matrix describing castling maneuvers */
3947 /* Row, ColRookFrom, ColKingFrom, ColRookTo, ColKingTo */
3948 static int castling_matrix[4][5] = {
3949 { 0, 0, 4, 3, 2 }, /* 0-0-0, white */
3950 { 0, 7, 4, 5, 6 }, /* 0-0, white */
3951 { 7, 0, 4, 3, 2 }, /* 0-0-0, black */
3952 { 7, 7, 4, 5, 6 } /* 0-0, black */
3955 /* Checks whether castling occurred. If it did, *rrow and *rcol
3956 are set to the destination (row,col) of the rook that moved.
3958 Returns 1 if castling occurred, 0 if not.
3960 Note: Only handles a max of 1 castling move, so be sure
3961 to call too_many_diffs() first.
3963 static int check_castle_draw(newb, oldb, rrow, rcol)
3970 /* For each type of castling... */
3971 for (i=0; i<4; ++i) {
3972 r = castling_matrix[i];
3974 /* Check the 4 squares involved in the castling move */
3976 for (j=1; j<=4; ++j) {
3977 if (newb[r[0]][r[j]] == oldb[r[0]][r[j]]) {
3984 /* All 4 changed, so it must be a castling move */
3993 static int damage[BOARD_SIZE][BOARD_SIZE];
3996 * event handler for redrawing the board
3998 void DrawPosition( repaint, board)
3999 /*Boolean*/int repaint;
4003 static int lastFlipView = 0;
4004 static int lastBoardValid = 0;
4005 static Board lastBoard;
4008 if (board == NULL) {
4009 if (!lastBoardValid) return;
4012 if (!lastBoardValid || lastFlipView != flipView) {
4013 // XtSetArg(args[0], XtNleftBitmap, (flipView ? xMarkPixmap : None));
4014 // XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flip View"),
4019 * It would be simpler to clear the window with XClearWindow()
4020 * but this causes a very distracting flicker.
4023 if (!repaint && lastBoardValid && lastFlipView == flipView)
4025 /* If too much changes (begin observing new game, etc.), don't
4027 do_flash = too_many_diffs(board, lastBoard) ? 0 : 1;
4029 /* Special check for castling so we don't flash both the king
4030 and the rook (just flash the king). */
4033 if (check_castle_draw(board, lastBoard, &rrow, &rcol))
4035 /* Draw rook with NO flashing. King will be drawn flashing later */
4036 DrawSquare(rrow, rcol, board[rrow][rcol], 0);
4037 lastBoard[rrow][rcol] = board[rrow][rcol];
4041 /* First pass -- Draw (newly) empty squares and repair damage.
4042 This prevents you from having a piece show up twice while it
4043 is flashing on its new square */
4044 for (i = 0; i < BOARD_HEIGHT; i++)
4045 for (j = 0; j < BOARD_WIDTH; j++)
4046 if ((board[i][j] != lastBoard[i][j] && board[i][j] == EmptySquare)
4049 DrawSquare(i, j, board[i][j], 0);
4050 damage[i][j] = False;
4053 /* Second pass -- Draw piece(s) in new position and flash them */
4054 for (i = 0; i < BOARD_HEIGHT; i++)
4055 for (j = 0; j < BOARD_WIDTH; j++)
4056 if (board[i][j] != lastBoard[i][j])
4058 DrawSquare(i, j, board[i][j], do_flash);
4070 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
4072 cairo_set_line_width (cr, lineGap);
4074 /* TODO: use appdata colors */
4075 cairo_set_source_rgba (cr, 0, 1, 0, 1.0);
4079 for (i = 0; i < BOARD_HEIGHT + 1; i++)
4082 x2 = lineGap + BOARD_WIDTH * (squareSize + lineGap);
4083 y1 = y2 = lineGap / 2 + (i * (squareSize + lineGap));
4085 cairo_move_to (cr, x1, y1);
4086 cairo_rel_line_to (cr, x2,0);
4090 for (j = 0; j < BOARD_WIDTH + 1; j++)
4093 y2 = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
4094 x1 = x2 = lineGap / 2 + (j * (squareSize + lineGap));
4096 cairo_move_to (cr, x1, y1);
4097 cairo_rel_line_to (cr, 0, y2);
4106 for (i = 0; i < BOARD_HEIGHT; i++)
4107 for (j = 0; j < BOARD_WIDTH; j++)
4109 DrawSquare(i, j, board[i][j], 0);
4110 damage[i][j] = False;
4114 CopyBoard(lastBoard, board);
4116 lastFlipView = flipView;
4118 /* Draw highlights */
4119 if (pm1X >= 0 && pm1Y >= 0)
4121 drawHighlight(pm1X, pm1Y, LINE_TYPE_PRE);
4123 if (pm2X >= 0 && pm2Y >= 0)
4125 drawHighlight(pm2X, pm2Y, LINE_TYPE_PRE);
4127 if (hi1X >= 0 && hi1Y >= 0)
4129 drawHighlight(hi1X, hi1Y, LINE_TYPE_HIGHLIGHT);
4131 if (hi2X >= 0 && hi2Y >= 0)
4133 drawHighlight(hi2X, hi2Y, LINE_TYPE_HIGHLIGHT);
4136 /* If piece being dragged around board, must redraw that too */
4143 * event handler for parsing user moves
4145 // [HGM] This routine will need quite some reworking. Although the backend still supports the old
4146 // way of doing things, by calling UserMoveEvent() to test the legality of the move and then perform
4147 // it at the end, and doing all kind of preliminary tests here (e.g. to weed out self-captures), it
4148 // should be made to use the new way, of calling UserMoveTest early to determine the legality of the
4149 // move, (which will weed out the illegal selfcaptures and moves into the holdings, and flag promotions),
4150 // and at the end FinishMove() to perform the move after optional promotion popups.
4151 // For now I patched it to allow self-capture with King, and suppress clicks between board and holdings.
4152 void HandleUserMove(w, event, prms, nprms)
4159 Boolean saveAnimate;
4160 static int second = 0;
4162 if (w != boardWidget || errorExitStatus != -1) return;
4164 if (event->type == ButtonPress) ErrorPopDown();
4167 if (event->type == ButtonPress) {
4168 // XtPopdown(promotionShell);
4169 // XtDestroyWidget(promotionShell);
4170 promotionUp = False;
4178 x = EventToSquare(event->xbutton.x, BOARD_WIDTH);
4179 y = EventToSquare(event->xbutton.y, BOARD_HEIGHT);
4180 if (!flipView && y >= 0) {
4181 y = BOARD_HEIGHT - 1 - y;
4183 if (flipView && x >= 0) {
4184 x = BOARD_WIDTH - 1 - x;
4187 /* [HGM] holdings: next 5 lines: ignore all clicks between board and holdings */
4188 if(event->type == ButtonPress
4189 && ( x == BOARD_LEFT-1 ||
4191 (x == BOARD_LEFT-2 && y < BOARD_HEIGHT-gameInfo.holdingsSize ) ||
4192 (x == BOARD_RGHT+1 && y >= gameInfo.holdingsSize)) )
4196 if (event->type == ButtonPress) {
4198 if (OKToStartUserMove(x, y)) {
4202 DragPieceBegin(event->xbutton.x, event->xbutton.y);
4203 if (appData.highlightDragging) {
4204 SetHighlights(x, y, -1, -1);
4212 if (event->type == ButtonPress && gameMode != EditPosition &&
4217 /* Check if clicking again on the same color piece */
4218 fromP = boards[currentMove][fromY][fromX];
4219 toP = boards[currentMove][y][x];
4220 if ((WhitePawn <= fromP && fromP < WhiteKing && // [HGM] this test should go, as UserMoveTest now does it.
4221 WhitePawn <= toP && toP <= WhiteKing) || // For now I made it less critical by exempting King
4222 (BlackPawn <= fromP && fromP < BlackKing && // moves, to not interfere with FRC castlings.
4223 BlackPawn <= toP && toP <= BlackKing)) {
4224 /* Clicked again on same color piece -- changed his mind */
4225 second = (x == fromX && y == fromY);
4226 if (appData.highlightDragging) {
4227 SetHighlights(x, y, -1, -1);
4231 if (OKToStartUserMove(x, y)) {
4234 DragPieceBegin(event->xbutton.x, event->xbutton.y);
4240 if (event->type == ButtonRelease && x == fromX && y == fromY) {
4241 DragPieceEnd(event->xbutton.x, event->xbutton.y);
4242 if (appData.animateDragging) {
4243 /* Undo animation damage if any */
4244 DrawPosition(FALSE, NULL);
4247 /* Second up/down in same square; just abort move */
4252 ClearPremoveHighlights();
4254 /* First upclick in same square; start click-click mode */
4255 SetHighlights(x, y, -1, -1);
4260 /* Completed move */
4263 saveAnimate = appData.animate;
4264 if (event->type == ButtonPress) {
4265 /* Finish clickclick move */
4266 if (appData.animate || appData.highlightLastMove) {
4267 SetHighlights(fromX, fromY, toX, toY);
4272 /* Finish drag move */
4273 if (appData.highlightLastMove) {
4274 SetHighlights(fromX, fromY, toX, toY);
4278 DragPieceEnd(event->xbutton.x, event->xbutton.y);
4279 /* Don't animate move and drag both */
4280 appData.animate = FALSE;
4282 if (IsPromotion(fromX, fromY, toX, toY)) {
4283 if (appData.alwaysPromoteToQueen) {
4284 UserMoveEvent(fromX, fromY, toX, toY, 'q');
4285 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
4286 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
4289 SetHighlights(fromX, fromY, toX, toY);
4293 UserMoveEvent(fromX, fromY, toX, toY, NULLCHAR);
4294 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
4295 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
4298 appData.animate = saveAnimate;
4299 if (appData.animate || appData.animateDragging) {
4300 /* Undo animation damage if needed */
4301 DrawPosition(FALSE, NULL);
4305 void AnimateUserMove (Widget w, XEvent * event,
4306 String * params, Cardinal * nParams)
4308 DragPieceMove(event->xmotion.x, event->xmotion.y);
4311 Widget CommentCreate(name, text, mutable, callback, lines)
4313 int /*Boolean*/ mutable;
4314 XtCallbackProc callback;
4318 Widget shell, layout, form, edit, b_ok, b_cancel, b_clear, b_close, b_edit;
4323 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4324 XtGetValues(boardWidget, args, j);
4327 XtSetArg(args[j], XtNresizable, True); j++;
4330 XtCreatePopupShell(name, topLevelShellWidgetClass,
4331 shellWidget, args, j);
4334 XtCreatePopupShell(name, transientShellWidgetClass,
4335 shellWidget, args, j);
4338 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
4339 layoutArgs, XtNumber(layoutArgs));
4341 XtCreateManagedWidget("form", formWidgetClass, layout,
4342 formArgs, XtNumber(formArgs));
4346 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
4347 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
4349 XtSetArg(args[j], XtNstring, text); j++;
4350 XtSetArg(args[j], XtNtop, XtChainTop); j++;
4351 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4352 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4353 XtSetArg(args[j], XtNright, XtChainRight); j++;
4354 XtSetArg(args[j], XtNresizable, True); j++;
4355 XtSetArg(args[j], XtNwidth, bw_width); j++; /*force wider than buttons*/
4357 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
4359 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
4360 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
4362 XtSetArg(args[j], XtNautoFill, True); j++;
4363 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
4365 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
4369 XtSetArg(args[j], XtNfromVert, edit); j++;
4370 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4371 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4372 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4373 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4375 XtCreateManagedWidget(_("ok"), commandWidgetClass, form, args, j);
4376 XtAddCallback(b_ok, XtNcallback, callback, (XtPointer) 0);
4379 XtSetArg(args[j], XtNfromVert, edit); j++;
4380 XtSetArg(args[j], XtNfromHoriz, b_ok); j++;
4381 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4382 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4383 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4384 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4386 XtCreateManagedWidget(_("cancel"), commandWidgetClass, form, args, j);
4387 XtAddCallback(b_cancel, XtNcallback, callback, (XtPointer) 0);
4390 XtSetArg(args[j], XtNfromVert, edit); j++;
4391 XtSetArg(args[j], XtNfromHoriz, b_cancel); j++;
4392 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4393 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4394 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4395 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4397 XtCreateManagedWidget(_("clear"), commandWidgetClass, form, args, j);
4398 XtAddCallback(b_clear, XtNcallback, callback, (XtPointer) 0);
4401 XtSetArg(args[j], XtNfromVert, edit); j++;
4402 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4403 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4404 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4405 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4407 XtCreateManagedWidget(_("close"), commandWidgetClass, form, args, j);
4408 XtAddCallback(b_close, XtNcallback, callback, (XtPointer) 0);
4411 XtSetArg(args[j], XtNfromVert, edit); j++;
4412 XtSetArg(args[j], XtNfromHoriz, b_close); j++;
4413 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4414 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4415 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4416 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4418 XtCreateManagedWidget(_("edit"), commandWidgetClass, form, args, j);
4419 XtAddCallback(b_edit, XtNcallback, callback, (XtPointer) 0);
4422 XtRealizeWidget(shell);
4424 if (commentX == -1) {
4427 Dimension pw_height;
4428 Dimension ew_height;
4431 XtSetArg(args[j], XtNheight, &ew_height); j++;
4432 XtGetValues(edit, args, j);
4435 XtSetArg(args[j], XtNheight, &pw_height); j++;
4436 XtGetValues(shell, args, j);
4437 commentH = pw_height + (lines - 1) * ew_height;
4438 commentW = bw_width - 16;
4440 XSync(xDisplay, False);
4442 /* This code seems to tickle an X bug if it is executed too soon
4443 after xboard starts up. The coordinates get transformed as if
4444 the main window was positioned at (0, 0).
4446 XtTranslateCoords(shellWidget,
4447 (bw_width - commentW) / 2, 0 - commentH / 2,
4448 &commentX, &commentY);
4450 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
4451 RootWindowOfScreen(XtScreen(shellWidget)),
4452 (bw_width - commentW) / 2, 0 - commentH / 2,
4457 if (commentY < 0) commentY = 0; /*avoid positioning top offscreen*/
4460 XtSetArg(args[j], XtNheight, commentH); j++;
4461 XtSetArg(args[j], XtNwidth, commentW); j++;
4462 XtSetArg(args[j], XtNx, commentX); j++;
4463 XtSetArg(args[j], XtNy, commentY); j++;
4464 XtSetValues(shell, args, j);
4465 XtSetKeyboardFocus(shell, edit);
4470 /* Used for analysis window and ICS input window */
4471 Widget MiscCreate(name, text, mutable, callback, lines)
4473 int /*Boolean*/ mutable;
4474 XtCallbackProc callback;
4478 Widget shell, layout, form, edit;
4480 Dimension bw_width, pw_height, ew_height, w, h;
4486 XtSetArg(args[j], XtNresizable, True); j++;
4489 XtCreatePopupShell(name, topLevelShellWidgetClass,
4490 shellWidget, args, j);
4493 XtCreatePopupShell(name, transientShellWidgetClass,
4494 shellWidget, args, j);
4497 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
4498 layoutArgs, XtNumber(layoutArgs));
4500 XtCreateManagedWidget("form", formWidgetClass, layout,
4501 formArgs, XtNumber(formArgs));
4505 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
4506 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
4508 XtSetArg(args[j], XtNstring, text); j++;
4509 XtSetArg(args[j], XtNtop, XtChainTop); j++;
4510 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4511 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4512 XtSetArg(args[j], XtNright, XtChainRight); j++;
4513 XtSetArg(args[j], XtNresizable, True); j++;
4515 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
4517 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
4518 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
4520 XtSetArg(args[j], XtNautoFill, True); j++;
4521 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
4523 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
4525 XtRealizeWidget(shell);
4528 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4529 XtGetValues(boardWidget, args, j);
4532 XtSetArg(args[j], XtNheight, &ew_height); j++;
4533 XtGetValues(edit, args, j);
4536 XtSetArg(args[j], XtNheight, &pw_height); j++;
4537 XtGetValues(shell, args, j);
4538 h = pw_height + (lines - 1) * ew_height;
4541 XSync(xDisplay, False);
4543 /* This code seems to tickle an X bug if it is executed too soon
4544 after xboard starts up. The coordinates get transformed as if
4545 the main window was positioned at (0, 0).
4547 XtTranslateCoords(shellWidget, (bw_width - w) / 2, 0 - h / 2, &x, &y);
4549 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
4550 RootWindowOfScreen(XtScreen(shellWidget)),
4551 (bw_width - w) / 2, 0 - h / 2, &xx, &yy, &junk);
4555 if (y < 0) y = 0; /*avoid positioning top offscreen*/
4558 XtSetArg(args[j], XtNheight, h); j++;
4559 XtSetArg(args[j], XtNwidth, w); j++;
4560 XtSetArg(args[j], XtNx, x); j++;
4561 XtSetArg(args[j], XtNy, y); j++;
4562 XtSetValues(shell, args, j);
4568 static int savedIndex; /* gross that this is global */
4570 void EditCommentPopUp(index, title, text)
4579 if (text == NULL) text = "";
4581 if (editShell == NULL) {
4583 CommentCreate(title, text, True, EditCommentCallback, 4);
4584 XtRealizeWidget(editShell);
4585 CatchDeleteWindow(editShell, "EditCommentPopDown");
4587 edit = XtNameToWidget(editShell, "*form.text");
4589 XtSetArg(args[j], XtNstring, text); j++;
4590 XtSetValues(edit, args, j);
4592 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4593 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4594 XtSetValues(editShell, args, j);
4597 XtPopup(editShell, XtGrabNone);
4601 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
4602 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
4606 void EditCommentCallback(w, client_data, call_data)
4608 XtPointer client_data, call_data;
4616 XtSetArg(args[j], XtNlabel, &name); j++;
4617 XtGetValues(w, args, j);
4619 if (strcmp(name, _("ok")) == 0) {
4620 edit = XtNameToWidget(editShell, "*form.text");
4622 XtSetArg(args[j], XtNstring, &val); j++;
4623 XtGetValues(edit, args, j);
4624 ReplaceComment(savedIndex, val);
4625 EditCommentPopDown();
4626 } else if (strcmp(name, _("cancel")) == 0) {
4627 EditCommentPopDown();
4628 } else if (strcmp(name, _("clear")) == 0) {
4629 edit = XtNameToWidget(editShell, "*form.text");
4630 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
4631 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
4635 void EditCommentPopDown()
4640 if (!editUp) return;
4642 XtSetArg(args[j], XtNx, &commentX); j++;
4643 XtSetArg(args[j], XtNy, &commentY); j++;
4644 XtSetArg(args[j], XtNheight, &commentH); j++;
4645 XtSetArg(args[j], XtNwidth, &commentW); j++;
4646 XtGetValues(editShell, args, j);
4647 XtPopdown(editShell);
4650 XtSetArg(args[j], XtNleftBitmap, None); j++;
4651 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
4655 void ICSInputBoxPopUp()
4660 char *title = _("ICS Input");
4663 if (ICSInputShell == NULL) {
4664 ICSInputShell = MiscCreate(title, "", True, NULL, 1);
4665 tr = XtParseTranslationTable(ICSInputTranslations);
4666 edit = XtNameToWidget(ICSInputShell, "*form.text");
4667 XtOverrideTranslations(edit, tr);
4668 XtRealizeWidget(ICSInputShell);
4669 CatchDeleteWindow(ICSInputShell, "ICSInputBoxPopDown");
4672 edit = XtNameToWidget(ICSInputShell, "*form.text");
4674 XtSetArg(args[j], XtNstring, ""); j++;
4675 XtSetValues(edit, args, j);
4677 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4678 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4679 XtSetValues(ICSInputShell, args, j);
4682 XtPopup(ICSInputShell, XtGrabNone);
4683 XtSetKeyboardFocus(ICSInputShell, edit);
4685 ICSInputBoxUp = True;
4687 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
4688 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
4692 void ICSInputSendText()
4699 edit = XtNameToWidget(ICSInputShell, "*form.text");
4701 XtSetArg(args[j], XtNstring, &val); j++;
4702 XtGetValues(edit, args, j);
4703 SendMultiLineToICS(val);
4704 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
4705 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
4708 void ICSInputBoxPopDown()
4713 if (!ICSInputBoxUp) return;
4715 XtPopdown(ICSInputShell);
4716 ICSInputBoxUp = False;
4718 XtSetArg(args[j], XtNleftBitmap, None); j++;
4719 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
4723 void CommentPopUp(title, text)
4730 if (commentShell == NULL) {
4732 CommentCreate(title, text, False, CommentCallback, 4);
4733 XtRealizeWidget(commentShell);
4734 CatchDeleteWindow(commentShell, "CommentPopDown");
4736 edit = XtNameToWidget(commentShell, "*form.text");
4738 XtSetArg(args[j], XtNstring, text); j++;
4739 XtSetValues(edit, args, j);
4741 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4742 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4743 XtSetValues(commentShell, args, j);
4746 XtPopup(commentShell, XtGrabNone);
4747 XSync(xDisplay, False);
4752 void AnalysisPopUp(title, text)
4759 if (analysisShell == NULL) {
4760 analysisShell = MiscCreate(title, text, False, NULL, 4);
4761 XtRealizeWidget(analysisShell);
4762 CatchDeleteWindow(analysisShell, "AnalysisPopDown");
4765 edit = XtNameToWidget(analysisShell, "*form.text");
4767 XtSetArg(args[j], XtNstring, text); j++;
4768 XtSetValues(edit, args, j);
4770 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4771 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4772 XtSetValues(analysisShell, args, j);
4776 XtPopup(analysisShell, XtGrabNone);
4778 XSync(xDisplay, False);
4783 void CommentCallback(w, client_data, call_data)
4785 XtPointer client_data, call_data;
4792 XtSetArg(args[j], XtNlabel, &name); j++;
4793 XtGetValues(w, args, j);
4795 if (strcmp(name, _("close")) == 0) {
4797 } else if (strcmp(name, _("edit")) == 0) {
4804 void CommentPopDown()
4809 if (!commentUp) return;
4811 XtSetArg(args[j], XtNx, &commentX); j++;
4812 XtSetArg(args[j], XtNy, &commentY); j++;
4813 XtSetArg(args[j], XtNwidth, &commentW); j++;
4814 XtSetArg(args[j], XtNheight, &commentH); j++;
4815 XtGetValues(commentShell, args, j);
4816 XtPopdown(commentShell);
4817 XSync(xDisplay, False);
4821 void AnalysisPopDown()
4823 if (!analysisUp) return;
4824 XtPopdown(analysisShell);
4825 XSync(xDisplay, False);
4827 if (appData.icsEngineAnalyze) ExitAnalyzeMode(); /* [DM] icsEngineAnalyze */
4831 void FileNamePopUp(label, def, proc, openMode)
4838 Widget popup, layout, dialog, edit;
4844 fileProc = proc; /* I can't see a way not */
4845 fileOpenMode = openMode; /* to use globals here */
4848 XtSetArg(args[i], XtNresizable, True); i++;
4849 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
4850 XtSetArg(args[i], XtNtitle, XtNewString(_("File name prompt"))); i++;
4851 fileNameShell = popup =
4852 XtCreatePopupShell("File name prompt", transientShellWidgetClass,
4853 shellWidget, args, i);
4856 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
4857 layoutArgs, XtNumber(layoutArgs));
4860 XtSetArg(args[i], XtNlabel, label); i++;
4861 XtSetArg(args[i], XtNvalue, def); i++;
4862 XtSetArg(args[i], XtNborderWidth, 0); i++;
4863 dialog = XtCreateManagedWidget("fileName", dialogWidgetClass,
4866 XawDialogAddButton(dialog, _("ok"), FileNameCallback, (XtPointer) dialog);
4867 XawDialogAddButton(dialog, _("cancel"), FileNameCallback,
4868 (XtPointer) dialog);
4870 XtRealizeWidget(popup);
4871 CatchDeleteWindow(popup, "FileNamePopDown");
4873 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
4874 &x, &y, &win_x, &win_y, &mask);
4876 XtSetArg(args[0], XtNx, x - 10);
4877 XtSetArg(args[1], XtNy, y - 30);
4878 XtSetValues(popup, args, 2);
4880 XtPopup(popup, XtGrabExclusive);
4883 edit = XtNameToWidget(dialog, "*value");
4884 XtSetKeyboardFocus(popup, edit);
4887 void FileNamePopDown()
4889 if (!filenameUp) return;
4890 XtPopdown(fileNameShell);
4891 XtDestroyWidget(fileNameShell);
4896 void FileNameCallback(w, client_data, call_data)
4898 XtPointer client_data, call_data;
4903 XtSetArg(args[0], XtNlabel, &name);
4904 XtGetValues(w, args, 1);
4906 if (strcmp(name, _("cancel")) == 0) {
4911 FileNameAction(w, NULL, NULL, NULL);
4914 void FileNameAction(w, event, prms, nprms)
4926 name = XawDialogGetValueString(w = XtParent(w));
4928 if ((name != NULL) && (*name != NULLCHAR)) {
4930 XtPopdown(w = XtParent(XtParent(w)));
4934 p = strrchr(buf, ' ');
4941 fullname = ExpandPathName(buf);
4943 ErrorPopUp(_("Error"), _("Can't open file"), FALSE);
4946 f = fopen(fullname, fileOpenMode);
4948 DisplayError(_("Failed to open file"), errno);
4950 (void) (*fileProc)(f, index, buf);
4957 XtPopdown(w = XtParent(XtParent(w)));
4963 void PromotionPopUp()
4966 Widget dialog, layout;
4968 Dimension bw_width, pw_width;
4972 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4973 XtGetValues(boardWidget, args, j);
4976 XtSetArg(args[j], XtNresizable, True); j++;
4977 XtSetArg(args[j], XtNtitle, XtNewString(_("Promotion"))); j++;
4979 XtCreatePopupShell("Promotion", transientShellWidgetClass,
4980 shellWidget, args, j);
4982 XtCreateManagedWidget(layoutName, formWidgetClass, promotionShell,
4983 layoutArgs, XtNumber(layoutArgs));
4986 XtSetArg(args[j], XtNlabel, _("Promote to what?")); j++;
4987 XtSetArg(args[j], XtNborderWidth, 0); j++;
4988 dialog = XtCreateManagedWidget("promotion", dialogWidgetClass,
4991 if(gameInfo.variant != VariantShogi) {
4992 XawDialogAddButton(dialog, _("Queen"), PromotionCallback,
4993 (XtPointer) dialog);
4994 XawDialogAddButton(dialog, _("Rook"), PromotionCallback,
4995 (XtPointer) dialog);
4996 XawDialogAddButton(dialog, _("Bishop"), PromotionCallback,
4997 (XtPointer) dialog);
4998 XawDialogAddButton(dialog, _("Knight"), PromotionCallback,
4999 (XtPointer) dialog);
5000 if (!appData.testLegality || gameInfo.variant == VariantSuicide ||
5001 gameInfo.variant == VariantGiveaway) {
5002 XawDialogAddButton(dialog, _("King"), PromotionCallback,
5003 (XtPointer) dialog);
5005 if(gameInfo.variant == VariantCapablanca ||
5006 gameInfo.variant == VariantGothic ||
5007 gameInfo.variant == VariantCapaRandom) {
5008 XawDialogAddButton(dialog, _("Archbishop"), PromotionCallback,
5009 (XtPointer) dialog);
5010 XawDialogAddButton(dialog, _("Chancellor"), PromotionCallback,
5011 (XtPointer) dialog);
5013 } else // [HGM] shogi
5015 XawDialogAddButton(dialog, _("Promote"), PromotionCallback,
5016 (XtPointer) dialog);
5017 XawDialogAddButton(dialog, _("Defer"), PromotionCallback,
5018 (XtPointer) dialog);
5020 XawDialogAddButton(dialog, _("cancel"), PromotionCallback,
5021 (XtPointer) dialog);
5023 XtRealizeWidget(promotionShell);
5024 CatchDeleteWindow(promotionShell, "PromotionPopDown");
5027 XtSetArg(args[j], XtNwidth, &pw_width); j++;
5028 XtGetValues(promotionShell, args, j);
5030 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
5031 lineGap + squareSize/3 +
5032 ((toY == BOARD_HEIGHT-1) ^ (flipView) ?
5033 0 : 6*(squareSize + lineGap)), &x, &y);
5036 XtSetArg(args[j], XtNx, x); j++;
5037 XtSetArg(args[j], XtNy, y); j++;
5038 XtSetValues(promotionShell, args, j);
5040 XtPopup(promotionShell, XtGrabNone);
5045 void PromotionPopDown()
5047 if (!promotionUp) return;
5048 XtPopdown(promotionShell);
5049 XtDestroyWidget(promotionShell);
5050 promotionUp = False;
5053 void PromotionCallback(w, client_data, call_data)
5055 XtPointer client_data, call_data;
5061 XtSetArg(args[0], XtNlabel, &name);
5062 XtGetValues(w, args, 1);
5066 if (fromX == -1) return;
5068 if (strcmp(name, _("cancel")) == 0) {
5072 } else if (strcmp(name, _("Knight")) == 0) {
5074 } else if (strcmp(name, _("Promote")) == 0) {
5076 } else if (strcmp(name, _("Defer")) == 0) {
5079 promoChar = ToLower(name[0]);
5082 UserMoveEvent(fromX, fromY, toX, toY, promoChar);
5084 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
5085 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
5090 void ErrorCallback(w, client_data, call_data)
5092 XtPointer client_data, call_data;
5095 XtPopdown(w = XtParent(XtParent(XtParent(w))));
5097 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5103 if (!errorUp) return;
5107 gtk_widget_destroy(GTK_WIDGET(GUI_Error));
5109 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5114 void ErrorPopUp(title, label, modal)
5115 char *title, *label;
5118 GUI_Error = gtk_message_dialog_new(GTK_WINDOW(GUI_Window),
5119 GTK_DIALOG_DESTROY_WITH_PARENT,
5124 gtk_window_set_title(GTK_WINDOW(GUI_Error),(gchar *) title);
5127 gtk_dialog_run(GTK_DIALOG(GUI_Error));
5128 gtk_widget_destroy(GTK_WIDGET(GUI_Error));
5132 g_signal_connect_swapped (GUI_Error, "response",
5133 G_CALLBACK (ErrorPopDownProc),
5136 gtk_widget_show(GTK_WIDGET(GUI_Error));
5142 /* Disable all user input other than deleting the window */
5143 static int frozen = 0;
5147 /* Grab by a widget that doesn't accept input */
5148 // XtAddGrab(messageWidget, TRUE, FALSE);
5152 /* Undo a FreezeUI */
5155 if (!frozen) return;
5156 // XtRemoveGrab(messageWidget);
5160 char *ModeToWidgetName(mode)
5164 case BeginningOfGame:
5165 if (appData.icsActive)
5166 return "menuMode.ICS Client";
5167 else if (appData.noChessProgram ||
5168 *appData.cmailGameName != NULLCHAR)
5169 return "menuMode.Edit Game";
5171 return "menuMode.Machine Black";
5172 case MachinePlaysBlack:
5173 return "menuMode.Machine Black";
5174 case MachinePlaysWhite:
5175 return "menuMode.Machine White";
5177 return "menuMode.Analysis Mode";
5179 return "menuMode.Analyze File";
5180 case TwoMachinesPlay:
5181 return "menuMode.Two Machines";
5183 return "menuMode.Edit Game";
5184 case PlayFromGameFile:
5185 return "menuFile.Load Game";
5187 return "menuMode.Edit Position";
5189 return "menuMode.Training";
5190 case IcsPlayingWhite:
5191 case IcsPlayingBlack:
5195 return "menuMode.ICS Client";
5202 void ModeHighlight()
5204 static int oldPausing = FALSE;
5205 static GameMode oldmode = (GameMode) -1;
5208 // todo this toggling of the pause button doesn't seem to work?
5209 // e.g. select pause from buttonbar doesn't activate menumode.pause
5211 // if (!boardWidget || !XtIsRealized(boardWidget)) return;
5213 if (pausing != oldPausing) {
5214 oldPausing = pausing;
5215 gtk_button_set_relief(GTK_BUTTON (gtk_builder_get_object (builder, "menuMode.Pause")),pausing?GTK_RELIEF_NORMAL:GTK_RELIEF_NONE);
5216 /* toggle background color in showbuttonbar */
5217 if (appData.showButtonBar) {
5219 gtk_button_pressed(GTK_BUTTON (gtk_builder_get_object (builder, "buttonbar.Pause")));
5221 gtk_button_released(GTK_BUTTON (gtk_builder_get_object (builder, "buttonbar.Pause")));
5226 wname = ModeToWidgetName(oldmode);
5228 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, wname)),True);
5232 /* Maybe all the enables should be handled here, not just this one */
5233 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuMode.Training")),
5234 gameMode == Training || gameMode == PlayFromGameFile);
5239 * Button/menu procedures
5242 int LoadGamePopUp(f, gameNumber, title)
5247 cmailMsgLoaded = FALSE;
5248 if (gameNumber == 0) {
5249 int error = GameListBuild(f);
5251 DisplayError(_("Cannot build game list"), error);
5252 } else if (!ListEmpty(&gameList) &&
5253 ((ListGame *) gameList.tailPred)->number > 1) {
5254 GameListPopUp(f, title);
5260 return LoadGame(f, gameNumber, title, FALSE);
5264 void LoadNextPositionProc(w, event, prms, nprms)
5273 void LoadPrevPositionProc(w, event, prms, nprms)
5282 void ReloadPositionProc(w, event, prms, nprms)
5291 void LoadPositionProc(w, event, prms, nprms)
5297 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
5300 FileNamePopUp(_("Load position file name?"), "", LoadPosition, "rb");
5303 void SaveGameProc(w, event, prms, nprms)
5309 FileNamePopUp(_("Save game file name?"),
5310 DefaultFileName(appData.oldSaveStyle ? "game" : "pgn"),
5314 void SavePositionProc(w, event, prms, nprms)
5320 FileNamePopUp(_("Save position file name?"),
5321 DefaultFileName(appData.oldSaveStyle ? "pos" : "fen"),
5325 void ReloadCmailMsgProc(w, event, prms, nprms)
5331 ReloadCmailMsgEvent(FALSE);
5334 void MailMoveProc(w, event, prms, nprms)
5343 /* this variable is shared between CopyPositionProc and SendPositionSelection */
5344 static char *selected_fen_position=NULL;
5347 SendPositionSelection(Widget w, Atom *selection, Atom *target,
5348 Atom *type_return, XtPointer *value_return,
5349 unsigned long *length_return, int *format_return)
5351 char *selection_tmp;
5353 if (!selected_fen_position) return False; /* should never happen */
5354 if (*target == XA_STRING){
5355 /* note: since no XtSelectionDoneProc was registered, Xt will
5356 * automatically call XtFree on the value returned. So have to
5357 * make a copy of it allocated with XtMalloc */
5358 selection_tmp= XtMalloc(strlen(selected_fen_position)+16);
5359 strcpy(selection_tmp, selected_fen_position);
5361 *value_return=selection_tmp;
5362 *length_return=strlen(selection_tmp);
5363 *type_return=XA_STRING;
5364 *format_return = 8; /* bits per byte */
5371 /* note: when called from menu all parameters are NULL, so no clue what the
5372 * Widget which was clicked on was, or what the click event was
5374 void CopyPositionProc(w, event, prms, nprms)
5382 if (selected_fen_position) free(selected_fen_position);
5383 selected_fen_position = (char *)PositionToFEN(currentMove, NULL);
5384 if (!selected_fen_position) return;
5385 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
5387 SendPositionSelection,
5388 NULL/* lose_ownership_proc */ ,
5389 NULL/* transfer_done_proc */);
5391 free(selected_fen_position);
5392 selected_fen_position=NULL;
5396 /* function called when the data to Paste is ready */
5398 PastePositionCB(Widget w, XtPointer client_data, Atom *selection,
5399 Atom *type, XtPointer value, unsigned long *len, int *format)
5402 if (value==NULL || *len==0) return; /* nothing had been selected to copy */
5403 fenstr[*len]='\0'; /* normally this string is terminated, but be safe */
5404 EditPositionPasteFEN(fenstr);
5408 /* called when Paste Position button is pressed,
5409 * all parameters will be NULL */
5410 void PastePositionProc(w, event, prms, nprms)
5416 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
5417 /* (XtSelectionCallbackProc) */ PastePositionCB,
5418 NULL, /* client_data passed to PastePositionCB */
5420 /* better to use the time field from the event that triggered the
5421 * call to this function, but that isn't trivial to get
5429 SendGameSelection(Widget w, Atom *selection, Atom *target,
5430 Atom *type_return, XtPointer *value_return,
5431 unsigned long *length_return, int *format_return)
5433 char *selection_tmp;
5435 if (*target == XA_STRING){
5436 FILE* f = fopen(gameCopyFilename, "r");
5439 if (f == NULL) return False;
5443 selection_tmp = XtMalloc(len + 1);
5444 count = fread(selection_tmp, 1, len, f);
5446 XtFree(selection_tmp);
5449 selection_tmp[len] = NULLCHAR;
5450 *value_return = selection_tmp;
5451 *length_return = len;
5452 *type_return = XA_STRING;
5453 *format_return = 8; /* bits per byte */
5460 /* note: when called from menu all parameters are NULL, so no clue what the
5461 * Widget which was clicked on was, or what the click event was
5463 void CopyGameProc(w, event, prms, nprms)
5471 ret = SaveGameToFile(gameCopyFilename, FALSE);
5474 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
5477 NULL/* lose_ownership_proc */ ,
5478 NULL/* transfer_done_proc */);
5481 /* function called when the data to Paste is ready */
5483 PasteGameCB(Widget w, XtPointer client_data, Atom *selection,
5484 Atom *type, XtPointer value, unsigned long *len, int *format)
5487 if (value == NULL || *len == 0) {
5488 return; /* nothing had been selected to copy */
5490 f = fopen(gamePasteFilename, "w");
5492 DisplayError(_("Can't open temp file"), errno);
5495 fwrite(value, 1, *len, f);
5498 LoadGameFromFile(gamePasteFilename, 0, gamePasteFilename, TRUE);
5501 /* called when Paste Game button is pressed,
5502 * all parameters will be NULL */
5503 void PasteGameProc(w, event, prms, nprms)
5509 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
5510 /* (XtSelectionCallbackProc) */ PasteGameCB,
5511 NULL, /* client_data passed to PasteGameCB */
5513 /* better to use the time field from the event that triggered the
5514 * call to this function, but that isn't trivial to get
5524 SaveGameProc(NULL, NULL, NULL, NULL);
5527 void AnalyzeModeProc(w, event, prms, nprms)
5535 if (!first.analysisSupport) {
5536 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
5537 DisplayError(buf, 0);
5540 /* [DM] icsEngineAnalyze [HGM] This is horrible code; reverse the gameMode and isEngineAnalyze tests! */
5541 if (appData.icsActive) {
5542 if (gameMode != IcsObserving) {
5543 sprintf(buf,_("You are not observing a game"));
5544 DisplayError(buf, 0);
5546 if (appData.icsEngineAnalyze) {
5547 if (appData.debugMode)
5548 fprintf(debugFP, _("Found unexpected active ICS engine analyze \n"));
5554 /* if enable, use want disable icsEngineAnalyze */
5555 if (appData.icsEngineAnalyze) {
5560 appData.icsEngineAnalyze = TRUE;
5561 if (appData.debugMode)
5562 fprintf(debugFP, _("ICS engine analyze starting... \n"));
5564 if (!appData.showThinking)
5565 ShowThinkingProc(w,event,prms,nprms);
5570 void AnalyzeFileProc(w, event, prms, nprms)
5576 if (!first.analysisSupport) {
5578 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
5579 DisplayError(buf, 0);
5584 if (!appData.showThinking)
5585 ShowThinkingProc(w,event,prms,nprms);
5588 FileNamePopUp(_("File to analyze"), "", LoadGamePopUp, "rb");
5589 AnalysisPeriodicEvent(1);
5592 void IcsClientProc(w, event, prms, nprms)
5601 void EditGameProc(w, event, prms, nprms)
5610 void EditPositionProc(w, event, prms, nprms)
5616 EditPositionEvent();
5619 void TrainingProc(w, event, prms, nprms)
5628 void EditCommentProc(w, event, prms, nprms)
5635 EditCommentPopDown();
5641 void IcsInputBoxProc(w, event, prms, nprms)
5647 if (ICSInputBoxUp) {
5648 ICSInputBoxPopDown();
5654 void AdjuWhiteProc(w, event, prms, nprms)
5660 UserAdjudicationEvent(+1);
5663 void AdjuBlackProc(w, event, prms, nprms)
5669 UserAdjudicationEvent(-1);
5672 void AdjuDrawProc(w, event, prms, nprms)
5678 UserAdjudicationEvent(0);
5681 void EnterKeyProc(w, event, prms, nprms)
5687 if (ICSInputBoxUp == True)
5691 void StopObservingProc(w, event, prms, nprms)
5697 StopObservingEvent();
5700 void StopExaminingProc(w, event, prms, nprms)
5706 StopExaminingEvent();
5710 void ForwardProc(w, event, prms, nprms)
5720 void BackwardProc(w, event, prms, nprms)
5729 void ToStartProc(w, event, prms, nprms)
5738 void ToEndProc(w, event, prms, nprms)
5747 void RevertProc(w, event, prms, nprms)
5756 void TruncateGameProc(w, event, prms, nprms)
5762 TruncateGameEvent();
5764 void RetractMoveProc(w, event, prms, nprms)
5773 void AlwaysQueenProc(w, event, prms, nprms)
5781 appData.alwaysPromoteToQueen = !appData.alwaysPromoteToQueen;
5783 if (appData.alwaysPromoteToQueen) {
5784 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5786 XtSetArg(args[0], XtNleftBitmap, None);
5788 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
5792 void AnimateDraggingProc(w, event, prms, nprms)
5800 appData.animateDragging = !appData.animateDragging;
5802 if (appData.animateDragging) {
5803 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5806 XtSetArg(args[0], XtNleftBitmap, None);
5808 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Dragging"),
5812 void AnimateMovingProc(w, event, prms, nprms)
5820 appData.animate = !appData.animate;
5822 if (appData.animate) {
5823 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5826 XtSetArg(args[0], XtNleftBitmap, None);
5828 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
5832 void AutocommProc(w, event, prms, nprms)
5840 appData.autoComment = !appData.autoComment;
5842 if (appData.autoComment) {
5843 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5845 XtSetArg(args[0], XtNleftBitmap, None);
5847 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
5852 void AutoflagProc(w, event, prms, nprms)
5860 appData.autoCallFlag = !appData.autoCallFlag;
5862 if (appData.autoCallFlag) {
5863 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5865 XtSetArg(args[0], XtNleftBitmap, None);
5867 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
5871 void AutoflipProc(w, event, prms, nprms)
5879 appData.autoFlipView = !appData.autoFlipView;
5881 if (appData.autoFlipView) {
5882 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5884 XtSetArg(args[0], XtNleftBitmap, None);
5886 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flip View"),
5890 void AutobsProc(w, event, prms, nprms)
5898 appData.autoObserve = !appData.autoObserve;
5900 if (appData.autoObserve) {
5901 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5903 XtSetArg(args[0], XtNleftBitmap, None);
5905 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
5909 void AutoraiseProc(w, event, prms, nprms)
5917 appData.autoRaiseBoard = !appData.autoRaiseBoard;
5919 if (appData.autoRaiseBoard) {
5920 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5922 XtSetArg(args[0], XtNleftBitmap, None);
5924 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Raise Board"),
5928 void AutosaveProc(w, event, prms, nprms)
5936 appData.autoSaveGames = !appData.autoSaveGames;
5938 if (appData.autoSaveGames) {
5939 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5941 XtSetArg(args[0], XtNleftBitmap, None);
5943 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
5947 void BlindfoldProc(w, event, prms, nprms)
5955 appData.blindfold = !appData.blindfold;
5957 if (appData.blindfold) {
5958 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5960 XtSetArg(args[0], XtNleftBitmap, None);
5962 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Blindfold"),
5965 DrawPosition(True, NULL);
5968 void TestLegalityProc(w, event, prms, nprms)
5976 appData.testLegality = !appData.testLegality;
5978 if (appData.testLegality) {
5979 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5981 XtSetArg(args[0], XtNleftBitmap, None);
5983 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Test Legality"),
5988 void FlashMovesProc(w, event, prms, nprms)
5996 if (appData.flashCount == 0) {
5997 appData.flashCount = 3;
5999 appData.flashCount = -appData.flashCount;
6002 if (appData.flashCount > 0) {
6003 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6005 XtSetArg(args[0], XtNleftBitmap, None);
6007 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flash Moves"),
6011 void FlipViewProc(w, event, prms, nprms)
6017 flipView = !flipView;
6018 DrawPosition(True, NULL);
6021 void GetMoveListProc(w, event, prms, nprms)
6029 appData.getMoveList = !appData.getMoveList;
6031 if (appData.getMoveList) {
6032 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6035 XtSetArg(args[0], XtNleftBitmap, None);
6037 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
6042 void HighlightDraggingProc(w, event, prms, nprms)
6050 appData.highlightDragging = !appData.highlightDragging;
6052 if (appData.highlightDragging) {
6053 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6055 XtSetArg(args[0], XtNleftBitmap, None);
6057 XtSetValues(XtNameToWidget(menuBarWidget,
6058 "menuOptions.Highlight Dragging"), args, 1);
6062 void HighlightLastMoveProc(w, event, prms, nprms)
6070 appData.highlightLastMove = !appData.highlightLastMove;
6072 if (appData.highlightLastMove) {
6073 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6075 XtSetArg(args[0], XtNleftBitmap, None);
6077 XtSetValues(XtNameToWidget(menuBarWidget,
6078 "menuOptions.Highlight Last Move"), args, 1);
6081 void IcsAlarmProc(w, event, prms, nprms)
6089 appData.icsAlarm = !appData.icsAlarm;
6091 if (appData.icsAlarm) {
6092 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6094 XtSetArg(args[0], XtNleftBitmap, None);
6096 XtSetValues(XtNameToWidget(menuBarWidget,
6097 "menuOptions.ICS Alarm"), args, 1);
6100 void MoveSoundProc(w, event, prms, nprms)
6108 appData.ringBellAfterMoves = !appData.ringBellAfterMoves;
6110 if (appData.ringBellAfterMoves) {
6111 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6113 XtSetArg(args[0], XtNleftBitmap, None);
6115 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
6120 void OldSaveStyleProc(w, event, prms, nprms)
6128 appData.oldSaveStyle = !appData.oldSaveStyle;
6130 if (appData.oldSaveStyle) {
6131 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6133 XtSetArg(args[0], XtNleftBitmap, None);
6135 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Old Save Style"),
6139 void PeriodicUpdatesProc(w, event, prms, nprms)
6147 PeriodicUpdatesEvent(!appData.periodicUpdates);
6149 if (appData.periodicUpdates) {
6150 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6152 XtSetArg(args[0], XtNleftBitmap, None);
6154 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Periodic Updates"),
6158 void PonderNextMoveProc(w, event, prms, nprms)
6166 PonderNextMoveEvent(!appData.ponderNextMove);
6168 if (appData.ponderNextMove) {
6169 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6171 XtSetArg(args[0], XtNleftBitmap, None);
6173 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Ponder Next Move"),
6177 void PopupExitMessageProc(w, event, prms, nprms)
6185 appData.popupExitMessage = !appData.popupExitMessage;
6187 if (appData.popupExitMessage) {
6188 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6190 XtSetArg(args[0], XtNleftBitmap, None);
6192 XtSetValues(XtNameToWidget(menuBarWidget,
6193 "menuOptions.Popup Exit Message"), args, 1);
6196 void PopupMoveErrorsProc(w, event, prms, nprms)
6204 appData.popupMoveErrors = !appData.popupMoveErrors;
6206 if (appData.popupMoveErrors) {
6207 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6209 XtSetArg(args[0], XtNleftBitmap, None);
6211 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Popup Move Errors"),
6215 void PremoveProc(w, event, prms, nprms)
6223 appData.premove = !appData.premove;
6225 if (appData.premove) {
6226 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6228 XtSetArg(args[0], XtNleftBitmap, None);
6230 XtSetValues(XtNameToWidget(menuBarWidget,
6231 "menuOptions.Premove"), args, 1);
6234 void QuietPlayProc(w, event, prms, nprms)
6242 appData.quietPlay = !appData.quietPlay;
6244 if (appData.quietPlay) {
6245 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6247 XtSetArg(args[0], XtNleftBitmap, None);
6249 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Quiet Play"),
6253 void ShowThinkingProc(w, event, prms, nprms)
6261 appData.showThinking = !appData.showThinking; // [HGM] thinking: tken out of ShowThinkingEvent
6262 ShowThinkingEvent();
6264 // [HGM] thinking: currently no suc menu item; replaced by Hide Thinking (From Human)
6265 if (appData.showThinking) {
6266 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6268 XtSetArg(args[0], XtNleftBitmap, None);
6270 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Thinking"),
6275 void HideThinkingProc(w, event, prms, nprms)
6283 appData.hideThinkingFromHuman = !appData.hideThinkingFromHuman; // [HGM] thinking: tken out of ShowThinkingEvent
6284 ShowThinkingEvent();
6286 if (appData.hideThinkingFromHuman) {
6287 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6289 XtSetArg(args[0], XtNleftBitmap, None);
6291 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
6295 void InfoProc(w, event, prms, nprms)
6302 snprintf(buf, sizeof(buf), "xterm -e info --directory %s --directory . -f %s &",
6307 void ManProc(w, event, prms, nprms)
6315 if (nprms && *nprms > 0)
6319 snprintf(buf, sizeof(buf), "xterm -e man %s &", name);
6323 void HintProc(w, event, prms, nprms)
6332 void BookProc(w, event, prms, nprms)
6341 void DebugProc(w, event, prms, nprms)
6347 appData.debugMode = !appData.debugMode;
6350 void AboutGameProc(w, event, prms, nprms)
6359 void NothingProc(w, event, prms, nprms)
6368 void Iconify(w, event, prms, nprms)
6377 XtSetArg(args[0], XtNiconic, True);
6378 XtSetValues(shellWidget, args, 1);
6381 void DisplayMessage(message, extMessage)
6382 gchar *message, *extMessage;
6389 snprintf(buf, sizeof(buf), "%s %s", message, extMessage);
6392 message = extMessage;
6395 gtk_label_set_text( GTK_LABEL(gtk_builder_get_object (builder, "Messages")),message);
6400 void DisplayTitle(text)
6403 gchar title[MSG_SIZ];
6405 if (text == NULL) text = "";
6407 if (appData.titleInWindow)
6412 if (*text != NULLCHAR)
6414 strcpy(title, text);
6416 else if (appData.icsActive)
6418 snprintf(title, sizeof(title), "%s: %s", programName, appData.icsHost);
6420 else if (appData.cmailGameName[0] != NULLCHAR)
6422 snprintf(title,sizeof(title), "%s: %s", programName, "CMail");
6424 // [HGM] license: This stuff should really be done in back-end, but WinBoard already had a pop-up for it
6426 else if (gameInfo.variant == VariantGothic)
6428 strcpy(title, GOTHIC);
6432 else if (gameInfo.variant == VariantFalcon)
6434 strcpy(title, FALCON);
6437 else if (appData.noChessProgram)
6439 strcpy(title, programName);
6443 snprintf(title,sizeof(title), "%s: %s", programName, first.tidy);
6445 gtk_window_set_title(GTK_WINDOW(GUI_Window),title);
6451 void DisplayError(message, error)
6458 if (appData.debugMode || appData.matchMode) {
6459 fprintf(stderr, "%s: %s\n", programName, message);
6462 if (appData.debugMode || appData.matchMode) {
6463 fprintf(stderr, "%s: %s: %s\n",
6464 programName, message, strerror(error));
6466 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
6469 ErrorPopUp(_("Error"), message, FALSE);
6473 void DisplayMoveError(message)
6478 DrawPosition(FALSE, NULL);
6479 if (appData.debugMode || appData.matchMode) {
6480 fprintf(stderr, "%s: %s\n", programName, message);
6482 if (appData.popupMoveErrors) {
6483 ErrorPopUp(_("Error"), message, FALSE);
6485 DisplayMessage(message, "");
6490 void DisplayFatalError(message, error, status)
6496 errorExitStatus = status;
6498 fprintf(stderr, "%s: %s\n", programName, message);
6500 fprintf(stderr, "%s: %s: %s\n",
6501 programName, message, strerror(error));
6502 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
6505 if (appData.popupExitMessage && boardWidget && XtIsRealized(boardWidget)) {
6506 ErrorPopUp(status ? _("Fatal Error") : _("Exiting"), message, TRUE);
6512 void DisplayInformation(message)
6516 ErrorPopUp(_("Information"), message, TRUE);
6519 void DisplayNote(message)
6523 ErrorPopUp(_("Note"), message, FALSE);
6527 NullXErrorCheck(dpy, error_event)
6529 XErrorEvent *error_event;
6534 void DisplayIcsInteractionTitle(message)
6537 if (oldICSInteractionTitle == NULL) {
6538 /* Magic to find the old window title, adapted from vim */
6539 char *wina = getenv("WINDOWID");
6541 Window win = (Window) atoi(wina);
6542 Window root, parent, *children;
6543 unsigned int nchildren;
6544 int (*oldHandler)() = XSetErrorHandler(NullXErrorCheck);
6546 if (XFetchName(xDisplay, win, &oldICSInteractionTitle)) break;
6547 if (!XQueryTree(xDisplay, win, &root, &parent,
6548 &children, &nchildren)) break;
6549 if (children) XFree((void *)children);
6550 if (parent == root || parent == 0) break;
6553 XSetErrorHandler(oldHandler);
6555 if (oldICSInteractionTitle == NULL) {
6556 oldICSInteractionTitle = "xterm";
6559 printf("\033]0;%s\007", message);
6563 char pendingReplyPrefix[MSG_SIZ];
6564 ProcRef pendingReplyPR;
6566 void AskQuestionProc(w, event, prms, nprms)
6573 fprintf(stderr, _("AskQuestionProc needed 4 parameters, got %d\n"),
6577 AskQuestionEvent(prms[0], prms[1], prms[2], prms[3]);
6580 void AskQuestionPopDown()
6582 if (!askQuestionUp) return;
6583 XtPopdown(askQuestionShell);
6584 XtDestroyWidget(askQuestionShell);
6585 askQuestionUp = False;
6588 void AskQuestionReplyAction(w, event, prms, nprms)
6598 reply = XawDialogGetValueString(w = XtParent(w));
6599 strcpy(buf, pendingReplyPrefix);
6600 if (*buf) strcat(buf, " ");
6603 OutputToProcess(pendingReplyPR, buf, strlen(buf), &err);
6604 AskQuestionPopDown();
6606 if (err) DisplayFatalError(_("Error writing to chess program"), err, 0);
6609 void AskQuestionCallback(w, client_data, call_data)
6611 XtPointer client_data, call_data;
6616 XtSetArg(args[0], XtNlabel, &name);
6617 XtGetValues(w, args, 1);
6619 if (strcmp(name, _("cancel")) == 0) {
6620 AskQuestionPopDown();
6622 AskQuestionReplyAction(w, NULL, NULL, NULL);
6626 void AskQuestion(title, question, replyPrefix, pr)
6627 char *title, *question, *replyPrefix;
6631 Widget popup, layout, dialog, edit;
6637 strcpy(pendingReplyPrefix, replyPrefix);
6638 pendingReplyPR = pr;
6641 XtSetArg(args[i], XtNresizable, True); i++;
6642 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
6643 askQuestionShell = popup =
6644 XtCreatePopupShell(title, transientShellWidgetClass,
6645 shellWidget, args, i);
6648 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
6649 layoutArgs, XtNumber(layoutArgs));
6652 XtSetArg(args[i], XtNlabel, question); i++;
6653 XtSetArg(args[i], XtNvalue, ""); i++;
6654 XtSetArg(args[i], XtNborderWidth, 0); i++;
6655 dialog = XtCreateManagedWidget("question", dialogWidgetClass,
6658 XawDialogAddButton(dialog, _("enter"), AskQuestionCallback,
6659 (XtPointer) dialog);
6660 XawDialogAddButton(dialog, _("cancel"), AskQuestionCallback,
6661 (XtPointer) dialog);
6663 XtRealizeWidget(popup);
6664 CatchDeleteWindow(popup, "AskQuestionPopDown");
6666 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
6667 &x, &y, &win_x, &win_y, &mask);
6669 XtSetArg(args[0], XtNx, x - 10);
6670 XtSetArg(args[1], XtNy, y - 30);
6671 XtSetValues(popup, args, 2);
6673 XtPopup(popup, XtGrabExclusive);
6674 askQuestionUp = True;
6676 edit = XtNameToWidget(dialog, "*value");
6677 XtSetKeyboardFocus(popup, edit);
6685 if (*name == NULLCHAR) {
6687 } else if (strcmp(name, "$") == 0) {
6688 putc(BELLCHAR, stderr);
6691 snprintf(buf, sizeof(buf), "%s '%s' &", appData.soundProgram, name);
6699 PlaySound(appData.soundMove);
6705 PlaySound(appData.soundIcsWin);
6711 PlaySound(appData.soundIcsLoss);
6717 PlaySound(appData.soundIcsDraw);
6721 PlayIcsUnfinishedSound()
6723 PlaySound(appData.soundIcsUnfinished);
6729 PlaySound(appData.soundIcsAlarm);
6735 system("stty echo");
6741 system("stty -echo");
6745 Colorize(cc, continuation)
6750 int count, outCount, error;
6752 if (textColors[(int)cc].bg > 0) {
6753 if (textColors[(int)cc].fg > 0) {
6754 sprintf(buf, "\033[0;%d;%d;%dm", textColors[(int)cc].attr,
6755 textColors[(int)cc].fg, textColors[(int)cc].bg);
6757 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
6758 textColors[(int)cc].bg);
6761 if (textColors[(int)cc].fg > 0) {
6762 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
6763 textColors[(int)cc].fg);
6765 sprintf(buf, "\033[0;%dm", textColors[(int)cc].attr);
6768 count = strlen(buf);
6769 outCount = OutputToProcess(NoProc, buf, count, &error);
6770 if (outCount < count) {
6771 DisplayFatalError(_("Error writing to display"), error, 1);
6774 if (continuation) return;
6777 PlaySound(appData.soundShout);
6780 PlaySound(appData.soundSShout);
6783 PlaySound(appData.soundChannel1);
6786 PlaySound(appData.soundChannel);
6789 PlaySound(appData.soundKibitz);
6792 PlaySound(appData.soundTell);
6794 case ColorChallenge:
6795 PlaySound(appData.soundChallenge);
6798 PlaySound(appData.soundRequest);
6801 PlaySound(appData.soundSeek);
6812 return getpwuid(getuid())->pw_name;
6815 static char *ExpandPathName(path)
6818 static char static_buf[2000];
6819 char *d, *s, buf[2000];
6825 while (*s && isspace(*s))
6834 if (*(s+1) == '/') {
6835 strcpy(d, getpwuid(getuid())->pw_dir);
6840 *strchr(buf, '/') = 0;
6841 pwd = getpwnam(buf);
6844 fprintf(stderr, _("ERROR: Unknown user %s (in path %s)\n"),
6848 strcpy(d, pwd->pw_dir);
6849 strcat(d, strchr(s+1, '/'));
6860 static char host_name[MSG_SIZ];
6862 #if HAVE_GETHOSTNAME
6863 gethostname(host_name, MSG_SIZ);
6865 #else /* not HAVE_GETHOSTNAME */
6866 # if HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H
6867 sysinfo(SI_HOSTNAME, host_name, MSG_SIZ);
6869 # else /* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
6871 # endif/* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
6872 #endif /* not HAVE_GETHOSTNAME */
6875 gint delayedEventTimerTag = 0;
6876 DelayedEventCallback delayedEventCallback = 0;
6879 FireDelayedEvent(data)
6882 delayedEventTimerTag = 0;
6883 delayedEventCallback();
6887 ScheduleDelayedEvent(cb, millisec)
6888 DelayedEventCallback cb; long millisec;
6890 delayedEventCallback = cb;
6891 delayedEventTimerTag = gtk_timeout_add(millisec,(GtkFunction) FireDelayedEvent, NULL);
6894 DelayedEventCallback
6897 if (delayedEventTimerTag)
6899 return delayedEventCallback;
6908 CancelDelayedEvent()
6910 if (delayedEventTimerTag)
6912 gtk_timeout_remove(delayedEventTimerTag);
6913 delayedEventTimerTag = 0;
6919 gint loadGameTimerTag = 0;
6921 int LoadGameTimerRunning()
6923 return loadGameTimerTag != 0;
6926 int StopLoadGameTimer()
6928 if (loadGameTimerTag != 0) {
6929 gtk_timeout_remove(loadGameTimerTag);
6930 loadGameTimerTag = 0;
6938 LoadGameTimerCallback(data)
6941 loadGameTimerTag = 0;
6946 StartLoadGameTimer(millisec)
6950 gtk_timeout_add( millisec, (GtkFunction) LoadGameTimerCallback, NULL);
6953 gint analysisClockTag = 0;
6956 AnalysisClockCallback(data)
6959 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile
6960 || appData.icsEngineAnalyze)
6962 AnalysisPeriodicEvent(0);
6963 StartAnalysisClock();
6968 StartAnalysisClock()
6971 gtk_timeout_add( 2000,(GtkFunction) AnalysisClockCallback, NULL);
6974 gint clockTimerTag = 0;
6976 int ClockTimerRunning()
6978 return clockTimerTag != 0;
6981 int StopClockTimer()
6983 if (clockTimerTag != 0)
6985 gtk_timeout_remove(clockTimerTag);
6996 ClockTimerCallback(data)
7005 StartClockTimer(millisec)
7008 clockTimerTag = gtk_timeout_add(millisec,(GtkFunction) ClockTimerCallback,NULL);
7013 DisplayTimerLabel(w, color, timer, highlight)
7022 if (appData.clockMode) {
7023 sprintf(buf, "%s: %s", color, TimeString(timer));
7025 sprintf(buf, "%s ", color);
7027 gtk_label_set_text(GTK_LABEL(w),buf);
7029 /* check for low time warning */
7030 // Pixel foregroundOrWarningColor = timerForegroundPixel;
7033 // appData.lowTimeWarning &&
7034 // (timer / 1000) < appData.icsAlarmTime)
7035 // foregroundOrWarningColor = lowTimeWarningColor;
7037 // if (appData.clockMode) {
7038 // sprintf(buf, "%s: %s", color, TimeString(timer));
7039 // XtSetArg(args[0], XtNlabel, buf);
7041 // sprintf(buf, "%s ", color);
7042 // XtSetArg(args[0], XtNlabel, buf);
7047 // XtSetArg(args[1], XtNbackground, foregroundOrWarningColor);
7048 // XtSetArg(args[2], XtNforeground, timerBackgroundPixel);
7050 // XtSetArg(args[1], XtNbackground, timerBackgroundPixel);
7051 // XtSetArg(args[2], XtNforeground, foregroundOrWarningColor);
7054 // XtSetValues(w, args, 3);
7059 DisplayWhiteClock(timeRemaining, highlight)
7063 if(appData.noGUI) return;
7065 DisplayTimerLabel(GUI_Whiteclock, _("White"), timeRemaining, highlight);
7066 if (highlight && WindowIcon == BlackIcon)
7068 WindowIcon = WhiteIcon;
7069 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
7074 DisplayBlackClock(timeRemaining, highlight)
7078 if(appData.noGUI) return;
7080 DisplayTimerLabel(GUI_Blackclock, _("Black"), timeRemaining, highlight);
7081 if (highlight && WindowIcon == WhiteIcon)
7083 WindowIcon = BlackIcon;
7084 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
7102 int StartChildProcess(cmdLine, dir, pr)
7109 int to_prog[2], from_prog[2];
7113 if (appData.debugMode) {
7114 fprintf(stderr, "StartChildProcess (dir=\"%s\") %s\n",dir, cmdLine);
7117 /* We do NOT feed the cmdLine to the shell; we just
7118 parse it into blank-separated arguments in the
7119 most simple-minded way possible.
7122 strcpy(buf, cmdLine);
7127 if (p == NULL) break;
7132 SetUpChildIO(to_prog, from_prog);
7134 if ((pid = fork()) == 0) {
7136 // [HGM] PSWBTM: made order resistant against case where fd of created pipe was 0 or 1
7137 close(to_prog[1]); // first close the unused pipe ends
7138 close(from_prog[0]);
7139 dup2(to_prog[0], 0); // to_prog was created first, nd is the only one to use 0 or 1
7140 dup2(from_prog[1], 1);
7141 if(to_prog[0] >= 2) close(to_prog[0]); // if 0 or 1, the dup2 already cosed the original
7142 close(from_prog[1]); // and closing again loses one of the pipes!
7143 if(fileno(stderr) >= 2) // better safe than sorry...
7144 dup2(1, fileno(stderr)); /* force stderr to the pipe */
7146 if (dir[0] != NULLCHAR && chdir(dir) != 0) {
7151 nice(appData.niceEngines); // [HGM] nice: adjust priority of engine proc
7153 execvp(argv[0], argv);
7155 /* If we get here, exec failed */
7160 /* Parent process */
7162 close(from_prog[1]);
7164 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7167 cp->fdFrom = from_prog[0];
7168 cp->fdTo = to_prog[1];
7173 // [HGM] kill: implement the 'hard killing' of AS's Winboard_x
7174 static RETSIGTYPE AlarmCallBack(int n)
7180 DestroyChildProcess(pr, signalType)
7184 ChildProc *cp = (ChildProc *) pr;
7186 if (cp->kind != CPReal) return;
7188 if (signalType == 10) { // [HGM] kill: if it does not terminate in 3 sec, kill
7189 signal(SIGALRM, AlarmCallBack);
7191 if(wait((int *) 0) == -1) { // process does not terminate on its own accord
7192 kill(cp->pid, SIGKILL); // kill it forcefully
7193 wait((int *) 0); // and wait again
7197 kill(cp->pid, signalType == 9 ? SIGKILL : SIGTERM); // [HGM] kill: use hard kill if so requested
7199 /* Process is exiting either because of the kill or because of
7200 a quit command sent by the backend; either way, wait for it to die.
7209 InterruptChildProcess(pr)
7212 ChildProc *cp = (ChildProc *) pr;
7214 if (cp->kind != CPReal) return;
7215 (void) kill(cp->pid, SIGINT); /* stop it thinking */
7218 int OpenTelnet(host, port, pr)
7223 char cmdLine[MSG_SIZ];
7225 if (port[0] == NULLCHAR) {
7226 snprintf(cmdLine, sizeof(cmdLine), "%s %s", appData.telnetProgram, host);
7228 snprintf(cmdLine, sizeof(cmdLine), "%s %s %s", appData.telnetProgram, host, port);
7230 return StartChildProcess(cmdLine, "", pr);
7233 int OpenTCP(host, port, pr)
7239 DisplayFatalError(_("Socket support is not configured in"), 0, 2);
7240 #else /* !OMIT_SOCKETS */
7242 struct sockaddr_in sa;
7244 unsigned short uport;
7247 if ((s = socket(AF_INET, SOCK_STREAM, 6)) < 0) {
7251 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
7252 sa.sin_family = AF_INET;
7253 sa.sin_addr.s_addr = INADDR_ANY;
7254 uport = (unsigned short) 0;
7255 sa.sin_port = htons(uport);
7256 if (bind(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)) < 0) {
7260 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
7261 if (!(hp = gethostbyname(host))) {
7263 if (sscanf(host, "%d.%d.%d.%d", &b0, &b1, &b2, &b3) == 4) {
7264 hp = (struct hostent *) calloc(1, sizeof(struct hostent));
7265 hp->h_addrtype = AF_INET;
7267 hp->h_addr_list = (char **) calloc(2, sizeof(char *));
7268 hp->h_addr_list[0] = (char *) malloc(4);
7269 hp->h_addr_list[0][0] = b0;
7270 hp->h_addr_list[0][1] = b1;
7271 hp->h_addr_list[0][2] = b2;
7272 hp->h_addr_list[0][3] = b3;
7277 sa.sin_family = hp->h_addrtype;
7278 uport = (unsigned short) atoi(port);
7279 sa.sin_port = htons(uport);
7280 memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);
7282 if (connect(s, (struct sockaddr *) &sa,
7283 sizeof(struct sockaddr_in)) < 0) {
7287 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7294 #endif /* !OMIT_SOCKETS */
7299 int OpenCommPort(name, pr)
7306 fd = open(name, 2, 0);
7307 if (fd < 0) return errno;
7309 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7319 int OpenLoopback(pr)
7325 SetUpChildIO(to, from);
7327 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7330 cp->fdFrom = to[0]; /* note not from[0]; we are doing a loopback */
7337 int OpenRcmd(host, user, cmd, pr)
7338 char *host, *user, *cmd;
7341 DisplayFatalError(_("internal rcmd not implemented for Unix"), 0, 1);
7345 #define INPUT_SOURCE_BUF_SIZE 8192
7354 char buf[INPUT_SOURCE_BUF_SIZE];
7359 DoInputCallback(closure, source, xid)
7364 InputSource *is = (InputSource *) closure;
7369 if (is->lineByLine) {
7370 count = read(is->fd, is->unused,
7371 INPUT_SOURCE_BUF_SIZE - (is->unused - is->buf));
7373 (is->func)(is, is->closure, is->buf, count, count ? errno : 0);
7376 is->unused += count;
7378 while (p < is->unused) {
7379 q = memchr(p, '\n', is->unused - p);
7380 if (q == NULL) break;
7382 (is->func)(is, is->closure, p, q - p, 0);
7386 while (p < is->unused) {
7391 count = read(is->fd, is->buf, INPUT_SOURCE_BUF_SIZE);
7396 (is->func)(is, is->closure, is->buf, count, error);
7400 InputSourceRef AddInputSource(pr, lineByLine, func, closure)
7407 ChildProc *cp = (ChildProc *) pr;
7409 is = (InputSource *) calloc(1, sizeof(InputSource));
7410 is->lineByLine = lineByLine;
7414 is->fd = fileno(stdin);
7416 is->kind = cp->kind;
7417 is->fd = cp->fdFrom;
7420 is->unused = is->buf;
7423 is->xid = XtAppAddInput(appContext, is->fd,
7424 (XtPointer) (XtInputReadMask),
7425 (XtInputCallbackProc) DoInputCallback,
7427 is->closure = closure;
7428 return (InputSourceRef) is;
7432 RemoveInputSource(isr)
7435 InputSource *is = (InputSource *) isr;
7437 if (is->xid == 0) return;
7438 XtRemoveInput(is->xid);
7442 int OutputToProcess(pr, message, count, outError)
7448 ChildProc *cp = (ChildProc *) pr;
7452 outCount = fwrite(message, 1, count, stdout);
7454 outCount = write(cp->fdTo, message, count);
7464 /* Output message to process, with "ms" milliseconds of delay
7465 between each character. This is needed when sending the logon
7466 script to ICC, which for some reason doesn't like the
7467 instantaneous send. */
7468 int OutputToProcessDelayed(pr, message, count, outError, msdelay)
7475 ChildProc *cp = (ChildProc *) pr;
7480 r = write(cp->fdTo, message++, 1);
7493 /**** Animation code by Hugh Fisher, DCS, ANU.
7495 Known problem: if a window overlapping the board is
7496 moved away while a piece is being animated underneath,
7497 the newly exposed area won't be updated properly.
7498 I can live with this.
7500 Known problem: if you look carefully at the animation
7501 of pieces in mono mode, they are being drawn as solid
7502 shapes without interior detail while moving. Fixing
7503 this would be a major complication for minimal return.
7506 /* Masks for XPM pieces. Black and white pieces can have
7507 different shapes, but in the interest of retaining my
7508 sanity pieces must have the same outline on both light
7509 and dark squares, and all pieces must use the same
7510 background square colors/images. */
7512 static int xpmDone = 0;
7515 CreateAnimMasks (pieceDepth)
7522 unsigned long plane;
7525 /* just return for gtk at the moment */
7528 /* Need a bitmap just to get a GC with right depth */
7529 buf = XCreatePixmap(xDisplay, xBoardWindow,
7531 values.foreground = 1;
7532 values.background = 0;
7533 /* Don't use XtGetGC, not read only */
7534 maskGC = XCreateGC(xDisplay, buf,
7535 GCForeground | GCBackground, &values);
7536 XFreePixmap(xDisplay, buf);
7538 buf = XCreatePixmap(xDisplay, xBoardWindow,
7539 squareSize, squareSize, pieceDepth);
7540 values.foreground = XBlackPixel(xDisplay, xScreen);
7541 values.background = XWhitePixel(xDisplay, xScreen);
7542 bufGC = XCreateGC(xDisplay, buf,
7543 GCForeground | GCBackground, &values);
7545 for (piece = WhitePawn; piece <= BlackKing; piece++) {
7546 /* Begin with empty mask */
7547 if(!xpmDone) // [HGM] pieces: keep using existing
7548 xpmMask[piece] = XCreatePixmap(xDisplay, xBoardWindow,
7549 squareSize, squareSize, 1);
7550 XSetFunction(xDisplay, maskGC, GXclear);
7551 XFillRectangle(xDisplay, xpmMask[piece], maskGC,
7552 0, 0, squareSize, squareSize);
7554 /* Take a copy of the piece */
7559 XSetFunction(xDisplay, bufGC, GXcopy);
7560 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn],
7562 0, 0, squareSize, squareSize, 0, 0);
7564 /* XOR the background (light) over the piece */
7565 XSetFunction(xDisplay, bufGC, GXxor);
7567 XCopyArea(xDisplay, xpmLightSquare, buf, bufGC,
7568 0, 0, squareSize, squareSize, 0, 0);
7570 XSetForeground(xDisplay, bufGC, lightSquareColor);
7571 XFillRectangle(xDisplay, buf, bufGC, 0, 0, squareSize, squareSize);
7574 /* We now have an inverted piece image with the background
7575 erased. Construct mask by just selecting all the non-zero
7576 pixels - no need to reconstruct the original image. */
7577 XSetFunction(xDisplay, maskGC, GXor);
7579 /* Might be quicker to download an XImage and create bitmap
7580 data from it rather than this N copies per piece, but it
7581 only takes a fraction of a second and there is a much
7582 longer delay for loading the pieces. */
7583 for (n = 0; n < pieceDepth; n ++) {
7584 XCopyPlane(xDisplay, buf, xpmMask[piece], maskGC,
7585 0, 0, squareSize, squareSize,
7591 XFreePixmap(xDisplay, buf);
7592 XFreeGC(xDisplay, bufGC);
7593 XFreeGC(xDisplay, maskGC);
7597 InitAnimState (anim, info)
7599 XWindowAttributes * info;
7604 /* Each buffer is square size, same depth as window */
7605 // anim->saveBuf = XCreatePixmap(xDisplay, xBoardWindow,
7606 // squareSize, squareSize, info->depth);
7607 // anim->newBuf = XCreatePixmap(xDisplay, xBoardWindow,
7608 // squareSize, squareSize, info->depth);
7610 // /* Create a plain GC for blitting */
7611 // mask = GCForeground | GCBackground | GCFunction |
7612 // GCPlaneMask | GCGraphicsExposures;
7613 // values.foreground = XBlackPixel(xDisplay, xScreen);
7614 // values.background = XWhitePixel(xDisplay, xScreen);
7615 // values.function = GXcopy;
7616 // values.plane_mask = AllPlanes;
7617 // values.graphics_exposures = False;
7618 // anim->blitGC = XCreateGC(xDisplay, xBoardWindow, mask, &values);
7620 // /* Piece will be copied from an existing context at
7621 // the start of each new animation/drag. */
7622 // anim->pieceGC = XCreateGC(xDisplay, xBoardWindow, 0, &values);
7624 // /* Outline will be a read-only copy of an existing */
7625 // anim->outlineGC = None;
7631 static VariantClass old = (VariantClass) -1; // [HGM] pieces: redo every time variant changes
7632 XWindowAttributes info;
7634 /* for gtk at the moment just ... */
7637 if (xpmDone && gameInfo.variant == old) return;
7638 if(xpmDone) old = gameInfo.variant; // first time pieces might not be created yet
7639 // XGetWindowAttributes(xDisplay, xBoardWindow, &info);
7641 // InitAnimState(&game, &info);
7642 // InitAnimState(&player, &info);
7644 /* For XPM pieces, we need bitmaps to use as masks. */
7646 // CreateAnimMasks(info.depth);
7652 static Boolean frameWaiting;
7654 static RETSIGTYPE FrameAlarm (sig)
7657 frameWaiting = False;
7658 /* In case System-V style signals. Needed?? */
7659 signal(SIGALRM, FrameAlarm);
7666 struct itimerval delay;
7668 XSync(xDisplay, False);
7671 frameWaiting = True;
7672 signal(SIGALRM, FrameAlarm);
7673 delay.it_interval.tv_sec =
7674 delay.it_value.tv_sec = time / 1000;
7675 delay.it_interval.tv_usec =
7676 delay.it_value.tv_usec = (time % 1000) * 1000;
7677 setitimer(ITIMER_REAL, &delay, NULL);
7679 /* Ugh -- busy-wait! --tpm */
7680 while (frameWaiting);
7682 while (frameWaiting) pause();
7684 delay.it_interval.tv_sec = delay.it_value.tv_sec = 0;
7685 delay.it_interval.tv_usec = delay.it_value.tv_usec = 0;
7686 setitimer(ITIMER_REAL, &delay, NULL);
7696 // XSync(xDisplay, False);
7698 usleep(time * 1000);
7703 /* Convert board position to corner of screen rect and color */
7706 ScreenSquare(column, row, pt, color)
7707 int column; int row; XPoint * pt; int * color;
7710 pt->x = lineGap + ((BOARD_WIDTH-1)-column) * (squareSize + lineGap);
7711 pt->y = lineGap + row * (squareSize + lineGap);
7713 pt->x = lineGap + column * (squareSize + lineGap);
7714 pt->y = lineGap + ((BOARD_HEIGHT-1)-row) * (squareSize + lineGap);
7716 *color = SquareColor(row, column);
7719 /* Convert window coords to square */
7722 BoardSquare(x, y, column, row)
7723 int x; int y; int * column; int * row;
7725 *column = EventToSquare(x, BOARD_WIDTH);
7726 if (flipView && *column >= 0)
7727 *column = BOARD_WIDTH - 1 - *column;
7728 *row = EventToSquare(y, BOARD_HEIGHT);
7729 if (!flipView && *row >= 0)
7730 *row = BOARD_HEIGHT - 1 - *row;
7735 #undef Max /* just in case */
7737 #define Max(a, b) ((a) > (b) ? (a) : (b))
7738 #define Min(a, b) ((a) < (b) ? (a) : (b))
7741 SetRect(rect, x, y, width, height)
7742 XRectangle * rect; int x; int y; int width; int height;
7746 rect->width = width;
7747 rect->height = height;
7750 /* Test if two frames overlap. If they do, return
7751 intersection rect within old and location of
7752 that rect within new. */
7755 Intersect(old, new, size, area, pt)
7756 XPoint * old; XPoint * new;
7757 int size; XRectangle * area; XPoint * pt;
7759 if (old->x > new->x + size || new->x > old->x + size ||
7760 old->y > new->y + size || new->y > old->y + size) {
7763 SetRect(area, Max(new->x - old->x, 0), Max(new->y - old->y, 0),
7764 size - abs(old->x - new->x), size - abs(old->y - new->y));
7765 pt->x = Max(old->x - new->x, 0);
7766 pt->y = Max(old->y - new->y, 0);
7771 /* For two overlapping frames, return the rect(s)
7772 in the old that do not intersect with the new. */
7775 CalcUpdateRects(old, new, size, update, nUpdates)
7776 XPoint * old; XPoint * new; int size;
7777 XRectangle update[]; int * nUpdates;
7781 /* If old = new (shouldn't happen) then nothing to draw */
7782 if (old->x == new->x && old->y == new->y) {
7786 /* Work out what bits overlap. Since we know the rects
7787 are the same size we don't need a full intersect calc. */
7789 /* Top or bottom edge? */
7790 if (new->y > old->y) {
7791 SetRect(&(update[count]), old->x, old->y, size, new->y - old->y);
7793 } else if (old->y > new->y) {
7794 SetRect(&(update[count]), old->x, old->y + size - (old->y - new->y),
7795 size, old->y - new->y);
7798 /* Left or right edge - don't overlap any update calculated above. */
7799 if (new->x > old->x) {
7800 SetRect(&(update[count]), old->x, Max(new->y, old->y),
7801 new->x - old->x, size - abs(new->y - old->y));
7803 } else if (old->x > new->x) {
7804 SetRect(&(update[count]), new->x + size, Max(new->y, old->y),
7805 old->x - new->x, size - abs(new->y - old->y));
7812 /* Generate a series of frame coords from start->mid->finish.
7813 The movement rate doubles until the half way point is
7814 reached, then halves back down to the final destination,
7815 which gives a nice slow in/out effect. The algorithmn
7816 may seem to generate too many intermediates for short
7817 moves, but remember that the purpose is to attract the
7818 viewers attention to the piece about to be moved and
7819 then to where it ends up. Too few frames would be less
7823 Tween(start, mid, finish, factor, frames, nFrames)
7824 XPoint * start; XPoint * mid;
7825 XPoint * finish; int factor;
7826 XPoint frames[]; int * nFrames;
7828 int fraction, n, count;
7832 /* Slow in, stepping 1/16th, then 1/8th, ... */
7834 for (n = 0; n < factor; n++)
7836 for (n = 0; n < factor; n++) {
7837 frames[count].x = start->x + (mid->x - start->x) / fraction;
7838 frames[count].y = start->y + (mid->y - start->y) / fraction;
7840 fraction = fraction / 2;
7844 frames[count] = *mid;
7847 /* Slow out, stepping 1/2, then 1/4, ... */
7849 for (n = 0; n < factor; n++) {
7850 frames[count].x = finish->x - (finish->x - mid->x) / fraction;
7851 frames[count].y = finish->y - (finish->y - mid->y) / fraction;
7853 fraction = fraction * 2;
7858 /* Draw a piece on the screen without disturbing what's there */
7861 SelectGCMask(piece, clip, outline, mask)
7862 ChessSquare piece; GC * clip; GC * outline; Pixmap * mask;
7866 /* Bitmap for piece being moved. */
7867 if (appData.monoMode) {
7868 *mask = *pieceToSolid(piece);
7869 } else if (useImages) {
7871 *mask = xpmMask[piece];
7873 *mask = ximMaskPm[piece];
7876 *mask = *pieceToSolid(piece);
7879 /* GC for piece being moved. Square color doesn't matter, but
7880 since it gets modified we make a copy of the original. */
7882 if (appData.monoMode)
7887 if (appData.monoMode)
7892 // XCopyGC(xDisplay, source, 0xFFFFFFFF, *clip);
7894 /* Outline only used in mono mode and is not modified */
7896 *outline = bwPieceGC;
7898 *outline = wbPieceGC;
7902 OverlayPiece(piece, clip, outline, dest)
7903 ChessSquare piece; GC clip; GC outline; Drawable dest;
7908 /* Draw solid rectangle which will be clipped to shape of piece */
7909 // XFillRectangle(xDisplay, dest, clip,
7910 // 0, 0, squareSize, squareSize)
7912 if (appData.monoMode)
7913 /* Also draw outline in contrasting color for black
7914 on black / white on white cases */
7915 // XCopyPlane(xDisplay, *pieceToOutline(piece), dest, outline,
7916 // 0, 0, squareSize, squareSize, 0, 0, 1)
7919 /* Copy the piece */
7924 // XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
7926 // 0, 0, squareSize, squareSize,
7931 /* Animate the movement of a single piece */
7934 BeginAnimation(anim, piece, startColor, start)
7942 /* The old buffer is initialised with the start square (empty) */
7943 BlankSquare(0, 0, startColor, EmptySquare, anim->saveBuf);
7944 anim->prevFrame = *start;
7946 /* The piece will be drawn using its own bitmap as a matte */
7947 // SelectGCMask(piece, &anim->pieceGC, &anim->outlineGC, &mask);
7948 // XSetClipMask(xDisplay, anim->pieceGC, mask);
7952 AnimationFrame(anim, frame, piece)
7957 XRectangle updates[4];
7962 /* Save what we are about to draw into the new buffer */
7963 // XCopyArea(xDisplay, xBoardWindow, anim->newBuf, anim->blitGC,
7964 // frame->x, frame->y, squareSize, squareSize,
7967 /* Erase bits of the previous frame */
7968 if (Intersect(&anim->prevFrame, frame, squareSize, &overlap, &pt)) {
7969 /* Where the new frame overlapped the previous,
7970 the contents in newBuf are wrong. */
7971 // XCopyArea(xDisplay, anim->saveBuf, anim->newBuf, anim->blitGC,
7972 // overlap.x, overlap.y,
7973 // overlap.width, overlap.height,
7975 /* Repaint the areas in the old that don't overlap new */
7976 CalcUpdateRects(&anim->prevFrame, frame, squareSize, updates, &count);
7977 for (i = 0; i < count; i++)
7978 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
7979 // updates[i].x - anim->prevFrame.x,
7980 // updates[i].y - anim->prevFrame.y,
7981 // updates[i].width, updates[i].height,
7982 // updates[i].x, updates[i].y)
7985 /* Easy when no overlap */
7986 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
7987 // 0, 0, squareSize, squareSize,
7988 // anim->prevFrame.x, anim->prevFrame.y);
7991 /* Save this frame for next time round */
7992 // XCopyArea(xDisplay, anim->newBuf, anim->saveBuf, anim->blitGC,
7993 // 0, 0, squareSize, squareSize,
7995 anim->prevFrame = *frame;
7997 /* Draw piece over original screen contents, not current,
7998 and copy entire rect. Wipes out overlapping piece images. */
7999 OverlayPiece(piece, anim->pieceGC, anim->outlineGC, anim->newBuf);
8000 // XCopyArea(xDisplay, anim->newBuf, xBoardWindow, anim->blitGC,
8001 // 0, 0, squareSize, squareSize,
8002 // frame->x, frame->y);
8006 EndAnimation (anim, finish)
8010 XRectangle updates[4];
8015 /* The main code will redraw the final square, so we
8016 only need to erase the bits that don't overlap. */
8017 if (Intersect(&anim->prevFrame, finish, squareSize, &overlap, &pt)) {
8018 CalcUpdateRects(&anim->prevFrame, finish, squareSize, updates, &count);
8019 for (i = 0; i < count; i++)
8020 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
8021 // updates[i].x - anim->prevFrame.x,
8022 // updates[i].y - anim->prevFrame.y,
8023 // updates[i].width, updates[i].height,
8024 // updates[i].x, updates[i].y)
8027 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
8028 // 0, 0, squareSize, squareSize,
8029 // anim->prevFrame.x, anim->prevFrame.y);
8034 FrameSequence(anim, piece, startColor, start, finish, frames, nFrames)
8036 ChessSquare piece; int startColor;
8037 XPoint * start; XPoint * finish;
8038 XPoint frames[]; int nFrames;
8042 BeginAnimation(anim, piece, startColor, start);
8043 for (n = 0; n < nFrames; n++) {
8044 AnimationFrame(anim, &(frames[n]), piece);
8045 FrameDelay(appData.animSpeed);
8047 EndAnimation(anim, finish);
8050 /* Main control logic for deciding what to animate and how */
8053 AnimateMove(board, fromX, fromY, toX, toY)
8062 XPoint start, finish, mid;
8063 XPoint frames[kFactor * 2 + 1];
8064 int nFrames, startColor, endColor;
8066 /* Are we animating? */
8067 if (!appData.animate || appData.blindfold)
8070 if(board[toY][toX] == WhiteRook && board[fromY][fromX] == WhiteKing ||
8071 board[toY][toX] == BlackRook && board[fromY][fromX] == BlackKing)
8072 return; // [HGM] FRC: no animtion of FRC castlings, as to-square is not true to-square
8074 if (fromY < 0 || fromX < 0 || toX < 0 || toY < 0) return;
8075 piece = board[fromY][fromX];
8076 if (piece >= EmptySquare) return;
8081 hop = (piece == WhiteKnight || piece == BlackKnight);
8084 if (appData.debugMode) {
8085 fprintf(debugFP, hop ? _("AnimateMove: piece %d hops from %d,%d to %d,%d \n") :
8086 _("AnimateMove: piece %d slides from %d,%d to %d,%d \n"),
8087 piece, fromX, fromY, toX, toY); }
8089 ScreenSquare(fromX, fromY, &start, &startColor);
8090 ScreenSquare(toX, toY, &finish, &endColor);
8093 /* Knight: make diagonal movement then straight */
8094 if (abs(toY - fromY) < abs(toX - fromX)) {
8095 mid.x = start.x + (finish.x - start.x) / 2;
8099 mid.y = start.y + (finish.y - start.y) / 2;
8102 mid.x = start.x + (finish.x - start.x) / 2;
8103 mid.y = start.y + (finish.y - start.y) / 2;
8106 /* Don't use as many frames for very short moves */
8107 if (abs(toY - fromY) + abs(toX - fromX) <= 2)
8108 Tween(&start, &mid, &finish, kFactor - 1, frames, &nFrames);
8110 Tween(&start, &mid, &finish, kFactor, frames, &nFrames);
8111 FrameSequence(&game, piece, startColor, &start, &finish, frames, nFrames);
8113 /* Be sure end square is redrawn */
8114 damage[toY][toX] = True;
8118 DragPieceBegin(x, y)
8121 int boardX, boardY, color;
8124 /* Are we animating? */
8125 if (!appData.animateDragging || appData.blindfold)
8128 /* Figure out which square we start in and the
8129 mouse position relative to top left corner. */
8130 BoardSquare(x, y, &boardX, &boardY);
8131 player.startBoardX = boardX;
8132 player.startBoardY = boardY;
8133 ScreenSquare(boardX, boardY, &corner, &color);
8134 player.startSquare = corner;
8135 player.startColor = color;
8137 /* Start from exactly where the piece is. This can be confusing
8138 if you start dragging far from the center of the square; most
8139 or all of the piece can be over a different square from the one
8140 the mouse pointer is in. */
8141 player.mouseDelta.x = x - corner.x;
8142 player.mouseDelta.y = y - corner.y;
8144 /* As soon as we start dragging, the piece will jump slightly to
8145 be centered over the mouse pointer. */
8146 player.mouseDelta.x = squareSize/2;
8147 player.mouseDelta.y = squareSize/2;
8149 /* Initialise animation */
8150 player.dragPiece = PieceForSquare(boardX, boardY);
8152 if (player.dragPiece >= 0 && player.dragPiece < EmptySquare) {
8153 player.dragActive = True;
8154 BeginAnimation(&player, player.dragPiece, color, &corner);
8155 /* Mark this square as needing to be redrawn. Note that
8156 we don't remove the piece though, since logically (ie
8157 as seen by opponent) the move hasn't been made yet. */
8158 if(boardX == BOARD_RGHT+1 && PieceForSquare(boardX-1, boardY) > 1 ||
8159 boardX == BOARD_LEFT-2 && PieceForSquare(boardX+1, boardY) > 1)
8160 // XCopyArea(xDisplay, xBoardWindow, player.saveBuf, player.blitGC,
8161 // corner.x, corner.y, squareSize, squareSize,
8162 // 0, 0); // [HGM] zh: unstack in stead of grab
8163 damage[boardY][boardX] = True;
8165 player.dragActive = False;
8175 /* Are we animating? */
8176 if (!appData.animateDragging || appData.blindfold)
8180 if (! player.dragActive)
8182 /* Move piece, maintaining same relative position
8183 of mouse within square */
8184 corner.x = x - player.mouseDelta.x;
8185 corner.y = y - player.mouseDelta.y;
8186 AnimationFrame(&player, &corner, player.dragPiece);
8188 if (appData.highlightDragging) {
8190 BoardSquare(x, y, &boardX, &boardY);
8191 SetHighlights(fromX, fromY, boardX, boardY);
8200 int boardX, boardY, color;
8203 /* Are we animating? */
8204 if (!appData.animateDragging || appData.blindfold)
8208 if (! player.dragActive)
8210 /* Last frame in sequence is square piece is
8211 placed on, which may not match mouse exactly. */
8212 BoardSquare(x, y, &boardX, &boardY);
8213 ScreenSquare(boardX, boardY, &corner, &color);
8214 EndAnimation(&player, &corner);
8216 /* Be sure end square is redrawn */
8217 damage[boardY][boardX] = True;
8219 /* This prevents weird things happening with fast successive
8220 clicks which on my Sun at least can cause motion events
8221 without corresponding press/release. */
8222 player.dragActive = False;
8225 /* Handle expose event while piece being dragged */
8230 if (!player.dragActive || appData.blindfold)
8233 /* What we're doing: logically, the move hasn't been made yet,
8234 so the piece is still in it's original square. But visually
8235 it's being dragged around the board. So we erase the square
8236 that the piece is on and draw it at the last known drag point. */
8237 BlankSquare(player.startSquare.x, player.startSquare.y,
8238 player.startColor, EmptySquare, xBoardWindow);
8239 AnimationFrame(&player, &player.prevFrame, player.dragPiece);
8240 damage[player.startBoardY][player.startBoardX] = TRUE;
8244 SetProgramStats( FrontEndProgramStats * stats )
8247 // [HGM] done, but perhaps backend should call this directly?
8248 EngineOutputUpdate( stats );