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 char *FindFont P((char *pattern, int targetPxlSize));
255 void PieceMenuPopup P((Widget w, XEvent *event,
256 String *params, Cardinal *num_params));
257 static void PieceMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
258 static void DropMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
259 int EventToSquare P((int x, int limit));
260 void DrawSquare P((int row, int column, ChessSquare piece, int do_flash));
261 void HandleUserMove P((Widget w, XEvent *event,
262 String *prms, Cardinal *nprms));
263 void AnimateUserMove P((Widget w, XEvent * event,
264 String * params, Cardinal * nParams));
265 void CommentPopUp P((char *title, char *label));
266 void CommentPopDown P((void));
267 void CommentCallback P((Widget w, XtPointer client_data,
268 XtPointer call_data));
269 void ICSInputBoxPopUp P((void));
270 void ICSInputBoxPopDown P((void));
271 void FileNamePopUp P((char *label, char *def,
272 FileProc proc, char *openMode));
273 void FileNamePopDown P((void));
274 void FileNameCallback P((Widget w, XtPointer client_data,
275 XtPointer call_data));
276 void FileNameAction P((Widget w, XEvent *event,
277 String *prms, Cardinal *nprms));
278 void AskQuestionReplyAction P((Widget w, XEvent *event,
279 String *prms, Cardinal *nprms));
280 void AskQuestionProc P((Widget w, XEvent *event,
281 String *prms, Cardinal *nprms));
282 void AskQuestionPopDown P((void));
283 void PromotionPopUp P((void));
284 void PromotionPopDown P((void));
285 void PromotionCallback P((Widget w, XtPointer client_data,
286 XtPointer call_data));
287 void EditCommentPopDown P((void));
288 void EditCommentCallback P((Widget w, XtPointer client_data,
289 XtPointer call_data));
290 void SelectCommand P((Widget w, XtPointer client_data, XtPointer call_data));
291 void LoadPositionProc P((Widget w, XEvent *event,
292 String *prms, Cardinal *nprms));
293 void CopyPositionProc P((Widget w, XEvent *event, String *prms,
295 void PastePositionProc P((Widget w, XEvent *event, String *prms,
297 void CopyGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
298 void PasteGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
299 void SaveGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
300 void SavePositionProc P((Widget w, XEvent *event,
301 String *prms, Cardinal *nprms));
302 void MailMoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
303 void ReloadCmailMsgProc P((Widget w, XEvent *event, String *prms,
305 void AnalyzeModeProc P((Widget w, XEvent *event,
306 String *prms, Cardinal *nprms));
307 void AnalyzeFileProc P((Widget w, XEvent *event,
308 String *prms, Cardinal *nprms));
309 void EditGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
310 void EditPositionProc P((Widget w, XEvent *event,
311 String *prms, Cardinal *nprms));
312 void TrainingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
313 void EditCommentProc P((Widget w, XEvent *event,
314 String *prms, Cardinal *nprms));
315 void IcsInputBoxProc P((Widget w, XEvent *event,
316 String *prms, Cardinal *nprms));
317 void EnterKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
318 void AlwaysQueenProc P((Widget w, XEvent *event, String *prms,
320 void AnimateDraggingProc P((Widget w, XEvent *event, String *prms,
322 void AnimateMovingProc P((Widget w, XEvent *event, String *prms,
324 void AutocommProc P((Widget w, XEvent *event, String *prms,
326 void AutoflagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
327 void AutoflipProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
328 void AutobsProc P((Widget w, XEvent *event, String *prms,
330 void AutoraiseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
331 void AutosaveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
332 void BlindfoldProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
333 void FlashMovesProc P((Widget w, XEvent *event, String *prms,
335 void HighlightDraggingProc P((Widget w, XEvent *event, String *prms,
337 void HighlightLastMoveProc P((Widget w, XEvent *event, String *prms,
339 void MoveSoundProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
340 void IcsAlarmProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
341 void OldSaveStyleProc P((Widget w, XEvent *event, String *prms,
343 void PeriodicUpdatesProc P((Widget w, XEvent *event, String *prms,
345 void PonderNextMoveProc P((Widget w, XEvent *event, String *prms,
347 void PopupMoveErrorsProc P((Widget w, XEvent *event, String *prms,
349 void PopupExitMessageProc P((Widget w, XEvent *event, String *prms,
351 void PremoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
352 void QuietPlayProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
353 void TestLegalityProc P((Widget w, XEvent *event, String *prms,
355 void AboutGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
356 void DebugProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
357 void NothingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
358 void Iconify P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
359 void DisplayMove P((int moveNumber));
360 void DisplayTitle P((char *title));
361 void ICSInitScript P((void));
362 int LoadGamePopUp P((FILE *f, int gameNumber, char *title));
363 void ErrorPopUp P((char *title, char *text, int modal));
364 void ErrorPopDown P((void));
365 static char *ExpandPathName P((char *path));
366 static void CreateAnimVars P((void));
367 void DragPieceBegin P((int x, int y));
368 static void DragPieceMove P((int x, int y));
369 void DragPieceEnd P((int x, int y));
370 static void DrawDragPiece P((void));
371 char *ModeToWidgetName P((GameMode mode));
372 void EngineOutputUpdate( FrontEndProgramStats * stats );
373 void ShuffleMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
374 void EngineMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
375 void UciMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
376 void TimeControlProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
377 void NewVariantProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
378 void FirstSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
379 void SecondSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
380 void ShufflePopDown P(());
381 void EnginePopDown P(());
382 void UciPopDown P(());
383 void TimeControlPopDown P(());
384 void NewVariantPopDown P(());
385 void SettingsPopDown P(());
386 void SetMenuEnables P((Enables *enab));
389 * XBoard depends on Xt R4 or higher
391 int xtVersion = XtSpecificationRelease;
396 Pixel lightSquareColor, darkSquareColor, whitePieceColor, blackPieceColor,
397 jailSquareColor, highlightSquareColor, premoveHighlightColor;
398 Pixel lowTimeWarningColor;
400 #define LINE_TYPE_NORMAL 0
401 #define LINE_TYPE_HIGHLIGHT 1
402 #define LINE_TYPE_PRE 2
405 GC lightSquareGC, darkSquareGC, jailSquareGC, wdPieceGC, wlPieceGC,
406 bdPieceGC, blPieceGC, wbPieceGC, bwPieceGC, coordGC,
407 wjPieceGC, bjPieceGC;
408 Pixmap iconPixmap, wIconPixmap, bIconPixmap, xMarkPixmap;
409 Widget shellWidget, layoutWidget, formWidget, boardWidget, messageWidget,
410 whiteTimerWidget, blackTimerWidget, titleWidget, widgetList[16],
411 commentShell, promotionShell, whitePieceMenu, blackPieceMenu, dropMenu,
412 menuBarWidget, editShell, errorShell, analysisShell,
413 ICSInputShell, fileNameShell, askQuestionShell;
414 Font clockFontID, coordFontID, countFontID;
415 XFontStruct *clockFontStruct, *coordFontStruct, *countFontStruct;
416 XtAppContext appContext;
418 char *oldICSInteractionTitle;
422 char installDir[] = "."; // [HGM] UCI: needed for UCI; probably needs run-time initializtion
424 Position commentX = -1, commentY = -1;
425 Dimension commentW, commentH;
427 int squareSize, smallLayout = 0, tinyLayout = 0,
428 marginW, marginH, // [HGM] for run-time resizing
429 fromX = -1, fromY = -1, toX, toY, commentUp = False, analysisUp = False,
430 ICSInputBoxUp = False, askQuestionUp = False,
431 filenameUp = False, promotionUp = False, pmFromX = -1, pmFromY = -1,
432 editUp = False, errorUp = False, errorExitStatus = -1, lineGap;
433 Pixel timerForegroundPixel, timerBackgroundPixel;
434 Pixel buttonForegroundPixel, buttonBackgroundPixel;
435 char *chessDir, *programName, *programVersion,
436 *gameCopyFilename, *gamePasteFilename;
440 Pixmap pieceBitmap[2][(int)BlackPawn];
441 Pixmap pieceBitmap2[2][(int)BlackPawn+4]; /* [HGM] pieces */
442 Pixmap xpmPieceBitmap[4][(int)BlackPawn]; /* LL, LD, DL, DD actually used*/
443 Pixmap xpmPieceBitmap2[4][(int)BlackPawn+4]; /* LL, LD, DL, DD set to select from */
444 Pixmap xpmLightSquare, xpmDarkSquare, xpmJailSquare;
445 int useImages=0, useImageSqs;
446 XImage *ximPieceBitmap[4][(int)BlackPawn+4]; /* LL, LD, DL, DD */
447 Pixmap ximMaskPm[(int)BlackPawn]; /* clipmasks, used for XIM pieces */
448 Pixmap ximMaskPm2[(int)BlackPawn+4]; /* clipmasks, used for XIM pieces */
449 XImage *ximLightSquare, *ximDarkSquare;
452 #define pieceToSolid(piece) &pieceBitmap[SOLID][(piece) % (int)BlackPawn]
453 #define pieceToOutline(piece) &pieceBitmap[OUTLINE][(piece) % (int)BlackPawn]
455 #define White(piece) ((int)(piece) < (int)BlackPawn)
457 /* Variables for doing smooth animation. This whole thing
458 would be much easier if the board was double-buffered,
459 but that would require a fairly major rewrite. */
464 GC blitGC, pieceGC, outlineGC;
465 XPoint startSquare, prevFrame, mouseDelta;
469 int startBoardX, startBoardY;
472 /* There can be two pieces being animated at once: a player
473 can begin dragging a piece before the remote opponent has moved. */
475 static AnimState game, player;
477 /* Bitmaps for use as masks when drawing XPM pieces.
478 Need one for each black and white piece. */
479 static Pixmap xpmMask[BlackKing + 1];
481 /* This magic number is the number of intermediate frames used
482 in each half of the animation. For short moves it's reduced
483 by 1. The total number of frames will be factor * 2 + 1. */
486 SizeDefaults sizeDefaults[] = SIZE_DEFAULTS;
488 Enables icsEnables[] = {
489 { "menuFile.Mail Move", False },
490 { "menuFile.Reload CMail Message", False },
491 { "menuMode.Machine Black", False },
492 { "menuMode.Machine White", False },
493 { "menuMode.Analysis Mode", False },
494 { "menuMode.Analyze File", False },
495 { "menuMode.Two Machines", False },
497 { "menuHelp.Hint", False },
498 { "menuHelp.Book", False },
499 { "menuStep.Move Now", False },
500 { "menuOptions.Periodic Updates", False },
501 { "menuOptions.Hide Thinking", False },
502 { "menuOptions.Ponder Next Move", False },
507 Enables ncpEnables[] = {
508 { "menuFile.Mail Move", False },
509 { "menuFile.Reload CMail Message", False },
510 { "menuMode.Machine White", False },
511 { "menuMode.Machine Black", False },
512 { "menuMode.Analysis Mode", False },
513 { "menuMode.Analyze File", False },
514 { "menuMode.Two Machines", False },
515 { "menuMode.ICS Client", False },
516 { "menuMode.ICS Input Box", False },
518 { "menuStep.Revert", False },
519 { "menuStep.Move Now", False },
520 { "menuStep.Retract Move", False },
521 { "menuOptions.Auto Comment", False },
522 { "menuOptions.Auto Flag", False },
523 { "menuOptions.Auto Flip View", False },
524 { "menuOptions.Auto Observe", False },
525 { "menuOptions.Auto Raise Board", False },
526 { "menuOptions.Get Move List", False },
527 { "menuOptions.ICS Alarm", False },
528 { "menuOptions.Move Sound", False },
529 { "menuOptions.Quiet Play", False },
530 { "menuOptions.Hide Thinking", False },
531 { "menuOptions.Periodic Updates", False },
532 { "menuOptions.Ponder Next Move", False },
533 { "menuHelp.Hint", False },
534 { "menuHelp.Book", False },
538 Enables gnuEnables[] = {
539 { "menuMode.ICS Client", False },
540 { "menuMode.ICS Input Box", False },
541 { "menuAction.Accept", False },
542 { "menuAction.Decline", False },
543 { "menuAction.Rematch", False },
544 { "menuAction.Adjourn", False },
545 { "menuAction.Stop Examining", False },
546 { "menuAction.Stop Observing", False },
547 { "menuStep.Revert", False },
548 { "menuOptions.Auto Comment", False },
549 { "menuOptions.Auto Observe", False },
550 { "menuOptions.Auto Raise Board", False },
551 { "menuOptions.Get Move List", False },
552 { "menuOptions.Premove", False },
553 { "menuOptions.Quiet Play", False },
555 /* The next two options rely on SetCmailMode being called *after* */
556 /* SetGNUMode so that when GNU is being used to give hints these */
557 /* menu options are still available */
559 { "menuFile.Mail Move", False },
560 { "menuFile.Reload CMail Message", False },
564 Enables cmailEnables[] = {
566 { "menuAction.Call Flag", False },
567 { "menuAction.Draw", True },
568 { "menuAction.Adjourn", False },
569 { "menuAction.Abort", False },
570 { "menuAction.Stop Observing", False },
571 { "menuAction.Stop Examining", False },
572 { "menuFile.Mail Move", True },
573 { "menuFile.Reload CMail Message", True },
577 Enables trainingOnEnables[] = {
578 { "menuMode.Edit Comment", False },
579 { "menuMode.Pause", False },
580 { "menuStep.Forward", False },
581 { "menuStep.Backward", False },
582 { "menuStep.Forward to End", False },
583 { "menuStep.Back to Start", False },
584 { "menuStep.Move Now", False },
585 { "menuStep.Truncate Game", False },
589 Enables trainingOffEnables[] = {
590 { "menuMode.Edit Comment", True },
591 { "menuMode.Pause", True },
592 { "menuStep.Forward", True },
593 { "menuStep.Backward", True },
594 { "menuStep.Forward to End", True },
595 { "menuStep.Back to Start", True },
596 { "menuStep.Move Now", True },
597 { "menuStep.Truncate Game", True },
601 Enables machineThinkingEnables[] = {
602 { "menuFile.Load Game", False },
603 { "menuFile.Load Next Game", False },
604 { "menuFile.Load Previous Game", False },
605 { "menuFile.Reload Same Game", False },
606 { "menuFile.Paste Game", False },
607 { "menuFile.Load Position", False },
608 { "menuFile.Load Next Position", False },
609 { "menuFile.Load Previous Position", False },
610 { "menuFile.Reload Same Position", False },
611 { "menuFile.Paste Position", False },
612 { "menuMode.Machine White", False },
613 { "menuMode.Machine Black", False },
614 { "menuMode.Two Machines", False },
615 { "menuStep.Retract Move", False },
619 Enables userThinkingEnables[] = {
620 { "menuFile.Load Game", True },
621 { "menuFile.Load Next Game", True },
622 { "menuFile.Load Previous Game", True },
623 { "menuFile.Reload Same Game", True },
624 { "menuFile.Paste Game", True },
625 { "menuFile.Load Position", True },
626 { "menuFile.Load Next Position", True },
627 { "menuFile.Load Previous Position", True },
628 { "menuFile.Reload Same Position", True },
629 { "menuFile.Paste Position", True },
630 { "menuMode.Machine White", True },
631 { "menuMode.Machine Black", True },
632 { "menuMode.Two Machines", True },
633 { "menuStep.Retract Move", True },
639 MenuItem fileMenu[] = {
640 {N_("New Shuffle Game ..."), ShuffleMenuProc},
641 {N_("New Variant ..."), NewVariantProc}, // [HGM] variant: not functional yet
642 {"----", NothingProc},
643 {N_("Save Game"), SaveGameProc},
644 {"----", NothingProc},
645 {N_("Copy Game"), CopyGameProc},
646 {N_("Paste Game"), PasteGameProc},
647 {"----", NothingProc},
648 {N_("Load Position"), LoadPositionProc},
649 // {N_("Load Next Position"), LoadNextPositionProc},
650 // {N_("Load Previous Position"), LoadPrevPositionProc},
651 // {N_("Reload Same Position"), ReloadPositionProc},
652 {N_("Save Position"), SavePositionProc},
653 {"----", NothingProc},
654 {N_("Copy Position"), CopyPositionProc},
655 {N_("Paste Position"), PastePositionProc},
656 {"----", NothingProc},
657 {N_("Mail Move"), MailMoveProc},
658 {N_("Reload CMail Message"), ReloadCmailMsgProc},
659 {"----", NothingProc},
663 MenuItem modeMenu[] = {
664 // {N_("Machine White"), MachineWhiteProc},
665 // {N_("Machine Black"), MachineBlackProc},
666 // {N_("Two Machines"), TwoMachinesProc},
667 {N_("Analysis Mode"), AnalyzeModeProc},
668 {N_("Analyze File"), AnalyzeFileProc },
669 // {N_("ICS Client"), IcsClientProc},
670 {N_("Edit Game"), EditGameProc},
671 {N_("Edit Position"), EditPositionProc},
672 {N_("Training"), TrainingProc},
673 {"----", NothingProc},
674 {N_("Show Engine Output"), EngineOutputProc},
675 {N_("Show Evaluation Graph"), NothingProc}, // [HGM] evalgr: not functional yet
676 {N_("Show Game List"), ShowGameListProc},
677 // {"Show Move History", HistoryShowProc}, // [HGM] hist: activate 4.2.7 code
678 {"----", NothingProc},
679 {N_("Edit Tags"), EditTagsProc},
680 {N_("Edit Comment"), EditCommentProc},
681 {N_("ICS Input Box"), IcsInputBoxProc},
685 MenuItem optionsMenu[] = {
686 // {N_("Flip View"), FlipViewProc},
687 // {"----", NothingProc},
688 {N_("Adjudications ..."), EngineMenuProc},
689 {N_("General Settings ..."), UciMenuProc},
690 {N_("Engine #1 Settings ..."), FirstSettingsProc},
691 {N_("Engine #2 Settings ..."), SecondSettingsProc},
692 {N_("Time Control ..."), TimeControlProc},
693 {"----", NothingProc},
694 {N_("Always Queen"), AlwaysQueenProc},
695 {N_("Animate Dragging"), AnimateDraggingProc},
696 {N_("Animate Moving"), AnimateMovingProc},
697 {N_("Auto Comment"), AutocommProc},
698 {N_("Auto Flag"), AutoflagProc},
699 {N_("Auto Flip View"), AutoflipProc},
700 {N_("Auto Observe"), AutobsProc},
701 {N_("Auto Raise Board"), AutoraiseProc},
702 {N_("Auto Save"), AutosaveProc},
703 {N_("Blindfold"), BlindfoldProc},
704 {N_("Flash Moves"), FlashMovesProc},
705 // {N_("Get Move List"), GetMoveListProc},
707 {N_("Highlight Dragging"), HighlightDraggingProc},
709 {N_("Highlight Last Move"), HighlightLastMoveProc},
710 {N_("Move Sound"), MoveSoundProc},
711 {N_("ICS Alarm"), IcsAlarmProc},
712 {N_("Old Save Style"), OldSaveStyleProc},
713 {N_("Periodic Updates"), PeriodicUpdatesProc},
714 {N_("Ponder Next Move"), PonderNextMoveProc},
715 {N_("Popup Exit Message"), PopupExitMessageProc},
716 {N_("Popup Move Errors"), PopupMoveErrorsProc},
717 {N_("Premove"), PremoveProc},
718 {N_("Quiet Play"), QuietPlayProc},
719 // {N_("Hide Thinking"), HideThinkingProc},
720 {N_("Test Legality"), TestLegalityProc},
725 {N_("File"), fileMenu},
726 {N_("Mode"), modeMenu},
727 {N_("Options"), optionsMenu},
731 #define PIECE_MENU_SIZE 18
732 String pieceMenuStrings[2][PIECE_MENU_SIZE] = {
733 { N_("White"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
734 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
735 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
736 N_("Empty square"), N_("Clear board") },
737 { N_("Black"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
738 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
739 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
740 N_("Empty square"), N_("Clear board") }
742 /* must be in same order as PieceMenuStrings! */
743 ChessSquare pieceMenuTranslation[2][PIECE_MENU_SIZE] = {
744 { WhitePlay, (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
745 WhiteRook, WhiteQueen, WhiteKing, (ChessSquare) 0, WhiteAlfil,
746 WhiteCannon, WhiteAngel, WhiteMarshall, (ChessSquare) 0,
747 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
748 { BlackPlay, (ChessSquare) 0, BlackPawn, BlackKnight, BlackBishop,
749 BlackRook, BlackQueen, BlackKing, (ChessSquare) 0, BlackAlfil,
750 BlackCannon, BlackAngel, BlackMarshall, (ChessSquare) 0,
751 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
754 #define DROP_MENU_SIZE 6
755 String dropMenuStrings[DROP_MENU_SIZE] = {
756 "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"), N_("Queen")
758 /* must be in same order as PieceMenuStrings! */
759 ChessSquare dropMenuTranslation[DROP_MENU_SIZE] = {
760 (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
761 WhiteRook, WhiteQueen
769 DropMenuEnables dmEnables[] = {
778 { XtNborderWidth, 0 },
779 { XtNdefaultDistance, 0 },
783 { XtNborderWidth, 0 },
784 { XtNresizable, (XtArgVal) True },
788 { XtNborderWidth, 0 },
793 XtResource clientResources[] = {
794 { "whitePieceColor", "whitePieceColor", XtRString, sizeof(String),
795 XtOffset(AppDataPtr, whitePieceColor), XtRString,
797 { "blackPieceColor", "blackPieceColor", XtRString, sizeof(String),
798 XtOffset(AppDataPtr, blackPieceColor), XtRString,
800 { "lightSquareColor", "lightSquareColor", XtRString,
801 sizeof(String), XtOffset(AppDataPtr, lightSquareColor),
802 XtRString, LIGHT_SQUARE_COLOR },
803 { "darkSquareColor", "darkSquareColor", XtRString, sizeof(String),
804 XtOffset(AppDataPtr, darkSquareColor), XtRString,
806 { "highlightSquareColor", "highlightSquareColor", XtRString,
807 sizeof(String), XtOffset(AppDataPtr, highlightSquareColor),
808 XtRString, HIGHLIGHT_SQUARE_COLOR },
809 { "premoveHighlightColor", "premoveHighlightColor", XtRString,
810 sizeof(String), XtOffset(AppDataPtr, premoveHighlightColor),
811 XtRString, PREMOVE_HIGHLIGHT_COLOR },
812 { "movesPerSession", "movesPerSession", XtRInt, sizeof(int),
813 XtOffset(AppDataPtr, movesPerSession), XtRImmediate,
814 (XtPointer) MOVES_PER_SESSION },
815 { "timeIncrement", "timeIncrement", XtRInt, sizeof(int),
816 XtOffset(AppDataPtr, timeIncrement), XtRImmediate,
817 (XtPointer) TIME_INCREMENT },
818 { "initString", "initString", XtRString, sizeof(String),
819 XtOffset(AppDataPtr, initString), XtRString, INIT_STRING },
820 { "secondInitString", "secondInitString", XtRString, sizeof(String),
821 XtOffset(AppDataPtr, secondInitString), XtRString, INIT_STRING },
822 { "firstComputerString", "firstComputerString", XtRString,
823 sizeof(String), XtOffset(AppDataPtr, firstComputerString), XtRString,
825 { "secondComputerString", "secondComputerString", XtRString,
826 sizeof(String), XtOffset(AppDataPtr, secondComputerString), XtRString,
828 { "firstChessProgram", "firstChessProgram", XtRString,
829 sizeof(String), XtOffset(AppDataPtr, firstChessProgram),
830 XtRString, FIRST_CHESS_PROGRAM },
831 { "secondChessProgram", "secondChessProgram", XtRString,
832 sizeof(String), XtOffset(AppDataPtr, secondChessProgram),
833 XtRString, SECOND_CHESS_PROGRAM },
834 { "firstPlaysBlack", "firstPlaysBlack", XtRBoolean,
835 sizeof(Boolean), XtOffset(AppDataPtr, firstPlaysBlack),
836 XtRImmediate, (XtPointer) False },
837 { "noChessProgram", "noChessProgram", XtRBoolean,
838 sizeof(Boolean), XtOffset(AppDataPtr, noChessProgram),
839 XtRImmediate, (XtPointer) False },
840 { "firstHost", "firstHost", XtRString, sizeof(String),
841 XtOffset(AppDataPtr, firstHost), XtRString, FIRST_HOST },
842 { "secondHost", "secondHost", XtRString, sizeof(String),
843 XtOffset(AppDataPtr, secondHost), XtRString, SECOND_HOST },
844 { "firstDirectory", "firstDirectory", XtRString, sizeof(String),
845 XtOffset(AppDataPtr, firstDirectory), XtRString, "." },
846 { "secondDirectory", "secondDirectory", XtRString, sizeof(String),
847 XtOffset(AppDataPtr, secondDirectory), XtRString, "." },
848 { "bitmapDirectory", "bitmapDirectory", XtRString,
849 sizeof(String), XtOffset(AppDataPtr, bitmapDirectory),
851 { "remoteShell", "remoteShell", XtRString, sizeof(String),
852 XtOffset(AppDataPtr, remoteShell), XtRString, REMOTE_SHELL },
853 { "remoteUser", "remoteUser", XtRString, sizeof(String),
854 XtOffset(AppDataPtr, remoteUser), XtRString, "" },
855 { "timeDelay", "timeDelay", XtRFloat, sizeof(float),
856 XtOffset(AppDataPtr, timeDelay), XtRString,
857 (XtPointer) TIME_DELAY_QUOTE },
858 { "timeControl", "timeControl", XtRString, sizeof(String),
859 XtOffset(AppDataPtr, timeControl), XtRString,
860 (XtPointer) TIME_CONTROL },
861 { "internetChessServerMode", "internetChessServerMode",
862 XtRBoolean, sizeof(Boolean),
863 XtOffset(AppDataPtr, icsActive), XtRImmediate,
865 { "internetChessServerHost", "internetChessServerHost",
866 XtRString, sizeof(String),
867 XtOffset(AppDataPtr, icsHost),
868 XtRString, (XtPointer) ICS_HOST },
869 { "internetChessServerPort", "internetChessServerPort",
870 XtRString, sizeof(String),
871 XtOffset(AppDataPtr, icsPort), XtRString,
872 (XtPointer) ICS_PORT },
873 { "internetChessServerCommPort", "internetChessServerCommPort",
874 XtRString, sizeof(String),
875 XtOffset(AppDataPtr, icsCommPort), XtRString,
877 { "internetChessServerLogonScript", "internetChessServerLogonScript",
878 XtRString, sizeof(String),
879 XtOffset(AppDataPtr, icsLogon), XtRString,
881 { "internetChessServerHelper", "internetChessServerHelper",
882 XtRString, sizeof(String),
883 XtOffset(AppDataPtr, icsHelper), XtRString, "" },
884 { "internetChessServerInputBox", "internetChessServerInputBox",
885 XtRBoolean, sizeof(Boolean),
886 XtOffset(AppDataPtr, icsInputBox), XtRImmediate,
888 { "icsAlarm", "icsAlarm",
889 XtRBoolean, sizeof(Boolean),
890 XtOffset(AppDataPtr, icsAlarm), XtRImmediate,
892 { "icsAlarmTime", "icsAlarmTime",
894 XtOffset(AppDataPtr, icsAlarmTime), XtRImmediate,
896 { "useTelnet", "useTelnet", XtRBoolean, sizeof(Boolean),
897 XtOffset(AppDataPtr, useTelnet), XtRImmediate,
899 { "telnetProgram", "telnetProgram", XtRString, sizeof(String),
900 XtOffset(AppDataPtr, telnetProgram), XtRString, TELNET_PROGRAM },
901 { "gateway", "gateway", XtRString, sizeof(String),
902 XtOffset(AppDataPtr, gateway), XtRString, "" },
903 { "loadGameFile", "loadGameFile", XtRString, sizeof(String),
904 XtOffset(AppDataPtr, loadGameFile), XtRString, "" },
905 { "loadGameIndex", "loadGameIndex",
907 XtOffset(AppDataPtr, loadGameIndex), XtRImmediate,
909 { "saveGameFile", "saveGameFile", XtRString, sizeof(String),
910 XtOffset(AppDataPtr, saveGameFile), XtRString, "" },
911 { "autoRaiseBoard", "autoRaiseBoard", XtRBoolean,
912 sizeof(Boolean), XtOffset(AppDataPtr, autoRaiseBoard),
913 XtRImmediate, (XtPointer) True },
914 { "autoSaveGames", "autoSaveGames", XtRBoolean,
915 sizeof(Boolean), XtOffset(AppDataPtr, autoSaveGames),
916 XtRImmediate, (XtPointer) False },
917 { "blindfold", "blindfold", XtRBoolean,
918 sizeof(Boolean), XtOffset(AppDataPtr, blindfold),
919 XtRImmediate, (XtPointer) False },
920 { "loadPositionFile", "loadPositionFile", XtRString,
921 sizeof(String), XtOffset(AppDataPtr, loadPositionFile),
923 { "loadPositionIndex", "loadPositionIndex",
925 XtOffset(AppDataPtr, loadPositionIndex), XtRImmediate,
927 { "savePositionFile", "savePositionFile", XtRString,
928 sizeof(String), XtOffset(AppDataPtr, savePositionFile),
930 { "matchMode", "matchMode", XtRBoolean, sizeof(Boolean),
931 XtOffset(AppDataPtr, matchMode), XtRImmediate, (XtPointer) False },
932 { "matchGames", "matchGames", XtRInt, sizeof(int),
933 XtOffset(AppDataPtr, matchGames), XtRImmediate,
935 { "monoMode", "monoMode", XtRBoolean, sizeof(Boolean),
936 XtOffset(AppDataPtr, monoMode), XtRImmediate,
938 { "debugMode", "debugMode", XtRBoolean, sizeof(Boolean),
939 XtOffset(AppDataPtr, debugMode), XtRImmediate,
941 { "clockMode", "clockMode", XtRBoolean, sizeof(Boolean),
942 XtOffset(AppDataPtr, clockMode), XtRImmediate,
944 { "boardSize", "boardSize", XtRString, sizeof(String),
945 XtOffset(AppDataPtr, boardSize), XtRString, "" },
946 { "searchTime", "searchTime", XtRString, sizeof(String),
947 XtOffset(AppDataPtr, searchTime), XtRString,
949 { "searchDepth", "searchDepth", XtRInt, sizeof(int),
950 XtOffset(AppDataPtr, searchDepth), XtRImmediate,
952 { "showCoords", "showCoords", XtRBoolean, sizeof(Boolean),
953 XtOffset(AppDataPtr, showCoords), XtRImmediate,
955 { "showJail", "showJail", XtRInt, sizeof(int),
956 XtOffset(AppDataPtr, showJail), XtRImmediate,
958 { "showThinking", "showThinking", XtRBoolean, sizeof(Boolean),
959 XtOffset(AppDataPtr, showThinking), XtRImmediate,
961 { "ponderNextMove", "ponderNextMove", XtRBoolean, sizeof(Boolean),
962 XtOffset(AppDataPtr, ponderNextMove), XtRImmediate,
964 { "periodicUpdates", "periodicUpdates", XtRBoolean, sizeof(Boolean),
965 XtOffset(AppDataPtr, periodicUpdates), XtRImmediate,
967 { "clockFont", "clockFont", XtRString, sizeof(String),
968 XtOffset(AppDataPtr, clockFont), XtRString, CLOCK_FONT },
969 { "coordFont", "coordFont", XtRString, sizeof(String),
970 XtOffset(AppDataPtr, coordFont), XtRString, COORD_FONT },
971 { "font", "font", XtRString, sizeof(String),
972 XtOffset(AppDataPtr, font), XtRString, DEFAULT_FONT },
973 { "ringBellAfterMoves", "ringBellAfterMoves",
974 XtRBoolean, sizeof(Boolean),
975 XtOffset(AppDataPtr, ringBellAfterMoves),
976 XtRImmediate, (XtPointer) False },
977 { "autoCallFlag", "autoCallFlag", XtRBoolean,
978 sizeof(Boolean), XtOffset(AppDataPtr, autoCallFlag),
979 XtRImmediate, (XtPointer) False },
980 { "autoFlipView", "autoFlipView", XtRBoolean,
981 sizeof(Boolean), XtOffset(AppDataPtr, autoFlipView),
982 XtRImmediate, (XtPointer) True },
983 { "autoObserve", "autoObserve", XtRBoolean,
984 sizeof(Boolean), XtOffset(AppDataPtr, autoObserve),
985 XtRImmediate, (XtPointer) False },
986 { "autoComment", "autoComment", XtRBoolean,
987 sizeof(Boolean), XtOffset(AppDataPtr, autoComment),
988 XtRImmediate, (XtPointer) False },
989 { "getMoveList", "getMoveList", XtRBoolean,
990 sizeof(Boolean), XtOffset(AppDataPtr, getMoveList),
991 XtRImmediate, (XtPointer) True },
993 { "highlightDragging", "highlightDragging", XtRBoolean,
994 sizeof(Boolean), XtOffset(AppDataPtr, highlightDragging),
995 XtRImmediate, (XtPointer) False },
997 { "highlightLastMove", "highlightLastMove", XtRBoolean,
998 sizeof(Boolean), XtOffset(AppDataPtr, highlightLastMove),
999 XtRImmediate, (XtPointer) False },
1000 { "premove", "premove", XtRBoolean,
1001 sizeof(Boolean), XtOffset(AppDataPtr, premove),
1002 XtRImmediate, (XtPointer) True },
1003 { "testLegality", "testLegality", XtRBoolean,
1004 sizeof(Boolean), XtOffset(AppDataPtr, testLegality),
1005 XtRImmediate, (XtPointer) True },
1006 { "flipView", "flipView", XtRBoolean,
1007 sizeof(Boolean), XtOffset(AppDataPtr, flipView),
1008 XtRImmediate, (XtPointer) False },
1009 { "cmail", "cmailGameName", XtRString, sizeof(String),
1010 XtOffset(AppDataPtr, cmailGameName), XtRString, "" },
1011 { "alwaysPromoteToQueen", "alwaysPromoteToQueen", XtRBoolean,
1012 sizeof(Boolean), XtOffset(AppDataPtr, alwaysPromoteToQueen),
1013 XtRImmediate, (XtPointer) False },
1014 { "oldSaveStyle", "oldSaveStyle", XtRBoolean,
1015 sizeof(Boolean), XtOffset(AppDataPtr, oldSaveStyle),
1016 XtRImmediate, (XtPointer) False },
1017 { "quietPlay", "quietPlay", XtRBoolean,
1018 sizeof(Boolean), XtOffset(AppDataPtr, quietPlay),
1019 XtRImmediate, (XtPointer) False },
1020 { "titleInWindow", "titleInWindow", XtRBoolean,
1021 sizeof(Boolean), XtOffset(AppDataPtr, titleInWindow),
1022 XtRImmediate, (XtPointer) False },
1023 { "localLineEditing", "localLineEditing", XtRBoolean,
1024 sizeof(Boolean), XtOffset(AppDataPtr, localLineEditing),
1025 XtRImmediate, (XtPointer) True }, /* not implemented, must be True */
1027 { "zippyTalk", "zippyTalk", XtRBoolean,
1028 sizeof(Boolean), XtOffset(AppDataPtr, zippyTalk),
1029 XtRImmediate, (XtPointer) ZIPPY_TALK },
1030 { "zippyPlay", "zippyPlay", XtRBoolean,
1031 sizeof(Boolean), XtOffset(AppDataPtr, zippyPlay),
1032 XtRImmediate, (XtPointer) ZIPPY_PLAY },
1033 { "zippyLines", "zippyLines", XtRString, sizeof(String),
1034 XtOffset(AppDataPtr, zippyLines), XtRString, ZIPPY_LINES },
1035 { "zippyPinhead", "zippyPinhead", XtRString, sizeof(String),
1036 XtOffset(AppDataPtr, zippyPinhead), XtRString, ZIPPY_PINHEAD },
1037 { "zippyPassword", "zippyPassword", XtRString, sizeof(String),
1038 XtOffset(AppDataPtr, zippyPassword), XtRString, ZIPPY_PASSWORD },
1039 { "zippyPassword2", "zippyPassword2", XtRString, sizeof(String),
1040 XtOffset(AppDataPtr, zippyPassword2), XtRString, ZIPPY_PASSWORD2 },
1041 { "zippyWrongPassword", "zippyWrongPassword", XtRString, sizeof(String),
1042 XtOffset(AppDataPtr, zippyWrongPassword), XtRString,
1043 ZIPPY_WRONG_PASSWORD },
1044 { "zippyAcceptOnly", "zippyAcceptOnly", XtRString, sizeof(String),
1045 XtOffset(AppDataPtr, zippyAcceptOnly), XtRString, ZIPPY_ACCEPT_ONLY },
1046 { "zippyUseI", "zippyUseI", XtRBoolean,
1047 sizeof(Boolean), XtOffset(AppDataPtr, zippyUseI),
1048 XtRImmediate, (XtPointer) ZIPPY_USE_I },
1049 { "zippyBughouse", "zippyBughouse", XtRInt,
1050 sizeof(int), XtOffset(AppDataPtr, zippyBughouse),
1051 XtRImmediate, (XtPointer) ZIPPY_BUGHOUSE },
1052 { "zippyNoplayCrafty", "zippyNoplayCrafty", XtRBoolean,
1053 sizeof(Boolean), XtOffset(AppDataPtr, zippyNoplayCrafty),
1054 XtRImmediate, (XtPointer) ZIPPY_NOPLAY_CRAFTY },
1055 { "zippyGameEnd", "zippyGameEnd", XtRString, sizeof(String),
1056 XtOffset(AppDataPtr, zippyGameEnd), XtRString, ZIPPY_GAME_END },
1057 { "zippyGameStart", "zippyGameStart", XtRString, sizeof(String),
1058 XtOffset(AppDataPtr, zippyGameStart), XtRString, ZIPPY_GAME_START },
1059 { "zippyAdjourn", "zippyAdjourn", XtRBoolean,
1060 sizeof(Boolean), XtOffset(AppDataPtr, zippyAdjourn),
1061 XtRImmediate, (XtPointer) ZIPPY_ADJOURN },
1062 { "zippyAbort", "zippyAbort", XtRBoolean,
1063 sizeof(Boolean), XtOffset(AppDataPtr, zippyAbort),
1064 XtRImmediate, (XtPointer) ZIPPY_ABORT },
1065 { "zippyVariants", "zippyVariants", XtRString, sizeof(String),
1066 XtOffset(AppDataPtr, zippyVariants), XtRString, ZIPPY_VARIANTS },
1067 { "zippyMaxGames", "zippyMaxGames", XtRInt, sizeof(int),
1068 XtOffset(AppDataPtr, zippyMaxGames), XtRImmediate,
1069 (XtPointer) ZIPPY_MAX_GAMES },
1070 { "zippyReplayTimeout", "zippyReplayTimeout", XtRInt, sizeof(int),
1071 XtOffset(AppDataPtr, zippyReplayTimeout), XtRImmediate,
1072 (XtPointer) ZIPPY_REPLAY_TIMEOUT },
1073 { "zippyShortGame", "zippyShortGame", XtRInt, sizeof(int),
1074 XtOffset(AppDataPtr, zippyShortGame), XtRImmediate,
1077 { "flashCount", "flashCount", XtRInt, sizeof(int),
1078 XtOffset(AppDataPtr, flashCount), XtRImmediate,
1079 (XtPointer) FLASH_COUNT },
1080 { "flashRate", "flashRate", XtRInt, sizeof(int),
1081 XtOffset(AppDataPtr, flashRate), XtRImmediate,
1082 (XtPointer) FLASH_RATE },
1083 { "pixmapDirectory", "pixmapDirectory", XtRString,
1084 sizeof(String), XtOffset(AppDataPtr, pixmapDirectory),
1086 { "msLoginDelay", "msLoginDelay", XtRInt, sizeof(int),
1087 XtOffset(AppDataPtr, msLoginDelay), XtRImmediate,
1088 (XtPointer) MS_LOGIN_DELAY },
1089 { "colorizeMessages", "colorizeMessages", XtRBoolean,
1090 sizeof(Boolean), XtOffset(AppDataPtr, colorize),
1091 XtRImmediate, (XtPointer) False },
1092 { "colorShout", "colorShout", XtRString,
1093 sizeof(String), XtOffset(AppDataPtr, colorShout),
1094 XtRString, COLOR_SHOUT },
1095 { "colorSShout", "colorSShout", XtRString,
1096 sizeof(String), XtOffset(AppDataPtr, colorSShout),
1097 XtRString, COLOR_SSHOUT },
1098 { "colorChannel1", "colorChannel1", XtRString,
1099 sizeof(String), XtOffset(AppDataPtr, colorChannel1),
1100 XtRString, COLOR_CHANNEL1 },
1101 { "colorChannel", "colorChannel", XtRString,
1102 sizeof(String), XtOffset(AppDataPtr, colorChannel),
1103 XtRString, COLOR_CHANNEL },
1104 { "colorKibitz", "colorKibitz", XtRString,
1105 sizeof(String), XtOffset(AppDataPtr, colorKibitz),
1106 XtRString, COLOR_KIBITZ },
1107 { "colorTell", "colorTell", XtRString,
1108 sizeof(String), XtOffset(AppDataPtr, colorTell),
1109 XtRString, COLOR_TELL },
1110 { "colorChallenge", "colorChallenge", XtRString,
1111 sizeof(String), XtOffset(AppDataPtr, colorChallenge),
1112 XtRString, COLOR_CHALLENGE },
1113 { "colorRequest", "colorRequest", XtRString,
1114 sizeof(String), XtOffset(AppDataPtr, colorRequest),
1115 XtRString, COLOR_REQUEST },
1116 { "colorSeek", "colorSeek", XtRString,
1117 sizeof(String), XtOffset(AppDataPtr, colorSeek),
1118 XtRString, COLOR_SEEK },
1119 { "colorNormal", "colorNormal", XtRString,
1120 sizeof(String), XtOffset(AppDataPtr, colorNormal),
1121 XtRString, COLOR_NORMAL },
1122 { "soundProgram", "soundProgram", XtRString,
1123 sizeof(String), XtOffset(AppDataPtr, soundProgram),
1124 XtRString, "play" },
1125 { "soundShout", "soundShout", XtRString,
1126 sizeof(String), XtOffset(AppDataPtr, soundShout),
1128 { "soundSShout", "soundSShout", XtRString,
1129 sizeof(String), XtOffset(AppDataPtr, soundSShout),
1131 { "soundChannel1", "soundChannel1", XtRString,
1132 sizeof(String), XtOffset(AppDataPtr, soundChannel1),
1134 { "soundChannel", "soundChannel", XtRString,
1135 sizeof(String), XtOffset(AppDataPtr, soundChannel),
1137 { "soundKibitz", "soundKibitz", XtRString,
1138 sizeof(String), XtOffset(AppDataPtr, soundKibitz),
1140 { "soundTell", "soundTell", XtRString,
1141 sizeof(String), XtOffset(AppDataPtr, soundTell),
1143 { "soundChallenge", "soundChallenge", XtRString,
1144 sizeof(String), XtOffset(AppDataPtr, soundChallenge),
1146 { "soundRequest", "soundRequest", XtRString,
1147 sizeof(String), XtOffset(AppDataPtr, soundRequest),
1149 { "soundSeek", "soundSeek", XtRString,
1150 sizeof(String), XtOffset(AppDataPtr, soundSeek),
1152 { "soundMove", "soundMove", XtRString,
1153 sizeof(String), XtOffset(AppDataPtr, soundMove),
1155 { "soundIcsWin", "soundIcsWin", XtRString,
1156 sizeof(String), XtOffset(AppDataPtr, soundIcsWin),
1158 { "soundIcsLoss", "soundIcsLoss", XtRString,
1159 sizeof(String), XtOffset(AppDataPtr, soundIcsLoss),
1161 { "soundIcsDraw", "soundIcsDraw", XtRString,
1162 sizeof(String), XtOffset(AppDataPtr, soundIcsDraw),
1164 { "soundIcsUnfinished", "soundIcsUnfinished", XtRString,
1165 sizeof(String), XtOffset(AppDataPtr, soundIcsUnfinished),
1167 { "soundIcsAlarm", "soundIcsAlarm", XtRString,
1168 sizeof(String), XtOffset(AppDataPtr, soundIcsAlarm),
1170 { "reuseFirst", "reuseFirst", XtRBoolean,
1171 sizeof(Boolean), XtOffset(AppDataPtr, reuseFirst),
1172 XtRImmediate, (XtPointer) True },
1173 { "reuseSecond", "reuseSecond", XtRBoolean,
1174 sizeof(Boolean), XtOffset(AppDataPtr, reuseSecond),
1175 XtRImmediate, (XtPointer) True },
1176 { "animateDragging", "animateDragging", XtRBoolean,
1177 sizeof(Boolean), XtOffset(AppDataPtr, animateDragging),
1178 XtRImmediate, (XtPointer) True },
1179 { "animateMoving", "animateMoving", XtRBoolean,
1180 sizeof(Boolean), XtOffset(AppDataPtr, animate),
1181 XtRImmediate, (XtPointer) True },
1182 { "animateSpeed", "animateSpeed", XtRInt,
1183 sizeof(int), XtOffset(AppDataPtr, animSpeed),
1184 XtRImmediate, (XtPointer)10 },
1185 { "popupExitMessage", "popupExitMessage", XtRBoolean,
1186 sizeof(Boolean), XtOffset(AppDataPtr, popupExitMessage),
1187 XtRImmediate, (XtPointer) True },
1188 { "popupMoveErrors", "popupMoveErrors", XtRBoolean,
1189 sizeof(Boolean), XtOffset(AppDataPtr, popupMoveErrors),
1190 XtRImmediate, (XtPointer) False },
1191 { "fontSizeTolerance", "fontSizeTolerance", XtRInt,
1192 sizeof(int), XtOffset(AppDataPtr, fontSizeTolerance),
1193 XtRImmediate, (XtPointer)4 },
1194 { "initialMode", "initialMode", XtRString,
1195 sizeof(String), XtOffset(AppDataPtr, initialMode),
1196 XtRImmediate, (XtPointer) "" },
1197 { "variant", "variant", XtRString,
1198 sizeof(String), XtOffset(AppDataPtr, variant),
1199 XtRImmediate, (XtPointer) "normal" },
1200 { "firstProtocolVersion", "firstProtocolVersion", XtRInt,
1201 sizeof(int), XtOffset(AppDataPtr, firstProtocolVersion),
1202 XtRImmediate, (XtPointer)PROTOVER },
1203 { "secondProtocolVersion", "secondProtocolVersion", XtRInt,
1204 sizeof(int), XtOffset(AppDataPtr, secondProtocolVersion),
1205 XtRImmediate, (XtPointer)PROTOVER },
1206 { "showButtonBar", "showButtonBar", XtRBoolean,
1207 sizeof(Boolean), XtOffset(AppDataPtr, showButtonBar),
1208 XtRImmediate, (XtPointer) True },
1209 { "lowTimeWarningColor", "lowTimeWarningColor", XtRString,
1210 sizeof(String), XtOffset(AppDataPtr, lowTimeWarningColor),
1211 XtRString, COLOR_LOWTIMEWARNING },
1212 { "lowTimeWarning", "lowTimeWarning", XtRBoolean,
1213 sizeof(Boolean), XtOffset(AppDataPtr, lowTimeWarning),
1214 XtRImmediate, (XtPointer) False },
1215 {"icsEngineAnalyze", "icsEngineAnalyze", XtRBoolean, /* [DM] icsEngineAnalyze */
1216 sizeof(Boolean), XtOffset(AppDataPtr, icsEngineAnalyze),
1217 XtRImmediate, (XtPointer) False },
1218 { "firstScoreAbs", "firstScoreAbs", XtRBoolean,
1219 sizeof(Boolean), XtOffset(AppDataPtr, firstScoreIsAbsolute),
1220 XtRImmediate, (XtPointer) False },
1221 { "secondScoreAbs", "secondScoreAbs", XtRBoolean,
1222 sizeof(Boolean), XtOffset(AppDataPtr, secondScoreIsAbsolute),
1223 XtRImmediate, (XtPointer) False },
1224 { "pgnExtendedInfo", "pgnExtendedInfo", XtRBoolean,
1225 sizeof(Boolean), XtOffset(AppDataPtr, saveExtendedInfoInPGN),
1226 XtRImmediate, (XtPointer) False },
1227 { "hideThinkingFromHuman", "hideThinkingFromHuman", XtRBoolean,
1228 sizeof(Boolean), XtOffset(AppDataPtr, hideThinkingFromHuman),
1229 XtRImmediate, (XtPointer) True },
1230 { "adjudicateLossThreshold", "adjudicateLossThreshold", XtRInt,
1231 sizeof(int), XtOffset(AppDataPtr, adjudicateLossThreshold),
1232 XtRImmediate, (XtPointer) 0},
1233 { "adjudicateDrawMoves", "adjudicateDrawMoves", XtRInt,
1234 sizeof(int), XtOffset(AppDataPtr, adjudicateDrawMoves),
1235 XtRImmediate, (XtPointer) 0},
1236 { "pgnEventHeader", "pgnEventHeader", XtRString,
1237 sizeof(String), XtOffset(AppDataPtr, pgnEventHeader),
1238 XtRImmediate, (XtPointer) "Computer Chess Game" },
1239 { "defaultFrcPosition", "defaultFrcPositon", XtRInt,
1240 sizeof(int), XtOffset(AppDataPtr, defaultFrcPosition),
1241 XtRImmediate, (XtPointer) -1},
1242 { "gameListTags", "gameListTags", XtRString,
1243 sizeof(String), XtOffset(AppDataPtr, gameListTags),
1244 XtRImmediate, (XtPointer) GLT_DEFAULT_TAGS },
1246 // [HGM] 4.3.xx options
1247 { "boardWidth", "boardWidth", XtRInt,
1248 sizeof(int), XtOffset(AppDataPtr, NrFiles),
1249 XtRImmediate, (XtPointer) -1},
1250 { "boardHeight", "boardHeight", XtRInt,
1251 sizeof(int), XtOffset(AppDataPtr, NrRanks),
1252 XtRImmediate, (XtPointer) -1},
1253 { "matchPause", "matchPause", XtRInt,
1254 sizeof(int), XtOffset(AppDataPtr, matchPause),
1255 XtRImmediate, (XtPointer) 10000},
1256 { "holdingsSize", "holdingsSize", XtRInt,
1257 sizeof(int), XtOffset(AppDataPtr, holdingsSize),
1258 XtRImmediate, (XtPointer) -1},
1259 { "flipBlack", "flipBlack", XtRBoolean,
1260 sizeof(Boolean), XtOffset(AppDataPtr, upsideDown),
1261 XtRImmediate, (XtPointer) False},
1262 { "allWhite", "allWhite", XtRBoolean,
1263 sizeof(Boolean), XtOffset(AppDataPtr, allWhite),
1264 XtRImmediate, (XtPointer) False},
1265 { "pieceToCharTable", "pieceToCharTable", XtRString,
1266 sizeof(String), XtOffset(AppDataPtr, pieceToCharTable),
1267 XtRImmediate, (XtPointer) 0},
1268 { "alphaRank", "alphaRank", XtRBoolean,
1269 sizeof(Boolean), XtOffset(AppDataPtr, alphaRank),
1270 XtRImmediate, (XtPointer) False},
1271 { "testClaims", "testClaims", XtRBoolean,
1272 sizeof(Boolean), XtOffset(AppDataPtr, testClaims),
1273 XtRImmediate, (XtPointer) True},
1274 { "checkMates", "checkMates", XtRBoolean,
1275 sizeof(Boolean), XtOffset(AppDataPtr, checkMates),
1276 XtRImmediate, (XtPointer) True},
1277 { "materialDraws", "materialDraws", XtRBoolean,
1278 sizeof(Boolean), XtOffset(AppDataPtr, materialDraws),
1279 XtRImmediate, (XtPointer) True},
1280 { "trivialDraws", "trivialDraws", XtRBoolean,
1281 sizeof(Boolean), XtOffset(AppDataPtr, trivialDraws),
1282 XtRImmediate, (XtPointer) False},
1283 { "ruleMoves", "ruleMoves", XtRInt,
1284 sizeof(int), XtOffset(AppDataPtr, ruleMoves),
1285 XtRImmediate, (XtPointer) 51},
1286 { "repeatsToDraw", "repeatsToDraw", XtRInt,
1287 sizeof(int), XtOffset(AppDataPtr, drawRepeats),
1288 XtRImmediate, (XtPointer) 6},
1289 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1290 sizeof(int), XtOffset(AppDataPtr, engineComments),
1291 XtRImmediate, (XtPointer) 1},
1292 { "userName", "userName", XtRString,
1293 sizeof(int), XtOffset(AppDataPtr, userName),
1294 XtRImmediate, (XtPointer) 0},
1295 { "autoKibitz", "autoKibitz", XtRBoolean,
1296 sizeof(Boolean), XtOffset(AppDataPtr, autoKibitz),
1297 XtRImmediate, (XtPointer) False},
1298 { "firstTimeOdds", "firstTimeOdds", XtRInt,
1299 sizeof(int), XtOffset(AppDataPtr, firstTimeOdds),
1300 XtRImmediate, (XtPointer) 1},
1301 { "secondTimeOdds", "secondTimeOdds", XtRInt,
1302 sizeof(int), XtOffset(AppDataPtr, secondTimeOdds),
1303 XtRImmediate, (XtPointer) 1},
1304 { "timeOddsMode", "timeOddsMode", XtRInt,
1305 sizeof(int), XtOffset(AppDataPtr, timeOddsMode),
1306 XtRImmediate, (XtPointer) 0},
1307 { "firstAccumulateTC", "firstAccumulateTC", XtRInt,
1308 sizeof(int), XtOffset(AppDataPtr, firstAccumulateTC),
1309 XtRImmediate, (XtPointer) 1},
1310 { "secondAccumulateTC", "secondAccumulateTC", XtRInt,
1311 sizeof(int), XtOffset(AppDataPtr, secondAccumulateTC),
1312 XtRImmediate, (XtPointer) 1},
1313 { "firstNPS", "firstNPS", XtRInt,
1314 sizeof(int), XtOffset(AppDataPtr, firstNPS),
1315 XtRImmediate, (XtPointer) -1},
1316 { "secondNPS", "secondNPS", XtRInt,
1317 sizeof(int), XtOffset(AppDataPtr, secondNPS),
1318 XtRImmediate, (XtPointer) -1},
1319 { "serverMoves", "serverMoves", XtRString,
1320 sizeof(String), XtOffset(AppDataPtr, serverMovesName),
1321 XtRImmediate, (XtPointer) 0},
1322 { "serverPause", "serverPause", XtRInt,
1323 sizeof(int), XtOffset(AppDataPtr, serverPause),
1324 XtRImmediate, (XtPointer) 0},
1325 { "suppressLoadMoves", "suppressLoadMoves", XtRBoolean,
1326 sizeof(Boolean), XtOffset(AppDataPtr, suppressLoadMoves),
1327 XtRImmediate, (XtPointer) False},
1328 { "userName", "userName", XtRString,
1329 sizeof(String), XtOffset(AppDataPtr, userName),
1330 XtRImmediate, (XtPointer) 0},
1331 { "egtFormats", "egtFormats", XtRString,
1332 sizeof(String), XtOffset(AppDataPtr, egtFormats),
1333 XtRImmediate, (XtPointer) 0},
1334 { "rewindIndex", "rewindIndex", XtRInt,
1335 sizeof(int), XtOffset(AppDataPtr, rewindIndex),
1336 XtRImmediate, (XtPointer) 0},
1337 { "sameColorGames", "sameColorGames", XtRInt,
1338 sizeof(int), XtOffset(AppDataPtr, sameColorGames),
1339 XtRImmediate, (XtPointer) 0},
1340 { "smpCores", "smpCores", XtRInt,
1341 sizeof(int), XtOffset(AppDataPtr, smpCores),
1342 XtRImmediate, (XtPointer) 1},
1343 { "niceEngines", "niceEngines", XtRInt,
1344 sizeof(int), XtOffset(AppDataPtr, niceEngines),
1345 XtRImmediate, (XtPointer) 0},
1346 { "nameOfDebugFile", "nameOfDebugFile", XtRString,
1347 sizeof(String), XtOffset(AppDataPtr, nameOfDebugFile),
1348 XtRImmediate, (XtPointer) "xboard.debug"},
1349 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1350 sizeof(int), XtOffset(AppDataPtr, engineComments),
1351 XtRImmediate, (XtPointer) 1},
1352 { "noGUI", "noGUI", XtRBoolean,
1353 sizeof(Boolean), XtOffset(AppDataPtr, noGUI),
1354 XtRImmediate, (XtPointer) 0},
1355 { "firstOptions", "firstOptions", XtRString,
1356 sizeof(String), XtOffset(AppDataPtr, firstOptions),
1357 XtRImmediate, (XtPointer) "" },
1358 { "secondOptions", "secondOptions", XtRString,
1359 sizeof(String), XtOffset(AppDataPtr, secondOptions),
1360 XtRImmediate, (XtPointer) "" },
1361 { "firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XtRString,
1362 sizeof(String), XtOffset(AppDataPtr, fenOverride1),
1363 XtRImmediate, (XtPointer) 0 },
1364 { "secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XtRString,
1365 sizeof(String), XtOffset(AppDataPtr, fenOverride2),
1366 XtRImmediate, (XtPointer) 0 },
1368 // [HGM] Winboard_x UCI options
1369 { "firstIsUCI", "firstIsUCI", XtRBoolean,
1370 sizeof(Boolean), XtOffset(AppDataPtr, firstIsUCI),
1371 XtRImmediate, (XtPointer) False},
1372 { "secondIsUCI", "secondIsUCI", XtRBoolean,
1373 sizeof(Boolean), XtOffset(AppDataPtr, secondIsUCI),
1374 XtRImmediate, (XtPointer) False},
1375 { "firstHasOwnBookUCI", "firstHasOwnBookUCI", XtRBoolean,
1376 sizeof(Boolean), XtOffset(AppDataPtr, firstHasOwnBookUCI),
1377 XtRImmediate, (XtPointer) True},
1378 { "secondHasOwnBookUCI", "secondHasOwnBookUCI", XtRBoolean,
1379 sizeof(Boolean), XtOffset(AppDataPtr, secondHasOwnBookUCI),
1380 XtRImmediate, (XtPointer) True},
1381 { "usePolyglotBook", "usePolyglotBook", XtRBoolean,
1382 sizeof(Boolean), XtOffset(AppDataPtr, usePolyglotBook),
1383 XtRImmediate, (XtPointer) False},
1384 { "defaultHashSize", "defaultHashSize", XtRInt,
1385 sizeof(int), XtOffset(AppDataPtr, defaultHashSize),
1386 XtRImmediate, (XtPointer) 64},
1387 { "defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XtRInt,
1388 sizeof(int), XtOffset(AppDataPtr, defaultCacheSizeEGTB),
1389 XtRImmediate, (XtPointer) 4},
1390 { "polyglotDir", "polyglotDir", XtRString,
1391 sizeof(String), XtOffset(AppDataPtr, polyglotDir),
1392 XtRImmediate, (XtPointer) "." },
1393 { "polyglotBook", "polyglotBook", XtRString,
1394 sizeof(String), XtOffset(AppDataPtr, polyglotBook),
1395 XtRImmediate, (XtPointer) "" },
1396 { "defaultPathEGTB", "defaultPathEGTB", XtRString,
1397 sizeof(String), XtOffset(AppDataPtr, defaultPathEGTB),
1398 XtRImmediate, (XtPointer) "/usr/local/share/egtb"},
1399 { "delayBeforeQuit", "delayBeforeQuit", XtRInt,
1400 sizeof(int), XtOffset(AppDataPtr, delayBeforeQuit),
1401 XtRImmediate, (XtPointer) 0},
1402 { "delayAfterQuit", "delayAfterQuit", XtRInt,
1403 sizeof(int), XtOffset(AppDataPtr, delayAfterQuit),
1404 XtRImmediate, (XtPointer) 0},
1405 { "keepAlive", "keepAlive", XtRInt,
1406 sizeof(int), XtOffset(AppDataPtr, keepAlive),
1407 XtRImmediate, (XtPointer) 0},
1408 { "forceIllegalMoves", "forceIllegalMoves", XtRBoolean,
1409 sizeof(Boolean), XtOffset(AppDataPtr, forceIllegal),
1410 XtRImmediate, (XtPointer) False},
1413 XrmOptionDescRec shellOptions[] = {
1414 { "-whitePieceColor", "whitePieceColor", XrmoptionSepArg, NULL },
1415 { "-blackPieceColor", "blackPieceColor", XrmoptionSepArg, NULL },
1416 { "-lightSquareColor", "lightSquareColor", XrmoptionSepArg, NULL },
1417 { "-darkSquareColor", "darkSquareColor", XrmoptionSepArg, NULL },
1418 { "-highlightSquareColor", "highlightSquareColor", XrmoptionSepArg, NULL },
1419 { "-premoveHighlightColor", "premoveHighlightColor", XrmoptionSepArg,NULL},
1420 { "-movesPerSession", "movesPerSession", XrmoptionSepArg, NULL },
1421 { "-mps", "movesPerSession", XrmoptionSepArg, NULL },
1422 { "-timeIncrement", "timeIncrement", XrmoptionSepArg, NULL },
1423 { "-inc", "timeIncrement", XrmoptionSepArg, NULL },
1424 { "-initString", "initString", XrmoptionSepArg, NULL },
1425 { "-firstInitString", "initString", XrmoptionSepArg, NULL },
1426 { "-secondInitString", "secondInitString", XrmoptionSepArg, NULL },
1427 { "-firstComputerString", "firstComputerString", XrmoptionSepArg, NULL },
1428 { "-secondComputerString", "secondComputerString", XrmoptionSepArg, NULL },
1429 { "-firstChessProgram", "firstChessProgram", XrmoptionSepArg, NULL },
1430 { "-fcp", "firstChessProgram", XrmoptionSepArg, NULL },
1431 { "-secondChessProgram", "secondChessProgram", XrmoptionSepArg, NULL },
1432 { "-scp", "secondChessProgram", XrmoptionSepArg, NULL },
1433 { "-firstPlaysBlack", "firstPlaysBlack", XrmoptionSepArg, NULL },
1434 { "-fb", "firstPlaysBlack", XrmoptionNoArg, "True" },
1435 { "-xfb", "firstPlaysBlack", XrmoptionNoArg, "False" },
1436 { "-noChessProgram", "noChessProgram", XrmoptionSepArg, NULL },
1437 { "-ncp", "noChessProgram", XrmoptionNoArg, "True" },
1438 { "-xncp", "noChessProgram", XrmoptionNoArg, "False" },
1439 { "-firstHost", "firstHost", XrmoptionSepArg, NULL },
1440 { "-fh", "firstHost", XrmoptionSepArg, NULL },
1441 { "-secondHost", "secondHost", XrmoptionSepArg, NULL },
1442 { "-sh", "secondHost", XrmoptionSepArg, NULL },
1443 { "-firstDirectory", "firstDirectory", XrmoptionSepArg, NULL },
1444 { "-fd", "firstDirectory", XrmoptionSepArg, NULL },
1445 { "-secondDirectory", "secondDirectory", XrmoptionSepArg, NULL },
1446 { "-sd", "secondDirectory", XrmoptionSepArg, NULL },
1447 { "-bitmapDirectory", "bitmapDirectory", XrmoptionSepArg, NULL },
1448 { "-bm", "bitmapDirectory", XrmoptionSepArg, NULL },
1449 { "-remoteShell", "remoteShell", XrmoptionSepArg, NULL },
1450 { "-rsh", "remoteShell", XrmoptionSepArg, NULL },
1451 { "-remoteUser", "remoteUser", XrmoptionSepArg, NULL },
1452 { "-ruser", "remoteUser", XrmoptionSepArg, NULL },
1453 { "-timeDelay", "timeDelay", XrmoptionSepArg, NULL },
1454 { "-td", "timeDelay", XrmoptionSepArg, NULL },
1455 { "-timeControl", "timeControl", XrmoptionSepArg, NULL },
1456 { "-tc", "timeControl", XrmoptionSepArg, NULL },
1457 { "-internetChessServerMode", "internetChessServerMode",
1458 XrmoptionSepArg, NULL },
1459 { "-ics", "internetChessServerMode", XrmoptionNoArg, "True" },
1460 { "-xics", "internetChessServerMode", XrmoptionNoArg, "False" },
1461 { "-internetChessServerHost", "internetChessServerHost",
1462 XrmoptionSepArg, NULL },
1463 { "-icshost", "internetChessServerHost", XrmoptionSepArg, NULL },
1464 { "-internetChessServerPort", "internetChessServerPort",
1465 XrmoptionSepArg, NULL },
1466 { "-icsport", "internetChessServerPort", XrmoptionSepArg, NULL },
1467 { "-internetChessServerCommPort", "internetChessServerCommPort",
1468 XrmoptionSepArg, NULL },
1469 { "-icscomm", "internetChessServerCommPort", XrmoptionSepArg, NULL },
1470 { "-internetChessServerLogonScript", "internetChessServerLogonScript",
1471 XrmoptionSepArg, NULL },
1472 { "-icslogon", "internetChessServerLogonScript", XrmoptionSepArg, NULL },
1473 { "-internetChessServerHelper", "internetChessServerHelper",
1474 XrmoptionSepArg, NULL },
1475 { "-icshelper", "internetChessServerHelper", XrmoptionSepArg, NULL },
1476 { "-internetChessServerInputBox", "internetChessServerInputBox",
1477 XrmoptionSepArg, NULL },
1478 { "-icsinput", "internetChessServerInputBox", XrmoptionNoArg, "True" },
1479 { "-xicsinput", "internetChessServerInputBox", XrmoptionNoArg, "False" },
1480 { "-icsAlarm", "icsAlarm", XrmoptionSepArg, NULL },
1481 { "-alarm", "icsAlarm", XrmoptionNoArg, "True" },
1482 { "-xalarm", "icsAlarm", XrmoptionNoArg, "False" },
1483 { "-icsAlarmTime", "icsAlarmTime", XrmoptionSepArg, NULL },
1484 { "-useTelnet", "useTelnet", XrmoptionSepArg, NULL },
1485 { "-telnet", "useTelnet", XrmoptionNoArg, "True" },
1486 { "-xtelnet", "useTelnet", XrmoptionNoArg, "False" },
1487 { "-telnetProgram", "telnetProgram", XrmoptionSepArg, NULL },
1488 { "-gateway", "gateway", XrmoptionSepArg, NULL },
1489 { "-loadGameFile", "loadGameFile", XrmoptionSepArg, NULL },
1490 { "-lgf", "loadGameFile", XrmoptionSepArg, NULL },
1491 { "-loadGameIndex", "loadGameIndex", XrmoptionSepArg, NULL },
1492 { "-lgi", "loadGameIndex", XrmoptionSepArg, NULL },
1493 { "-saveGameFile", "saveGameFile", XrmoptionSepArg, NULL },
1494 { "-sgf", "saveGameFile", XrmoptionSepArg, NULL },
1495 { "-autoSaveGames", "autoSaveGames", XrmoptionSepArg, NULL },
1496 { "-autosave", "autoSaveGames", XrmoptionNoArg, "True" },
1497 { "-xautosave", "autoSaveGames", XrmoptionNoArg, "False" },
1498 { "-autoRaiseBoard", "autoRaiseBoard", XrmoptionSepArg, NULL },
1499 { "-autoraise", "autoRaiseBoard", XrmoptionNoArg, "True" },
1500 { "-xautoraise", "autoRaiseBoard", XrmoptionNoArg, "False" },
1501 { "-blindfold", "blindfold", XrmoptionSepArg, NULL },
1502 { "-blind", "blindfold", XrmoptionNoArg, "True" },
1503 { "-xblind", "blindfold", XrmoptionNoArg, "False" },
1504 { "-loadPositionFile", "loadPositionFile", XrmoptionSepArg, NULL },
1505 { "-lpf", "loadPositionFile", XrmoptionSepArg, NULL },
1506 { "-loadPositionIndex", "loadPositionIndex", XrmoptionSepArg, NULL },
1507 { "-lpi", "loadPositionIndex", XrmoptionSepArg, NULL },
1508 { "-savePositionFile", "savePositionFile", XrmoptionSepArg, NULL },
1509 { "-spf", "savePositionFile", XrmoptionSepArg, NULL },
1510 { "-matchMode", "matchMode", XrmoptionSepArg, NULL },
1511 { "-mm", "matchMode", XrmoptionNoArg, "True" },
1512 { "-xmm", "matchMode", XrmoptionNoArg, "False" },
1513 { "-matchGames", "matchGames", XrmoptionSepArg, NULL },
1514 { "-mg", "matchGames", XrmoptionSepArg, NULL },
1515 { "-monoMode", "monoMode", XrmoptionSepArg, NULL },
1516 { "-mono", "monoMode", XrmoptionNoArg, "True" },
1517 { "-xmono", "monoMode", XrmoptionNoArg, "False" },
1518 { "-debugMode", "debugMode", XrmoptionSepArg, NULL },
1519 { "-debug", "debugMode", XrmoptionNoArg, "True" },
1520 { "-xdebug", "debugMode", XrmoptionNoArg, "False" },
1521 { "-clockMode", "clockMode", XrmoptionSepArg, NULL },
1522 { "-clock", "clockMode", XrmoptionNoArg, "True" },
1523 { "-xclock", "clockMode", XrmoptionNoArg, "False" },
1524 { "-boardSize", "boardSize", XrmoptionSepArg, NULL },
1525 { "-size", "boardSize", XrmoptionSepArg, NULL },
1526 { "-searchTime", "searchTime", XrmoptionSepArg, NULL },
1527 { "-st", "searchTime", XrmoptionSepArg, NULL },
1528 { "-searchDepth", "searchDepth", XrmoptionSepArg, NULL },
1529 { "-depth", "searchDepth", XrmoptionSepArg, NULL },
1530 { "-showCoords", "showCoords", XrmoptionSepArg, NULL },
1531 { "-coords", "showCoords", XrmoptionNoArg, "True" },
1532 { "-xcoords", "showCoords", XrmoptionNoArg, "False" },
1534 { "-showJail", "showJail", XrmoptionSepArg, NULL },
1535 { "-jail", "showJail", XrmoptionNoArg, "1" },
1536 { "-sidejail", "showJail", XrmoptionNoArg, "2" },
1537 { "-xjail", "showJail", XrmoptionNoArg, "0" },
1539 { "-showThinking", "showThinking", XrmoptionSepArg, NULL },
1540 { "-thinking", "showThinking", XrmoptionNoArg, "True" },
1541 { "-xthinking", "showThinking", XrmoptionNoArg, "False" },
1542 { "-ponderNextMove", "ponderNextMove", XrmoptionSepArg, NULL },
1543 { "-ponder", "ponderNextMove", XrmoptionNoArg, "True" },
1544 { "-xponder", "ponderNextMove", XrmoptionNoArg, "False" },
1545 { "-periodicUpdates", "periodicUpdates", XrmoptionSepArg, NULL },
1546 { "-periodic", "periodicUpdates", XrmoptionNoArg, "True" },
1547 { "-xperiodic", "periodicUpdates", XrmoptionNoArg, "False" },
1548 { "-clockFont", "clockFont", XrmoptionSepArg, NULL },
1549 { "-coordFont", "coordFont", XrmoptionSepArg, NULL },
1550 { "-font", "font", XrmoptionSepArg, NULL },
1551 { "-ringBellAfterMoves", "ringBellAfterMoves", XrmoptionSepArg, NULL },
1552 { "-bell", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1553 { "-xbell", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1554 { "-movesound", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1555 { "-xmovesound", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1556 { "-autoCallFlag", "autoCallFlag", XrmoptionSepArg, NULL },
1557 { "-autoflag", "autoCallFlag", XrmoptionNoArg, "True" },
1558 { "-xautoflag", "autoCallFlag", XrmoptionNoArg, "False" },
1559 { "-autoFlipView", "autoFlipView", XrmoptionSepArg, NULL },
1560 { "-autoflip", "autoFlipView", XrmoptionNoArg, "True" },
1561 { "-xautoflip", "autoFlipView", XrmoptionNoArg, "False" },
1562 { "-autoObserve", "autoObserve", XrmoptionSepArg, NULL },
1563 { "-autobs", "autoObserve", XrmoptionNoArg, "True" },
1564 { "-xautobs", "autoObserve", XrmoptionNoArg, "False" },
1565 { "-autoComment", "autoComment", XrmoptionSepArg, NULL },
1566 { "-autocomm", "autoComment", XrmoptionNoArg, "True" },
1567 { "-xautocomm", "autoComment", XrmoptionNoArg, "False" },
1568 { "-getMoveList", "getMoveList", XrmoptionSepArg, NULL },
1569 { "-moves", "getMoveList", XrmoptionNoArg, "True" },
1570 { "-xmoves", "getMoveList", XrmoptionNoArg, "False" },
1572 { "-highlightDragging", "highlightDragging", XrmoptionSepArg, NULL },
1573 { "-highdrag", "highlightDragging", XrmoptionNoArg, "True" },
1574 { "-xhighdrag", "highlightDragging", XrmoptionNoArg, "False" },
1576 { "-highlightLastMove", "highlightLastMove", XrmoptionSepArg, NULL },
1577 { "-highlight", "highlightLastMove", XrmoptionNoArg, "True" },
1578 { "-xhighlight", "highlightLastMove", XrmoptionNoArg, "False" },
1579 { "-premove", "premove", XrmoptionSepArg, NULL },
1580 { "-pre", "premove", XrmoptionNoArg, "True" },
1581 { "-xpre", "premove", XrmoptionNoArg, "False" },
1582 { "-testLegality", "testLegality", XrmoptionSepArg, NULL },
1583 { "-legal", "testLegality", XrmoptionNoArg, "True" },
1584 { "-xlegal", "testLegality", XrmoptionNoArg, "False" },
1585 { "-flipView", "flipView", XrmoptionSepArg, NULL },
1586 { "-flip", "flipView", XrmoptionNoArg, "True" },
1587 { "-xflip", "flipView", XrmoptionNoArg, "False" },
1588 { "-cmail", "cmailGameName", XrmoptionSepArg, NULL },
1589 { "-alwaysPromoteToQueen", "alwaysPromoteToQueen",
1590 XrmoptionSepArg, NULL },
1591 { "-queen", "alwaysPromoteToQueen", XrmoptionNoArg, "True" },
1592 { "-xqueen", "alwaysPromoteToQueen", XrmoptionNoArg, "False" },
1593 { "-oldSaveStyle", "oldSaveStyle", XrmoptionSepArg, NULL },
1594 { "-oldsave", "oldSaveStyle", XrmoptionNoArg, "True" },
1595 { "-xoldsave", "oldSaveStyle", XrmoptionNoArg, "False" },
1596 { "-quietPlay", "quietPlay", XrmoptionSepArg, NULL },
1597 { "-quiet", "quietPlay", XrmoptionNoArg, "True" },
1598 { "-xquiet", "quietPlay", XrmoptionNoArg, "False" },
1599 { "-titleInWindow", "titleInWindow", XrmoptionSepArg, NULL },
1600 { "-title", "titleInWindow", XrmoptionNoArg, "True" },
1601 { "-xtitle", "titleInWindow", XrmoptionNoArg, "False" },
1603 { "-zippyTalk", "zippyTalk", XrmoptionSepArg, NULL },
1604 { "-zt", "zippyTalk", XrmoptionNoArg, "True" },
1605 { "-xzt", "zippyTalk", XrmoptionNoArg, "False" },
1606 { "-zippyPlay", "zippyPlay", XrmoptionSepArg, NULL },
1607 { "-zp", "zippyPlay", XrmoptionNoArg, "True" },
1608 { "-xzp", "zippyPlay", XrmoptionNoArg, "False" },
1609 { "-zippyLines", "zippyLines", XrmoptionSepArg, NULL },
1610 { "-zippyPinhead", "zippyPinhead", XrmoptionSepArg, NULL },
1611 { "-zippyPassword", "zippyPassword", XrmoptionSepArg, NULL },
1612 { "-zippyPassword2", "zippyPassword2", XrmoptionSepArg, NULL },
1613 { "-zippyWrongPassword", "zippyWrongPassword", XrmoptionSepArg, NULL },
1614 { "-zippyAcceptOnly", "zippyAcceptOnly", XrmoptionSepArg, NULL },
1615 { "-zippyUseI", "zippyUseI", XrmoptionSepArg, NULL },
1616 { "-zui", "zippyUseI", XrmoptionNoArg, "True" },
1617 { "-xzui", "zippyUseI", XrmoptionNoArg, "False" },
1618 { "-zippyBughouse", "zippyBughouse", XrmoptionSepArg, NULL },
1619 { "-zippyNoplayCrafty", "zippyNoplayCrafty", XrmoptionSepArg, NULL },
1620 { "-znc", "zippyNoplayCrafty", XrmoptionNoArg, "True" },
1621 { "-xznc", "zippyNoplayCrafty", XrmoptionNoArg, "False" },
1622 { "-zippyGameEnd", "zippyGameEnd", XrmoptionSepArg, NULL },
1623 { "-zippyGameStart", "zippyGameStart", XrmoptionSepArg, NULL },
1624 { "-zippyAdjourn", "zippyAdjourn", XrmoptionSepArg, NULL },
1625 { "-zadj", "zippyAdjourn", XrmoptionNoArg, "True" },
1626 { "-xzadj", "zippyAdjourn", XrmoptionNoArg, "False" },
1627 { "-zippyAbort", "zippyAbort", XrmoptionSepArg, NULL },
1628 { "-zab", "zippyAbort", XrmoptionNoArg, "True" },
1629 { "-xzab", "zippyAbort", XrmoptionNoArg, "False" },
1630 { "-zippyVariants", "zippyVariants", XrmoptionSepArg, NULL },
1631 { "-zippyMaxGames", "zippyMaxGames", XrmoptionSepArg, NULL },
1632 { "-zippyReplayTimeout", "zippyReplayTimeout", XrmoptionSepArg, NULL },
1633 { "-zippyShortGame", "zippyShortGame", XrmoptionSepArg, NULL },
1635 { "-flashCount", "flashCount", XrmoptionSepArg, NULL },
1636 { "-flash", "flashCount", XrmoptionNoArg, "3" },
1637 { "-xflash", "flashCount", XrmoptionNoArg, "0" },
1638 { "-flashRate", "flashRate", XrmoptionSepArg, NULL },
1639 { "-pixmapDirectory", "pixmapDirectory", XrmoptionSepArg, NULL },
1640 { "-msLoginDelay", "msLoginDelay", XrmoptionSepArg, NULL },
1641 { "-pixmap", "pixmapDirectory", XrmoptionSepArg, NULL },
1642 { "-colorizeMessages", "colorizeMessages", XrmoptionSepArg, NULL },
1643 { "-colorize", "colorizeMessages", XrmoptionNoArg, "True" },
1644 { "-xcolorize", "colorizeMessages", XrmoptionNoArg, "False" },
1645 { "-colorShout", "colorShout", XrmoptionSepArg, NULL },
1646 { "-colorSShout", "colorSShout", XrmoptionSepArg, NULL },
1647 { "-colorCShout", "colorSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1648 { "-colorChannel1", "colorChannel1", XrmoptionSepArg, NULL },
1649 { "-colorChannel", "colorChannel", XrmoptionSepArg, NULL },
1650 { "-colorKibitz", "colorKibitz", XrmoptionSepArg, NULL },
1651 { "-colorTell", "colorTell", XrmoptionSepArg, NULL },
1652 { "-colorChallenge", "colorChallenge", XrmoptionSepArg, NULL },
1653 { "-colorRequest", "colorRequest", XrmoptionSepArg, NULL },
1654 { "-colorSeek", "colorSeek", XrmoptionSepArg, NULL },
1655 { "-colorNormal", "colorNormal", XrmoptionSepArg, NULL },
1656 { "-soundProgram", "soundProgram", XrmoptionSepArg, NULL },
1657 { "-soundShout", "soundShout", XrmoptionSepArg, NULL },
1658 { "-soundSShout", "soundSShout", XrmoptionSepArg, NULL },
1659 { "-soundCShout", "soundSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1660 { "-soundChannel1", "soundChannel1", XrmoptionSepArg, NULL },
1661 { "-soundChannel", "soundChannel", XrmoptionSepArg, NULL },
1662 { "-soundKibitz", "soundKibitz", XrmoptionSepArg, NULL },
1663 { "-soundTell", "soundTell", XrmoptionSepArg, NULL },
1664 { "-soundChallenge", "soundChallenge", XrmoptionSepArg, NULL },
1665 { "-soundRequest", "soundRequest", XrmoptionSepArg, NULL },
1666 { "-soundSeek", "soundSeek", XrmoptionSepArg, NULL },
1667 { "-soundMove", "soundMove", XrmoptionSepArg, NULL },
1668 { "-soundIcsWin", "soundIcsWin", XrmoptionSepArg, NULL },
1669 { "-soundIcsLoss", "soundIcsLoss", XrmoptionSepArg, NULL },
1670 { "-soundIcsDraw", "soundIcsDraw", XrmoptionSepArg, NULL },
1671 { "-soundIcsUnfinished", "soundIcsUnfinished", XrmoptionSepArg, NULL },
1672 { "-soundIcsAlarm", "soundIcsAlarm", XrmoptionSepArg, NULL },
1673 { "-reuseFirst", "reuseFirst", XrmoptionSepArg, NULL },
1674 { "-reuseChessPrograms", "reuseFirst", XrmoptionSepArg, NULL }, /*compat*/
1675 { "-reuse", "reuseFirst", XrmoptionNoArg, "True" },
1676 { "-xreuse", "reuseFirst", XrmoptionNoArg, "False" },
1677 { "-reuseSecond", "reuseSecond", XrmoptionSepArg, NULL },
1678 { "-reuse2", "reuseSecond", XrmoptionNoArg, "True" },
1679 { "-xreuse2", "reuseSecond", XrmoptionNoArg, "False" },
1680 { "-animateMoving", "animateMoving", XrmoptionSepArg, NULL },
1681 { "-animate", "animateMoving", XrmoptionNoArg, "True" },
1682 { "-xanimate", "animateMoving", XrmoptionNoArg, "False" },
1683 { "-animateDragging", "animateDragging", XrmoptionSepArg, NULL },
1684 { "-drag", "animateDragging", XrmoptionNoArg, "True" },
1685 { "-xdrag", "animateDragging", XrmoptionNoArg, "False" },
1686 { "-animateSpeed", "animateSpeed", XrmoptionSepArg, NULL },
1687 { "-popupExitMessage", "popupExitMessage", XrmoptionSepArg, NULL },
1688 { "-exit", "popupExitMessage", XrmoptionNoArg, "True" },
1689 { "-xexit", "popupExitMessage", XrmoptionNoArg, "False" },
1690 { "-popupMoveErrors", "popupMoveErrors", XrmoptionSepArg, NULL },
1691 { "-popup", "popupMoveErrors", XrmoptionNoArg, "True" },
1692 { "-xpopup", "popupMoveErrors", XrmoptionNoArg, "False" },
1693 { "-fontSizeTolerance", "fontSizeTolerance", XrmoptionSepArg, NULL },
1694 { "-initialMode", "initialMode", XrmoptionSepArg, NULL },
1695 { "-mode", "initialMode", XrmoptionSepArg, NULL },
1696 { "-variant", "variant", XrmoptionSepArg, NULL },
1697 { "-firstProtocolVersion", "firstProtocolVersion", XrmoptionSepArg, NULL },
1698 { "-secondProtocolVersion","secondProtocolVersion",XrmoptionSepArg, NULL },
1699 { "-showButtonBar", "showButtonBar", XrmoptionSepArg, NULL },
1700 { "-buttons", "showButtonBar", XrmoptionNoArg, "True" },
1701 { "-xbuttons", "showButtonBar", XrmoptionNoArg, "False" },
1702 { "-lowTimeWarningColor", "lowTimeWarningColor", XrmoptionSepArg, NULL },
1703 { "-lowTimeWarning", "lowTimeWarning", XrmoptionSepArg, NULL },
1704 /* [AS,HR] New features */
1705 { "-firstScoreAbs", "firstScoreAbs", XrmoptionSepArg, NULL },
1706 { "-secondScoreAbs", "secondScoreAbs", XrmoptionSepArg, NULL },
1707 { "-pgnExtendedInfo", "pgnExtendedInfo", XrmoptionSepArg, NULL },
1708 { "-hideThinkingFromHuman", "hideThinkingFromHuman", XrmoptionSepArg, NULL },
1709 { "-adjudicateLossThreshold", "adjudicateLossThreshold", XrmoptionSepArg, NULL },
1710 { "-adjudicateDrawMoves", "adjudicateDrawMoves", XrmoptionSepArg, NULL },
1711 { "-pgnEventHeader", "pgnEventHeader", XrmoptionSepArg, NULL },
1712 { "-firstIsUCI", "firstIsUCI", XrmoptionSepArg, NULL },
1713 { "-secondIsUCI", "secondIsUCI", XrmoptionSepArg, NULL },
1714 { "-fUCI", "firstIsUCI", XrmoptionNoArg, "True" },
1715 { "-sUCI", "secondIsUCI", XrmoptionNoArg, "True" },
1716 { "-firstHasOwnBookUCI", "firstHasOwnBookUCI", XrmoptionSepArg, NULL },
1717 { "-secondHasOwnBookUCI", "secondHasOwnBookUCI", XrmoptionSepArg, NULL },
1718 { "-fNoOwnBookUCI", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1719 { "-sNoOwnBookUCI", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1720 { "-firstXBook", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1721 { "-secondXBook", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1722 { "-polyglotDir", "polyglotDir", XrmoptionSepArg, NULL },
1723 { "-usePolyglotBook", "usePolyglotBook", XrmoptionSepArg, NULL },
1724 { "-polyglotBook", "polyglotBook", XrmoptionSepArg, NULL },
1725 { "-defaultHashSize", "defaultHashSize", XrmoptionSepArg, NULL },
1726 { "-defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XrmoptionSepArg, NULL },
1727 { "-defaultPathEGTB", "defaultPathEGTB", XrmoptionSepArg, NULL },
1728 { "-defaultFrcPosition", "defaultFrcPosition", XrmoptionSepArg, NULL },
1729 { "-gameListTags", "gameListTags", XrmoptionSepArg, NULL },
1730 // [HGM] I am sure AS added many more options, but we have to fish them out, from the list in winboard.c
1732 /* [HGM,HR] User-selectable board size */
1733 { "-boardWidth", "boardWidth", XrmoptionSepArg, NULL },
1734 { "-boardHeight", "boardHeight", XrmoptionSepArg, NULL },
1735 { "-matchPause", "matchPause", XrmoptionSepArg, NULL },
1737 /* [HGM] new arguments of 4.3.xx. All except first three are back-end options, which should work immediately */
1738 { "-holdingsSize", "holdingsSize", XrmoptionSepArg, NULL }, // requires extensive front-end changes to work
1739 { "-flipBlack", "flipBlack", XrmoptionSepArg, NULL }, // requires front-end changes to work
1740 { "-allWhite", "allWhite", XrmoptionSepArg, NULL }, // requires front-end changes to work
1741 { "-pieceToCharTable", "pieceToCharTable", XrmoptionSepArg, NULL },
1742 { "-alphaRank", "alphaRank", XrmoptionSepArg, NULL },
1743 { "-testClaims", "testClaims", XrmoptionSepArg, NULL },
1744 { "-checkMates", "checkMates", XrmoptionSepArg, NULL },
1745 { "-materialDraws", "materialDraws", XrmoptionSepArg, NULL },
1746 { "-trivialDraws", "trivialDraws", XrmoptionSepArg, NULL },
1747 { "-ruleMoves", "ruleMoves", XrmoptionSepArg, NULL },
1748 { "-repeatsToDraw", "repeatsToDraw", XrmoptionSepArg, NULL },
1749 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1750 { "-userName", "userName", XrmoptionSepArg, NULL },
1751 { "-autoKibitz", "autoKibitz", XrmoptionNoArg, "True" },
1752 { "-firstTimeOdds", "firstTimeOdds", XrmoptionSepArg, NULL },
1753 { "-secondTimeOdds", "secondTimeOdds", XrmoptionSepArg, NULL },
1754 { "-timeOddsMode", "timeOddsMode", XrmoptionSepArg, NULL },
1755 { "-firstAccumulateTC", "firstAccumulateTC", XrmoptionSepArg, NULL },
1756 { "-secondAccumulateTC", "secondAccumulateTC", XrmoptionSepArg, NULL },
1757 { "-firstNPS", "firstNPS", XrmoptionSepArg, NULL },
1758 { "-secondNPS", "secondNPS", XrmoptionSepArg, NULL },
1759 { "-serverMoves", "serverMoves", XrmoptionSepArg, NULL },
1760 { "-serverPause", "serverPause", XrmoptionSepArg, NULL },
1761 { "-suppressLoadMoves", "suppressLoadMoves", XrmoptionSepArg, NULL },
1762 { "-egtFormats", "egtFormats", XrmoptionSepArg, NULL },
1763 { "-userName", "userName", XrmoptionSepArg, NULL },
1764 { "-smpCores", "smpCores", XrmoptionSepArg, NULL },
1765 { "-sameColorGames", "sameColorGames", XrmoptionSepArg, NULL },
1766 { "-rewindIndex", "rewindIndex", XrmoptionSepArg, NULL },
1767 { "-niceEngines", "niceEngines", XrmoptionSepArg, NULL },
1768 { "-delayBeforeQuit", "delayBeforeQuit", XrmoptionSepArg, NULL },
1769 { "-delayAfterQuit", "delayAfterQuit", XrmoptionSepArg, NULL },
1770 { "-nameOfDebugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1771 { "-debugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1772 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1773 { "-noGUI", "noGUI", XrmoptionNoArg, "True" },
1774 { "-firstOptions", "firstOptions", XrmoptionSepArg, NULL },
1775 { "-secondOptions", "secondOptions", XrmoptionSepArg, NULL },
1776 { "-firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1777 { "-secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1778 { "-keepAlive", "keepAlive", XrmoptionSepArg, NULL },
1779 { "-forceIllegalMoves", "forceIllegalMoves", XrmoptionNoArg, "True" },
1783 XtActionsRec boardActions[] = {
1784 { "HandleUserMove", HandleUserMove },
1785 { "AnimateUserMove", AnimateUserMove },
1786 { "FileNameAction", FileNameAction },
1787 { "AskQuestionProc", AskQuestionProc },
1788 { "AskQuestionReplyAction", AskQuestionReplyAction },
1789 { "PieceMenuPopup", PieceMenuPopup },
1790 // { "WhiteClock", WhiteClock },
1791 // { "BlackClock", BlackClock },
1792 { "Iconify", Iconify },
1793 { "LoadSelectedProc", LoadSelectedProc },
1794 { "LoadPositionProc", LoadPositionProc },
1795 // { "LoadNextPositionProc", LoadNextPositionProc },
1796 // { "LoadPrevPositionProc", LoadPrevPositionProc },
1797 // { "ReloadPositionProc", ReloadPositionProc },
1798 { "CopyPositionProc", CopyPositionProc },
1799 { "PastePositionProc", PastePositionProc },
1800 { "CopyGameProc", CopyGameProc },
1801 { "PasteGameProc", PasteGameProc },
1802 { "SaveGameProc", SaveGameProc },
1803 { "SavePositionProc", SavePositionProc },
1804 { "MailMoveProc", MailMoveProc },
1805 { "ReloadCmailMsgProc", ReloadCmailMsgProc },
1806 // { "MachineWhiteProc", MachineWhiteProc },
1807 // { "MachineBlackProc", MachineBlackProc },
1808 { "AnalysisModeProc", AnalyzeModeProc },
1809 { "AnalyzeFileProc", AnalyzeFileProc },
1810 // { "TwoMachinesProc", TwoMachinesProc },
1811 // { "IcsClientProc", IcsClientProc },
1812 { "EditGameProc", EditGameProc },
1813 { "EditPositionProc", EditPositionProc },
1814 { "TrainingProc", EditPositionProc },
1815 { "EngineOutputProc", EngineOutputProc}, // [HGM] Winboard_x engine-output window
1816 { "ShowGameListProc", ShowGameListProc },
1817 // { "ShowMoveListProc", HistoryShowProc},
1818 { "EditTagsProc", EditCommentProc },
1819 { "EditCommentProc", EditCommentProc },
1820 { "IcsAlarmProc", IcsAlarmProc },
1821 { "IcsInputBoxProc", IcsInputBoxProc },
1822 // { "AcceptProc", AcceptProc },
1823 // { "DeclineProc", DeclineProc },
1824 // { "RematchProc", RematchProc },
1825 // { "CallFlagProc", CallFlagProc },
1826 // { "DrawProc", DrawProc },
1827 // { "AdjournProc", AdjournProc },
1828 // { "AbortProc", AbortProc },
1829 // { "ResignProc", ResignProc },
1830 // { "AdjuWhiteProc", AdjuWhiteProc },
1831 // { "AdjuBlackProc", AdjuBlackProc },
1832 // { "AdjuDrawProc", AdjuDrawProc },
1833 { "EnterKeyProc", EnterKeyProc },
1834 // { "StopObservingProc", StopObservingProc },
1835 // { "StopExaminingProc", StopExaminingProc },
1836 // { "BackwardProc", BackwardProc },
1837 // { "ForwardProc", ForwardProc },
1838 // { "ToStartProc", ToStartProc },
1839 // { "ToEndProc", ToEndProc },
1840 // { "RevertProc", RevertProc },
1841 // { "TruncateGameProc", TruncateGameProc },
1842 // { "MoveNowProc", MoveNowProc },
1843 // { "RetractMoveProc", RetractMoveProc },
1844 { "AlwaysQueenProc", AlwaysQueenProc },
1845 { "AnimateDraggingProc", AnimateDraggingProc },
1846 { "AnimateMovingProc", AnimateMovingProc },
1847 { "AutoflagProc", AutoflagProc },
1848 { "AutoflipProc", AutoflipProc },
1849 { "AutobsProc", AutobsProc },
1850 { "AutoraiseProc", AutoraiseProc },
1851 { "AutosaveProc", AutosaveProc },
1852 { "BlindfoldProc", BlindfoldProc },
1853 { "FlashMovesProc", FlashMovesProc },
1854 // { "FlipViewProc", FlipViewProc },
1855 // { "GetMoveListProc", GetMoveListProc },
1857 { "HighlightDraggingProc", HighlightDraggingProc },
1859 { "HighlightLastMoveProc", HighlightLastMoveProc },
1860 { "IcsAlarmProc", IcsAlarmProc },
1861 { "MoveSoundProc", MoveSoundProc },
1862 { "OldSaveStyleProc", OldSaveStyleProc },
1863 { "PeriodicUpdatesProc", PeriodicUpdatesProc },
1864 { "PonderNextMoveProc", PonderNextMoveProc },
1865 { "PopupExitMessageProc", PopupExitMessageProc },
1866 { "PopupMoveErrorsProc", PopupMoveErrorsProc },
1867 { "PremoveProc", PremoveProc },
1868 { "QuietPlayProc", QuietPlayProc },
1869 // { "ShowThinkingProc", ShowThinkingProc },
1870 // { "HideThinkingProc", HideThinkingProc },
1871 { "TestLegalityProc", TestLegalityProc },
1872 // { "InfoProc", InfoProc },
1873 // { "ManProc", ManProc },
1874 // { "HintProc", HintProc },
1875 // { "BookProc", BookProc },
1876 { "AboutGameProc", AboutGameProc },
1877 { "DebugProc", DebugProc },
1878 { "NothingProc", NothingProc },
1879 { "CommentPopDown", (XtActionProc) CommentPopDown },
1880 { "EditCommentPopDown", (XtActionProc) EditCommentPopDown },
1881 { "TagsPopDown", (XtActionProc) TagsPopDown },
1882 { "ErrorPopDown", (XtActionProc) ErrorPopDown },
1883 { "ICSInputBoxPopDown", (XtActionProc) ICSInputBoxPopDown },
1884 { "AnalysisPopDown", (XtActionProc) AnalysisPopDown },
1885 { "FileNamePopDown", (XtActionProc) FileNamePopDown },
1886 { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown },
1887 { "GameListPopDown", (XtActionProc) GameListPopDown },
1888 { "PromotionPopDown", (XtActionProc) PromotionPopDown },
1889 // { "HistoryPopDown", (XtActionProc) HistoryPopDown },
1890 { "EngineOutputPopDown", (XtActionProc) EngineOutputPopDown },
1891 { "ShufflePopDown", (XtActionProc) ShufflePopDown },
1892 { "EnginePopDown", (XtActionProc) EnginePopDown },
1893 { "UciPopDown", (XtActionProc) UciPopDown },
1894 { "TimeControlPopDown", (XtActionProc) TimeControlPopDown },
1895 { "NewVariantPopDown", (XtActionProc) NewVariantPopDown },
1896 { "SettingsPopDown", (XtActionProc) SettingsPopDown },
1900 char ICSInputTranslations[] =
1901 "<Key>Return: EnterKeyProc() \n";
1903 String xboardResources[] = {
1904 "*fileName*value.translations: #override\\n <Key>Return: FileNameAction()",
1905 "*question*value.translations: #override\\n <Key>Return: AskQuestionReplyAction()",
1906 "*errorpopup*translations: #override\\n <Key>Return: ErrorPopDown()",
1910 static char *cnames[9] = { "black", "red", "green", "yellow", "blue",
1911 "magenta", "cyan", "white" };
1915 TextColors textColors[(int)NColorClasses];
1917 /* String is: "fg, bg, attr". Which is 0, 1, 2 */
1919 parse_color(str, which)
1923 char *p, buf[100], *d;
1926 if (strlen(str) > 99) /* watch bounds on buf */
1931 for (i=0; i<which; ++i) {
1938 /* Could be looking at something like:
1940 .. in which case we want to stop on a comma also */
1941 while (*p && *p != ',' && !isalpha(*p) && !isdigit(*p))
1945 return -1; /* Use default for empty field */
1948 if (which == 2 || isdigit(*p))
1951 while (*p && isalpha(*p))
1956 for (i=0; i<8; ++i) {
1957 if (!StrCaseCmp(buf, cnames[i]))
1958 return which? (i+40) : (i+30);
1960 if (!StrCaseCmp(buf, "default")) return -1;
1962 fprintf(stderr, _("%s: unrecognized color %s\n"), programName, buf);
1967 parse_cpair(cc, str)
1971 if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {
1972 fprintf(stderr, _("%s: can't parse foreground color in `%s'\n"),
1977 /* bg and attr are optional */
1978 textColors[(int)cc].bg = parse_color(str, 1);
1979 if ((textColors[(int)cc].attr = parse_color(str, 2)) < 0) {
1980 textColors[(int)cc].attr = 0;
1986 /* Arrange to catch delete-window events */
1987 Atom wm_delete_window;
1989 CatchDeleteWindow(Widget w, String procname)
1992 XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
1993 snprintf(buf, sizeof(buf), "<Message>WM_PROTOCOLS: %s() \n", procname);
1994 XtAugmentTranslations(w, XtParseTranslationTable(buf));
2000 /* this should raise the board to the top */
2001 gtk_window_present(GTK_WINDOW(GUI_Window));
2005 #define BoardSize int
2006 void InitDrawingSizes(BoardSize boardSize, int flags)
2007 { // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
2008 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2010 XtGeometryResult gres;
2013 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2014 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2016 timerWidth = (boardWidth - sep) / 2;
2018 if (appData.titleInWindow)
2023 w = boardWidth - 2*bor;
2027 w = boardWidth - w - sep - 2*bor - 2; // WIDTH_FUDGE
2031 if(!formWidget) return;
2034 * Inhibit shell resizing.
2037 // [HGM] pieces: tailor piece bitmaps to needs of specific variant
2040 for(i=0; i<4; i++) {
2042 for(p=0; p<=(int)WhiteKing; p++)
2043 xpmPieceBitmap[i][p] = xpmPieceBitmap2[i][p]; // defaults
2044 if(gameInfo.variant == VariantShogi) {
2045 xpmPieceBitmap[i][(int)WhiteCannon] = xpmPieceBitmap2[i][(int)WhiteKing+1];
2046 xpmPieceBitmap[i][(int)WhiteNightrider] = xpmPieceBitmap2[i][(int)WhiteKing+2];
2047 xpmPieceBitmap[i][(int)WhiteSilver] = xpmPieceBitmap2[i][(int)WhiteKing+3];
2048 xpmPieceBitmap[i][(int)WhiteGrasshopper] = xpmPieceBitmap2[i][(int)WhiteKing+4];
2049 xpmPieceBitmap[i][(int)WhiteQueen] = xpmPieceBitmap2[i][(int)WhiteLance];
2052 if(gameInfo.variant == VariantGothic) {
2053 xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteSilver];
2057 // [HGM] why are thee ximMasks used at all? the ximPieceBitmaps seem to be never used!
2058 for(p=0; p<=(int)WhiteKing; p++)
2059 ximMaskPm[p] = ximMaskPm2[p]; // defaults
2060 if(gameInfo.variant == VariantShogi) {
2061 ximMaskPm[(int)WhiteCannon] = ximMaskPm2[(int)WhiteKing+1];
2062 ximMaskPm[(int)WhiteNightrider] = ximMaskPm2[(int)WhiteKing+2];
2063 ximMaskPm[(int)WhiteSilver] = ximMaskPm2[(int)WhiteKing+3];
2064 ximMaskPm[(int)WhiteGrasshopper] = ximMaskPm2[(int)WhiteKing+4];
2065 ximMaskPm[(int)WhiteQueen] = ximMaskPm2[(int)WhiteLance];
2068 if(gameInfo.variant == VariantGothic) {
2069 ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[(int)WhiteSilver];
2075 for(i=0; i<2; i++) {
2077 for(p=0; p<=(int)WhiteKing; p++)
2078 pieceBitmap[i][p] = pieceBitmap2[i][p]; // defaults
2079 if(gameInfo.variant == VariantShogi) {
2080 pieceBitmap[i][(int)WhiteCannon] = pieceBitmap2[i][(int)WhiteKing+1];
2081 pieceBitmap[i][(int)WhiteNightrider] = pieceBitmap2[i][(int)WhiteKing+2];
2082 pieceBitmap[i][(int)WhiteSilver] = pieceBitmap2[i][(int)WhiteKing+3];
2083 pieceBitmap[i][(int)WhiteGrasshopper] = pieceBitmap2[i][(int)WhiteKing+4];
2084 pieceBitmap[i][(int)WhiteQueen] = pieceBitmap2[i][(int)WhiteLance];
2087 if(gameInfo.variant == VariantGothic) {
2088 pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteSilver];
2098 void EscapeExpand(char *p, char *q)
2099 { // [HGM] initstring: routine to shape up string arguments
2100 while(*p++ = *q++) if(p[-1] == '\\')
2102 case 'n': p[-1] = '\n'; break;
2103 case 'r': p[-1] = '\r'; break;
2104 case 't': p[-1] = '\t'; break;
2105 case '\\': p[-1] = '\\'; break;
2106 case 0: *p = 0; return;
2107 default: p[-1] = q[-1]; break;
2116 int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
2117 XSetWindowAttributes window_attributes;
2119 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2120 XrmValue vFrom, vTo;
2121 XtGeometryResult gres;
2124 int forceMono = False;
2128 // [HGM] before anything else, expand any indirection files amongst options
2129 char *argvCopy[1000]; // 1000 seems enough
2130 char newArgs[10000]; // holds actual characters
2133 srandom(time(0)); // [HGM] book: make random truly random
2136 for(i=0; i<argc; i++) {
2137 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2138 //fprintf(stderr, "arg %s\n", argv[i]);
2139 if(argv[i][0] != '@') argvCopy[j++] = argv[i]; else {
2141 FILE *f = fopen(argv[i]+1, "rb");
2142 if(f == NULL) { fprintf(stderr, _("ignore %s\n"), argv[i]); continue; } // do not expand non-existing
2143 argvCopy[j++] = newArgs + k; // get ready for first argument from file
2144 while((c = fgetc(f)) != EOF) { // each line of file inserts 1 argument in the list
2146 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2147 newArgs[k++] = 0; // terminate current arg
2148 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2149 argvCopy[j++] = newArgs + k; // get ready for next
2151 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2165 setbuf(stdout, NULL);
2166 setbuf(stderr, NULL);
2169 programName = strrchr(argv[0], '/');
2170 if (programName == NULL)
2171 programName = argv[0];
2176 XtSetLanguageProc(NULL, NULL, NULL);
2177 bindtextdomain(PACKAGE, LOCALEDIR);
2178 textdomain(PACKAGE);
2182 XtAppInitialize(&appContext, "XBoard", shellOptions,
2183 XtNumber(shellOptions),
2184 &argc, argv, xboardResources, NULL, 0);
2187 gtk_init (&argc, &argv);
2189 /* parse glade file to build widgets */
2191 builder = gtk_builder_new ();
2192 gtk_builder_add_from_file (builder, "gtk-interface.xml", NULL);
2194 /* test if everything worked ok */
2196 GUI_Window = GTK_WIDGET (gtk_builder_get_object (builder, "MainWindow"));
2197 if(!GUI_Window) printf("Error: gtk_builder didn't work!\n");
2199 GUI_History = GTK_WIDGET (gtk_builder_get_object (builder, "MoveHistory"));
2200 if(!GUI_History) printf("Error: gtk_builder didn't work!\n");
2202 GUI_Menubar = GTK_WIDGET (gtk_builder_get_object (builder, "MenuBar"));
2203 if(!GUI_Menubar) printf("Error: gtk_builder didn't work!\n");
2204 GUI_Timer = GTK_WIDGET (gtk_builder_get_object (builder, "Timer"));
2205 if(!GUI_Timer) printf("Error: gtk_builder didn't work!\n");
2206 GUI_Buttonbar = GTK_WIDGET (gtk_builder_get_object (builder, "ButtonBar"));
2207 if(!GUI_Buttonbar) printf("Error: gtk_builder didn't work!\n");
2208 GUI_Board = GTK_WIDGET (gtk_builder_get_object (builder, "Board"));
2209 if(!GUI_Board) printf("Error: gtk_builder didn't work!\n");
2211 GUI_Whiteclock = GTK_WIDGET (gtk_builder_get_object (builder, "WhiteClock"));
2212 if(!GUI_Whiteclock) printf("Error: gtk_builder didn't work!\n");
2214 GUI_Blackclock = GTK_WIDGET (gtk_builder_get_object (builder, "BlackClock"));
2215 if(!GUI_Blackclock) printf("Error: gtk_builder didn't work!\n");
2217 LIST_MoveHistory = GTK_LIST_STORE (gtk_builder_get_object (builder, "MoveHistoryStore"));
2218 if(!LIST_MoveHistory) printf("Error: gtk_builder didn't work!\n");
2221 gtk_builder_connect_signals (builder, NULL);
2223 // don't unref the builder, since we use it to get references to widgets
2224 // g_object_unref (G_OBJECT (builder));
2226 /* end parse glade file */
2230 fprintf(stderr, _("%s: unrecognized argument %s\n"),
2231 programName, argv[1]);
2233 fprintf(stderr, "Recognized options:\n");
2234 for(i = 0; i < XtNumber(shellOptions); i++)
2236 /* print first column */
2237 j = fprintf(stderr, " %s%s", shellOptions[i].option,
2238 (shellOptions[i].argKind == XrmoptionSepArg
2240 /* print second column and end line */
2241 if (++i < XtNumber(shellOptions))
2243 fprintf(stderr, "%*c%s%s\n", 40 - j, ' ',
2244 shellOptions[i].option,
2245 (shellOptions[i].argKind == XrmoptionSepArg
2250 fprintf(stderr, "\n");
2257 if (p == NULL) p = "/tmp";
2258 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
2259 gameCopyFilename = (char*) malloc(i);
2260 gamePasteFilename = (char*) malloc(i);
2261 snprintf(gameCopyFilename,i, "%s/.xboard%05uc.pgn", p, getpid());
2262 snprintf(gamePasteFilename,i, "%s/.xboard%05up.pgn", p, getpid());
2264 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
2265 clientResources, XtNumber(clientResources),
2268 { // [HGM] initstring: kludge to fix bad bug. expand '\n' characters in init string and computer string.
2269 static char buf[MSG_SIZ];
2270 EscapeExpand(buf, appData.initString);
2271 appData.initString = strdup(buf);
2272 EscapeExpand(buf, appData.secondInitString);
2273 appData.secondInitString = strdup(buf);
2274 EscapeExpand(buf, appData.firstComputerString);
2275 appData.firstComputerString = strdup(buf);
2276 EscapeExpand(buf, appData.secondComputerString);
2277 appData.secondComputerString = strdup(buf);
2280 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
2283 if (chdir(chessDir) != 0) {
2284 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
2290 if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) {
2291 /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */
2292 if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL) {
2293 printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile);
2296 setbuf(debugFP, NULL);
2299 /* [HGM,HR] make sure board size is acceptable */
2300 if(appData.NrFiles > BOARD_SIZE ||
2301 appData.NrRanks > BOARD_SIZE )
2302 DisplayFatalError(_("Recompile with BOARD_SIZE > 12, to support this size"), 0, 2);
2305 /* This feature does not work; animation needs a rewrite */
2306 appData.highlightDragging = FALSE;
2310 xDisplay = XtDisplay(shellWidget);
2311 xScreen = DefaultScreen(xDisplay);
2312 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
2314 gameInfo.variant = StringToVariant(appData.variant);
2315 InitPosition(FALSE);
2317 /* calc board size */
2318 if (isdigit(appData.boardSize[0]))
2320 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
2321 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
2322 &fontPxlSize, &smallLayout, &tinyLayout);
2325 fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
2326 programName, appData.boardSize);
2331 /* Find some defaults; use the nearest known size */
2332 SizeDefaults *szd, *nearest;
2333 int distance = 99999;
2334 nearest = szd = sizeDefaults;
2335 while (szd->name != NULL)
2337 if (abs(szd->squareSize - squareSize) < distance)
2340 distance = abs(szd->squareSize - squareSize);
2341 if (distance == 0) break;
2345 if (i < 2) lineGap = nearest->lineGap;
2346 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
2347 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
2348 if (i < 5) fontPxlSize = nearest->fontPxlSize;
2349 if (i < 6) smallLayout = nearest->smallLayout;
2350 if (i < 7) tinyLayout = nearest->tinyLayout;
2355 SizeDefaults *szd = sizeDefaults;
2356 if (*appData.boardSize == NULLCHAR)
2358 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize
2359 || DisplayHeight(xDisplay, xScreen) < szd->minScreenSize)
2363 if (szd->name == NULL) szd--;
2367 while (szd->name != NULL
2368 && StrCaseCmp(szd->name, appData.boardSize) != 0)
2370 if (szd->name == NULL)
2372 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
2373 programName, appData.boardSize);
2377 squareSize = szd->squareSize;
2378 lineGap = szd->lineGap;
2379 clockFontPxlSize = szd->clockFontPxlSize;
2380 coordFontPxlSize = szd->coordFontPxlSize;
2381 fontPxlSize = szd->fontPxlSize;
2382 smallLayout = szd->smallLayout;
2383 tinyLayout = szd->tinyLayout;
2385 /* end figuring out what size to use */
2387 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2388 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2391 * Determine what fonts to use.
2393 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
2394 clockFontID = XLoadFont(xDisplay, appData.clockFont);
2395 clockFontStruct = XQueryFont(xDisplay, clockFontID);
2396 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
2397 coordFontID = XLoadFont(xDisplay, appData.coordFont);
2398 coordFontStruct = XQueryFont(xDisplay, coordFontID);
2399 appData.font = FindFont(appData.font, fontPxlSize);
2400 countFontID = XLoadFont(xDisplay, appData.coordFont); // [HGM] holdings
2401 countFontStruct = XQueryFont(xDisplay, countFontID);
2402 // appData.font = FindFont(appData.font, fontPxlSize);
2404 xdb = XtDatabase(xDisplay);
2405 XrmPutStringResource(&xdb, "*font", appData.font);
2408 * Detect if there are not enough colors available and adapt.
2410 if (DefaultDepth(xDisplay, xScreen) <= 2) {
2411 appData.monoMode = True;
2414 if (!appData.monoMode) {
2415 vFrom.addr = (caddr_t) appData.lightSquareColor;
2416 vFrom.size = strlen(appData.lightSquareColor);
2417 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2418 if (vTo.addr == NULL) {
2419 appData.monoMode = True;
2422 lightSquareColor = *(Pixel *) vTo.addr;
2425 if (!appData.monoMode) {
2426 vFrom.addr = (caddr_t) appData.darkSquareColor;
2427 vFrom.size = strlen(appData.darkSquareColor);
2428 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2429 if (vTo.addr == NULL) {
2430 appData.monoMode = True;
2433 darkSquareColor = *(Pixel *) vTo.addr;
2436 if (!appData.monoMode) {
2437 vFrom.addr = (caddr_t) appData.whitePieceColor;
2438 vFrom.size = strlen(appData.whitePieceColor);
2439 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2440 if (vTo.addr == NULL) {
2441 appData.monoMode = True;
2444 whitePieceColor = *(Pixel *) vTo.addr;
2447 if (!appData.monoMode) {
2448 vFrom.addr = (caddr_t) appData.blackPieceColor;
2449 vFrom.size = strlen(appData.blackPieceColor);
2450 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2451 if (vTo.addr == NULL) {
2452 appData.monoMode = True;
2455 blackPieceColor = *(Pixel *) vTo.addr;
2459 if (!appData.monoMode) {
2460 vFrom.addr = (caddr_t) appData.highlightSquareColor;
2461 vFrom.size = strlen(appData.highlightSquareColor);
2462 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2463 if (vTo.addr == NULL) {
2464 appData.monoMode = True;
2467 highlightSquareColor = *(Pixel *) vTo.addr;
2471 if (!appData.monoMode) {
2472 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
2473 vFrom.size = strlen(appData.premoveHighlightColor);
2474 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2475 if (vTo.addr == NULL) {
2476 appData.monoMode = True;
2479 premoveHighlightColor = *(Pixel *) vTo.addr;
2484 fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2487 if (appData.bitmapDirectory == NULL ||
2488 appData.bitmapDirectory[0] == NULLCHAR)
2489 appData.bitmapDirectory = DEF_BITMAP_DIR;
2492 if (appData.lowTimeWarning && !appData.monoMode) {
2493 vFrom.addr = (caddr_t) appData.lowTimeWarningColor;
2494 vFrom.size = strlen(appData.lowTimeWarningColor);
2495 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2496 if (vTo.addr == NULL)
2497 appData.monoMode = True;
2499 lowTimeWarningColor = *(Pixel *) vTo.addr;
2502 if (appData.monoMode && appData.debugMode) {
2503 fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2504 (unsigned long) XWhitePixel(xDisplay, xScreen),
2505 (unsigned long) XBlackPixel(xDisplay, xScreen));
2508 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
2509 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
2510 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
2511 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
2512 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
2513 parse_cpair(ColorTell, appData.colorTell) < 0 ||
2514 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
2515 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
2516 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
2517 parse_cpair(ColorNormal, appData.colorNormal) < 0)
2519 if (appData.colorize) {
2521 _("%s: can't parse color names; disabling colorization\n"),
2524 appData.colorize = FALSE;
2526 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2527 textColors[ColorNone].attr = 0;
2529 // XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2535 layoutName = "tinyLayout";
2536 } else if (smallLayout) {
2537 layoutName = "smallLayout";
2539 layoutName = "normalLayout";
2542 if (appData.titleInWindow) {
2543 /* todo check what this appdata does */
2546 if (appData.showButtonBar) {
2547 /* TODO hide button bar if requested */
2551 if (appData.titleInWindow)
2556 if (appData.showButtonBar)
2563 if (appData.showButtonBar)
2573 /* set some checkboxes in the menu according to appData */
2575 if (appData.alwaysPromoteToQueen)
2576 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Always Queen")),TRUE);
2578 if (appData.animateDragging)
2579 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Animate Dragging")),TRUE);
2581 if (appData.animate)
2582 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Animate Moving")),TRUE);
2584 if (appData.autoComment)
2585 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Comment")),TRUE);
2587 if (appData.autoCallFlag)
2588 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Flag")),TRUE);
2590 if (appData.autoFlipView)
2591 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Flip View")),TRUE);
2593 if (appData.autoObserve)
2594 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Observe")),TRUE);
2596 if (appData.autoRaiseBoard)
2597 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Raise Board")),TRUE);
2599 if (appData.autoSaveGames)
2600 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Save")),TRUE);
2602 if (appData.saveGameFile[0] != NULLCHAR)
2604 /* Can't turn this off from menu */
2605 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Save")),TRUE);
2606 gtk_action_set_sensitive(GTK_ACTION (gtk_builder_get_object (builder, "menuOptions.Auto Save")),FALSE);
2609 if (appData.blindfold)
2610 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Blindfold")),TRUE);
2612 if (appData.flashCount > 0)
2613 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Flash Moves")),TRUE);
2615 if (appData.getMoveList)
2616 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Get Move List")),TRUE);
2619 if (appData.highlightDragging)
2620 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Highlight Dragging")),TRUE);
2623 if (appData.highlightLastMove)
2624 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Highlight Last Move")),TRUE);
2626 if (appData.icsAlarm)
2627 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.ICS Alarm")),TRUE);
2629 if (appData.ringBellAfterMoves)
2630 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Move Sound")),TRUE);
2632 if (appData.oldSaveStyle)
2633 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Old Save Style")),TRUE);
2635 if (appData.periodicUpdates)
2636 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Periodic Updates")),TRUE);
2638 if (appData.ponderNextMove)
2639 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Ponder Next Move")),TRUE);
2641 if (appData.popupExitMessage)
2642 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Popup Exit Message")),TRUE);
2644 if (appData.popupMoveErrors)
2645 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Popup Move Errors")),TRUE);
2647 if (appData.premove)
2648 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Premove")),TRUE);
2650 if (appData.quietPlay)
2651 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Quit Play")),TRUE);
2653 if (appData.showCoords)
2654 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Show Coords")),TRUE);
2656 if (appData.showThinking)
2657 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Show Thinking")),TRUE);
2659 if (appData.testLegality)
2660 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Test Legality")),TRUE);
2662 /* end setting check boxes */
2664 /* load square colors */
2665 SVGLightSquare = load_pixbuf("svg/LightSquare.svg",squareSize);
2666 SVGDarkSquare = load_pixbuf("svg/DarkSquare.svg",squareSize);
2667 SVGNeutralSquare = load_pixbuf("svg/NeutralSquare.svg",squareSize);
2669 /* use two icons to indicate if it is white's or black's turn */
2670 WhiteIcon = load_pixbuf("svg/icon_white.svg",0);
2671 BlackIcon = load_pixbuf("svg/icon_black.svg",0);
2672 WindowIcon = WhiteIcon;
2673 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
2676 /* realize window */
2677 gtk_widget_show (GUI_Window);
2679 /* recalc boardsize */
2684 if (appData.animate || appData.animateDragging)
2689 if (errorExitStatus == -1) {
2690 if (appData.icsActive) {
2691 /* We now wait until we see "login:" from the ICS before
2692 sending the logon script (problems with timestamp otherwise) */
2693 /*ICSInitScript();*/
2694 if (appData.icsInputBox) ICSInputBoxPopUp();
2697 signal(SIGINT, IntSigHandler);
2698 signal(SIGTERM, IntSigHandler);
2699 if (*appData.cmailGameName != NULLCHAR) {
2700 signal(SIGUSR1, CmailSigHandler);
2703 gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes()
2707 * Create a cursor for the board widget.
2708 * (This needs to be called after the window has been created to have access to board-window)
2711 BoardCursor = gdk_cursor_new(GDK_HAND2);
2712 gdk_window_set_cursor(GUI_Board->window, BoardCursor);
2713 gdk_cursor_destroy(BoardCursor);
2718 if (appData.debugMode) fclose(debugFP); // [DM] debug
2725 if (appData.icsActive && oldICSInteractionTitle != NULL) {
2726 DisplayIcsInteractionTitle(oldICSInteractionTitle);
2728 unlink(gameCopyFilename);
2729 unlink(gamePasteFilename);
2740 CmailSigHandler(sig)
2746 signal(SIGUSR1, SIG_IGN); /* suspend handler */
2748 /* Activate call-back function CmailSigHandlerCallBack() */
2749 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
2751 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
2755 CmailSigHandlerCallBack(isr, closure, message, count, error)
2763 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
2765 /**** end signal code ****/
2775 f = fopen(appData.icsLogon, "r");
2781 strcat(buf, appData.icsLogon);
2782 f = fopen(buf, "r");
2786 ProcessICSInitScript(f);
2793 EditCommentPopDown();
2799 SetMenuEnables(enab)
2804 if (!builder) return;
2805 while (enab->name != NULL) {
2806 o = gtk_builder_get_object(builder, enab->name);
2807 if(GTK_IS_WIDGET(o))
2808 gtk_widget_set_sensitive(GTK_WIDGET (o),enab->value);
2811 if(GTK_IS_ACTION(o))
2812 gtk_action_set_sensitive(GTK_ACTION (o),enab->value);
2814 DisplayError(enab->name, 0);
2822 SetMenuEnables(icsEnables);
2825 if (appData.zippyPlay && !appData.noChessProgram) /* [DM] icsEngineAnalyze */
2826 {}; // XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
2833 SetMenuEnables(ncpEnables);
2839 SetMenuEnables(gnuEnables);
2845 SetMenuEnables(cmailEnables);
2851 SetMenuEnables(trainingOnEnables);
2852 if (appData.showButtonBar) {
2853 // XtSetSensitive(buttonBarWidget, False);
2859 SetTrainingModeOff()
2861 SetMenuEnables(trainingOffEnables);
2862 if (appData.showButtonBar) {
2863 // XtSetSensitive(buttonBarWidget, True);
2868 SetUserThinkingEnables()
2870 if (appData.noChessProgram) return;
2871 SetMenuEnables(userThinkingEnables);
2875 SetMachineThinkingEnables()
2877 if (appData.noChessProgram) return;
2878 SetMenuEnables(machineThinkingEnables);
2880 case MachinePlaysBlack:
2881 case MachinePlaysWhite:
2882 case TwoMachinesPlay:
2883 // XtSetSensitive(XtNameToWidget(menuBarWidget,
2884 // ModeToWidgetName(gameMode)), True);
2891 #define Abs(n) ((n)<0 ? -(n) : (n))
2894 * Find a font that matches "pattern" that is as close as
2895 * possible to the targetPxlSize. Prefer fonts that are k
2896 * pixels smaller to fonts that are k pixels larger. The
2897 * pattern must be in the X Consortium standard format,
2898 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
2899 * The return value should be freed with XtFree when no
2902 char *FindFont(pattern, targetPxlSize)
2906 char **fonts, *p, *best, *scalable, *scalableTail;
2907 int i, j, nfonts, minerr, err, pxlSize;
2910 char **missing_list;
2912 char *def_string, *base_fnt_lst, strInt[3];
2914 XFontStruct **fnt_list;
2916 base_fnt_lst = calloc(1, strlen(pattern) + 3);
2917 sprintf(strInt, "%d", targetPxlSize);
2918 p = strstr(pattern, "--");
2919 strncpy(base_fnt_lst, pattern, p - pattern + 2);
2920 strcat(base_fnt_lst, strInt);
2921 strcat(base_fnt_lst, strchr(p + 2, '-'));
2923 if ((fntSet = XCreateFontSet(xDisplay,
2927 &def_string)) == NULL) {
2929 fprintf(stderr, _("Unable to create font set.\n"));
2933 nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
2935 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
2937 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
2938 programName, pattern);
2946 for (i=0; i<nfonts; i++) {
2949 if (*p != '-') continue;
2951 if (*p == NULLCHAR) break;
2952 if (*p++ == '-') j++;
2954 if (j < 7) continue;
2957 scalable = fonts[i];
2960 err = pxlSize - targetPxlSize;
2961 if (Abs(err) < Abs(minerr) ||
2962 (minerr > 0 && err < 0 && -err == minerr)) {
2968 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
2969 /* If the error is too big and there is a scalable font,
2970 use the scalable font. */
2971 int headlen = scalableTail - scalable;
2972 p = (char *) XtMalloc(strlen(scalable) + 10);
2973 while (isdigit(*scalableTail)) scalableTail++;
2974 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
2976 p = (char *) XtMalloc(strlen(best) + 1);
2979 if (appData.debugMode) {
2980 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
2981 pattern, targetPxlSize, p);
2984 if (missing_count > 0)
2985 XFreeStringList(missing_list);
2986 XFreeFontSet(xDisplay, fntSet);
2988 XFreeFontNames(fonts);
2995 /* GCs are not needed anymore for GTK just left them in here for the moment, since there is a lot of X-code still around that's wants them*/
2997 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
2998 | GCBackground | GCFunction | GCPlaneMask;
2999 XGCValues gc_values;
3002 gc_values.plane_mask = AllPlanes;
3003 gc_values.line_width = lineGap;
3004 gc_values.line_style = LineSolid;
3005 gc_values.function = GXcopy;
3007 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3008 gc_values.background = XWhitePixel(xDisplay, xScreen);
3009 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
3010 XSetFont(xDisplay, coordGC, coordFontID);
3012 if (appData.monoMode) {
3013 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3014 gc_values.background = XBlackPixel(xDisplay, xScreen);
3015 lightSquareGC = wbPieceGC
3016 = XtGetGC(shellWidget, value_mask, &gc_values);
3018 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3019 gc_values.background = XWhitePixel(xDisplay, xScreen);
3020 darkSquareGC = bwPieceGC
3021 = XtGetGC(shellWidget, value_mask, &gc_values);
3023 if (DefaultDepth(xDisplay, xScreen) == 1) {
3024 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3025 gc_values.function = GXcopyInverted;
3026 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3027 gc_values.function = GXcopy;
3028 if (XBlackPixel(xDisplay, xScreen) == 1) {
3029 bwPieceGC = darkSquareGC;
3030 wbPieceGC = copyInvertedGC;
3032 bwPieceGC = copyInvertedGC;
3033 wbPieceGC = lightSquareGC;
3037 gc_values.foreground = lightSquareColor;
3038 gc_values.background = darkSquareColor;
3039 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3041 gc_values.foreground = darkSquareColor;
3042 gc_values.background = lightSquareColor;
3043 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3045 gc_values.foreground = jailSquareColor;
3046 gc_values.background = jailSquareColor;
3047 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3049 gc_values.foreground = whitePieceColor;
3050 gc_values.background = darkSquareColor;
3051 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3053 gc_values.foreground = whitePieceColor;
3054 gc_values.background = lightSquareColor;
3055 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3057 gc_values.foreground = whitePieceColor;
3058 gc_values.background = jailSquareColor;
3059 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3061 gc_values.foreground = blackPieceColor;
3062 gc_values.background = darkSquareColor;
3063 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3065 gc_values.foreground = blackPieceColor;
3066 gc_values.background = lightSquareColor;
3067 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3069 gc_values.foreground = blackPieceColor;
3070 gc_values.background = jailSquareColor;
3071 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3080 for(i=0;i<MAXPIECES;i++)
3084 g_free(SVGpieces[i]);
3091 SVGLightSquare = load_pixbuf("svg/LightSquare.svg",squareSize);
3092 SVGDarkSquare = load_pixbuf("svg/DarkSquare.svg",squareSize);
3093 SVGNeutralSquare = load_pixbuf("svg/NeutralSquare.svg",squareSize);
3096 /* get some defaults going */
3097 for(i=WhitePawn; i<DemotePiece+1; i++)
3098 SVGpieces[i] = load_pixbuf("svg/NeutralSquare.svg",squareSize);
3100 SVGpieces[WhitePawn] = load_pixbuf("svg/WhitePawn.svg",squareSize);
3101 SVGpieces[WhiteKnight] = load_pixbuf("svg/WhiteKnight.svg",squareSize);
3102 SVGpieces[WhiteBishop] = load_pixbuf("svg/WhiteBishop.svg",squareSize);
3103 SVGpieces[WhiteRook] = load_pixbuf("svg/WhiteRook.svg",squareSize);
3104 SVGpieces[WhiteQueen] = load_pixbuf("svg/WhiteQueen.svg",squareSize);
3105 SVGpieces[WhiteKing] = load_pixbuf("svg/WhiteKing.svg",squareSize);
3107 SVGpieces[BlackPawn] = load_pixbuf("svg/BlackPawn.svg",squareSize);
3108 SVGpieces[BlackKnight] = load_pixbuf("svg/BlackKnight.svg",squareSize);
3109 SVGpieces[BlackBishop] = load_pixbuf("svg/BlackBishop.svg",squareSize);
3110 SVGpieces[BlackRook] = load_pixbuf("svg/BlackRook.svg",squareSize);
3111 SVGpieces[BlackQueen] = load_pixbuf("svg/BlackQueen.svg",squareSize);
3112 SVGpieces[BlackKing] = load_pixbuf("svg/BlackKing.svg",squareSize);
3118 static void MenuBarSelect(w, addr, index)
3123 XtActionProc proc = (XtActionProc) addr;
3125 (proc)(NULL, NULL, NULL, NULL);
3128 void CreateMenuBarPopup(parent, name, mb)
3138 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3141 XtSetArg(args[j], XtNleftMargin, 20); j++;
3142 XtSetArg(args[j], XtNrightMargin, 20); j++;
3144 while (mi->string != NULL) {
3145 if (strcmp(mi->string, "----") == 0) {
3146 entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
3149 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string)));
3150 entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass,
3152 XtAddCallback(entry, XtNcallback,
3153 (XtCallbackProc) MenuBarSelect,
3154 (caddr_t) mi->proc);
3160 Widget CreateMenuBar(mb)
3164 Widget anchor, menuBar;
3166 char menuName[MSG_SIZ];
3169 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3170 XtSetArg(args[j], XtNvSpace, 0); j++;
3171 XtSetArg(args[j], XtNborderWidth, 0); j++;
3172 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
3173 formWidget, args, j);
3175 while (mb->name != NULL) {
3176 strcpy(menuName, "menu");
3177 strcat(menuName, mb->name);
3179 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
3182 shortName[0] = _(mb->name)[0];
3183 shortName[1] = NULLCHAR;
3184 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
3187 XtSetArg(args[j], XtNlabel, XtNewString(_(mb->name))); j++;
3190 XtSetArg(args[j], XtNborderWidth, 0); j++;
3191 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
3193 CreateMenuBarPopup(menuBar, menuName, mb);
3201 CreatePieceMenu(name, color)
3208 ChessSquare selection;
3210 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3211 boardWidget, args, 0);
3213 for (i = 0; i < PIECE_MENU_SIZE; i++) {
3214 String item = pieceMenuStrings[color][i];
3216 if (strcmp(item, "----") == 0) {
3217 entry = XtCreateManagedWidget(item, smeLineObjectClass,
3220 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3221 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3223 selection = pieceMenuTranslation[color][i];
3224 XtAddCallback(entry, XtNcallback,
3225 (XtCallbackProc) PieceMenuSelect,
3226 (caddr_t) selection);
3227 if (selection == WhitePawn || selection == BlackPawn) {
3228 XtSetArg(args[0], XtNpopupOnEntry, entry);
3229 XtSetValues(menu, args, 1);
3242 ChessSquare selection;
3244 // whitePieceMenu = CreatePieceMenu("menuW", 0);
3245 // blackPieceMenu = CreatePieceMenu("menuB", 1);
3247 // XtRegisterGrabAction(PieceMenuPopup, True,
3248 // (unsigned)(ButtonPressMask|ButtonReleaseMask),
3249 // GrabModeAsync, GrabModeAsync);
3251 // XtSetArg(args[0], XtNlabel, _("Drop"));
3252 // dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
3253 // boardWidget, args, 1);
3254 // for (i = 0; i < DROP_MENU_SIZE; i++) {
3255 // String item = dropMenuStrings[i];
3257 // if (strcmp(item, "----") == 0) {
3258 // entry = XtCreateManagedWidget(item, smeLineObjectClass,
3259 // dropMenu, NULL, 0);
3261 // XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3262 // entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3263 // dropMenu, args, 1);
3264 // selection = dropMenuTranslation[i];
3265 // XtAddCallback(entry, XtNcallback,
3266 // (XtCallbackProc) DropMenuSelect,
3267 // (caddr_t) selection);
3272 void SetupDropMenu()
3280 for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
3281 entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
3282 p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
3283 dmEnables[i].piece);
3284 XtSetSensitive(entry, p != NULL || !appData.testLegality
3285 /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
3286 && !appData.icsActive));
3288 while (p && *p++ == dmEnables[i].piece) count++;
3289 snprintf(label, sizeof(label), "%s %d", dmEnables[i].widget, count);
3291 XtSetArg(args[j], XtNlabel, label); j++;
3292 XtSetValues(entry, args, j);
3296 void PieceMenuPopup(w, event, params, num_params)
3300 Cardinal *num_params;
3303 if (event->type != ButtonPress) return;
3304 if (errorUp) ErrorPopDown();
3308 whichMenu = params[0];
3310 case IcsPlayingWhite:
3311 case IcsPlayingBlack:
3313 case MachinePlaysWhite:
3314 case MachinePlaysBlack:
3315 if (appData.testLegality &&
3316 gameInfo.variant != VariantBughouse &&
3317 gameInfo.variant != VariantCrazyhouse) return;
3319 whichMenu = "menuD";
3325 if (((pmFromX = EventToSquare(event->xbutton.x, BOARD_WIDTH)) < 0) ||
3326 ((pmFromY = EventToSquare(event->xbutton.y, BOARD_HEIGHT)) < 0)) {
3327 pmFromX = pmFromY = -1;
3331 pmFromX = BOARD_WIDTH - 1 - pmFromX;
3333 pmFromY = BOARD_HEIGHT - 1 - pmFromY;
3335 XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
3338 static void PieceMenuSelect(w, piece, junk)
3343 if (pmFromX < 0 || pmFromY < 0) return;
3344 EditPositionMenuEvent(piece, pmFromX, pmFromY);
3347 static void DropMenuSelect(w, piece, junk)
3352 if (pmFromX < 0 || pmFromY < 0) return;
3353 DropMenuEvent(piece, pmFromX, pmFromY);
3357 * If the user selects on a border boundary, return -1; if off the board,
3358 * return -2. Otherwise map the event coordinate to the square.
3360 int EventToSquare(x, limit)
3368 if ((x % (squareSize + lineGap)) >= squareSize)
3370 x /= (squareSize + lineGap);
3376 static void do_flash_delay(msec)
3382 static void drawHighlight(file, rank, line_type)
3383 int file, rank, line_type;
3388 if (lineGap == 0 || appData.blindfold) return;
3392 x = lineGap/2 + ((BOARD_WIDTH-1)-file) *
3393 (squareSize + lineGap);
3394 y = lineGap/2 + rank * (squareSize + lineGap);
3398 x = lineGap/2 + file * (squareSize + lineGap);
3399 y = lineGap/2 + ((BOARD_HEIGHT-1)-rank) *
3400 (squareSize + lineGap);
3404 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3406 /* draw the highlight */
3407 cairo_move_to (cr, x, y);
3408 cairo_rel_line_to (cr, 0,squareSize+lineGap);
3409 cairo_rel_line_to (cr, squareSize+lineGap,0);
3410 cairo_rel_line_to (cr, 0,-squareSize-lineGap);
3411 cairo_close_path (cr);
3413 cairo_set_line_width (cr, lineGap);
3416 /* TODO: use appdata colors */
3417 case LINE_TYPE_HIGHLIGHT:
3418 cairo_set_source_rgba (cr, 1, 1, 0, 1.0);
3421 cairo_set_source_rgba (cr, 1, 0, 0, 1.0);
3423 case LINE_TYPE_NORMAL:
3425 cairo_set_source_rgba (cr, 0, 1, 0, 1.0);
3436 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
3437 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
3440 SetHighlights(fromX, fromY, toX, toY)
3441 int fromX, fromY, toX, toY;
3443 if (hi1X != fromX || hi1Y != fromY)
3445 if (hi1X >= 0 && hi1Y >= 0)
3447 drawHighlight(hi1X, hi1Y, LINE_TYPE_NORMAL);
3449 if (fromX >= 0 && fromY >= 0)
3451 drawHighlight(fromX, fromY, LINE_TYPE_HIGHLIGHT);
3454 if (hi2X != toX || hi2Y != toY)
3456 if (hi2X >= 0 && hi2Y >= 0)
3458 drawHighlight(hi2X, hi2Y, LINE_TYPE_NORMAL);
3460 if (toX >= 0 && toY >= 0)
3462 drawHighlight(toX, toY, LINE_TYPE_HIGHLIGHT);
3476 SetHighlights(-1, -1, -1, -1);
3481 SetPremoveHighlights(fromX, fromY, toX, toY)
3482 int fromX, fromY, toX, toY;
3484 if (pm1X != fromX || pm1Y != fromY)
3486 if (pm1X >= 0 && pm1Y >= 0)
3488 drawHighlight(pm1X, pm1Y, LINE_TYPE_NORMAL);
3490 if (fromX >= 0 && fromY >= 0)
3492 drawHighlight(fromX, fromY, LINE_TYPE_PRE);
3495 if (pm2X != toX || pm2Y != toY)
3497 if (pm2X >= 0 && pm2Y >= 0)
3499 drawHighlight(pm2X, pm2Y, LINE_TYPE_NORMAL);
3501 if (toX >= 0 && toY >= 0)
3503 drawHighlight(toX, toY, LINE_TYPE_PRE);
3516 ClearPremoveHighlights()
3518 SetPremoveHighlights(-1, -1, -1, -1);
3521 static void BlankSquare(x, y, color, piece, dest)
3534 pb = SVGLightSquare;
3536 case 2: /* neutral */
3538 pb = SVGNeutralSquare;
3541 gdk_draw_pixbuf(GDK_WINDOW(GUI_Board->window),NULL,pb,0,0,x,y,-1,-1, GDK_RGB_DITHER_NORMAL, 0, 0);
3545 static void DrawPiece(piece, square_color, x, y, dest)
3547 int square_color, x, y;
3550 /* redraw background, since piece might be transparent in some areas */
3551 BlankSquare(x,y,square_color,piece,dest);
3554 gdk_draw_pixbuf(GDK_WINDOW(GUI_Board->window),NULL,
3555 GDK_PIXBUF(SVGpieces[piece]),0,0,x,y,-1,-1,
3556 GDK_RGB_DITHER_NORMAL, 0, 0);
3560 /* [HR] determine square color depending on chess variant. */
3561 static int SquareColor(row, column)
3566 if (gameInfo.variant == VariantXiangqi) {
3567 if (column >= 3 && column <= 5 && row >= 0 && row <= 2) {
3569 } else if (column >= 3 && column <= 5 && row >= 7 && row <= 9) {
3571 } else if (row <= 4) {
3577 square_color = ((column + row) % 2) == 1;
3580 /* [hgm] holdings: next line makes all holdings squares light */
3581 if(column < BOARD_LEFT || column >= BOARD_RGHT) square_color = 1;
3583 return square_color;
3586 void DrawSquare(row, column, piece, do_flash)
3587 int row, column, do_flash;
3590 int square_color, x, y;
3595 /* Calculate delay in milliseconds (2-delays per complete flash) */
3596 flash_delay = 500 / appData.flashRate;
3598 /* calculate x and y coordinates from row and column */
3601 x = lineGap + ((BOARD_WIDTH-1)-column) *
3602 (squareSize + lineGap);
3603 y = lineGap + row * (squareSize + lineGap);
3607 x = lineGap + column * (squareSize + lineGap);
3608 y = lineGap + ((BOARD_HEIGHT-1)-row) *
3609 (squareSize + lineGap);
3612 square_color = SquareColor(row, column);
3614 // [HGM] holdings: blank out area between board and holdings
3615 if ( column == BOARD_LEFT-1 || column == BOARD_RGHT
3616 || (column == BOARD_LEFT-2 && row < BOARD_HEIGHT-gameInfo.holdingsSize)
3617 || (column == BOARD_RGHT+1 && row >= gameInfo.holdingsSize) )
3619 BlankSquare(x, y, 2, EmptySquare, xBoardWindow);
3621 // [HGM] print piece counts next to holdings
3622 string[1] = NULLCHAR;
3625 cairo_text_extents_t extents;
3630 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3632 string[0] = '0' + piece;
3634 /* TODO this has to go into the font-selection */
3635 cairo_select_font_face (cr, "Sans",
3636 CAIRO_FONT_SLANT_NORMAL,
3637 CAIRO_FONT_WEIGHT_NORMAL);
3639 cairo_set_font_size (cr, 12.0);
3640 cairo_text_extents (cr, string, &extents);
3642 if (column == (flipView ? BOARD_LEFT-1 : BOARD_RGHT) )
3644 xpos= x + squareSize - extents.width - 2;
3645 ypos= y + extents.y_bearing + 1;
3647 if (column == (flipView ? BOARD_RGHT : BOARD_LEFT-1) && piece > 1)
3650 ypos = y + extents.y_bearing + 1;
3653 /* TODO mono mode? */
3654 cairo_move_to (cr, xpos, ypos);
3655 cairo_text_path (cr, string);
3656 cairo_set_source_rgb (cr, 1.0, 1.0, 1);
3657 cairo_fill_preserve (cr);
3658 cairo_set_source_rgb (cr, 0, 0, 0);
3659 cairo_set_line_width (cr, 0.1);
3668 /* square on the board */
3669 if (piece == EmptySquare || appData.blindfold)
3671 BlankSquare(x, y, square_color, piece, xBoardWindow);
3675 if (do_flash && appData.flashCount > 0)
3677 for (i=0; i<appData.flashCount; ++i)
3680 DrawPiece(piece, square_color, x, y, xBoardWindow);
3681 do_flash_delay(flash_delay);
3683 BlankSquare(x, y, square_color, piece, xBoardWindow);
3684 do_flash_delay(flash_delay);
3687 DrawPiece(piece, square_color, x, y, xBoardWindow);
3691 /* show coordinates if necessary */
3692 if(appData.showCoords)
3694 cairo_text_extents_t extents;
3698 /* TODO this has to go into the font-selection */
3699 cairo_select_font_face (cr, "Sans",
3700 CAIRO_FONT_SLANT_NORMAL,
3701 CAIRO_FONT_WEIGHT_NORMAL);
3702 cairo_set_font_size (cr, 12.0);
3704 string[1] = NULLCHAR;
3707 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3709 if (row == (flipView ? BOARD_HEIGHT-1 : 0) &&
3710 column >= BOARD_LEFT && column < BOARD_RGHT)
3712 string[0] = 'a' + column - BOARD_LEFT;
3713 cairo_text_extents (cr, string, &extents);
3715 xpos = x + squareSize - extents.width - 2;
3716 ypos = y + squareSize - extents.height - extents.y_bearing - 1;
3718 if (appData.monoMode)
3725 cairo_move_to (cr, xpos, ypos);
3726 cairo_text_path (cr, string);
3727 cairo_set_source_rgb (cr, 0.0, 0.0, 0);
3728 cairo_fill_preserve (cr);
3729 cairo_set_source_rgb (cr, 0, 1.0, 0);
3730 cairo_set_line_width (cr, 0.1);
3733 if ( column == (flipView ? BOARD_RGHT-1 : BOARD_LEFT))
3736 string[0] = ONE + row;
3737 cairo_text_extents (cr, string, &extents);
3740 ypos = y + extents.height + 1;
3742 if (appData.monoMode)
3749 cairo_move_to (cr, xpos, ypos);
3750 cairo_text_path (cr, string);
3751 cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
3752 cairo_fill_preserve (cr);
3753 cairo_set_source_rgb (cr, 0, 0, 1.0);
3754 cairo_set_line_width (cr, 0.1);
3766 /* Returns 1 if there are "too many" differences between b1 and b2
3767 (i.e. more than 1 move was made) */
3768 static int too_many_diffs(b1, b2)
3774 for (i=0; i<BOARD_HEIGHT; ++i) {
3775 for (j=0; j<BOARD_WIDTH; ++j) {
3776 if (b1[i][j] != b2[i][j]) {
3777 if (++c > 4) /* Castling causes 4 diffs */
3786 /* Matrix describing castling maneuvers */
3787 /* Row, ColRookFrom, ColKingFrom, ColRookTo, ColKingTo */
3788 static int castling_matrix[4][5] = {
3789 { 0, 0, 4, 3, 2 }, /* 0-0-0, white */
3790 { 0, 7, 4, 5, 6 }, /* 0-0, white */
3791 { 7, 0, 4, 3, 2 }, /* 0-0-0, black */
3792 { 7, 7, 4, 5, 6 } /* 0-0, black */
3795 /* Checks whether castling occurred. If it did, *rrow and *rcol
3796 are set to the destination (row,col) of the rook that moved.
3798 Returns 1 if castling occurred, 0 if not.
3800 Note: Only handles a max of 1 castling move, so be sure
3801 to call too_many_diffs() first.
3803 static int check_castle_draw(newb, oldb, rrow, rcol)
3810 /* For each type of castling... */
3811 for (i=0; i<4; ++i) {
3812 r = castling_matrix[i];
3814 /* Check the 4 squares involved in the castling move */
3816 for (j=1; j<=4; ++j) {
3817 if (newb[r[0]][r[j]] == oldb[r[0]][r[j]]) {
3824 /* All 4 changed, so it must be a castling move */
3833 static int damage[BOARD_SIZE][BOARD_SIZE];
3836 * event handler for redrawing the board
3838 void DrawPosition( repaint, board)
3839 /*Boolean*/int repaint;
3843 static int lastFlipView = 0;
3844 static int lastBoardValid = 0;
3845 static Board lastBoard;
3848 if (board == NULL) {
3849 if (!lastBoardValid) return;
3852 if (!lastBoardValid || lastFlipView != flipView) {
3853 // XtSetArg(args[0], XtNleftBitmap, (flipView ? xMarkPixmap : None));
3854 // XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flip View"),
3859 * It would be simpler to clear the window with XClearWindow()
3860 * but this causes a very distracting flicker.
3863 if (!repaint && lastBoardValid && lastFlipView == flipView)
3865 /* If too much changes (begin observing new game, etc.), don't
3867 do_flash = too_many_diffs(board, lastBoard) ? 0 : 1;
3869 /* Special check for castling so we don't flash both the king
3870 and the rook (just flash the king). */
3873 if (check_castle_draw(board, lastBoard, &rrow, &rcol))
3875 /* Draw rook with NO flashing. King will be drawn flashing later */
3876 DrawSquare(rrow, rcol, board[rrow][rcol], 0);
3877 lastBoard[rrow][rcol] = board[rrow][rcol];
3881 /* First pass -- Draw (newly) empty squares and repair damage.
3882 This prevents you from having a piece show up twice while it
3883 is flashing on its new square */
3884 for (i = 0; i < BOARD_HEIGHT; i++)
3885 for (j = 0; j < BOARD_WIDTH; j++)
3886 if ((board[i][j] != lastBoard[i][j] && board[i][j] == EmptySquare)
3889 DrawSquare(i, j, board[i][j], 0);
3890 damage[i][j] = False;
3893 /* Second pass -- Draw piece(s) in new position and flash them */
3894 for (i = 0; i < BOARD_HEIGHT; i++)
3895 for (j = 0; j < BOARD_WIDTH; j++)
3896 if (board[i][j] != lastBoard[i][j])
3898 DrawSquare(i, j, board[i][j], do_flash);
3910 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3912 cairo_set_line_width (cr, lineGap);
3914 /* TODO: use appdata colors */
3915 cairo_set_source_rgba (cr, 0, 1, 0, 1.0);
3919 for (i = 0; i < BOARD_HEIGHT + 1; i++)
3922 x2 = lineGap + BOARD_WIDTH * (squareSize + lineGap);
3923 y1 = y2 = lineGap / 2 + (i * (squareSize + lineGap));
3925 cairo_move_to (cr, x1, y1);
3926 cairo_rel_line_to (cr, x2,0);
3930 for (j = 0; j < BOARD_WIDTH + 1; j++)
3933 y2 = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
3934 x1 = x2 = lineGap / 2 + (j * (squareSize + lineGap));
3936 cairo_move_to (cr, x1, y1);
3937 cairo_rel_line_to (cr, 0, y2);
3946 for (i = 0; i < BOARD_HEIGHT; i++)
3947 for (j = 0; j < BOARD_WIDTH; j++)
3949 DrawSquare(i, j, board[i][j], 0);
3950 damage[i][j] = False;
3954 CopyBoard(lastBoard, board);
3956 lastFlipView = flipView;
3958 /* Draw highlights */
3959 if (pm1X >= 0 && pm1Y >= 0)
3961 drawHighlight(pm1X, pm1Y, LINE_TYPE_PRE);
3963 if (pm2X >= 0 && pm2Y >= 0)
3965 drawHighlight(pm2X, pm2Y, LINE_TYPE_PRE);
3967 if (hi1X >= 0 && hi1Y >= 0)
3969 drawHighlight(hi1X, hi1Y, LINE_TYPE_HIGHLIGHT);
3971 if (hi2X >= 0 && hi2Y >= 0)
3973 drawHighlight(hi2X, hi2Y, LINE_TYPE_HIGHLIGHT);
3976 /* If piece being dragged around board, must redraw that too */
3983 * event handler for parsing user moves
3985 // [HGM] This routine will need quite some reworking. Although the backend still supports the old
3986 // way of doing things, by calling UserMoveEvent() to test the legality of the move and then perform
3987 // it at the end, and doing all kind of preliminary tests here (e.g. to weed out self-captures), it
3988 // should be made to use the new way, of calling UserMoveTest early to determine the legality of the
3989 // move, (which will weed out the illegal selfcaptures and moves into the holdings, and flag promotions),
3990 // and at the end FinishMove() to perform the move after optional promotion popups.
3991 // For now I patched it to allow self-capture with King, and suppress clicks between board and holdings.
3992 void HandleUserMove(w, event, prms, nprms)
3999 Boolean saveAnimate;
4000 static int second = 0, promotionChoice = 0;
4003 if (w != boardWidget || errorExitStatus != -1) return;
4005 x = EventToSquare(event->xbutton.x, BOARD_WIDTH);
4006 y = EventToSquare(event->xbutton.y, BOARD_HEIGHT);
4007 if (!flipView && y >= 0) {
4008 y = BOARD_HEIGHT - 1 - y;
4010 if (flipView && x >= 0) {
4011 x = BOARD_WIDTH - 1 - x;
4014 if(promotionChoice) { // we are waiting for a click to indicate promotion piece
4015 if(event->type == ButtonRelease) return; // ignore upclick of click-click destination
4016 promotionChoice = FALSE; // only one chance: if click not OK it is interpreted as cancel
4017 if(appData.debugMode) fprintf(debugFP, "promotion click, x=%d, y=%d\n", x, y);
4018 if(gameInfo.holdingsWidth &&
4019 (WhiteOnMove(currentMove)
4020 ? x == BOARD_WIDTH-1 && y < gameInfo.holdingsSize && y > 0
4021 : x == 0 && y >= BOARD_HEIGHT - gameInfo.holdingsSize && y < BOARD_HEIGHT-1) ) {
4022 // click in right holdings, for determining promotion piece
4023 ChessSquare p = boards[currentMove][y][x];
4024 if(appData.debugMode) fprintf(debugFP, "square contains %d\n", (int)p);
4025 if(p != EmptySquare) {
4026 FinishMove(NormalMove, fromX, fromY, toX, toY, ToLower(PieceToChar(p)));
4031 DrawPosition(FALSE, boards[currentMove]);
4034 if (event->type == ButtonPress) ErrorPopDown();
4037 if (event->type == ButtonPress) {
4038 // XtPopdown(promotionShell);
4039 // XtDestroyWidget(promotionShell);
4040 promotionUp = False;
4048 /* [HGM] holdings: next 5 lines: ignore all clicks between board and holdings */
4049 if(event->type == ButtonPress
4050 && ( x == BOARD_LEFT-1 ||
4052 (x == BOARD_LEFT-2 && y < BOARD_HEIGHT-gameInfo.holdingsSize ) ||
4053 (x == BOARD_RGHT+1 && y >= gameInfo.holdingsSize)) )
4057 if (event->type == ButtonPress) {
4058 /* First square, prepare to drag */
4059 if (OKToStartUserMove(x, y)) {
4063 DragPieceBegin(event->xbutton.x, event->xbutton.y);
4064 if (appData.highlightDragging) {
4065 SetHighlights(x, y, -1, -1);
4073 if (event->type == ButtonRelease && x == fromX && y == fromY) {
4074 /* Click on single square in stead of drag-drop */
4075 DragPieceEnd(event->xbutton.x, event->xbutton.y);
4076 if (appData.animateDragging) {
4077 /* Undo animation damage if any */
4078 DrawPosition(FALSE, NULL);
4081 /* Second up/down in same square; just abort move */
4086 ClearPremoveHighlights();
4088 /* First upclick in same square; start click-click mode */
4089 SetHighlights(x, y, -1, -1);
4094 moveType = UserMoveTest(fromX, fromY, x, y, NULLCHAR, event->type == ButtonRelease);
4096 if (moveType == Comment) { // kludge for indicating capture-own on Press
4097 /* Clicked again on same color piece -- changed his mind */
4098 /* note that re-clicking same square always hits same color piece */
4099 second = (x == fromX && y == fromY);
4100 if (appData.highlightDragging) {
4101 SetHighlights(x, y, -1, -1);
4105 if (OKToStartUserMove(x, y)) {
4108 DragPieceBegin(event->xbutton.x, event->xbutton.y);
4113 if(moveType == AmbiguousMove) { // kludge to indicate edit-position move
4116 DragPieceEnd(event->xbutton.x, event->xbutton.y);
4117 DrawPosition(FALSE, boards[currentMove]);
4121 /* Complete move; (x,y) is now different from (fromX, fromY) on both Press and Release */
4124 saveAnimate = appData.animate;
4125 if (event->type == ButtonPress) {
4126 /* Finish clickclick move */
4127 if (appData.animate || appData.highlightLastMove) {
4128 SetHighlights(fromX, fromY, toX, toY);
4133 /* Finish drag move */
4134 if (appData.highlightLastMove) {
4135 SetHighlights(fromX, fromY, toX, toY);
4139 DragPieceEnd(event->xbutton.x, event->xbutton.y);
4140 /* Don't animate move and drag both */
4141 appData.animate = FALSE;
4143 if (moveType == WhitePromotionKnight || moveType == BlackPromotionKnight ||
4144 (moveType == WhitePromotionQueen || moveType == BlackPromotionQueen) &&
4145 appData.alwaysPromoteToQueen) { // promotion, but no choice
4146 FinishMove(moveType, fromX, fromY, toX, toY, 'q');
4148 if (moveType == WhitePromotionQueen || moveType == BlackPromotionQueen ) {
4149 SetHighlights(fromX, fromY, toX, toY);
4150 if(gameInfo.variant == VariantSuper || gameInfo.variant == VariantGreat) {
4151 // [HGM] super: promotion to captured piece selected from holdings
4152 ChessSquare p = boards[currentMove][fromY][fromX], q = boards[currentMove][toY][toX];
4153 promotionChoice = TRUE;
4154 // kludge follows to temporarily execute move on display, without promoting yet
4155 boards[currentMove][fromY][fromX] = EmptySquare; // move Pawn to 8th rank
4156 boards[currentMove][toY][toX] = p;
4157 DrawPosition(FALSE, boards[currentMove]);
4158 boards[currentMove][fromY][fromX] = p; // take back, but display stays
4159 boards[currentMove][toY][toX] = q;
4160 DisplayMessage("Click in holdings to choose piece", "");
4164 goto skipClearingFrom; // the skipped stuff is done asynchronously by PromotionCallback
4166 if(moveType != ImpossibleMove) { // valid move, but no promotion
4167 FinishMove(moveType, fromX, fromY, toX, toY, NULLCHAR);
4168 } else { // invalid move; could have set premove
4171 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
4172 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
4175 appData.animate = saveAnimate;
4176 if (appData.animate || appData.animateDragging) {
4177 /* Undo animation damage if needed */
4178 DrawPosition(FALSE, NULL);
4182 void AnimateUserMove (Widget w, XEvent * event,
4183 String * params, Cardinal * nParams)
4185 DragPieceMove(event->xmotion.x, event->xmotion.y);
4188 Widget CommentCreate(name, text, mutable, callback, lines)
4190 int /*Boolean*/ mutable;
4191 XtCallbackProc callback;
4195 Widget shell, layout, form, edit, b_ok, b_cancel, b_clear, b_close, b_edit;
4200 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4201 XtGetValues(boardWidget, args, j);
4204 XtSetArg(args[j], XtNresizable, True); j++;
4207 XtCreatePopupShell(name, topLevelShellWidgetClass,
4208 shellWidget, args, j);
4211 XtCreatePopupShell(name, transientShellWidgetClass,
4212 shellWidget, args, j);
4215 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
4216 layoutArgs, XtNumber(layoutArgs));
4218 XtCreateManagedWidget("form", formWidgetClass, layout,
4219 formArgs, XtNumber(formArgs));
4223 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
4224 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
4226 XtSetArg(args[j], XtNstring, text); j++;
4227 XtSetArg(args[j], XtNtop, XtChainTop); j++;
4228 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4229 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4230 XtSetArg(args[j], XtNright, XtChainRight); j++;
4231 XtSetArg(args[j], XtNresizable, True); j++;
4232 XtSetArg(args[j], XtNwidth, bw_width); j++; /*force wider than buttons*/
4233 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
4234 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
4235 XtSetArg(args[j], XtNautoFill, True); j++;
4236 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
4238 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
4242 XtSetArg(args[j], XtNfromVert, edit); j++;
4243 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4244 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4245 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4246 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4248 XtCreateManagedWidget(_("ok"), commandWidgetClass, form, args, j);
4249 XtAddCallback(b_ok, XtNcallback, callback, (XtPointer) 0);
4252 XtSetArg(args[j], XtNfromVert, edit); j++;
4253 XtSetArg(args[j], XtNfromHoriz, b_ok); j++;
4254 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4255 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4256 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4257 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4259 XtCreateManagedWidget(_("cancel"), commandWidgetClass, form, args, j);
4260 XtAddCallback(b_cancel, XtNcallback, callback, (XtPointer) 0);
4263 XtSetArg(args[j], XtNfromVert, edit); j++;
4264 XtSetArg(args[j], XtNfromHoriz, b_cancel); j++;
4265 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4266 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4267 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4268 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4270 XtCreateManagedWidget(_("clear"), commandWidgetClass, form, args, j);
4271 XtAddCallback(b_clear, XtNcallback, callback, (XtPointer) 0);
4274 XtSetArg(args[j], XtNfromVert, edit); j++;
4275 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4276 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4277 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4278 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4280 XtCreateManagedWidget(_("close"), commandWidgetClass, form, args, j);
4281 XtAddCallback(b_close, XtNcallback, callback, (XtPointer) 0);
4284 XtSetArg(args[j], XtNfromVert, edit); j++;
4285 XtSetArg(args[j], XtNfromHoriz, b_close); j++;
4286 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4287 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4288 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4289 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4291 XtCreateManagedWidget(_("edit"), commandWidgetClass, form, args, j);
4292 XtAddCallback(b_edit, XtNcallback, callback, (XtPointer) 0);
4295 XtRealizeWidget(shell);
4297 if (commentX == -1) {
4300 Dimension pw_height;
4301 Dimension ew_height;
4304 XtSetArg(args[j], XtNheight, &ew_height); j++;
4305 XtGetValues(edit, args, j);
4308 XtSetArg(args[j], XtNheight, &pw_height); j++;
4309 XtGetValues(shell, args, j);
4310 commentH = pw_height + (lines - 1) * ew_height;
4311 commentW = bw_width - 16;
4313 XSync(xDisplay, False);
4315 /* This code seems to tickle an X bug if it is executed too soon
4316 after xboard starts up. The coordinates get transformed as if
4317 the main window was positioned at (0, 0).
4319 XtTranslateCoords(shellWidget,
4320 (bw_width - commentW) / 2, 0 - commentH / 2,
4321 &commentX, &commentY);
4323 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
4324 RootWindowOfScreen(XtScreen(shellWidget)),
4325 (bw_width - commentW) / 2, 0 - commentH / 2,
4330 if (commentY < 0) commentY = 0; /*avoid positioning top offscreen*/
4333 XtSetArg(args[j], XtNheight, commentH); j++;
4334 XtSetArg(args[j], XtNwidth, commentW); j++;
4335 XtSetArg(args[j], XtNx, commentX); j++;
4336 XtSetArg(args[j], XtNy, commentY); j++;
4337 XtSetValues(shell, args, j);
4338 XtSetKeyboardFocus(shell, edit);
4343 /* Used for analysis window and ICS input window */
4344 Widget MiscCreate(name, text, mutable, callback, lines)
4346 int /*Boolean*/ mutable;
4347 XtCallbackProc callback;
4351 Widget shell, layout, form, edit;
4353 Dimension bw_width, pw_height, ew_height, w, h;
4359 XtSetArg(args[j], XtNresizable, True); j++;
4362 XtCreatePopupShell(name, topLevelShellWidgetClass,
4363 shellWidget, args, j);
4366 XtCreatePopupShell(name, transientShellWidgetClass,
4367 shellWidget, args, j);
4370 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
4371 layoutArgs, XtNumber(layoutArgs));
4373 XtCreateManagedWidget("form", formWidgetClass, layout,
4374 formArgs, XtNumber(formArgs));
4378 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
4379 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
4381 XtSetArg(args[j], XtNstring, text); j++;
4382 XtSetArg(args[j], XtNtop, XtChainTop); j++;
4383 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4384 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4385 XtSetArg(args[j], XtNright, XtChainRight); j++;
4386 XtSetArg(args[j], XtNresizable, True); j++;
4387 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
4388 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
4389 XtSetArg(args[j], XtNautoFill, True); j++;
4390 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
4392 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
4394 XtRealizeWidget(shell);
4397 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4398 XtGetValues(boardWidget, args, j);
4401 XtSetArg(args[j], XtNheight, &ew_height); j++;
4402 XtGetValues(edit, args, j);
4405 XtSetArg(args[j], XtNheight, &pw_height); j++;
4406 XtGetValues(shell, args, j);
4407 h = pw_height + (lines - 1) * ew_height;
4410 XSync(xDisplay, False);
4412 /* This code seems to tickle an X bug if it is executed too soon
4413 after xboard starts up. The coordinates get transformed as if
4414 the main window was positioned at (0, 0).
4416 XtTranslateCoords(shellWidget, (bw_width - w) / 2, 0 - h / 2, &x, &y);
4418 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
4419 RootWindowOfScreen(XtScreen(shellWidget)),
4420 (bw_width - w) / 2, 0 - h / 2, &xx, &yy, &junk);
4424 if (y < 0) y = 0; /*avoid positioning top offscreen*/
4427 XtSetArg(args[j], XtNheight, h); j++;
4428 XtSetArg(args[j], XtNwidth, w); j++;
4429 XtSetArg(args[j], XtNx, x); j++;
4430 XtSetArg(args[j], XtNy, y); j++;
4431 XtSetValues(shell, args, j);
4437 static int savedIndex; /* gross that this is global */
4439 void EditCommentPopUp(index, title, text)
4448 if (text == NULL) text = "";
4450 if (editShell == NULL) {
4452 CommentCreate(title, text, True, EditCommentCallback, 4);
4453 XtRealizeWidget(editShell);
4454 CatchDeleteWindow(editShell, "EditCommentPopDown");
4456 edit = XtNameToWidget(editShell, "*form.text");
4458 XtSetArg(args[j], XtNstring, text); j++;
4459 XtSetValues(edit, args, j);
4461 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4462 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4463 XtSetValues(editShell, args, j);
4466 XtPopup(editShell, XtGrabNone);
4470 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
4471 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
4475 void EditCommentCallback(w, client_data, call_data)
4477 XtPointer client_data, call_data;
4485 XtSetArg(args[j], XtNlabel, &name); j++;
4486 XtGetValues(w, args, j);
4488 if (strcmp(name, _("ok")) == 0) {
4489 edit = XtNameToWidget(editShell, "*form.text");
4491 XtSetArg(args[j], XtNstring, &val); j++;
4492 XtGetValues(edit, args, j);
4493 ReplaceComment(savedIndex, val);
4494 EditCommentPopDown();
4495 } else if (strcmp(name, _("cancel")) == 0) {
4496 EditCommentPopDown();
4497 } else if (strcmp(name, _("clear")) == 0) {
4498 edit = XtNameToWidget(editShell, "*form.text");
4499 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
4500 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
4504 void EditCommentPopDown()
4509 if (!editUp) return;
4511 XtSetArg(args[j], XtNx, &commentX); j++;
4512 XtSetArg(args[j], XtNy, &commentY); j++;
4513 XtSetArg(args[j], XtNheight, &commentH); j++;
4514 XtSetArg(args[j], XtNwidth, &commentW); j++;
4515 XtGetValues(editShell, args, j);
4516 XtPopdown(editShell);
4519 XtSetArg(args[j], XtNleftBitmap, None); j++;
4520 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
4524 void ICSInputBoxPopUp()
4529 char *title = _("ICS Input");
4532 if (ICSInputShell == NULL) {
4533 ICSInputShell = MiscCreate(title, "", True, NULL, 1);
4534 tr = XtParseTranslationTable(ICSInputTranslations);
4535 edit = XtNameToWidget(ICSInputShell, "*form.text");
4536 XtOverrideTranslations(edit, tr);
4537 XtRealizeWidget(ICSInputShell);
4538 CatchDeleteWindow(ICSInputShell, "ICSInputBoxPopDown");
4541 edit = XtNameToWidget(ICSInputShell, "*form.text");
4543 XtSetArg(args[j], XtNstring, ""); j++;
4544 XtSetValues(edit, args, j);
4546 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4547 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4548 XtSetValues(ICSInputShell, args, j);
4551 XtPopup(ICSInputShell, XtGrabNone);
4552 XtSetKeyboardFocus(ICSInputShell, edit);
4554 ICSInputBoxUp = True;
4556 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
4557 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
4561 void ICSInputSendText()
4568 edit = XtNameToWidget(ICSInputShell, "*form.text");
4570 XtSetArg(args[j], XtNstring, &val); j++;
4571 XtGetValues(edit, args, j);
4572 SendMultiLineToICS(val);
4573 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
4574 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
4577 void ICSInputBoxPopDown()
4582 if (!ICSInputBoxUp) return;
4584 XtPopdown(ICSInputShell);
4585 ICSInputBoxUp = False;
4587 XtSetArg(args[j], XtNleftBitmap, None); j++;
4588 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
4592 void CommentPopUp(title, text)
4599 if (commentShell == NULL) {
4601 CommentCreate(title, text, False, CommentCallback, 4);
4602 XtRealizeWidget(commentShell);
4603 CatchDeleteWindow(commentShell, "CommentPopDown");
4605 edit = XtNameToWidget(commentShell, "*form.text");
4607 XtSetArg(args[j], XtNstring, text); j++;
4608 XtSetValues(edit, args, j);
4610 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4611 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4612 XtSetValues(commentShell, args, j);
4615 XtPopup(commentShell, XtGrabNone);
4616 XSync(xDisplay, False);
4621 void AnalysisPopUp(title, text)
4628 if (analysisShell == NULL) {
4629 analysisShell = MiscCreate(title, text, False, NULL, 4);
4630 XtRealizeWidget(analysisShell);
4631 CatchDeleteWindow(analysisShell, "AnalysisPopDown");
4634 edit = XtNameToWidget(analysisShell, "*form.text");
4636 XtSetArg(args[j], XtNstring, text); j++;
4637 XtSetValues(edit, args, j);
4639 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4640 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4641 XtSetValues(analysisShell, args, j);
4645 XtPopup(analysisShell, XtGrabNone);
4647 XSync(xDisplay, False);
4652 void CommentCallback(w, client_data, call_data)
4654 XtPointer client_data, call_data;
4661 XtSetArg(args[j], XtNlabel, &name); j++;
4662 XtGetValues(w, args, j);
4664 if (strcmp(name, _("close")) == 0) {
4666 } else if (strcmp(name, _("edit")) == 0) {
4673 void CommentPopDown()
4678 if (!commentUp) return;
4680 XtSetArg(args[j], XtNx, &commentX); j++;
4681 XtSetArg(args[j], XtNy, &commentY); j++;
4682 XtSetArg(args[j], XtNwidth, &commentW); j++;
4683 XtSetArg(args[j], XtNheight, &commentH); j++;
4684 XtGetValues(commentShell, args, j);
4685 XtPopdown(commentShell);
4686 XSync(xDisplay, False);
4690 void AnalysisPopDown()
4692 if (!analysisUp) return;
4693 XtPopdown(analysisShell);
4694 XSync(xDisplay, False);
4696 if (appData.icsEngineAnalyze) ExitAnalyzeMode(); /* [DM] icsEngineAnalyze */
4700 void FileNamePopUp(label, def, proc, openMode)
4707 Widget popup, layout, dialog, edit;
4713 fileProc = proc; /* I can't see a way not */
4714 fileOpenMode = openMode; /* to use globals here */
4717 XtSetArg(args[i], XtNresizable, True); i++;
4718 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
4719 XtSetArg(args[i], XtNtitle, XtNewString(_("File name prompt"))); i++;
4720 fileNameShell = popup =
4721 XtCreatePopupShell("File name prompt", transientShellWidgetClass,
4722 shellWidget, args, i);
4725 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
4726 layoutArgs, XtNumber(layoutArgs));
4729 XtSetArg(args[i], XtNlabel, label); i++;
4730 XtSetArg(args[i], XtNvalue, def); i++;
4731 XtSetArg(args[i], XtNborderWidth, 0); i++;
4732 dialog = XtCreateManagedWidget("fileName", dialogWidgetClass,
4735 XawDialogAddButton(dialog, _("ok"), FileNameCallback, (XtPointer) dialog);
4736 XawDialogAddButton(dialog, _("cancel"), FileNameCallback,
4737 (XtPointer) dialog);
4739 XtRealizeWidget(popup);
4740 CatchDeleteWindow(popup, "FileNamePopDown");
4742 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
4743 &x, &y, &win_x, &win_y, &mask);
4745 XtSetArg(args[0], XtNx, x - 10);
4746 XtSetArg(args[1], XtNy, y - 30);
4747 XtSetValues(popup, args, 2);
4749 XtPopup(popup, XtGrabExclusive);
4752 edit = XtNameToWidget(dialog, "*value");
4753 XtSetKeyboardFocus(popup, edit);
4756 void FileNamePopDown()
4758 if (!filenameUp) return;
4759 XtPopdown(fileNameShell);
4760 XtDestroyWidget(fileNameShell);
4765 void FileNameCallback(w, client_data, call_data)
4767 XtPointer client_data, call_data;
4772 XtSetArg(args[0], XtNlabel, &name);
4773 XtGetValues(w, args, 1);
4775 if (strcmp(name, _("cancel")) == 0) {
4780 FileNameAction(w, NULL, NULL, NULL);
4783 void FileNameAction(w, event, prms, nprms)
4795 name = XawDialogGetValueString(w = XtParent(w));
4797 if ((name != NULL) && (*name != NULLCHAR)) {
4799 XtPopdown(w = XtParent(XtParent(w)));
4803 p = strrchr(buf, ' ');
4810 fullname = ExpandPathName(buf);
4812 ErrorPopUp(_("Error"), _("Can't open file"), FALSE);
4815 f = fopen(fullname, fileOpenMode);
4817 DisplayError(_("Failed to open file"), errno);
4819 (void) (*fileProc)(f, index, buf);
4826 XtPopdown(w = XtParent(XtParent(w)));
4832 void PromotionPopUp()
4835 Widget dialog, layout;
4837 Dimension bw_width, pw_width;
4841 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4842 XtGetValues(boardWidget, args, j);
4845 XtSetArg(args[j], XtNresizable, True); j++;
4846 XtSetArg(args[j], XtNtitle, XtNewString(_("Promotion"))); j++;
4848 XtCreatePopupShell("Promotion", transientShellWidgetClass,
4849 shellWidget, args, j);
4851 XtCreateManagedWidget(layoutName, formWidgetClass, promotionShell,
4852 layoutArgs, XtNumber(layoutArgs));
4855 XtSetArg(args[j], XtNlabel, _("Promote to what?")); j++;
4856 XtSetArg(args[j], XtNborderWidth, 0); j++;
4857 dialog = XtCreateManagedWidget("promotion", dialogWidgetClass,
4860 if(gameInfo.variant != VariantShogi) {
4861 XawDialogAddButton(dialog, _("Queen"), PromotionCallback,
4862 (XtPointer) dialog);
4863 XawDialogAddButton(dialog, _("Rook"), PromotionCallback,
4864 (XtPointer) dialog);
4865 XawDialogAddButton(dialog, _("Bishop"), PromotionCallback,
4866 (XtPointer) dialog);
4867 XawDialogAddButton(dialog, _("Knight"), PromotionCallback,
4868 (XtPointer) dialog);
4869 if (!appData.testLegality || gameInfo.variant == VariantSuicide ||
4870 gameInfo.variant == VariantGiveaway) {
4871 XawDialogAddButton(dialog, _("King"), PromotionCallback,
4872 (XtPointer) dialog);
4874 if(gameInfo.variant == VariantCapablanca ||
4875 gameInfo.variant == VariantGothic ||
4876 gameInfo.variant == VariantCapaRandom) {
4877 XawDialogAddButton(dialog, _("Archbishop"), PromotionCallback,
4878 (XtPointer) dialog);
4879 XawDialogAddButton(dialog, _("Chancellor"), PromotionCallback,
4880 (XtPointer) dialog);
4882 } else // [HGM] shogi
4884 XawDialogAddButton(dialog, _("Promote"), PromotionCallback,
4885 (XtPointer) dialog);
4886 XawDialogAddButton(dialog, _("Defer"), PromotionCallback,
4887 (XtPointer) dialog);
4889 XawDialogAddButton(dialog, _("cancel"), PromotionCallback,
4890 (XtPointer) dialog);
4892 XtRealizeWidget(promotionShell);
4893 CatchDeleteWindow(promotionShell, "PromotionPopDown");
4896 XtSetArg(args[j], XtNwidth, &pw_width); j++;
4897 XtGetValues(promotionShell, args, j);
4899 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
4900 lineGap + squareSize/3 +
4901 ((toY == BOARD_HEIGHT-1) ^ (flipView) ?
4902 0 : 6*(squareSize + lineGap)), &x, &y);
4905 XtSetArg(args[j], XtNx, x); j++;
4906 XtSetArg(args[j], XtNy, y); j++;
4907 XtSetValues(promotionShell, args, j);
4909 XtPopup(promotionShell, XtGrabNone);
4914 void PromotionPopDown()
4916 if (!promotionUp) return;
4917 XtPopdown(promotionShell);
4918 XtDestroyWidget(promotionShell);
4919 promotionUp = False;
4922 void PromotionCallback(w, client_data, call_data)
4924 XtPointer client_data, call_data;
4930 XtSetArg(args[0], XtNlabel, &name);
4931 XtGetValues(w, args, 1);
4935 if (fromX == -1) return;
4937 if (strcmp(name, _("cancel")) == 0) {
4941 } else if (strcmp(name, _("Knight")) == 0) {
4943 } else if (strcmp(name, _("Promote")) == 0) {
4945 } else if (strcmp(name, _("Defer")) == 0) {
4948 promoChar = ToLower(name[0]);
4951 FinishMove(NormalMove, fromX, fromY, toX, toY, promoChar);
4953 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
4954 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
4959 void ErrorCallback(w, client_data, call_data)
4961 XtPointer client_data, call_data;
4964 XtPopdown(w = XtParent(XtParent(XtParent(w))));
4966 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
4972 if (!errorUp) return;
4976 gtk_widget_destroy(GTK_WIDGET(GUI_Error));
4978 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
4983 void ErrorPopUp(title, label, modal)
4984 char *title, *label;
4987 GUI_Error = gtk_message_dialog_new(GTK_WINDOW(GUI_Window),
4988 GTK_DIALOG_DESTROY_WITH_PARENT,
4993 gtk_window_set_title(GTK_WINDOW(GUI_Error),(gchar *) title);
4996 gtk_dialog_run(GTK_DIALOG(GUI_Error));
4997 gtk_widget_destroy(GTK_WIDGET(GUI_Error));
5001 g_signal_connect_swapped (GUI_Error, "response",
5002 G_CALLBACK (ErrorPopDownProc),
5005 gtk_widget_show(GTK_WIDGET(GUI_Error));
5011 /* Disable all user input other than deleting the window */
5012 static int frozen = 0;
5016 /* Grab by a widget that doesn't accept input */
5017 // XtAddGrab(messageWidget, TRUE, FALSE);
5021 /* Undo a FreezeUI */
5024 if (!frozen) return;
5025 // XtRemoveGrab(messageWidget);
5029 char *ModeToWidgetName(mode)
5033 case BeginningOfGame:
5034 if (appData.icsActive)
5035 return "menuMode.ICS Client";
5036 else if (appData.noChessProgram ||
5037 *appData.cmailGameName != NULLCHAR)
5038 return "menuMode.Edit Game";
5040 return "menuMode.Machine Black";
5041 case MachinePlaysBlack:
5042 return "menuMode.Machine Black";
5043 case MachinePlaysWhite:
5044 return "menuMode.Machine White";
5046 return "menuMode.Analysis Mode";
5048 return "menuMode.Analyze File";
5049 case TwoMachinesPlay:
5050 return "menuMode.Two Machines";
5052 return "menuMode.Edit Game";
5053 case PlayFromGameFile:
5054 return "menuFile.Load Game";
5056 return "menuMode.Edit Position";
5058 return "menuMode.Training";
5059 case IcsPlayingWhite:
5060 case IcsPlayingBlack:
5064 return "menuMode.ICS Client";
5071 void ModeHighlight()
5073 static int oldPausing = FALSE;
5074 static GameMode oldmode = (GameMode) -1;
5077 // todo this toggling of the pause button doesn't seem to work?
5078 // e.g. select pause from buttonbar doesn't activate menumode.pause
5080 // if (!boardWidget || !XtIsRealized(boardWidget)) return;
5082 if (pausing != oldPausing) {
5083 oldPausing = pausing;
5084 gtk_button_set_relief(GTK_BUTTON (gtk_builder_get_object (builder, "menuMode.Pause")),pausing?GTK_RELIEF_NORMAL:GTK_RELIEF_NONE);
5085 /* toggle background color in showbuttonbar */
5086 if (appData.showButtonBar) {
5088 gtk_button_pressed(GTK_BUTTON (gtk_builder_get_object (builder, "buttonbar.Pause")));
5090 gtk_button_released(GTK_BUTTON (gtk_builder_get_object (builder, "buttonbar.Pause")));
5095 wname = ModeToWidgetName(oldmode);
5097 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, wname)),True);
5101 /* Maybe all the enables should be handled here, not just this one */
5102 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuMode.Training")),
5103 gameMode == Training || gameMode == PlayFromGameFile);
5108 * Button/menu procedures
5111 int LoadGamePopUp(f, gameNumber, title)
5116 cmailMsgLoaded = FALSE;
5118 if (gameNumber == 0)
5120 int error = GameListBuild(f);
5124 DisplayError(_("Cannot build game list"), error);
5126 else if (!ListEmpty(&gameList)
5127 && ((ListGame *) gameList.tailPred)->number > 1)
5129 GameListPopUp(f, title);
5137 return LoadGame(f, gameNumber, title, FALSE);
5140 void LoadPositionProc(w, event, prms, nprms)
5146 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
5149 FileNamePopUp(_("Load position file name?"), "", LoadPosition, "rb");
5152 void SaveGameProc(w, event, prms, nprms)
5158 FileNamePopUp(_("Save game file name?"),
5159 DefaultFileName(appData.oldSaveStyle ? "game" : "pgn"),
5163 void SavePositionProc(w, event, prms, nprms)
5169 FileNamePopUp(_("Save position file name?"),
5170 DefaultFileName(appData.oldSaveStyle ? "pos" : "fen"),
5174 void ReloadCmailMsgProc(w, event, prms, nprms)
5180 ReloadCmailMsgEvent(FALSE);
5183 void MailMoveProc(w, event, prms, nprms)
5192 /* this variable is shared between CopyPositionProc and SendPositionSelection */
5193 static char *selected_fen_position=NULL;
5196 SendPositionSelection(Widget w, Atom *selection, Atom *target,
5197 Atom *type_return, XtPointer *value_return,
5198 unsigned long *length_return, int *format_return)
5200 char *selection_tmp;
5202 if (!selected_fen_position) return False; /* should never happen */
5203 if (*target == XA_STRING){
5204 /* note: since no XtSelectionDoneProc was registered, Xt will
5205 * automatically call XtFree on the value returned. So have to
5206 * make a copy of it allocated with XtMalloc */
5207 selection_tmp= XtMalloc(strlen(selected_fen_position)+16);
5208 strcpy(selection_tmp, selected_fen_position);
5210 *value_return=selection_tmp;
5211 *length_return=strlen(selection_tmp);
5212 *type_return=XA_STRING;
5213 *format_return = 8; /* bits per byte */
5220 /* note: when called from menu all parameters are NULL, so no clue what the
5221 * Widget which was clicked on was, or what the click event was
5223 void CopyPositionProc(w, event, prms, nprms)
5231 if (selected_fen_position) free(selected_fen_position);
5232 selected_fen_position = (char *)PositionToFEN(currentMove, NULL);
5233 if (!selected_fen_position) return;
5234 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
5236 SendPositionSelection,
5237 NULL/* lose_ownership_proc */ ,
5238 NULL/* transfer_done_proc */);
5240 free(selected_fen_position);
5241 selected_fen_position=NULL;
5245 /* function called when the data to Paste is ready */
5247 PastePositionCB(Widget w, XtPointer client_data, Atom *selection,
5248 Atom *type, XtPointer value, unsigned long *len, int *format)
5251 if (value==NULL || *len==0) return; /* nothing had been selected to copy */
5252 fenstr[*len]='\0'; /* normally this string is terminated, but be safe */
5253 EditPositionPasteFEN(fenstr);
5257 /* called when Paste Position button is pressed,
5258 * all parameters will be NULL */
5259 void PastePositionProc(w, event, prms, nprms)
5265 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
5266 /* (XtSelectionCallbackProc) */ PastePositionCB,
5267 NULL, /* client_data passed to PastePositionCB */
5269 /* better to use the time field from the event that triggered the
5270 * call to this function, but that isn't trivial to get
5278 SendGameSelection(Widget w, Atom *selection, Atom *target,
5279 Atom *type_return, XtPointer *value_return,
5280 unsigned long *length_return, int *format_return)
5282 char *selection_tmp;
5284 if (*target == XA_STRING){
5285 FILE* f = fopen(gameCopyFilename, "r");
5288 if (f == NULL) return False;
5292 selection_tmp = XtMalloc(len + 1);
5293 count = fread(selection_tmp, 1, len, f);
5295 XtFree(selection_tmp);
5298 selection_tmp[len] = NULLCHAR;
5299 *value_return = selection_tmp;
5300 *length_return = len;
5301 *type_return = XA_STRING;
5302 *format_return = 8; /* bits per byte */
5309 /* note: when called from menu all parameters are NULL, so no clue what the
5310 * Widget which was clicked on was, or what the click event was
5312 void CopyGameProc(w, event, prms, nprms)
5320 ret = SaveGameToFile(gameCopyFilename, FALSE);
5323 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
5326 NULL/* lose_ownership_proc */ ,
5327 NULL/* transfer_done_proc */);
5330 /* function called when the data to Paste is ready */
5332 PasteGameCB(Widget w, XtPointer client_data, Atom *selection,
5333 Atom *type, XtPointer value, unsigned long *len, int *format)
5336 if (value == NULL || *len == 0) {
5337 return; /* nothing had been selected to copy */
5339 f = fopen(gamePasteFilename, "w");
5341 DisplayError(_("Can't open temp file"), errno);
5344 fwrite(value, 1, *len, f);
5347 LoadGameFromFile(gamePasteFilename, 0, gamePasteFilename, TRUE);
5350 /* called when Paste Game button is pressed,
5351 * all parameters will be NULL */
5352 void PasteGameProc(w, event, prms, nprms)
5358 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
5359 /* (XtSelectionCallbackProc) */ PasteGameCB,
5360 NULL, /* client_data passed to PasteGameCB */
5362 /* better to use the time field from the event that triggered the
5363 * call to this function, but that isn't trivial to get
5373 SaveGameProc(NULL, NULL, NULL, NULL);
5376 void AnalyzeModeProc(w, event, prms, nprms)
5384 if (!first.analysisSupport) {
5385 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
5386 DisplayError(buf, 0);
5389 /* [DM] icsEngineAnalyze [HGM] This is horrible code; reverse the gameMode and isEngineAnalyze tests! */
5390 if (appData.icsActive) {
5391 if (gameMode != IcsObserving) {
5392 sprintf(buf,_("You are not observing a game"));
5393 DisplayError(buf, 0);
5395 if (appData.icsEngineAnalyze) {
5396 if (appData.debugMode)
5397 fprintf(debugFP, _("Found unexpected active ICS engine analyze \n"));
5403 /* if enable, use want disable icsEngineAnalyze */
5404 if (appData.icsEngineAnalyze) {
5409 appData.icsEngineAnalyze = TRUE;
5410 if (appData.debugMode)
5411 fprintf(debugFP, _("ICS engine analyze starting... \n"));
5413 if (!appData.showThinking)
5414 ShowThinkingProc(NULL,NULL);
5419 void AnalyzeFileProc(w, event, prms, nprms)
5425 if (!first.analysisSupport) {
5427 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
5428 DisplayError(buf, 0);
5433 if (!appData.showThinking)
5434 ShowThinkingProc(NULL,NULL);
5437 FileNamePopUp(_("File to analyze"), "", LoadGamePopUp, "rb");
5438 AnalysisPeriodicEvent(1);
5442 void EditGameProc(w, event, prms, nprms)
5451 void EditPositionProc(w, event, prms, nprms)
5457 EditPositionEvent();
5460 void TrainingProc(w, event, prms, nprms)
5469 void EditCommentProc(w, event, prms, nprms)
5476 EditCommentPopDown();
5482 void IcsInputBoxProc(w, event, prms, nprms)
5488 if (ICSInputBoxUp) {
5489 ICSInputBoxPopDown();
5496 void EnterKeyProc(w, event, prms, nprms)
5502 if (ICSInputBoxUp == True)
5506 void AlwaysQueenProc(w, event, prms, nprms)
5514 appData.alwaysPromoteToQueen = !appData.alwaysPromoteToQueen;
5516 if (appData.alwaysPromoteToQueen) {
5517 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5519 XtSetArg(args[0], XtNleftBitmap, None);
5521 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
5525 void AnimateDraggingProc(w, event, prms, nprms)
5533 appData.animateDragging = !appData.animateDragging;
5535 if (appData.animateDragging) {
5536 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5539 XtSetArg(args[0], XtNleftBitmap, None);
5541 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Dragging"),
5545 void AnimateMovingProc(w, event, prms, nprms)
5553 appData.animate = !appData.animate;
5555 if (appData.animate) {
5556 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5559 XtSetArg(args[0], XtNleftBitmap, None);
5561 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
5565 void AutocommProc(w, event, prms, nprms)
5573 appData.autoComment = !appData.autoComment;
5575 if (appData.autoComment) {
5576 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5578 XtSetArg(args[0], XtNleftBitmap, None);
5580 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
5585 void AutoflagProc(w, event, prms, nprms)
5593 appData.autoCallFlag = !appData.autoCallFlag;
5595 if (appData.autoCallFlag) {
5596 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5598 XtSetArg(args[0], XtNleftBitmap, None);
5600 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
5604 void AutoflipProc(w, event, prms, nprms)
5612 appData.autoFlipView = !appData.autoFlipView;
5614 if (appData.autoFlipView) {
5615 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5617 XtSetArg(args[0], XtNleftBitmap, None);
5619 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flip View"),
5623 void AutobsProc(w, event, prms, nprms)
5631 appData.autoObserve = !appData.autoObserve;
5633 if (appData.autoObserve) {
5634 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5636 XtSetArg(args[0], XtNleftBitmap, None);
5638 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
5642 void AutoraiseProc(w, event, prms, nprms)
5650 appData.autoRaiseBoard = !appData.autoRaiseBoard;
5652 if (appData.autoRaiseBoard) {
5653 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5655 XtSetArg(args[0], XtNleftBitmap, None);
5657 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Raise Board"),
5661 void AutosaveProc(w, event, prms, nprms)
5669 appData.autoSaveGames = !appData.autoSaveGames;
5671 if (appData.autoSaveGames) {
5672 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5674 XtSetArg(args[0], XtNleftBitmap, None);
5676 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
5680 void BlindfoldProc(w, event, prms, nprms)
5688 appData.blindfold = !appData.blindfold;
5690 if (appData.blindfold) {
5691 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5693 XtSetArg(args[0], XtNleftBitmap, None);
5695 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Blindfold"),
5698 DrawPosition(True, NULL);
5701 void TestLegalityProc(w, event, prms, nprms)
5709 appData.testLegality = !appData.testLegality;
5711 if (appData.testLegality) {
5712 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5714 XtSetArg(args[0], XtNleftBitmap, None);
5716 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Test Legality"),
5721 void FlashMovesProc(w, event, prms, nprms)
5729 if (appData.flashCount == 0) {
5730 appData.flashCount = 3;
5732 appData.flashCount = -appData.flashCount;
5735 if (appData.flashCount > 0) {
5736 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5738 XtSetArg(args[0], XtNleftBitmap, None);
5740 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flash Moves"),
5745 void HighlightDraggingProc(w, event, prms, nprms)
5753 appData.highlightDragging = !appData.highlightDragging;
5755 if (appData.highlightDragging) {
5756 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5758 XtSetArg(args[0], XtNleftBitmap, None);
5760 XtSetValues(XtNameToWidget(menuBarWidget,
5761 "menuOptions.Highlight Dragging"), args, 1);
5765 void HighlightLastMoveProc(w, event, prms, nprms)
5773 appData.highlightLastMove = !appData.highlightLastMove;
5775 if (appData.highlightLastMove) {
5776 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5778 XtSetArg(args[0], XtNleftBitmap, None);
5780 XtSetValues(XtNameToWidget(menuBarWidget,
5781 "menuOptions.Highlight Last Move"), args, 1);
5784 void IcsAlarmProc(w, event, prms, nprms)
5792 appData.icsAlarm = !appData.icsAlarm;
5794 if (appData.icsAlarm) {
5795 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5797 XtSetArg(args[0], XtNleftBitmap, None);
5799 XtSetValues(XtNameToWidget(menuBarWidget,
5800 "menuOptions.ICS Alarm"), args, 1);
5803 void MoveSoundProc(w, event, prms, nprms)
5811 appData.ringBellAfterMoves = !appData.ringBellAfterMoves;
5813 if (appData.ringBellAfterMoves) {
5814 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5816 XtSetArg(args[0], XtNleftBitmap, None);
5818 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
5823 void OldSaveStyleProc(w, event, prms, nprms)
5831 appData.oldSaveStyle = !appData.oldSaveStyle;
5833 if (appData.oldSaveStyle) {
5834 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5836 XtSetArg(args[0], XtNleftBitmap, None);
5838 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Old Save Style"),
5842 void PeriodicUpdatesProc(w, event, prms, nprms)
5850 PeriodicUpdatesEvent(!appData.periodicUpdates);
5852 if (appData.periodicUpdates) {
5853 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5855 XtSetArg(args[0], XtNleftBitmap, None);
5857 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Periodic Updates"),
5861 void PonderNextMoveProc(w, event, prms, nprms)
5869 PonderNextMoveEvent(!appData.ponderNextMove);
5871 if (appData.ponderNextMove) {
5872 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5874 XtSetArg(args[0], XtNleftBitmap, None);
5876 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Ponder Next Move"),
5880 void PopupExitMessageProc(w, event, prms, nprms)
5888 appData.popupExitMessage = !appData.popupExitMessage;
5890 if (appData.popupExitMessage) {
5891 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5893 XtSetArg(args[0], XtNleftBitmap, None);
5895 XtSetValues(XtNameToWidget(menuBarWidget,
5896 "menuOptions.Popup Exit Message"), args, 1);
5899 void PopupMoveErrorsProc(w, event, prms, nprms)
5907 appData.popupMoveErrors = !appData.popupMoveErrors;
5909 if (appData.popupMoveErrors) {
5910 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5912 XtSetArg(args[0], XtNleftBitmap, None);
5914 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Popup Move Errors"),
5918 void PremoveProc(w, event, prms, nprms)
5926 appData.premove = !appData.premove;
5928 if (appData.premove) {
5929 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5931 XtSetArg(args[0], XtNleftBitmap, None);
5933 XtSetValues(XtNameToWidget(menuBarWidget,
5934 "menuOptions.Premove"), args, 1);
5937 void QuietPlayProc(w, event, prms, nprms)
5945 appData.quietPlay = !appData.quietPlay;
5947 if (appData.quietPlay) {
5948 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5950 XtSetArg(args[0], XtNleftBitmap, None);
5952 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Quiet Play"),
5956 void DebugProc(w, event, prms, nprms)
5962 appData.debugMode = !appData.debugMode;
5965 void AboutGameProc(w, event, prms, nprms)
5974 void NothingProc(w, event, prms, nprms)
5983 void Iconify(w, event, prms, nprms)
5992 XtSetArg(args[0], XtNiconic, True);
5993 XtSetValues(shellWidget, args, 1);
5996 void DisplayMessage(message, extMessage)
5997 gchar *message, *extMessage;
6004 snprintf(buf, sizeof(buf), "%s %s", message, extMessage);
6007 message = extMessage;
6010 gtk_label_set_text( GTK_LABEL(gtk_builder_get_object (builder, "Messages")),message);
6015 void DisplayTitle(text)
6018 gchar title[MSG_SIZ];
6020 if (text == NULL) text = "";
6022 if (appData.titleInWindow)
6027 if (*text != NULLCHAR)
6029 strcpy(title, text);
6031 else if (appData.icsActive)
6033 snprintf(title, sizeof(title), "%s: %s", programName, appData.icsHost);
6035 else if (appData.cmailGameName[0] != NULLCHAR)
6037 snprintf(title,sizeof(title), "%s: %s", programName, "CMail");
6039 // [HGM] license: This stuff should really be done in back-end, but WinBoard already had a pop-up for it
6041 else if (gameInfo.variant == VariantGothic)
6043 strcpy(title, GOTHIC);
6047 else if (gameInfo.variant == VariantFalcon)
6049 strcpy(title, FALCON);
6052 else if (appData.noChessProgram)
6054 strcpy(title, programName);
6058 snprintf(title,sizeof(title), "%s: %s", programName, first.tidy);
6060 gtk_window_set_title(GTK_WINDOW(GUI_Window),title);
6066 void DisplayError(message, error)
6073 if (appData.debugMode || appData.matchMode) {
6074 fprintf(stderr, "%s: %s\n", programName, message);
6077 if (appData.debugMode || appData.matchMode) {
6078 fprintf(stderr, "%s: %s: %s\n",
6079 programName, message, strerror(error));
6081 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
6084 ErrorPopUp(_("Error"), message, FALSE);
6088 void DisplayMoveError(message)
6093 DrawPosition(FALSE, NULL);
6094 if (appData.debugMode || appData.matchMode) {
6095 fprintf(stderr, "%s: %s\n", programName, message);
6097 if (appData.popupMoveErrors) {
6098 ErrorPopUp(_("Error"), message, FALSE);
6100 DisplayMessage(message, "");
6105 void DisplayFatalError(message, error, status)
6111 errorExitStatus = status;
6113 fprintf(stderr, "%s: %s\n", programName, message);
6115 fprintf(stderr, "%s: %s: %s\n",
6116 programName, message, strerror(error));
6117 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
6120 if (appData.popupExitMessage && boardWidget && XtIsRealized(boardWidget)) {
6121 ErrorPopUp(status ? _("Fatal Error") : _("Exiting"), message, TRUE);
6127 void DisplayInformation(message)
6131 ErrorPopUp(_("Information"), message, TRUE);
6134 void DisplayNote(message)
6138 ErrorPopUp(_("Note"), message, FALSE);
6142 NullXErrorCheck(dpy, error_event)
6144 XErrorEvent *error_event;
6149 void DisplayIcsInteractionTitle(message)
6152 if (oldICSInteractionTitle == NULL) {
6153 /* Magic to find the old window title, adapted from vim */
6154 char *wina = getenv("WINDOWID");
6156 Window win = (Window) atoi(wina);
6157 Window root, parent, *children;
6158 unsigned int nchildren;
6159 int (*oldHandler)() = XSetErrorHandler(NullXErrorCheck);
6161 if (XFetchName(xDisplay, win, &oldICSInteractionTitle)) break;
6162 if (!XQueryTree(xDisplay, win, &root, &parent,
6163 &children, &nchildren)) break;
6164 if (children) XFree((void *)children);
6165 if (parent == root || parent == 0) break;
6168 XSetErrorHandler(oldHandler);
6170 if (oldICSInteractionTitle == NULL) {
6171 oldICSInteractionTitle = "xterm";
6174 printf("\033]0;%s\007", message);
6178 char pendingReplyPrefix[MSG_SIZ];
6179 ProcRef pendingReplyPR;
6181 void AskQuestionProc(w, event, prms, nprms)
6188 fprintf(stderr, _("AskQuestionProc needed 4 parameters, got %d\n"),
6192 AskQuestionEvent(prms[0], prms[1], prms[2], prms[3]);
6195 void AskQuestionPopDown()
6197 if (!askQuestionUp) return;
6198 XtPopdown(askQuestionShell);
6199 XtDestroyWidget(askQuestionShell);
6200 askQuestionUp = False;
6203 void AskQuestionReplyAction(w, event, prms, nprms)
6213 reply = XawDialogGetValueString(w = XtParent(w));
6214 strcpy(buf, pendingReplyPrefix);
6215 if (*buf) strcat(buf, " ");
6218 OutputToProcess(pendingReplyPR, buf, strlen(buf), &err);
6219 AskQuestionPopDown();
6221 if (err) DisplayFatalError(_("Error writing to chess program"), err, 0);
6224 void AskQuestionCallback(w, client_data, call_data)
6226 XtPointer client_data, call_data;
6231 XtSetArg(args[0], XtNlabel, &name);
6232 XtGetValues(w, args, 1);
6234 if (strcmp(name, _("cancel")) == 0) {
6235 AskQuestionPopDown();
6237 AskQuestionReplyAction(w, NULL, NULL, NULL);
6241 void AskQuestion(title, question, replyPrefix, pr)
6242 char *title, *question, *replyPrefix;
6246 Widget popup, layout, dialog, edit;
6252 strcpy(pendingReplyPrefix, replyPrefix);
6253 pendingReplyPR = pr;
6256 XtSetArg(args[i], XtNresizable, True); i++;
6257 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
6258 askQuestionShell = popup =
6259 XtCreatePopupShell(title, transientShellWidgetClass,
6260 shellWidget, args, i);
6263 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
6264 layoutArgs, XtNumber(layoutArgs));
6267 XtSetArg(args[i], XtNlabel, question); i++;
6268 XtSetArg(args[i], XtNvalue, ""); i++;
6269 XtSetArg(args[i], XtNborderWidth, 0); i++;
6270 dialog = XtCreateManagedWidget("question", dialogWidgetClass,
6273 XawDialogAddButton(dialog, _("enter"), AskQuestionCallback,
6274 (XtPointer) dialog);
6275 XawDialogAddButton(dialog, _("cancel"), AskQuestionCallback,
6276 (XtPointer) dialog);
6278 XtRealizeWidget(popup);
6279 CatchDeleteWindow(popup, "AskQuestionPopDown");
6281 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
6282 &x, &y, &win_x, &win_y, &mask);
6284 XtSetArg(args[0], XtNx, x - 10);
6285 XtSetArg(args[1], XtNy, y - 30);
6286 XtSetValues(popup, args, 2);
6288 XtPopup(popup, XtGrabExclusive);
6289 askQuestionUp = True;
6291 edit = XtNameToWidget(dialog, "*value");
6292 XtSetKeyboardFocus(popup, edit);
6300 if (*name == NULLCHAR) {
6302 } else if (strcmp(name, "$") == 0) {
6303 putc(BELLCHAR, stderr);
6306 snprintf(buf, sizeof(buf), "%s '%s' &", appData.soundProgram, name);
6314 PlaySound(appData.soundMove);
6320 PlaySound(appData.soundIcsWin);
6326 PlaySound(appData.soundIcsLoss);
6332 PlaySound(appData.soundIcsDraw);
6336 PlayIcsUnfinishedSound()
6338 PlaySound(appData.soundIcsUnfinished);
6344 PlaySound(appData.soundIcsAlarm);
6350 system("stty echo");
6356 system("stty -echo");
6360 Colorize(cc, continuation)
6365 int count, outCount, error;
6367 if (textColors[(int)cc].bg > 0) {
6368 if (textColors[(int)cc].fg > 0) {
6369 sprintf(buf, "\033[0;%d;%d;%dm", textColors[(int)cc].attr,
6370 textColors[(int)cc].fg, textColors[(int)cc].bg);
6372 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
6373 textColors[(int)cc].bg);
6376 if (textColors[(int)cc].fg > 0) {
6377 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
6378 textColors[(int)cc].fg);
6380 sprintf(buf, "\033[0;%dm", textColors[(int)cc].attr);
6383 count = strlen(buf);
6384 outCount = OutputToProcess(NoProc, buf, count, &error);
6385 if (outCount < count) {
6386 DisplayFatalError(_("Error writing to display"), error, 1);
6389 if (continuation) return;
6392 PlaySound(appData.soundShout);
6395 PlaySound(appData.soundSShout);
6398 PlaySound(appData.soundChannel1);
6401 PlaySound(appData.soundChannel);
6404 PlaySound(appData.soundKibitz);
6407 PlaySound(appData.soundTell);
6409 case ColorChallenge:
6410 PlaySound(appData.soundChallenge);
6413 PlaySound(appData.soundRequest);
6416 PlaySound(appData.soundSeek);
6427 return getpwuid(getuid())->pw_name;
6430 static char *ExpandPathName(path)
6433 static char static_buf[2000];
6434 char *d, *s, buf[2000];
6440 while (*s && isspace(*s))
6449 if (*(s+1) == '/') {
6450 strcpy(d, getpwuid(getuid())->pw_dir);
6455 *strchr(buf, '/') = 0;
6456 pwd = getpwnam(buf);
6459 fprintf(stderr, _("ERROR: Unknown user %s (in path %s)\n"),
6463 strcpy(d, pwd->pw_dir);
6464 strcat(d, strchr(s+1, '/'));
6475 static char host_name[MSG_SIZ];
6477 #if HAVE_GETHOSTNAME
6478 gethostname(host_name, MSG_SIZ);
6480 #else /* not HAVE_GETHOSTNAME */
6481 # if HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H
6482 sysinfo(SI_HOSTNAME, host_name, MSG_SIZ);
6484 # else /* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
6486 # endif/* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
6487 #endif /* not HAVE_GETHOSTNAME */
6490 guint delayedEventTimerTag = 0;
6491 DelayedEventCallback delayedEventCallback = 0;
6494 FireDelayedEvent(data)
6498 g_source_remove(delayedEventTimerTag);
6499 delayedEventTimerTag = 0;
6502 delayedEventCallback();
6508 ScheduleDelayedEvent(cb, millisec)
6509 DelayedEventCallback cb; guint millisec;
6511 if(delayedEventTimerTag && delayedEventCallback == cb)
6512 // [HGM] alive: replace, rather than add or flush identical event
6513 g_source_remove(delayedEventTimerTag);
6514 delayedEventCallback = cb;
6515 delayedEventTimerTag = g_timeout_add(millisec,(GSourceFunc) FireDelayedEvent, NULL);
6519 DelayedEventCallback
6522 if (delayedEventTimerTag)
6524 return delayedEventCallback;
6533 CancelDelayedEvent()
6535 if (delayedEventTimerTag)
6537 g_source_remove(delayedEventTimerTag);
6538 delayedEventTimerTag = 0;
6544 guint loadGameTimerTag = 0;
6546 int LoadGameTimerRunning()
6548 return loadGameTimerTag != 0;
6551 int StopLoadGameTimer()
6553 if (loadGameTimerTag != 0) {
6554 g_source_remove(loadGameTimerTag);
6555 loadGameTimerTag = 0;
6563 LoadGameTimerCallback(data)
6567 g_source_remove(loadGameTimerTag);
6568 loadGameTimerTag = 0;
6575 StartLoadGameTimer(millisec)
6579 g_timeout_add( millisec, (GSourceFunc) LoadGameTimerCallback, NULL);
6583 guint analysisClockTag = 0;
6586 AnalysisClockCallback(data)
6589 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile
6590 || appData.icsEngineAnalyze)
6592 AnalysisPeriodicEvent(0);
6593 return 1; /* keep on going */
6595 return 0; /* stop timer */
6599 StartAnalysisClock()
6602 g_timeout_add( 2000,(GSourceFunc) AnalysisClockCallback, NULL);
6606 guint clockTimerTag = 0;
6608 int ClockTimerRunning()
6610 return clockTimerTag != 0;
6613 int StopClockTimer()
6615 if (clockTimerTag != 0)
6617 g_source_remove(clockTimerTag);
6628 ClockTimerCallback(data)
6632 g_source_remove(clockTimerTag);
6640 StartClockTimer(millisec)
6643 clockTimerTag = g_timeout_add(millisec,(GSourceFunc) ClockTimerCallback,NULL);
6648 DisplayTimerLabel(w, color, timer, highlight)
6657 if (appData.clockMode) {
6658 sprintf(buf, "%s: %s", color, TimeString(timer));
6660 sprintf(buf, "%s ", color);
6662 gtk_label_set_text(GTK_LABEL(w),buf);
6664 /* check for low time warning */
6665 // Pixel foregroundOrWarningColor = timerForegroundPixel;
6668 // appData.lowTimeWarning &&
6669 // (timer / 1000) < appData.icsAlarmTime)
6670 // foregroundOrWarningColor = lowTimeWarningColor;
6672 // if (appData.clockMode) {
6673 // sprintf(buf, "%s: %s", color, TimeString(timer));
6674 // XtSetArg(args[0], XtNlabel, buf);
6676 // sprintf(buf, "%s ", color);
6677 // XtSetArg(args[0], XtNlabel, buf);
6682 // XtSetArg(args[1], XtNbackground, foregroundOrWarningColor);
6683 // XtSetArg(args[2], XtNforeground, timerBackgroundPixel);
6685 // XtSetArg(args[1], XtNbackground, timerBackgroundPixel);
6686 // XtSetArg(args[2], XtNforeground, foregroundOrWarningColor);
6689 // XtSetValues(w, args, 3);
6694 DisplayWhiteClock(timeRemaining, highlight)
6698 if(appData.noGUI) return;
6700 DisplayTimerLabel(GUI_Whiteclock, _("White"), timeRemaining, highlight);
6701 if (highlight && WindowIcon == BlackIcon)
6703 WindowIcon = WhiteIcon;
6704 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
6709 DisplayBlackClock(timeRemaining, highlight)
6713 if(appData.noGUI) return;
6715 DisplayTimerLabel(GUI_Blackclock, _("Black"), timeRemaining, highlight);
6716 if (highlight && WindowIcon == WhiteIcon)
6718 WindowIcon = BlackIcon;
6719 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
6737 int StartChildProcess(cmdLine, dir, pr)
6744 int to_prog[2], from_prog[2];
6748 if (appData.debugMode) {
6749 fprintf(stderr, "StartChildProcess (dir=\"%s\") %s\n",dir, cmdLine);
6752 /* We do NOT feed the cmdLine to the shell; we just
6753 parse it into blank-separated arguments in the
6754 most simple-minded way possible.
6757 strcpy(buf, cmdLine);
6762 if (p == NULL) break;
6767 SetUpChildIO(to_prog, from_prog);
6769 if ((pid = fork()) == 0) {
6771 // [HGM] PSWBTM: made order resistant against case where fd of created pipe was 0 or 1
6772 close(to_prog[1]); // first close the unused pipe ends
6773 close(from_prog[0]);
6774 dup2(to_prog[0], 0); // to_prog was created first, nd is the only one to use 0 or 1
6775 dup2(from_prog[1], 1);
6776 if(to_prog[0] >= 2) close(to_prog[0]); // if 0 or 1, the dup2 already cosed the original
6777 close(from_prog[1]); // and closing again loses one of the pipes!
6778 if(fileno(stderr) >= 2) // better safe than sorry...
6779 dup2(1, fileno(stderr)); /* force stderr to the pipe */
6781 if (dir[0] != NULLCHAR && chdir(dir) != 0) {
6786 nice(appData.niceEngines); // [HGM] nice: adjust priority of engine proc
6788 execvp(argv[0], argv);
6790 /* If we get here, exec failed */
6795 /* Parent process */
6797 close(from_prog[1]);
6799 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
6802 cp->fdFrom = from_prog[0];
6803 cp->fdTo = to_prog[1];
6808 // [HGM] kill: implement the 'hard killing' of AS's Winboard_x
6809 static RETSIGTYPE AlarmCallBack(int n)
6815 DestroyChildProcess(pr, signalType)
6819 ChildProc *cp = (ChildProc *) pr;
6821 if (cp->kind != CPReal) return;
6823 if (signalType == 10) { // [HGM] kill: if it does not terminate in 3 sec, kill
6824 signal(SIGALRM, AlarmCallBack);
6826 if(wait((int *) 0) == -1) { // process does not terminate on its own accord
6827 kill(cp->pid, SIGKILL); // kill it forcefully
6828 wait((int *) 0); // and wait again
6832 kill(cp->pid, signalType == 9 ? SIGKILL : SIGTERM); // [HGM] kill: use hard kill if so requested
6834 /* Process is exiting either because of the kill or because of
6835 a quit command sent by the backend; either way, wait for it to die.
6844 InterruptChildProcess(pr)
6847 ChildProc *cp = (ChildProc *) pr;
6849 if (cp->kind != CPReal) return;
6850 (void) kill(cp->pid, SIGINT); /* stop it thinking */
6853 int OpenTelnet(host, port, pr)
6858 char cmdLine[MSG_SIZ];
6860 if (port[0] == NULLCHAR) {
6861 snprintf(cmdLine, sizeof(cmdLine), "%s %s", appData.telnetProgram, host);
6863 snprintf(cmdLine, sizeof(cmdLine), "%s %s %s", appData.telnetProgram, host, port);
6865 return StartChildProcess(cmdLine, "", pr);
6868 int OpenTCP(host, port, pr)
6874 DisplayFatalError(_("Socket support is not configured in"), 0, 2);
6875 #else /* !OMIT_SOCKETS */
6877 struct sockaddr_in sa;
6879 unsigned short uport;
6882 if ((s = socket(AF_INET, SOCK_STREAM, 6)) < 0) {
6886 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
6887 sa.sin_family = AF_INET;
6888 sa.sin_addr.s_addr = INADDR_ANY;
6889 uport = (unsigned short) 0;
6890 sa.sin_port = htons(uport);
6891 if (bind(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)) < 0) {
6895 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
6896 if (!(hp = gethostbyname(host))) {
6898 if (sscanf(host, "%d.%d.%d.%d", &b0, &b1, &b2, &b3) == 4) {
6899 hp = (struct hostent *) calloc(1, sizeof(struct hostent));
6900 hp->h_addrtype = AF_INET;
6902 hp->h_addr_list = (char **) calloc(2, sizeof(char *));
6903 hp->h_addr_list[0] = (char *) malloc(4);
6904 hp->h_addr_list[0][0] = b0;
6905 hp->h_addr_list[0][1] = b1;
6906 hp->h_addr_list[0][2] = b2;
6907 hp->h_addr_list[0][3] = b3;
6912 sa.sin_family = hp->h_addrtype;
6913 uport = (unsigned short) atoi(port);
6914 sa.sin_port = htons(uport);
6915 memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);
6917 if (connect(s, (struct sockaddr *) &sa,
6918 sizeof(struct sockaddr_in)) < 0) {
6922 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
6929 #endif /* !OMIT_SOCKETS */
6934 int OpenCommPort(name, pr)
6941 fd = open(name, 2, 0);
6942 if (fd < 0) return errno;
6944 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
6954 int OpenLoopback(pr)
6960 SetUpChildIO(to, from);
6962 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
6965 cp->fdFrom = to[0]; /* note not from[0]; we are doing a loopback */
6972 int OpenRcmd(host, user, cmd, pr)
6973 char *host, *user, *cmd;
6976 DisplayFatalError(_("internal rcmd not implemented for Unix"), 0, 1);
6980 #define INPUT_SOURCE_BUF_SIZE 8192
6989 char buf[INPUT_SOURCE_BUF_SIZE];
6994 DoInputCallback(io,cond,data)
6999 /* read input from one of the input source (for example a chess program, ICS, etc).
7000 * and call a function that will handle the input
7003 int count; /* how many bytes did we read */
7007 /* All information (callback function, file descriptor, etc) is
7008 * saved in an InputSource structure
7010 InputSource *is = (InputSource *) data;
7014 count = read(is->fd, is->unused,
7015 INPUT_SOURCE_BUF_SIZE - (is->unused - is->buf));
7019 (is->func)(is, is->closure, is->buf, count, count ? errno : 0);
7022 is->unused += count;
7024 /* break input into lines and call the callback function on each
7027 while (p < is->unused)
7029 q = memchr(p, '\n', is->unused - p);
7030 if (q == NULL) break;
7032 (is->func)(is, is->closure, p, q - p, 0);
7035 /* remember not yet used part of the buffer */
7037 while (p < is->unused)
7045 /* read maximum length of input buffer and send the whole buffer
7046 * to the callback function
7048 count = read(is->fd, is->buf, INPUT_SOURCE_BUF_SIZE);
7053 (is->func)(is, is->closure, is->buf, count, error);
7059 InputSourceRef AddInputSource(pr, lineByLine, func, closure)
7066 GIOChannel *channel;
7067 ChildProc *cp = (ChildProc *) pr;
7069 is = (InputSource *) calloc(1, sizeof(InputSource));
7070 is->lineByLine = lineByLine;
7074 is->fd = fileno(stdin);
7076 is->kind = cp->kind;
7077 is->fd = cp->fdFrom;
7080 is->unused = is->buf;
7084 // is->xid = XtAppAddInput(appContext, is->fd,
7085 // (XtPointer) (XtInputReadMask),
7086 // (XtInputCallbackProc) DoInputCallback,
7090 /* TODO: will this work on windows?*/
7091 printf("DEBUG: fd=%d %d\n",is->fd,is);
7093 channel = g_io_channel_unix_new(is->fd);
7094 g_io_channel_set_close_on_unref (channel, TRUE);
7095 is->sid = g_io_add_watch(channel, G_IO_IN,(GIOFunc) DoInputCallback, is);
7096 is->closure = closure;
7097 return (InputSourceRef) is;
7101 RemoveInputSource(isr)
7104 InputSource *is = (InputSource *) isr;
7106 if (is->sid == 0) return;
7107 g_source_remove(is->sid);
7112 int OutputToProcess(pr, message, count, outError)
7118 ChildProc *cp = (ChildProc *) pr;
7122 outCount = fwrite(message, 1, count, stdout);
7124 outCount = write(cp->fdTo, message, count);
7134 /* Output message to process, with "ms" milliseconds of delay
7135 between each character. This is needed when sending the logon
7136 script to ICC, which for some reason doesn't like the
7137 instantaneous send. */
7138 int OutputToProcessDelayed(pr, message, count, outError, msdelay)
7145 ChildProc *cp = (ChildProc *) pr;
7150 r = write(cp->fdTo, message++, 1);
7163 /**** Animation code by Hugh Fisher, DCS, ANU.
7165 Known problem: if a window overlapping the board is
7166 moved away while a piece is being animated underneath,
7167 the newly exposed area won't be updated properly.
7168 I can live with this.
7170 Known problem: if you look carefully at the animation
7171 of pieces in mono mode, they are being drawn as solid
7172 shapes without interior detail while moving. Fixing
7173 this would be a major complication for minimal return.
7176 /* Masks for XPM pieces. Black and white pieces can have
7177 different shapes, but in the interest of retaining my
7178 sanity pieces must have the same outline on both light
7179 and dark squares, and all pieces must use the same
7180 background square colors/images. */
7182 static int xpmDone = 0;
7185 CreateAnimMasks (pieceDepth)
7192 unsigned long plane;
7195 /* just return for gtk at the moment */
7198 /* Need a bitmap just to get a GC with right depth */
7199 buf = XCreatePixmap(xDisplay, xBoardWindow,
7201 values.foreground = 1;
7202 values.background = 0;
7203 /* Don't use XtGetGC, not read only */
7204 maskGC = XCreateGC(xDisplay, buf,
7205 GCForeground | GCBackground, &values);
7206 XFreePixmap(xDisplay, buf);
7208 buf = XCreatePixmap(xDisplay, xBoardWindow,
7209 squareSize, squareSize, pieceDepth);
7210 values.foreground = XBlackPixel(xDisplay, xScreen);
7211 values.background = XWhitePixel(xDisplay, xScreen);
7212 bufGC = XCreateGC(xDisplay, buf,
7213 GCForeground | GCBackground, &values);
7215 for (piece = WhitePawn; piece <= BlackKing; piece++) {
7216 /* Begin with empty mask */
7217 if(!xpmDone) // [HGM] pieces: keep using existing
7218 xpmMask[piece] = XCreatePixmap(xDisplay, xBoardWindow,
7219 squareSize, squareSize, 1);
7220 XSetFunction(xDisplay, maskGC, GXclear);
7221 XFillRectangle(xDisplay, xpmMask[piece], maskGC,
7222 0, 0, squareSize, squareSize);
7224 /* Take a copy of the piece */
7229 XSetFunction(xDisplay, bufGC, GXcopy);
7230 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn],
7232 0, 0, squareSize, squareSize, 0, 0);
7234 /* XOR the background (light) over the piece */
7235 XSetFunction(xDisplay, bufGC, GXxor);
7237 XCopyArea(xDisplay, xpmLightSquare, buf, bufGC,
7238 0, 0, squareSize, squareSize, 0, 0);
7240 XSetForeground(xDisplay, bufGC, lightSquareColor);
7241 XFillRectangle(xDisplay, buf, bufGC, 0, 0, squareSize, squareSize);
7244 /* We now have an inverted piece image with the background
7245 erased. Construct mask by just selecting all the non-zero
7246 pixels - no need to reconstruct the original image. */
7247 XSetFunction(xDisplay, maskGC, GXor);
7249 /* Might be quicker to download an XImage and create bitmap
7250 data from it rather than this N copies per piece, but it
7251 only takes a fraction of a second and there is a much
7252 longer delay for loading the pieces. */
7253 for (n = 0; n < pieceDepth; n ++) {
7254 XCopyPlane(xDisplay, buf, xpmMask[piece], maskGC,
7255 0, 0, squareSize, squareSize,
7261 XFreePixmap(xDisplay, buf);
7262 XFreeGC(xDisplay, bufGC);
7263 XFreeGC(xDisplay, maskGC);
7267 InitAnimState (anim, info)
7269 XWindowAttributes * info;
7274 /* Each buffer is square size, same depth as window */
7275 // anim->saveBuf = XCreatePixmap(xDisplay, xBoardWindow,
7276 // squareSize, squareSize, info->depth);
7277 // anim->newBuf = XCreatePixmap(xDisplay, xBoardWindow,
7278 // squareSize, squareSize, info->depth);
7280 // /* Create a plain GC for blitting */
7281 // mask = GCForeground | GCBackground | GCFunction |
7282 // GCPlaneMask | GCGraphicsExposures;
7283 // values.foreground = XBlackPixel(xDisplay, xScreen);
7284 // values.background = XWhitePixel(xDisplay, xScreen);
7285 // values.function = GXcopy;
7286 // values.plane_mask = AllPlanes;
7287 // values.graphics_exposures = False;
7288 // anim->blitGC = XCreateGC(xDisplay, xBoardWindow, mask, &values);
7290 // /* Piece will be copied from an existing context at
7291 // the start of each new animation/drag. */
7292 // anim->pieceGC = XCreateGC(xDisplay, xBoardWindow, 0, &values);
7294 // /* Outline will be a read-only copy of an existing */
7295 // anim->outlineGC = None;
7301 static VariantClass old = (VariantClass) -1; // [HGM] pieces: redo every time variant changes
7302 XWindowAttributes info;
7304 /* for gtk at the moment just ... */
7307 if (xpmDone && gameInfo.variant == old) return;
7308 if(xpmDone) old = gameInfo.variant; // first time pieces might not be created yet
7309 // XGetWindowAttributes(xDisplay, xBoardWindow, &info);
7311 // InitAnimState(&game, &info);
7312 // InitAnimState(&player, &info);
7314 /* For XPM pieces, we need bitmaps to use as masks. */
7316 // CreateAnimMasks(info.depth);
7322 static Boolean frameWaiting;
7324 static RETSIGTYPE FrameAlarm (sig)
7327 frameWaiting = False;
7328 /* In case System-V style signals. Needed?? */
7329 signal(SIGALRM, FrameAlarm);
7336 struct itimerval delay;
7338 XSync(xDisplay, False);
7341 frameWaiting = True;
7342 signal(SIGALRM, FrameAlarm);
7343 delay.it_interval.tv_sec =
7344 delay.it_value.tv_sec = time / 1000;
7345 delay.it_interval.tv_usec =
7346 delay.it_value.tv_usec = (time % 1000) * 1000;
7347 setitimer(ITIMER_REAL, &delay, NULL);
7348 while (frameWaiting) pause();
7349 delay.it_interval.tv_sec = delay.it_value.tv_sec = 0;
7350 delay.it_interval.tv_usec = delay.it_value.tv_usec = 0;
7351 setitimer(ITIMER_REAL, &delay, NULL);
7361 // XSync(xDisplay, False);
7363 usleep(time * 1000);
7368 /* Convert board position to corner of screen rect and color */
7371 ScreenSquare(column, row, pt, color)
7372 int column; int row; XPoint * pt; int * color;
7375 pt->x = lineGap + ((BOARD_WIDTH-1)-column) * (squareSize + lineGap);
7376 pt->y = lineGap + row * (squareSize + lineGap);
7378 pt->x = lineGap + column * (squareSize + lineGap);
7379 pt->y = lineGap + ((BOARD_HEIGHT-1)-row) * (squareSize + lineGap);
7381 *color = SquareColor(row, column);
7384 /* Convert window coords to square */
7387 BoardSquare(x, y, column, row)
7388 int x; int y; int * column; int * row;
7390 *column = EventToSquare(x, BOARD_WIDTH);
7391 if (flipView && *column >= 0)
7392 *column = BOARD_WIDTH - 1 - *column;
7393 *row = EventToSquare(y, BOARD_HEIGHT);
7394 if (!flipView && *row >= 0)
7395 *row = BOARD_HEIGHT - 1 - *row;
7400 #undef Max /* just in case */
7402 #define Max(a, b) ((a) > (b) ? (a) : (b))
7403 #define Min(a, b) ((a) < (b) ? (a) : (b))
7406 SetRect(rect, x, y, width, height)
7407 XRectangle * rect; int x; int y; int width; int height;
7411 rect->width = width;
7412 rect->height = height;
7415 /* Test if two frames overlap. If they do, return
7416 intersection rect within old and location of
7417 that rect within new. */
7420 Intersect(old, new, size, area, pt)
7421 XPoint * old; XPoint * new;
7422 int size; XRectangle * area; XPoint * pt;
7424 if (old->x > new->x + size || new->x > old->x + size ||
7425 old->y > new->y + size || new->y > old->y + size) {
7428 SetRect(area, Max(new->x - old->x, 0), Max(new->y - old->y, 0),
7429 size - abs(old->x - new->x), size - abs(old->y - new->y));
7430 pt->x = Max(old->x - new->x, 0);
7431 pt->y = Max(old->y - new->y, 0);
7436 /* For two overlapping frames, return the rect(s)
7437 in the old that do not intersect with the new. */
7440 CalcUpdateRects(old, new, size, update, nUpdates)
7441 XPoint * old; XPoint * new; int size;
7442 XRectangle update[]; int * nUpdates;
7446 /* If old = new (shouldn't happen) then nothing to draw */
7447 if (old->x == new->x && old->y == new->y) {
7451 /* Work out what bits overlap. Since we know the rects
7452 are the same size we don't need a full intersect calc. */
7454 /* Top or bottom edge? */
7455 if (new->y > old->y) {
7456 SetRect(&(update[count]), old->x, old->y, size, new->y - old->y);
7458 } else if (old->y > new->y) {
7459 SetRect(&(update[count]), old->x, old->y + size - (old->y - new->y),
7460 size, old->y - new->y);
7463 /* Left or right edge - don't overlap any update calculated above. */
7464 if (new->x > old->x) {
7465 SetRect(&(update[count]), old->x, Max(new->y, old->y),
7466 new->x - old->x, size - abs(new->y - old->y));
7468 } else if (old->x > new->x) {
7469 SetRect(&(update[count]), new->x + size, Max(new->y, old->y),
7470 old->x - new->x, size - abs(new->y - old->y));
7477 /* Generate a series of frame coords from start->mid->finish.
7478 The movement rate doubles until the half way point is
7479 reached, then halves back down to the final destination,
7480 which gives a nice slow in/out effect. The algorithmn
7481 may seem to generate too many intermediates for short
7482 moves, but remember that the purpose is to attract the
7483 viewers attention to the piece about to be moved and
7484 then to where it ends up. Too few frames would be less
7488 Tween(start, mid, finish, factor, frames, nFrames)
7489 XPoint * start; XPoint * mid;
7490 XPoint * finish; int factor;
7491 XPoint frames[]; int * nFrames;
7493 int fraction, n, count;
7497 /* Slow in, stepping 1/16th, then 1/8th, ... */
7499 for (n = 0; n < factor; n++)
7501 for (n = 0; n < factor; n++) {
7502 frames[count].x = start->x + (mid->x - start->x) / fraction;
7503 frames[count].y = start->y + (mid->y - start->y) / fraction;
7505 fraction = fraction / 2;
7509 frames[count] = *mid;
7512 /* Slow out, stepping 1/2, then 1/4, ... */
7514 for (n = 0; n < factor; n++) {
7515 frames[count].x = finish->x - (finish->x - mid->x) / fraction;
7516 frames[count].y = finish->y - (finish->y - mid->y) / fraction;
7518 fraction = fraction * 2;
7523 /* Draw a piece on the screen without disturbing what's there */
7526 SelectGCMask(piece, clip, outline, mask)
7527 ChessSquare piece; GC * clip; GC * outline; Pixmap * mask;
7531 /* Bitmap for piece being moved. */
7532 if (appData.monoMode) {
7533 *mask = *pieceToSolid(piece);
7534 } else if (useImages) {
7536 *mask = xpmMask[piece];
7538 *mask = ximMaskPm[piece];
7541 *mask = *pieceToSolid(piece);
7544 /* GC for piece being moved. Square color doesn't matter, but
7545 since it gets modified we make a copy of the original. */
7547 if (appData.monoMode)
7552 if (appData.monoMode)
7557 // XCopyGC(xDisplay, source, 0xFFFFFFFF, *clip);
7559 /* Outline only used in mono mode and is not modified */
7561 *outline = bwPieceGC;
7563 *outline = wbPieceGC;
7567 OverlayPiece(piece, clip, outline, dest)
7568 ChessSquare piece; GC clip; GC outline; Drawable dest;
7573 /* Draw solid rectangle which will be clipped to shape of piece */
7574 // XFillRectangle(xDisplay, dest, clip,
7575 // 0, 0, squareSize, squareSize)
7577 if (appData.monoMode)
7578 /* Also draw outline in contrasting color for black
7579 on black / white on white cases */
7580 // XCopyPlane(xDisplay, *pieceToOutline(piece), dest, outline,
7581 // 0, 0, squareSize, squareSize, 0, 0, 1)
7584 /* Copy the piece */
7589 // XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
7591 // 0, 0, squareSize, squareSize,
7596 /* Animate the movement of a single piece */
7599 BeginAnimation(anim, piece, startColor, start)
7607 /* The old buffer is initialised with the start square (empty) */
7608 BlankSquare(0, 0, startColor, EmptySquare, anim->saveBuf);
7609 anim->prevFrame = *start;
7611 /* The piece will be drawn using its own bitmap as a matte */
7612 // SelectGCMask(piece, &anim->pieceGC, &anim->outlineGC, &mask);
7613 // XSetClipMask(xDisplay, anim->pieceGC, mask);
7617 AnimationFrame(anim, frame, piece)
7622 XRectangle updates[4];
7627 /* Save what we are about to draw into the new buffer */
7628 // XCopyArea(xDisplay, xBoardWindow, anim->newBuf, anim->blitGC,
7629 // frame->x, frame->y, squareSize, squareSize,
7632 /* Erase bits of the previous frame */
7633 if (Intersect(&anim->prevFrame, frame, squareSize, &overlap, &pt)) {
7634 /* Where the new frame overlapped the previous,
7635 the contents in newBuf are wrong. */
7636 // XCopyArea(xDisplay, anim->saveBuf, anim->newBuf, anim->blitGC,
7637 // overlap.x, overlap.y,
7638 // overlap.width, overlap.height,
7640 /* Repaint the areas in the old that don't overlap new */
7641 CalcUpdateRects(&anim->prevFrame, frame, squareSize, updates, &count);
7642 for (i = 0; i < count; i++)
7643 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
7644 // updates[i].x - anim->prevFrame.x,
7645 // updates[i].y - anim->prevFrame.y,
7646 // updates[i].width, updates[i].height,
7647 // updates[i].x, updates[i].y)
7650 /* Easy when no overlap */
7651 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
7652 // 0, 0, squareSize, squareSize,
7653 // anim->prevFrame.x, anim->prevFrame.y);
7656 /* Save this frame for next time round */
7657 // XCopyArea(xDisplay, anim->newBuf, anim->saveBuf, anim->blitGC,
7658 // 0, 0, squareSize, squareSize,
7660 anim->prevFrame = *frame;
7662 /* Draw piece over original screen contents, not current,
7663 and copy entire rect. Wipes out overlapping piece images. */
7664 OverlayPiece(piece, anim->pieceGC, anim->outlineGC, anim->newBuf);
7665 // XCopyArea(xDisplay, anim->newBuf, xBoardWindow, anim->blitGC,
7666 // 0, 0, squareSize, squareSize,
7667 // frame->x, frame->y);
7671 EndAnimation (anim, finish)
7675 XRectangle updates[4];
7680 /* The main code will redraw the final square, so we
7681 only need to erase the bits that don't overlap. */
7682 if (Intersect(&anim->prevFrame, finish, squareSize, &overlap, &pt)) {
7683 CalcUpdateRects(&anim->prevFrame, finish, squareSize, updates, &count);
7684 for (i = 0; i < count; i++)
7685 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
7686 // updates[i].x - anim->prevFrame.x,
7687 // updates[i].y - anim->prevFrame.y,
7688 // updates[i].width, updates[i].height,
7689 // updates[i].x, updates[i].y)
7692 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
7693 // 0, 0, squareSize, squareSize,
7694 // anim->prevFrame.x, anim->prevFrame.y);
7699 FrameSequence(anim, piece, startColor, start, finish, frames, nFrames)
7701 ChessSquare piece; int startColor;
7702 XPoint * start; XPoint * finish;
7703 XPoint frames[]; int nFrames;
7707 BeginAnimation(anim, piece, startColor, start);
7708 for (n = 0; n < nFrames; n++) {
7709 AnimationFrame(anim, &(frames[n]), piece);
7710 FrameDelay(appData.animSpeed);
7712 EndAnimation(anim, finish);
7715 /* Main control logic for deciding what to animate and how */
7718 AnimateMove(board, fromX, fromY, toX, toY)
7727 XPoint start, finish, mid;
7728 XPoint frames[kFactor * 2 + 1];
7729 int nFrames, startColor, endColor;
7731 /* Are we animating? */
7732 if (!appData.animate || appData.blindfold)
7735 if(board[toY][toX] == WhiteRook && board[fromY][fromX] == WhiteKing ||
7736 board[toY][toX] == BlackRook && board[fromY][fromX] == BlackKing)
7737 return; // [HGM] FRC: no animtion of FRC castlings, as to-square is not true to-square
7739 if (fromY < 0 || fromX < 0 || toX < 0 || toY < 0) return;
7740 piece = board[fromY][fromX];
7741 if (piece >= EmptySquare) return;
7746 hop = (piece == WhiteKnight || piece == BlackKnight);
7749 if (appData.debugMode) {
7750 fprintf(debugFP, hop ? _("AnimateMove: piece %d hops from %d,%d to %d,%d \n") :
7751 _("AnimateMove: piece %d slides from %d,%d to %d,%d \n"),
7752 piece, fromX, fromY, toX, toY); }
7754 ScreenSquare(fromX, fromY, &start, &startColor);
7755 ScreenSquare(toX, toY, &finish, &endColor);
7758 /* Knight: make diagonal movement then straight */
7759 if (abs(toY - fromY) < abs(toX - fromX)) {
7760 mid.x = start.x + (finish.x - start.x) / 2;
7764 mid.y = start.y + (finish.y - start.y) / 2;
7767 mid.x = start.x + (finish.x - start.x) / 2;
7768 mid.y = start.y + (finish.y - start.y) / 2;
7771 /* Don't use as many frames for very short moves */
7772 if (abs(toY - fromY) + abs(toX - fromX) <= 2)
7773 Tween(&start, &mid, &finish, kFactor - 1, frames, &nFrames);
7775 Tween(&start, &mid, &finish, kFactor, frames, &nFrames);
7776 FrameSequence(&game, piece, startColor, &start, &finish, frames, nFrames);
7778 /* Be sure end square is redrawn */
7779 damage[toY][toX] = True;
7783 DragPieceBegin(x, y)
7786 int boardX, boardY, color;
7789 /* Are we animating? */
7790 if (!appData.animateDragging || appData.blindfold)
7793 /* Figure out which square we start in and the
7794 mouse position relative to top left corner. */
7795 BoardSquare(x, y, &boardX, &boardY);
7796 player.startBoardX = boardX;
7797 player.startBoardY = boardY;
7798 ScreenSquare(boardX, boardY, &corner, &color);
7799 player.startSquare = corner;
7800 player.startColor = color;
7801 /* As soon as we start dragging, the piece will jump slightly to
7802 be centered over the mouse pointer. */
7803 player.mouseDelta.x = squareSize/2;
7804 player.mouseDelta.y = squareSize/2;
7805 /* Initialise animation */
7806 player.dragPiece = PieceForSquare(boardX, boardY);
7808 if (player.dragPiece >= 0 && player.dragPiece < EmptySquare) {
7809 player.dragActive = True;
7810 BeginAnimation(&player, player.dragPiece, color, &corner);
7811 /* Mark this square as needing to be redrawn. Note that
7812 we don't remove the piece though, since logically (ie
7813 as seen by opponent) the move hasn't been made yet. */
7814 if(boardX == BOARD_RGHT+1 && PieceForSquare(boardX-1, boardY) > 1 ||
7815 boardX == BOARD_LEFT-2 && PieceForSquare(boardX+1, boardY) > 1)
7816 // XCopyArea(xDisplay, xBoardWindow, player.saveBuf, player.blitGC,
7817 // corner.x, corner.y, squareSize, squareSize,
7818 // 0, 0); // [HGM] zh: unstack in stead of grab
7819 damage[boardY][boardX] = True;
7821 player.dragActive = False;
7831 /* Are we animating? */
7832 if (!appData.animateDragging || appData.blindfold)
7836 if (! player.dragActive)
7838 /* Move piece, maintaining same relative position
7839 of mouse within square */
7840 corner.x = x - player.mouseDelta.x;
7841 corner.y = y - player.mouseDelta.y;
7842 AnimationFrame(&player, &corner, player.dragPiece);
7844 if (appData.highlightDragging) {
7846 BoardSquare(x, y, &boardX, &boardY);
7847 SetHighlights(fromX, fromY, boardX, boardY);
7856 int boardX, boardY, color;
7859 /* Are we animating? */
7860 if (!appData.animateDragging || appData.blindfold)
7864 if (! player.dragActive)
7866 /* Last frame in sequence is square piece is
7867 placed on, which may not match mouse exactly. */
7868 BoardSquare(x, y, &boardX, &boardY);
7869 ScreenSquare(boardX, boardY, &corner, &color);
7870 EndAnimation(&player, &corner);
7872 /* Be sure end square is redrawn */
7873 damage[boardY][boardX] = True;
7875 /* This prevents weird things happening with fast successive
7876 clicks which on my Sun at least can cause motion events
7877 without corresponding press/release. */
7878 player.dragActive = False;
7881 /* Handle expose event while piece being dragged */
7886 if (!player.dragActive || appData.blindfold)
7889 /* What we're doing: logically, the move hasn't been made yet,
7890 so the piece is still in it's original square. But visually
7891 it's being dragged around the board. So we erase the square
7892 that the piece is on and draw it at the last known drag point. */
7893 BlankSquare(player.startSquare.x, player.startSquare.y,
7894 player.startColor, EmptySquare, xBoardWindow);
7895 AnimationFrame(&player, &player.prevFrame, player.dragPiece);
7896 damage[player.startBoardY][player.startBoardX] = TRUE;
7900 SetProgramStats( FrontEndProgramStats * stats )
7903 // [HGM] done, but perhaps backend should call this directly?
7904 EngineOutputUpdate( stats );