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 WhiteClock P((Widget w, XEvent *event,
266 String *prms, Cardinal *nprms));
267 void BlackClock P((Widget w, XEvent *event,
268 String *prms, Cardinal *nprms));
269 void CommentPopUp P((char *title, char *label));
270 void CommentPopDown P((void));
271 void CommentCallback P((Widget w, XtPointer client_data,
272 XtPointer call_data));
273 void ICSInputBoxPopUp P((void));
274 void ICSInputBoxPopDown P((void));
275 void FileNamePopUp P((char *label, char *def,
276 FileProc proc, char *openMode));
277 void FileNamePopDown P((void));
278 void FileNameCallback P((Widget w, XtPointer client_data,
279 XtPointer call_data));
280 void FileNameAction P((Widget w, XEvent *event,
281 String *prms, Cardinal *nprms));
282 void AskQuestionReplyAction P((Widget w, XEvent *event,
283 String *prms, Cardinal *nprms));
284 void AskQuestionProc P((Widget w, XEvent *event,
285 String *prms, Cardinal *nprms));
286 void AskQuestionPopDown P((void));
287 void PromotionPopUp P((void));
288 void PromotionPopDown P((void));
289 void PromotionCallback P((Widget w, XtPointer client_data,
290 XtPointer call_data));
291 void EditCommentPopDown P((void));
292 void EditCommentCallback P((Widget w, XtPointer client_data,
293 XtPointer call_data));
294 void SelectCommand P((Widget w, XtPointer client_data, XtPointer call_data));
295 void LoadPositionProc P((Widget w, XEvent *event,
296 String *prms, Cardinal *nprms));
297 void CopyPositionProc P((Widget w, XEvent *event, String *prms,
299 void PastePositionProc P((Widget w, XEvent *event, String *prms,
301 void CopyGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
302 void PasteGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
303 void SaveGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
304 void SavePositionProc P((Widget w, XEvent *event,
305 String *prms, Cardinal *nprms));
306 void MailMoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
307 void ReloadCmailMsgProc P((Widget w, XEvent *event, String *prms,
309 void AnalyzeModeProc P((Widget w, XEvent *event,
310 String *prms, Cardinal *nprms));
311 void AnalyzeFileProc P((Widget w, XEvent *event,
312 String *prms, Cardinal *nprms));
313 void EditGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
314 void EditPositionProc P((Widget w, XEvent *event,
315 String *prms, Cardinal *nprms));
316 void TrainingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
317 void EditCommentProc P((Widget w, XEvent *event,
318 String *prms, Cardinal *nprms));
319 void IcsInputBoxProc P((Widget w, XEvent *event,
320 String *prms, Cardinal *nprms));
321 void EnterKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
322 void AlwaysQueenProc P((Widget w, XEvent *event, String *prms,
324 void AnimateDraggingProc P((Widget w, XEvent *event, String *prms,
326 void AnimateMovingProc P((Widget w, XEvent *event, String *prms,
328 void AutocommProc P((Widget w, XEvent *event, String *prms,
330 void AutoflagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
331 void AutoflipProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
332 void AutobsProc P((Widget w, XEvent *event, String *prms,
334 void AutoraiseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
335 void AutosaveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
336 void BlindfoldProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
337 void FlashMovesProc P((Widget w, XEvent *event, String *prms,
339 void HighlightDraggingProc P((Widget w, XEvent *event, String *prms,
341 void HighlightLastMoveProc P((Widget w, XEvent *event, String *prms,
343 void MoveSoundProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
344 void IcsAlarmProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
345 void OldSaveStyleProc P((Widget w, XEvent *event, String *prms,
347 void PeriodicUpdatesProc P((Widget w, XEvent *event, String *prms,
349 void PonderNextMoveProc P((Widget w, XEvent *event, String *prms,
351 void PopupMoveErrorsProc P((Widget w, XEvent *event, String *prms,
353 void PopupExitMessageProc P((Widget w, XEvent *event, String *prms,
355 void PremoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
356 void QuietPlayProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
357 void TestLegalityProc P((Widget w, XEvent *event, String *prms,
359 void AboutGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
360 void DebugProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
361 void NothingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
362 void Iconify P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
363 void DisplayMove P((int moveNumber));
364 void DisplayTitle P((char *title));
365 void ICSInitScript P((void));
366 int LoadGamePopUp P((FILE *f, int gameNumber, char *title));
367 void ErrorPopUp P((char *title, char *text, int modal));
368 void ErrorPopDown P((void));
369 static char *ExpandPathName P((char *path));
370 static void CreateAnimVars P((void));
371 void DragPieceBegin P((int x, int y));
372 static void DragPieceMove P((int x, int y));
373 void DragPieceEnd P((int x, int y));
374 static void DrawDragPiece P((void));
375 char *ModeToWidgetName P((GameMode mode));
376 void EngineOutputUpdate( FrontEndProgramStats * stats );
377 void ShuffleMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
378 void EngineMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
379 void UciMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
380 void TimeControlProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
381 void NewVariantProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
382 void FirstSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
383 void SecondSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
384 void ShufflePopDown P(());
385 void EnginePopDown P(());
386 void UciPopDown P(());
387 void TimeControlPopDown P(());
388 void NewVariantPopDown P(());
389 void SettingsPopDown P(());
390 void SetMenuEnables P((Enables *enab));
393 * XBoard depends on Xt R4 or higher
395 int xtVersion = XtSpecificationRelease;
400 Pixel lightSquareColor, darkSquareColor, whitePieceColor, blackPieceColor,
401 jailSquareColor, highlightSquareColor, premoveHighlightColor;
402 Pixel lowTimeWarningColor;
404 #define LINE_TYPE_NORMAL 0
405 #define LINE_TYPE_HIGHLIGHT 1
406 #define LINE_TYPE_PRE 2
409 GC lightSquareGC, darkSquareGC, jailSquareGC, wdPieceGC, wlPieceGC,
410 bdPieceGC, blPieceGC, wbPieceGC, bwPieceGC, coordGC,
411 wjPieceGC, bjPieceGC;
412 Pixmap iconPixmap, wIconPixmap, bIconPixmap, xMarkPixmap;
413 Widget shellWidget, layoutWidget, formWidget, boardWidget, messageWidget,
414 whiteTimerWidget, blackTimerWidget, titleWidget, widgetList[16],
415 commentShell, promotionShell, whitePieceMenu, blackPieceMenu, dropMenu,
416 menuBarWidget, editShell, errorShell, analysisShell,
417 ICSInputShell, fileNameShell, askQuestionShell;
418 Font clockFontID, coordFontID, countFontID;
419 XFontStruct *clockFontStruct, *coordFontStruct, *countFontStruct;
420 XtAppContext appContext;
422 char *oldICSInteractionTitle;
426 char installDir[] = "."; // [HGM] UCI: needed for UCI; probably needs run-time initializtion
428 Position commentX = -1, commentY = -1;
429 Dimension commentW, commentH;
431 int squareSize, smallLayout = 0, tinyLayout = 0,
432 marginW, marginH, // [HGM] for run-time resizing
433 fromX = -1, fromY = -1, toX, toY, commentUp = False, analysisUp = False,
434 ICSInputBoxUp = False, askQuestionUp = False,
435 filenameUp = False, promotionUp = False, pmFromX = -1, pmFromY = -1,
436 editUp = False, errorUp = False, errorExitStatus = -1, lineGap;
437 Pixel timerForegroundPixel, timerBackgroundPixel;
438 Pixel buttonForegroundPixel, buttonBackgroundPixel;
439 char *chessDir, *programName, *programVersion,
440 *gameCopyFilename, *gamePasteFilename;
444 Pixmap pieceBitmap[2][(int)BlackPawn];
445 Pixmap pieceBitmap2[2][(int)BlackPawn+4]; /* [HGM] pieces */
446 Pixmap xpmPieceBitmap[4][(int)BlackPawn]; /* LL, LD, DL, DD actually used*/
447 Pixmap xpmPieceBitmap2[4][(int)BlackPawn+4]; /* LL, LD, DL, DD set to select from */
448 Pixmap xpmLightSquare, xpmDarkSquare, xpmJailSquare;
449 int useImages=0, useImageSqs;
450 XImage *ximPieceBitmap[4][(int)BlackPawn+4]; /* LL, LD, DL, DD */
451 Pixmap ximMaskPm[(int)BlackPawn]; /* clipmasks, used for XIM pieces */
452 Pixmap ximMaskPm2[(int)BlackPawn+4]; /* clipmasks, used for XIM pieces */
453 XImage *ximLightSquare, *ximDarkSquare;
456 #define pieceToSolid(piece) &pieceBitmap[SOLID][(piece) % (int)BlackPawn]
457 #define pieceToOutline(piece) &pieceBitmap[OUTLINE][(piece) % (int)BlackPawn]
459 #define White(piece) ((int)(piece) < (int)BlackPawn)
461 /* Variables for doing smooth animation. This whole thing
462 would be much easier if the board was double-buffered,
463 but that would require a fairly major rewrite. */
468 GC blitGC, pieceGC, outlineGC;
469 XPoint startSquare, prevFrame, mouseDelta;
473 int startBoardX, startBoardY;
476 /* There can be two pieces being animated at once: a player
477 can begin dragging a piece before the remote opponent has moved. */
479 static AnimState game, player;
481 /* Bitmaps for use as masks when drawing XPM pieces.
482 Need one for each black and white piece. */
483 static Pixmap xpmMask[BlackKing + 1];
485 /* This magic number is the number of intermediate frames used
486 in each half of the animation. For short moves it's reduced
487 by 1. The total number of frames will be factor * 2 + 1. */
490 SizeDefaults sizeDefaults[] = SIZE_DEFAULTS;
492 Enables icsEnables[] = {
493 { "menuFile.Mail Move", False },
494 { "menuFile.Reload CMail Message", False },
495 { "menuMode.Machine Black", False },
496 { "menuMode.Machine White", False },
497 { "menuMode.Analysis Mode", False },
498 { "menuMode.Analyze File", False },
499 { "menuMode.Two Machines", False },
501 { "menuHelp.Hint", False },
502 { "menuHelp.Book", False },
503 { "menuStep.Move Now", False },
504 { "menuOptions.Periodic Updates", False },
505 { "menuOptions.Hide Thinking", False },
506 { "menuOptions.Ponder Next Move", False },
511 Enables ncpEnables[] = {
512 { "menuFile.Mail Move", False },
513 { "menuFile.Reload CMail Message", False },
514 { "menuMode.Machine White", False },
515 { "menuMode.Machine Black", False },
516 { "menuMode.Analysis Mode", False },
517 { "menuMode.Analyze File", False },
518 { "menuMode.Two Machines", False },
519 { "menuMode.ICS Client", False },
520 { "menuMode.ICS Input Box", False },
522 { "menuStep.Revert", False },
523 { "menuStep.Move Now", False },
524 { "menuStep.Retract Move", False },
525 { "menuOptions.Auto Comment", False },
526 { "menuOptions.Auto Flag", False },
527 { "menuOptions.Auto Flip View", False },
528 { "menuOptions.Auto Observe", False },
529 { "menuOptions.Auto Raise Board", False },
530 { "menuOptions.Get Move List", False },
531 { "menuOptions.ICS Alarm", False },
532 { "menuOptions.Move Sound", False },
533 { "menuOptions.Quiet Play", False },
534 { "menuOptions.Hide Thinking", False },
535 { "menuOptions.Periodic Updates", False },
536 { "menuOptions.Ponder Next Move", False },
537 { "menuHelp.Hint", False },
538 { "menuHelp.Book", False },
542 Enables gnuEnables[] = {
543 { "menuMode.ICS Client", False },
544 { "menuMode.ICS Input Box", False },
545 { "menuAction.Accept", False },
546 { "menuAction.Decline", False },
547 { "menuAction.Rematch", False },
548 { "menuAction.Adjourn", False },
549 { "menuAction.Stop Examining", False },
550 { "menuAction.Stop Observing", False },
551 { "menuStep.Revert", False },
552 { "menuOptions.Auto Comment", False },
553 { "menuOptions.Auto Observe", False },
554 { "menuOptions.Auto Raise Board", False },
555 { "menuOptions.Get Move List", False },
556 { "menuOptions.Premove", False },
557 { "menuOptions.Quiet Play", False },
559 /* The next two options rely on SetCmailMode being called *after* */
560 /* SetGNUMode so that when GNU is being used to give hints these */
561 /* menu options are still available */
563 { "menuFile.Mail Move", False },
564 { "menuFile.Reload CMail Message", False },
568 Enables cmailEnables[] = {
570 { "menuAction.Call Flag", False },
571 { "menuAction.Draw", True },
572 { "menuAction.Adjourn", False },
573 { "menuAction.Abort", False },
574 { "menuAction.Stop Observing", False },
575 { "menuAction.Stop Examining", False },
576 { "menuFile.Mail Move", True },
577 { "menuFile.Reload CMail Message", True },
581 Enables trainingOnEnables[] = {
582 { "menuMode.Edit Comment", False },
583 { "menuMode.Pause", False },
584 { "menuStep.Forward", False },
585 { "menuStep.Backward", False },
586 { "menuStep.Forward to End", False },
587 { "menuStep.Back to Start", False },
588 { "menuStep.Move Now", False },
589 { "menuStep.Truncate Game", False },
593 Enables trainingOffEnables[] = {
594 { "menuMode.Edit Comment", True },
595 { "menuMode.Pause", True },
596 { "menuStep.Forward", True },
597 { "menuStep.Backward", True },
598 { "menuStep.Forward to End", True },
599 { "menuStep.Back to Start", True },
600 { "menuStep.Move Now", True },
601 { "menuStep.Truncate Game", True },
605 Enables machineThinkingEnables[] = {
606 { "menuFile.Load Game", False },
607 { "menuFile.Load Next Game", False },
608 { "menuFile.Load Previous Game", False },
609 { "menuFile.Reload Same Game", False },
610 { "menuFile.Paste Game", False },
611 { "menuFile.Load Position", False },
612 { "menuFile.Load Next Position", False },
613 { "menuFile.Load Previous Position", False },
614 { "menuFile.Reload Same Position", False },
615 { "menuFile.Paste Position", False },
616 { "menuMode.Machine White", False },
617 { "menuMode.Machine Black", False },
618 { "menuMode.Two Machines", False },
619 { "menuStep.Retract Move", False },
623 Enables userThinkingEnables[] = {
624 { "menuFile.Load Game", True },
625 { "menuFile.Load Next Game", True },
626 { "menuFile.Load Previous Game", True },
627 { "menuFile.Reload Same Game", True },
628 { "menuFile.Paste Game", True },
629 { "menuFile.Load Position", True },
630 { "menuFile.Load Next Position", True },
631 { "menuFile.Load Previous Position", True },
632 { "menuFile.Reload Same Position", True },
633 { "menuFile.Paste Position", True },
634 { "menuMode.Machine White", True },
635 { "menuMode.Machine Black", True },
636 { "menuMode.Two Machines", True },
637 { "menuStep.Retract Move", True },
643 MenuItem fileMenu[] = {
644 {N_("New Shuffle Game ..."), ShuffleMenuProc},
645 {N_("New Variant ..."), NewVariantProc}, // [HGM] variant: not functional yet
646 {"----", NothingProc},
647 {N_("Save Game"), SaveGameProc},
648 {"----", NothingProc},
649 {N_("Copy Game"), CopyGameProc},
650 {N_("Paste Game"), PasteGameProc},
651 {"----", NothingProc},
652 {N_("Load Position"), LoadPositionProc},
653 // {N_("Load Next Position"), LoadNextPositionProc},
654 // {N_("Load Previous Position"), LoadPrevPositionProc},
655 // {N_("Reload Same Position"), ReloadPositionProc},
656 {N_("Save Position"), SavePositionProc},
657 {"----", NothingProc},
658 {N_("Copy Position"), CopyPositionProc},
659 {N_("Paste Position"), PastePositionProc},
660 {"----", NothingProc},
661 {N_("Mail Move"), MailMoveProc},
662 {N_("Reload CMail Message"), ReloadCmailMsgProc},
663 {"----", NothingProc},
667 MenuItem modeMenu[] = {
668 // {N_("Machine White"), MachineWhiteProc},
669 // {N_("Machine Black"), MachineBlackProc},
670 // {N_("Two Machines"), TwoMachinesProc},
671 {N_("Analysis Mode"), AnalyzeModeProc},
672 {N_("Analyze File"), AnalyzeFileProc },
673 // {N_("ICS Client"), IcsClientProc},
674 {N_("Edit Game"), EditGameProc},
675 {N_("Edit Position"), EditPositionProc},
676 {N_("Training"), TrainingProc},
677 {"----", NothingProc},
678 {N_("Show Engine Output"), EngineOutputProc},
679 {N_("Show Evaluation Graph"), NothingProc}, // [HGM] evalgr: not functional yet
680 {N_("Show Game List"), ShowGameListProc},
681 // {"Show Move History", HistoryShowProc}, // [HGM] hist: activate 4.2.7 code
682 {"----", NothingProc},
683 {N_("Edit Tags"), EditTagsProc},
684 {N_("Edit Comment"), EditCommentProc},
685 {N_("ICS Input Box"), IcsInputBoxProc},
689 MenuItem optionsMenu[] = {
690 // {N_("Flip View"), FlipViewProc},
691 // {"----", NothingProc},
692 {N_("Adjudications ..."), EngineMenuProc},
693 {N_("General Settings ..."), UciMenuProc},
694 {N_("Engine #1 Settings ..."), FirstSettingsProc},
695 {N_("Engine #2 Settings ..."), SecondSettingsProc},
696 {N_("Time Control ..."), TimeControlProc},
697 {"----", NothingProc},
698 {N_("Always Queen"), AlwaysQueenProc},
699 {N_("Animate Dragging"), AnimateDraggingProc},
700 {N_("Animate Moving"), AnimateMovingProc},
701 {N_("Auto Comment"), AutocommProc},
702 {N_("Auto Flag"), AutoflagProc},
703 {N_("Auto Flip View"), AutoflipProc},
704 {N_("Auto Observe"), AutobsProc},
705 {N_("Auto Raise Board"), AutoraiseProc},
706 {N_("Auto Save"), AutosaveProc},
707 {N_("Blindfold"), BlindfoldProc},
708 {N_("Flash Moves"), FlashMovesProc},
709 // {N_("Get Move List"), GetMoveListProc},
711 {N_("Highlight Dragging"), HighlightDraggingProc},
713 {N_("Highlight Last Move"), HighlightLastMoveProc},
714 {N_("Move Sound"), MoveSoundProc},
715 {N_("ICS Alarm"), IcsAlarmProc},
716 {N_("Old Save Style"), OldSaveStyleProc},
717 {N_("Periodic Updates"), PeriodicUpdatesProc},
718 {N_("Ponder Next Move"), PonderNextMoveProc},
719 {N_("Popup Exit Message"), PopupExitMessageProc},
720 {N_("Popup Move Errors"), PopupMoveErrorsProc},
721 {N_("Premove"), PremoveProc},
722 {N_("Quiet Play"), QuietPlayProc},
723 // {N_("Hide Thinking"), HideThinkingProc},
724 {N_("Test Legality"), TestLegalityProc},
729 {N_("File"), fileMenu},
730 {N_("Mode"), modeMenu},
731 {N_("Options"), optionsMenu},
735 #define PIECE_MENU_SIZE 18
736 String pieceMenuStrings[2][PIECE_MENU_SIZE] = {
737 { N_("White"), "----", 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") },
741 { N_("Black"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
742 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
743 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
744 N_("Empty square"), N_("Clear board") }
746 /* must be in same order as PieceMenuStrings! */
747 ChessSquare pieceMenuTranslation[2][PIECE_MENU_SIZE] = {
748 { WhitePlay, (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
749 WhiteRook, WhiteQueen, WhiteKing, (ChessSquare) 0, WhiteAlfil,
750 WhiteCannon, WhiteAngel, WhiteMarshall, (ChessSquare) 0,
751 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
752 { BlackPlay, (ChessSquare) 0, BlackPawn, BlackKnight, BlackBishop,
753 BlackRook, BlackQueen, BlackKing, (ChessSquare) 0, BlackAlfil,
754 BlackCannon, BlackAngel, BlackMarshall, (ChessSquare) 0,
755 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
758 #define DROP_MENU_SIZE 6
759 String dropMenuStrings[DROP_MENU_SIZE] = {
760 "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"), N_("Queen")
762 /* must be in same order as PieceMenuStrings! */
763 ChessSquare dropMenuTranslation[DROP_MENU_SIZE] = {
764 (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
765 WhiteRook, WhiteQueen
773 DropMenuEnables dmEnables[] = {
782 { XtNborderWidth, 0 },
783 { XtNdefaultDistance, 0 },
787 { XtNborderWidth, 0 },
788 { XtNresizable, (XtArgVal) True },
792 { XtNborderWidth, 0 },
797 XtResource clientResources[] = {
798 { "whitePieceColor", "whitePieceColor", XtRString, sizeof(String),
799 XtOffset(AppDataPtr, whitePieceColor), XtRString,
801 { "blackPieceColor", "blackPieceColor", XtRString, sizeof(String),
802 XtOffset(AppDataPtr, blackPieceColor), XtRString,
804 { "lightSquareColor", "lightSquareColor", XtRString,
805 sizeof(String), XtOffset(AppDataPtr, lightSquareColor),
806 XtRString, LIGHT_SQUARE_COLOR },
807 { "darkSquareColor", "darkSquareColor", XtRString, sizeof(String),
808 XtOffset(AppDataPtr, darkSquareColor), XtRString,
810 { "highlightSquareColor", "highlightSquareColor", XtRString,
811 sizeof(String), XtOffset(AppDataPtr, highlightSquareColor),
812 XtRString, HIGHLIGHT_SQUARE_COLOR },
813 { "premoveHighlightColor", "premoveHighlightColor", XtRString,
814 sizeof(String), XtOffset(AppDataPtr, premoveHighlightColor),
815 XtRString, PREMOVE_HIGHLIGHT_COLOR },
816 { "movesPerSession", "movesPerSession", XtRInt, sizeof(int),
817 XtOffset(AppDataPtr, movesPerSession), XtRImmediate,
818 (XtPointer) MOVES_PER_SESSION },
819 { "timeIncrement", "timeIncrement", XtRInt, sizeof(int),
820 XtOffset(AppDataPtr, timeIncrement), XtRImmediate,
821 (XtPointer) TIME_INCREMENT },
822 { "initString", "initString", XtRString, sizeof(String),
823 XtOffset(AppDataPtr, initString), XtRString, INIT_STRING },
824 { "secondInitString", "secondInitString", XtRString, sizeof(String),
825 XtOffset(AppDataPtr, secondInitString), XtRString, INIT_STRING },
826 { "firstComputerString", "firstComputerString", XtRString,
827 sizeof(String), XtOffset(AppDataPtr, firstComputerString), XtRString,
829 { "secondComputerString", "secondComputerString", XtRString,
830 sizeof(String), XtOffset(AppDataPtr, secondComputerString), XtRString,
832 { "firstChessProgram", "firstChessProgram", XtRString,
833 sizeof(String), XtOffset(AppDataPtr, firstChessProgram),
834 XtRString, FIRST_CHESS_PROGRAM },
835 { "secondChessProgram", "secondChessProgram", XtRString,
836 sizeof(String), XtOffset(AppDataPtr, secondChessProgram),
837 XtRString, SECOND_CHESS_PROGRAM },
838 { "firstPlaysBlack", "firstPlaysBlack", XtRBoolean,
839 sizeof(Boolean), XtOffset(AppDataPtr, firstPlaysBlack),
840 XtRImmediate, (XtPointer) False },
841 { "noChessProgram", "noChessProgram", XtRBoolean,
842 sizeof(Boolean), XtOffset(AppDataPtr, noChessProgram),
843 XtRImmediate, (XtPointer) False },
844 { "firstHost", "firstHost", XtRString, sizeof(String),
845 XtOffset(AppDataPtr, firstHost), XtRString, FIRST_HOST },
846 { "secondHost", "secondHost", XtRString, sizeof(String),
847 XtOffset(AppDataPtr, secondHost), XtRString, SECOND_HOST },
848 { "firstDirectory", "firstDirectory", XtRString, sizeof(String),
849 XtOffset(AppDataPtr, firstDirectory), XtRString, "." },
850 { "secondDirectory", "secondDirectory", XtRString, sizeof(String),
851 XtOffset(AppDataPtr, secondDirectory), XtRString, "." },
852 { "bitmapDirectory", "bitmapDirectory", XtRString,
853 sizeof(String), XtOffset(AppDataPtr, bitmapDirectory),
855 { "remoteShell", "remoteShell", XtRString, sizeof(String),
856 XtOffset(AppDataPtr, remoteShell), XtRString, REMOTE_SHELL },
857 { "remoteUser", "remoteUser", XtRString, sizeof(String),
858 XtOffset(AppDataPtr, remoteUser), XtRString, "" },
859 { "timeDelay", "timeDelay", XtRFloat, sizeof(float),
860 XtOffset(AppDataPtr, timeDelay), XtRString,
861 (XtPointer) TIME_DELAY_QUOTE },
862 { "timeControl", "timeControl", XtRString, sizeof(String),
863 XtOffset(AppDataPtr, timeControl), XtRString,
864 (XtPointer) TIME_CONTROL },
865 { "internetChessServerMode", "internetChessServerMode",
866 XtRBoolean, sizeof(Boolean),
867 XtOffset(AppDataPtr, icsActive), XtRImmediate,
869 { "internetChessServerHost", "internetChessServerHost",
870 XtRString, sizeof(String),
871 XtOffset(AppDataPtr, icsHost),
872 XtRString, (XtPointer) ICS_HOST },
873 { "internetChessServerPort", "internetChessServerPort",
874 XtRString, sizeof(String),
875 XtOffset(AppDataPtr, icsPort), XtRString,
876 (XtPointer) ICS_PORT },
877 { "internetChessServerCommPort", "internetChessServerCommPort",
878 XtRString, sizeof(String),
879 XtOffset(AppDataPtr, icsCommPort), XtRString,
881 { "internetChessServerLogonScript", "internetChessServerLogonScript",
882 XtRString, sizeof(String),
883 XtOffset(AppDataPtr, icsLogon), XtRString,
885 { "internetChessServerHelper", "internetChessServerHelper",
886 XtRString, sizeof(String),
887 XtOffset(AppDataPtr, icsHelper), XtRString, "" },
888 { "internetChessServerInputBox", "internetChessServerInputBox",
889 XtRBoolean, sizeof(Boolean),
890 XtOffset(AppDataPtr, icsInputBox), XtRImmediate,
892 { "icsAlarm", "icsAlarm",
893 XtRBoolean, sizeof(Boolean),
894 XtOffset(AppDataPtr, icsAlarm), XtRImmediate,
896 { "icsAlarmTime", "icsAlarmTime",
898 XtOffset(AppDataPtr, icsAlarmTime), XtRImmediate,
900 { "useTelnet", "useTelnet", XtRBoolean, sizeof(Boolean),
901 XtOffset(AppDataPtr, useTelnet), XtRImmediate,
903 { "telnetProgram", "telnetProgram", XtRString, sizeof(String),
904 XtOffset(AppDataPtr, telnetProgram), XtRString, TELNET_PROGRAM },
905 { "gateway", "gateway", XtRString, sizeof(String),
906 XtOffset(AppDataPtr, gateway), XtRString, "" },
907 { "loadGameFile", "loadGameFile", XtRString, sizeof(String),
908 XtOffset(AppDataPtr, loadGameFile), XtRString, "" },
909 { "loadGameIndex", "loadGameIndex",
911 XtOffset(AppDataPtr, loadGameIndex), XtRImmediate,
913 { "saveGameFile", "saveGameFile", XtRString, sizeof(String),
914 XtOffset(AppDataPtr, saveGameFile), XtRString, "" },
915 { "autoRaiseBoard", "autoRaiseBoard", XtRBoolean,
916 sizeof(Boolean), XtOffset(AppDataPtr, autoRaiseBoard),
917 XtRImmediate, (XtPointer) True },
918 { "autoSaveGames", "autoSaveGames", XtRBoolean,
919 sizeof(Boolean), XtOffset(AppDataPtr, autoSaveGames),
920 XtRImmediate, (XtPointer) False },
921 { "blindfold", "blindfold", XtRBoolean,
922 sizeof(Boolean), XtOffset(AppDataPtr, blindfold),
923 XtRImmediate, (XtPointer) False },
924 { "loadPositionFile", "loadPositionFile", XtRString,
925 sizeof(String), XtOffset(AppDataPtr, loadPositionFile),
927 { "loadPositionIndex", "loadPositionIndex",
929 XtOffset(AppDataPtr, loadPositionIndex), XtRImmediate,
931 { "savePositionFile", "savePositionFile", XtRString,
932 sizeof(String), XtOffset(AppDataPtr, savePositionFile),
934 { "matchMode", "matchMode", XtRBoolean, sizeof(Boolean),
935 XtOffset(AppDataPtr, matchMode), XtRImmediate, (XtPointer) False },
936 { "matchGames", "matchGames", XtRInt, sizeof(int),
937 XtOffset(AppDataPtr, matchGames), XtRImmediate,
939 { "monoMode", "monoMode", XtRBoolean, sizeof(Boolean),
940 XtOffset(AppDataPtr, monoMode), XtRImmediate,
942 { "debugMode", "debugMode", XtRBoolean, sizeof(Boolean),
943 XtOffset(AppDataPtr, debugMode), XtRImmediate,
945 { "clockMode", "clockMode", XtRBoolean, sizeof(Boolean),
946 XtOffset(AppDataPtr, clockMode), XtRImmediate,
948 { "boardSize", "boardSize", XtRString, sizeof(String),
949 XtOffset(AppDataPtr, boardSize), XtRString, "" },
950 { "searchTime", "searchTime", XtRString, sizeof(String),
951 XtOffset(AppDataPtr, searchTime), XtRString,
953 { "searchDepth", "searchDepth", XtRInt, sizeof(int),
954 XtOffset(AppDataPtr, searchDepth), XtRImmediate,
956 { "showCoords", "showCoords", XtRBoolean, sizeof(Boolean),
957 XtOffset(AppDataPtr, showCoords), XtRImmediate,
959 { "showJail", "showJail", XtRInt, sizeof(int),
960 XtOffset(AppDataPtr, showJail), XtRImmediate,
962 { "showThinking", "showThinking", XtRBoolean, sizeof(Boolean),
963 XtOffset(AppDataPtr, showThinking), XtRImmediate,
965 { "ponderNextMove", "ponderNextMove", XtRBoolean, sizeof(Boolean),
966 XtOffset(AppDataPtr, ponderNextMove), XtRImmediate,
968 { "periodicUpdates", "periodicUpdates", XtRBoolean, sizeof(Boolean),
969 XtOffset(AppDataPtr, periodicUpdates), XtRImmediate,
971 { "clockFont", "clockFont", XtRString, sizeof(String),
972 XtOffset(AppDataPtr, clockFont), XtRString, CLOCK_FONT },
973 { "coordFont", "coordFont", XtRString, sizeof(String),
974 XtOffset(AppDataPtr, coordFont), XtRString, COORD_FONT },
975 { "font", "font", XtRString, sizeof(String),
976 XtOffset(AppDataPtr, font), XtRString, DEFAULT_FONT },
977 { "ringBellAfterMoves", "ringBellAfterMoves",
978 XtRBoolean, sizeof(Boolean),
979 XtOffset(AppDataPtr, ringBellAfterMoves),
980 XtRImmediate, (XtPointer) False },
981 { "autoCallFlag", "autoCallFlag", XtRBoolean,
982 sizeof(Boolean), XtOffset(AppDataPtr, autoCallFlag),
983 XtRImmediate, (XtPointer) False },
984 { "autoFlipView", "autoFlipView", XtRBoolean,
985 sizeof(Boolean), XtOffset(AppDataPtr, autoFlipView),
986 XtRImmediate, (XtPointer) True },
987 { "autoObserve", "autoObserve", XtRBoolean,
988 sizeof(Boolean), XtOffset(AppDataPtr, autoObserve),
989 XtRImmediate, (XtPointer) False },
990 { "autoComment", "autoComment", XtRBoolean,
991 sizeof(Boolean), XtOffset(AppDataPtr, autoComment),
992 XtRImmediate, (XtPointer) False },
993 { "getMoveList", "getMoveList", XtRBoolean,
994 sizeof(Boolean), XtOffset(AppDataPtr, getMoveList),
995 XtRImmediate, (XtPointer) True },
997 { "highlightDragging", "highlightDragging", XtRBoolean,
998 sizeof(Boolean), XtOffset(AppDataPtr, highlightDragging),
999 XtRImmediate, (XtPointer) False },
1001 { "highlightLastMove", "highlightLastMove", XtRBoolean,
1002 sizeof(Boolean), XtOffset(AppDataPtr, highlightLastMove),
1003 XtRImmediate, (XtPointer) False },
1004 { "premove", "premove", XtRBoolean,
1005 sizeof(Boolean), XtOffset(AppDataPtr, premove),
1006 XtRImmediate, (XtPointer) True },
1007 { "testLegality", "testLegality", XtRBoolean,
1008 sizeof(Boolean), XtOffset(AppDataPtr, testLegality),
1009 XtRImmediate, (XtPointer) True },
1010 { "flipView", "flipView", XtRBoolean,
1011 sizeof(Boolean), XtOffset(AppDataPtr, flipView),
1012 XtRImmediate, (XtPointer) False },
1013 { "cmail", "cmailGameName", XtRString, sizeof(String),
1014 XtOffset(AppDataPtr, cmailGameName), XtRString, "" },
1015 { "alwaysPromoteToQueen", "alwaysPromoteToQueen", XtRBoolean,
1016 sizeof(Boolean), XtOffset(AppDataPtr, alwaysPromoteToQueen),
1017 XtRImmediate, (XtPointer) False },
1018 { "oldSaveStyle", "oldSaveStyle", XtRBoolean,
1019 sizeof(Boolean), XtOffset(AppDataPtr, oldSaveStyle),
1020 XtRImmediate, (XtPointer) False },
1021 { "quietPlay", "quietPlay", XtRBoolean,
1022 sizeof(Boolean), XtOffset(AppDataPtr, quietPlay),
1023 XtRImmediate, (XtPointer) False },
1024 { "titleInWindow", "titleInWindow", XtRBoolean,
1025 sizeof(Boolean), XtOffset(AppDataPtr, titleInWindow),
1026 XtRImmediate, (XtPointer) False },
1027 { "localLineEditing", "localLineEditing", XtRBoolean,
1028 sizeof(Boolean), XtOffset(AppDataPtr, localLineEditing),
1029 XtRImmediate, (XtPointer) True }, /* not implemented, must be True */
1031 { "zippyTalk", "zippyTalk", XtRBoolean,
1032 sizeof(Boolean), XtOffset(AppDataPtr, zippyTalk),
1033 XtRImmediate, (XtPointer) ZIPPY_TALK },
1034 { "zippyPlay", "zippyPlay", XtRBoolean,
1035 sizeof(Boolean), XtOffset(AppDataPtr, zippyPlay),
1036 XtRImmediate, (XtPointer) ZIPPY_PLAY },
1037 { "zippyLines", "zippyLines", XtRString, sizeof(String),
1038 XtOffset(AppDataPtr, zippyLines), XtRString, ZIPPY_LINES },
1039 { "zippyPinhead", "zippyPinhead", XtRString, sizeof(String),
1040 XtOffset(AppDataPtr, zippyPinhead), XtRString, ZIPPY_PINHEAD },
1041 { "zippyPassword", "zippyPassword", XtRString, sizeof(String),
1042 XtOffset(AppDataPtr, zippyPassword), XtRString, ZIPPY_PASSWORD },
1043 { "zippyPassword2", "zippyPassword2", XtRString, sizeof(String),
1044 XtOffset(AppDataPtr, zippyPassword2), XtRString, ZIPPY_PASSWORD2 },
1045 { "zippyWrongPassword", "zippyWrongPassword", XtRString, sizeof(String),
1046 XtOffset(AppDataPtr, zippyWrongPassword), XtRString,
1047 ZIPPY_WRONG_PASSWORD },
1048 { "zippyAcceptOnly", "zippyAcceptOnly", XtRString, sizeof(String),
1049 XtOffset(AppDataPtr, zippyAcceptOnly), XtRString, ZIPPY_ACCEPT_ONLY },
1050 { "zippyUseI", "zippyUseI", XtRBoolean,
1051 sizeof(Boolean), XtOffset(AppDataPtr, zippyUseI),
1052 XtRImmediate, (XtPointer) ZIPPY_USE_I },
1053 { "zippyBughouse", "zippyBughouse", XtRInt,
1054 sizeof(int), XtOffset(AppDataPtr, zippyBughouse),
1055 XtRImmediate, (XtPointer) ZIPPY_BUGHOUSE },
1056 { "zippyNoplayCrafty", "zippyNoplayCrafty", XtRBoolean,
1057 sizeof(Boolean), XtOffset(AppDataPtr, zippyNoplayCrafty),
1058 XtRImmediate, (XtPointer) ZIPPY_NOPLAY_CRAFTY },
1059 { "zippyGameEnd", "zippyGameEnd", XtRString, sizeof(String),
1060 XtOffset(AppDataPtr, zippyGameEnd), XtRString, ZIPPY_GAME_END },
1061 { "zippyGameStart", "zippyGameStart", XtRString, sizeof(String),
1062 XtOffset(AppDataPtr, zippyGameStart), XtRString, ZIPPY_GAME_START },
1063 { "zippyAdjourn", "zippyAdjourn", XtRBoolean,
1064 sizeof(Boolean), XtOffset(AppDataPtr, zippyAdjourn),
1065 XtRImmediate, (XtPointer) ZIPPY_ADJOURN },
1066 { "zippyAbort", "zippyAbort", XtRBoolean,
1067 sizeof(Boolean), XtOffset(AppDataPtr, zippyAbort),
1068 XtRImmediate, (XtPointer) ZIPPY_ABORT },
1069 { "zippyVariants", "zippyVariants", XtRString, sizeof(String),
1070 XtOffset(AppDataPtr, zippyVariants), XtRString, ZIPPY_VARIANTS },
1071 { "zippyMaxGames", "zippyMaxGames", XtRInt, sizeof(int),
1072 XtOffset(AppDataPtr, zippyMaxGames), XtRImmediate,
1073 (XtPointer) ZIPPY_MAX_GAMES },
1074 { "zippyReplayTimeout", "zippyReplayTimeout", XtRInt, sizeof(int),
1075 XtOffset(AppDataPtr, zippyReplayTimeout), XtRImmediate,
1076 (XtPointer) ZIPPY_REPLAY_TIMEOUT },
1077 { "zippyShortGame", "zippyShortGame", XtRInt, sizeof(int),
1078 XtOffset(AppDataPtr, zippyShortGame), XtRImmediate,
1081 { "flashCount", "flashCount", XtRInt, sizeof(int),
1082 XtOffset(AppDataPtr, flashCount), XtRImmediate,
1083 (XtPointer) FLASH_COUNT },
1084 { "flashRate", "flashRate", XtRInt, sizeof(int),
1085 XtOffset(AppDataPtr, flashRate), XtRImmediate,
1086 (XtPointer) FLASH_RATE },
1087 { "pixmapDirectory", "pixmapDirectory", XtRString,
1088 sizeof(String), XtOffset(AppDataPtr, pixmapDirectory),
1090 { "msLoginDelay", "msLoginDelay", XtRInt, sizeof(int),
1091 XtOffset(AppDataPtr, msLoginDelay), XtRImmediate,
1092 (XtPointer) MS_LOGIN_DELAY },
1093 { "colorizeMessages", "colorizeMessages", XtRBoolean,
1094 sizeof(Boolean), XtOffset(AppDataPtr, colorize),
1095 XtRImmediate, (XtPointer) False },
1096 { "colorShout", "colorShout", XtRString,
1097 sizeof(String), XtOffset(AppDataPtr, colorShout),
1098 XtRString, COLOR_SHOUT },
1099 { "colorSShout", "colorSShout", XtRString,
1100 sizeof(String), XtOffset(AppDataPtr, colorSShout),
1101 XtRString, COLOR_SSHOUT },
1102 { "colorChannel1", "colorChannel1", XtRString,
1103 sizeof(String), XtOffset(AppDataPtr, colorChannel1),
1104 XtRString, COLOR_CHANNEL1 },
1105 { "colorChannel", "colorChannel", XtRString,
1106 sizeof(String), XtOffset(AppDataPtr, colorChannel),
1107 XtRString, COLOR_CHANNEL },
1108 { "colorKibitz", "colorKibitz", XtRString,
1109 sizeof(String), XtOffset(AppDataPtr, colorKibitz),
1110 XtRString, COLOR_KIBITZ },
1111 { "colorTell", "colorTell", XtRString,
1112 sizeof(String), XtOffset(AppDataPtr, colorTell),
1113 XtRString, COLOR_TELL },
1114 { "colorChallenge", "colorChallenge", XtRString,
1115 sizeof(String), XtOffset(AppDataPtr, colorChallenge),
1116 XtRString, COLOR_CHALLENGE },
1117 { "colorRequest", "colorRequest", XtRString,
1118 sizeof(String), XtOffset(AppDataPtr, colorRequest),
1119 XtRString, COLOR_REQUEST },
1120 { "colorSeek", "colorSeek", XtRString,
1121 sizeof(String), XtOffset(AppDataPtr, colorSeek),
1122 XtRString, COLOR_SEEK },
1123 { "colorNormal", "colorNormal", XtRString,
1124 sizeof(String), XtOffset(AppDataPtr, colorNormal),
1125 XtRString, COLOR_NORMAL },
1126 { "soundProgram", "soundProgram", XtRString,
1127 sizeof(String), XtOffset(AppDataPtr, soundProgram),
1128 XtRString, "play" },
1129 { "soundShout", "soundShout", XtRString,
1130 sizeof(String), XtOffset(AppDataPtr, soundShout),
1132 { "soundSShout", "soundSShout", XtRString,
1133 sizeof(String), XtOffset(AppDataPtr, soundSShout),
1135 { "soundChannel1", "soundChannel1", XtRString,
1136 sizeof(String), XtOffset(AppDataPtr, soundChannel1),
1138 { "soundChannel", "soundChannel", XtRString,
1139 sizeof(String), XtOffset(AppDataPtr, soundChannel),
1141 { "soundKibitz", "soundKibitz", XtRString,
1142 sizeof(String), XtOffset(AppDataPtr, soundKibitz),
1144 { "soundTell", "soundTell", XtRString,
1145 sizeof(String), XtOffset(AppDataPtr, soundTell),
1147 { "soundChallenge", "soundChallenge", XtRString,
1148 sizeof(String), XtOffset(AppDataPtr, soundChallenge),
1150 { "soundRequest", "soundRequest", XtRString,
1151 sizeof(String), XtOffset(AppDataPtr, soundRequest),
1153 { "soundSeek", "soundSeek", XtRString,
1154 sizeof(String), XtOffset(AppDataPtr, soundSeek),
1156 { "soundMove", "soundMove", XtRString,
1157 sizeof(String), XtOffset(AppDataPtr, soundMove),
1159 { "soundIcsWin", "soundIcsWin", XtRString,
1160 sizeof(String), XtOffset(AppDataPtr, soundIcsWin),
1162 { "soundIcsLoss", "soundIcsLoss", XtRString,
1163 sizeof(String), XtOffset(AppDataPtr, soundIcsLoss),
1165 { "soundIcsDraw", "soundIcsDraw", XtRString,
1166 sizeof(String), XtOffset(AppDataPtr, soundIcsDraw),
1168 { "soundIcsUnfinished", "soundIcsUnfinished", XtRString,
1169 sizeof(String), XtOffset(AppDataPtr, soundIcsUnfinished),
1171 { "soundIcsAlarm", "soundIcsAlarm", XtRString,
1172 sizeof(String), XtOffset(AppDataPtr, soundIcsAlarm),
1174 { "reuseFirst", "reuseFirst", XtRBoolean,
1175 sizeof(Boolean), XtOffset(AppDataPtr, reuseFirst),
1176 XtRImmediate, (XtPointer) True },
1177 { "reuseSecond", "reuseSecond", XtRBoolean,
1178 sizeof(Boolean), XtOffset(AppDataPtr, reuseSecond),
1179 XtRImmediate, (XtPointer) True },
1180 { "animateDragging", "animateDragging", XtRBoolean,
1181 sizeof(Boolean), XtOffset(AppDataPtr, animateDragging),
1182 XtRImmediate, (XtPointer) True },
1183 { "animateMoving", "animateMoving", XtRBoolean,
1184 sizeof(Boolean), XtOffset(AppDataPtr, animate),
1185 XtRImmediate, (XtPointer) True },
1186 { "animateSpeed", "animateSpeed", XtRInt,
1187 sizeof(int), XtOffset(AppDataPtr, animSpeed),
1188 XtRImmediate, (XtPointer)10 },
1189 { "popupExitMessage", "popupExitMessage", XtRBoolean,
1190 sizeof(Boolean), XtOffset(AppDataPtr, popupExitMessage),
1191 XtRImmediate, (XtPointer) True },
1192 { "popupMoveErrors", "popupMoveErrors", XtRBoolean,
1193 sizeof(Boolean), XtOffset(AppDataPtr, popupMoveErrors),
1194 XtRImmediate, (XtPointer) False },
1195 { "fontSizeTolerance", "fontSizeTolerance", XtRInt,
1196 sizeof(int), XtOffset(AppDataPtr, fontSizeTolerance),
1197 XtRImmediate, (XtPointer)4 },
1198 { "initialMode", "initialMode", XtRString,
1199 sizeof(String), XtOffset(AppDataPtr, initialMode),
1200 XtRImmediate, (XtPointer) "" },
1201 { "variant", "variant", XtRString,
1202 sizeof(String), XtOffset(AppDataPtr, variant),
1203 XtRImmediate, (XtPointer) "normal" },
1204 { "firstProtocolVersion", "firstProtocolVersion", XtRInt,
1205 sizeof(int), XtOffset(AppDataPtr, firstProtocolVersion),
1206 XtRImmediate, (XtPointer)PROTOVER },
1207 { "secondProtocolVersion", "secondProtocolVersion", XtRInt,
1208 sizeof(int), XtOffset(AppDataPtr, secondProtocolVersion),
1209 XtRImmediate, (XtPointer)PROTOVER },
1210 { "showButtonBar", "showButtonBar", XtRBoolean,
1211 sizeof(Boolean), XtOffset(AppDataPtr, showButtonBar),
1212 XtRImmediate, (XtPointer) True },
1213 { "lowTimeWarningColor", "lowTimeWarningColor", XtRString,
1214 sizeof(String), XtOffset(AppDataPtr, lowTimeWarningColor),
1215 XtRString, COLOR_LOWTIMEWARNING },
1216 { "lowTimeWarning", "lowTimeWarning", XtRBoolean,
1217 sizeof(Boolean), XtOffset(AppDataPtr, lowTimeWarning),
1218 XtRImmediate, (XtPointer) False },
1219 {"icsEngineAnalyze", "icsEngineAnalyze", XtRBoolean, /* [DM] icsEngineAnalyze */
1220 sizeof(Boolean), XtOffset(AppDataPtr, icsEngineAnalyze),
1221 XtRImmediate, (XtPointer) False },
1222 { "firstScoreAbs", "firstScoreAbs", XtRBoolean,
1223 sizeof(Boolean), XtOffset(AppDataPtr, firstScoreIsAbsolute),
1224 XtRImmediate, (XtPointer) False },
1225 { "secondScoreAbs", "secondScoreAbs", XtRBoolean,
1226 sizeof(Boolean), XtOffset(AppDataPtr, secondScoreIsAbsolute),
1227 XtRImmediate, (XtPointer) False },
1228 { "pgnExtendedInfo", "pgnExtendedInfo", XtRBoolean,
1229 sizeof(Boolean), XtOffset(AppDataPtr, saveExtendedInfoInPGN),
1230 XtRImmediate, (XtPointer) False },
1231 { "hideThinkingFromHuman", "hideThinkingFromHuman", XtRBoolean,
1232 sizeof(Boolean), XtOffset(AppDataPtr, hideThinkingFromHuman),
1233 XtRImmediate, (XtPointer) True },
1234 { "adjudicateLossThreshold", "adjudicateLossThreshold", XtRInt,
1235 sizeof(int), XtOffset(AppDataPtr, adjudicateLossThreshold),
1236 XtRImmediate, (XtPointer) 0},
1237 { "adjudicateDrawMoves", "adjudicateDrawMoves", XtRInt,
1238 sizeof(int), XtOffset(AppDataPtr, adjudicateDrawMoves),
1239 XtRImmediate, (XtPointer) 0},
1240 { "pgnEventHeader", "pgnEventHeader", XtRString,
1241 sizeof(String), XtOffset(AppDataPtr, pgnEventHeader),
1242 XtRImmediate, (XtPointer) "Computer Chess Game" },
1243 { "defaultFrcPosition", "defaultFrcPositon", XtRInt,
1244 sizeof(int), XtOffset(AppDataPtr, defaultFrcPosition),
1245 XtRImmediate, (XtPointer) -1},
1246 { "gameListTags", "gameListTags", XtRString,
1247 sizeof(String), XtOffset(AppDataPtr, gameListTags),
1248 XtRImmediate, (XtPointer) GLT_DEFAULT_TAGS },
1250 // [HGM] 4.3.xx options
1251 { "boardWidth", "boardWidth", XtRInt,
1252 sizeof(int), XtOffset(AppDataPtr, NrFiles),
1253 XtRImmediate, (XtPointer) -1},
1254 { "boardHeight", "boardHeight", XtRInt,
1255 sizeof(int), XtOffset(AppDataPtr, NrRanks),
1256 XtRImmediate, (XtPointer) -1},
1257 { "matchPause", "matchPause", XtRInt,
1258 sizeof(int), XtOffset(AppDataPtr, matchPause),
1259 XtRImmediate, (XtPointer) 10000},
1260 { "holdingsSize", "holdingsSize", XtRInt,
1261 sizeof(int), XtOffset(AppDataPtr, holdingsSize),
1262 XtRImmediate, (XtPointer) -1},
1263 { "flipBlack", "flipBlack", XtRBoolean,
1264 sizeof(Boolean), XtOffset(AppDataPtr, upsideDown),
1265 XtRImmediate, (XtPointer) False},
1266 { "allWhite", "allWhite", XtRBoolean,
1267 sizeof(Boolean), XtOffset(AppDataPtr, allWhite),
1268 XtRImmediate, (XtPointer) False},
1269 { "pieceToCharTable", "pieceToCharTable", XtRString,
1270 sizeof(String), XtOffset(AppDataPtr, pieceToCharTable),
1271 XtRImmediate, (XtPointer) 0},
1272 { "alphaRank", "alphaRank", XtRBoolean,
1273 sizeof(Boolean), XtOffset(AppDataPtr, alphaRank),
1274 XtRImmediate, (XtPointer) False},
1275 { "testClaims", "testClaims", XtRBoolean,
1276 sizeof(Boolean), XtOffset(AppDataPtr, testClaims),
1277 XtRImmediate, (XtPointer) True},
1278 { "checkMates", "checkMates", XtRBoolean,
1279 sizeof(Boolean), XtOffset(AppDataPtr, checkMates),
1280 XtRImmediate, (XtPointer) True},
1281 { "materialDraws", "materialDraws", XtRBoolean,
1282 sizeof(Boolean), XtOffset(AppDataPtr, materialDraws),
1283 XtRImmediate, (XtPointer) True},
1284 { "trivialDraws", "trivialDraws", XtRBoolean,
1285 sizeof(Boolean), XtOffset(AppDataPtr, trivialDraws),
1286 XtRImmediate, (XtPointer) False},
1287 { "ruleMoves", "ruleMoves", XtRInt,
1288 sizeof(int), XtOffset(AppDataPtr, ruleMoves),
1289 XtRImmediate, (XtPointer) 51},
1290 { "repeatsToDraw", "repeatsToDraw", XtRInt,
1291 sizeof(int), XtOffset(AppDataPtr, drawRepeats),
1292 XtRImmediate, (XtPointer) 6},
1293 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1294 sizeof(int), XtOffset(AppDataPtr, engineComments),
1295 XtRImmediate, (XtPointer) 1},
1296 { "userName", "userName", XtRString,
1297 sizeof(int), XtOffset(AppDataPtr, userName),
1298 XtRImmediate, (XtPointer) 0},
1299 { "autoKibitz", "autoKibitz", XtRBoolean,
1300 sizeof(Boolean), XtOffset(AppDataPtr, autoKibitz),
1301 XtRImmediate, (XtPointer) False},
1302 { "firstTimeOdds", "firstTimeOdds", XtRInt,
1303 sizeof(int), XtOffset(AppDataPtr, firstTimeOdds),
1304 XtRImmediate, (XtPointer) 1},
1305 { "secondTimeOdds", "secondTimeOdds", XtRInt,
1306 sizeof(int), XtOffset(AppDataPtr, secondTimeOdds),
1307 XtRImmediate, (XtPointer) 1},
1308 { "timeOddsMode", "timeOddsMode", XtRInt,
1309 sizeof(int), XtOffset(AppDataPtr, timeOddsMode),
1310 XtRImmediate, (XtPointer) 0},
1311 { "firstAccumulateTC", "firstAccumulateTC", XtRInt,
1312 sizeof(int), XtOffset(AppDataPtr, firstAccumulateTC),
1313 XtRImmediate, (XtPointer) 1},
1314 { "secondAccumulateTC", "secondAccumulateTC", XtRInt,
1315 sizeof(int), XtOffset(AppDataPtr, secondAccumulateTC),
1316 XtRImmediate, (XtPointer) 1},
1317 { "firstNPS", "firstNPS", XtRInt,
1318 sizeof(int), XtOffset(AppDataPtr, firstNPS),
1319 XtRImmediate, (XtPointer) -1},
1320 { "secondNPS", "secondNPS", XtRInt,
1321 sizeof(int), XtOffset(AppDataPtr, secondNPS),
1322 XtRImmediate, (XtPointer) -1},
1323 { "serverMoves", "serverMoves", XtRString,
1324 sizeof(String), XtOffset(AppDataPtr, serverMovesName),
1325 XtRImmediate, (XtPointer) 0},
1326 { "serverPause", "serverPause", XtRInt,
1327 sizeof(int), XtOffset(AppDataPtr, serverPause),
1328 XtRImmediate, (XtPointer) 0},
1329 { "suppressLoadMoves", "suppressLoadMoves", XtRBoolean,
1330 sizeof(Boolean), XtOffset(AppDataPtr, suppressLoadMoves),
1331 XtRImmediate, (XtPointer) False},
1332 { "userName", "userName", XtRString,
1333 sizeof(String), XtOffset(AppDataPtr, userName),
1334 XtRImmediate, (XtPointer) 0},
1335 { "egtFormats", "egtFormats", XtRString,
1336 sizeof(String), XtOffset(AppDataPtr, egtFormats),
1337 XtRImmediate, (XtPointer) 0},
1338 { "rewindIndex", "rewindIndex", XtRInt,
1339 sizeof(int), XtOffset(AppDataPtr, rewindIndex),
1340 XtRImmediate, (XtPointer) 0},
1341 { "sameColorGames", "sameColorGames", XtRInt,
1342 sizeof(int), XtOffset(AppDataPtr, sameColorGames),
1343 XtRImmediate, (XtPointer) 0},
1344 { "smpCores", "smpCores", XtRInt,
1345 sizeof(int), XtOffset(AppDataPtr, smpCores),
1346 XtRImmediate, (XtPointer) 1},
1347 { "niceEngines", "niceEngines", XtRInt,
1348 sizeof(int), XtOffset(AppDataPtr, niceEngines),
1349 XtRImmediate, (XtPointer) 0},
1350 { "nameOfDebugFile", "nameOfDebugFile", XtRString,
1351 sizeof(String), XtOffset(AppDataPtr, nameOfDebugFile),
1352 XtRImmediate, (XtPointer) "xboard.debug"},
1353 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1354 sizeof(int), XtOffset(AppDataPtr, engineComments),
1355 XtRImmediate, (XtPointer) 1},
1356 { "noGUI", "noGUI", XtRBoolean,
1357 sizeof(Boolean), XtOffset(AppDataPtr, noGUI),
1358 XtRImmediate, (XtPointer) 0},
1359 { "firstOptions", "firstOptions", XtRString,
1360 sizeof(String), XtOffset(AppDataPtr, firstOptions),
1361 XtRImmediate, (XtPointer) "" },
1362 { "secondOptions", "secondOptions", XtRString,
1363 sizeof(String), XtOffset(AppDataPtr, secondOptions),
1364 XtRImmediate, (XtPointer) "" },
1365 { "firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XtRString,
1366 sizeof(String), XtOffset(AppDataPtr, fenOverride1),
1367 XtRImmediate, (XtPointer) 0 },
1368 { "secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XtRString,
1369 sizeof(String), XtOffset(AppDataPtr, fenOverride2),
1370 XtRImmediate, (XtPointer) 0 },
1372 // [HGM] Winboard_x UCI options
1373 { "firstIsUCI", "firstIsUCI", XtRBoolean,
1374 sizeof(Boolean), XtOffset(AppDataPtr, firstIsUCI),
1375 XtRImmediate, (XtPointer) False},
1376 { "secondIsUCI", "secondIsUCI", XtRBoolean,
1377 sizeof(Boolean), XtOffset(AppDataPtr, secondIsUCI),
1378 XtRImmediate, (XtPointer) False},
1379 { "firstHasOwnBookUCI", "firstHasOwnBookUCI", XtRBoolean,
1380 sizeof(Boolean), XtOffset(AppDataPtr, firstHasOwnBookUCI),
1381 XtRImmediate, (XtPointer) True},
1382 { "secondHasOwnBookUCI", "secondHasOwnBookUCI", XtRBoolean,
1383 sizeof(Boolean), XtOffset(AppDataPtr, secondHasOwnBookUCI),
1384 XtRImmediate, (XtPointer) True},
1385 { "usePolyglotBook", "usePolyglotBook", XtRBoolean,
1386 sizeof(Boolean), XtOffset(AppDataPtr, usePolyglotBook),
1387 XtRImmediate, (XtPointer) False},
1388 { "defaultHashSize", "defaultHashSize", XtRInt,
1389 sizeof(int), XtOffset(AppDataPtr, defaultHashSize),
1390 XtRImmediate, (XtPointer) 64},
1391 { "defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XtRInt,
1392 sizeof(int), XtOffset(AppDataPtr, defaultCacheSizeEGTB),
1393 XtRImmediate, (XtPointer) 4},
1394 { "polyglotDir", "polyglotDir", XtRString,
1395 sizeof(String), XtOffset(AppDataPtr, polyglotDir),
1396 XtRImmediate, (XtPointer) "." },
1397 { "polyglotBook", "polyglotBook", XtRString,
1398 sizeof(String), XtOffset(AppDataPtr, polyglotBook),
1399 XtRImmediate, (XtPointer) "" },
1400 { "defaultPathEGTB", "defaultPathEGTB", XtRString,
1401 sizeof(String), XtOffset(AppDataPtr, defaultPathEGTB),
1402 XtRImmediate, (XtPointer) "/usr/local/share/egtb"},
1403 { "delayBeforeQuit", "delayBeforeQuit", XtRInt,
1404 sizeof(int), XtOffset(AppDataPtr, delayBeforeQuit),
1405 XtRImmediate, (XtPointer) 0},
1406 { "delayAfterQuit", "delayAfterQuit", XtRInt,
1407 sizeof(int), XtOffset(AppDataPtr, delayAfterQuit),
1408 XtRImmediate, (XtPointer) 0},
1409 { "keepAlive", "keepAlive", XtRInt,
1410 sizeof(int), XtOffset(AppDataPtr, keepAlive),
1411 XtRImmediate, (XtPointer) 0},
1412 { "forceIllegalMoves", "forceIllegalMoves", XtRBoolean,
1413 sizeof(Boolean), XtOffset(AppDataPtr, forceIllegal),
1414 XtRImmediate, (XtPointer) False},
1417 XrmOptionDescRec shellOptions[] = {
1418 { "-whitePieceColor", "whitePieceColor", XrmoptionSepArg, NULL },
1419 { "-blackPieceColor", "blackPieceColor", XrmoptionSepArg, NULL },
1420 { "-lightSquareColor", "lightSquareColor", XrmoptionSepArg, NULL },
1421 { "-darkSquareColor", "darkSquareColor", XrmoptionSepArg, NULL },
1422 { "-highlightSquareColor", "highlightSquareColor", XrmoptionSepArg, NULL },
1423 { "-premoveHighlightColor", "premoveHighlightColor", XrmoptionSepArg,NULL},
1424 { "-movesPerSession", "movesPerSession", XrmoptionSepArg, NULL },
1425 { "-mps", "movesPerSession", XrmoptionSepArg, NULL },
1426 { "-timeIncrement", "timeIncrement", XrmoptionSepArg, NULL },
1427 { "-inc", "timeIncrement", XrmoptionSepArg, NULL },
1428 { "-initString", "initString", XrmoptionSepArg, NULL },
1429 { "-firstInitString", "initString", XrmoptionSepArg, NULL },
1430 { "-secondInitString", "secondInitString", XrmoptionSepArg, NULL },
1431 { "-firstComputerString", "firstComputerString", XrmoptionSepArg, NULL },
1432 { "-secondComputerString", "secondComputerString", XrmoptionSepArg, NULL },
1433 { "-firstChessProgram", "firstChessProgram", XrmoptionSepArg, NULL },
1434 { "-fcp", "firstChessProgram", XrmoptionSepArg, NULL },
1435 { "-secondChessProgram", "secondChessProgram", XrmoptionSepArg, NULL },
1436 { "-scp", "secondChessProgram", XrmoptionSepArg, NULL },
1437 { "-firstPlaysBlack", "firstPlaysBlack", XrmoptionSepArg, NULL },
1438 { "-fb", "firstPlaysBlack", XrmoptionNoArg, "True" },
1439 { "-xfb", "firstPlaysBlack", XrmoptionNoArg, "False" },
1440 { "-noChessProgram", "noChessProgram", XrmoptionSepArg, NULL },
1441 { "-ncp", "noChessProgram", XrmoptionNoArg, "True" },
1442 { "-xncp", "noChessProgram", XrmoptionNoArg, "False" },
1443 { "-firstHost", "firstHost", XrmoptionSepArg, NULL },
1444 { "-fh", "firstHost", XrmoptionSepArg, NULL },
1445 { "-secondHost", "secondHost", XrmoptionSepArg, NULL },
1446 { "-sh", "secondHost", XrmoptionSepArg, NULL },
1447 { "-firstDirectory", "firstDirectory", XrmoptionSepArg, NULL },
1448 { "-fd", "firstDirectory", XrmoptionSepArg, NULL },
1449 { "-secondDirectory", "secondDirectory", XrmoptionSepArg, NULL },
1450 { "-sd", "secondDirectory", XrmoptionSepArg, NULL },
1451 { "-bitmapDirectory", "bitmapDirectory", XrmoptionSepArg, NULL },
1452 { "-bm", "bitmapDirectory", XrmoptionSepArg, NULL },
1453 { "-remoteShell", "remoteShell", XrmoptionSepArg, NULL },
1454 { "-rsh", "remoteShell", XrmoptionSepArg, NULL },
1455 { "-remoteUser", "remoteUser", XrmoptionSepArg, NULL },
1456 { "-ruser", "remoteUser", XrmoptionSepArg, NULL },
1457 { "-timeDelay", "timeDelay", XrmoptionSepArg, NULL },
1458 { "-td", "timeDelay", XrmoptionSepArg, NULL },
1459 { "-timeControl", "timeControl", XrmoptionSepArg, NULL },
1460 { "-tc", "timeControl", XrmoptionSepArg, NULL },
1461 { "-internetChessServerMode", "internetChessServerMode",
1462 XrmoptionSepArg, NULL },
1463 { "-ics", "internetChessServerMode", XrmoptionNoArg, "True" },
1464 { "-xics", "internetChessServerMode", XrmoptionNoArg, "False" },
1465 { "-internetChessServerHost", "internetChessServerHost",
1466 XrmoptionSepArg, NULL },
1467 { "-icshost", "internetChessServerHost", XrmoptionSepArg, NULL },
1468 { "-internetChessServerPort", "internetChessServerPort",
1469 XrmoptionSepArg, NULL },
1470 { "-icsport", "internetChessServerPort", XrmoptionSepArg, NULL },
1471 { "-internetChessServerCommPort", "internetChessServerCommPort",
1472 XrmoptionSepArg, NULL },
1473 { "-icscomm", "internetChessServerCommPort", XrmoptionSepArg, NULL },
1474 { "-internetChessServerLogonScript", "internetChessServerLogonScript",
1475 XrmoptionSepArg, NULL },
1476 { "-icslogon", "internetChessServerLogonScript", XrmoptionSepArg, NULL },
1477 { "-internetChessServerHelper", "internetChessServerHelper",
1478 XrmoptionSepArg, NULL },
1479 { "-icshelper", "internetChessServerHelper", XrmoptionSepArg, NULL },
1480 { "-internetChessServerInputBox", "internetChessServerInputBox",
1481 XrmoptionSepArg, NULL },
1482 { "-icsinput", "internetChessServerInputBox", XrmoptionNoArg, "True" },
1483 { "-xicsinput", "internetChessServerInputBox", XrmoptionNoArg, "False" },
1484 { "-icsAlarm", "icsAlarm", XrmoptionSepArg, NULL },
1485 { "-alarm", "icsAlarm", XrmoptionNoArg, "True" },
1486 { "-xalarm", "icsAlarm", XrmoptionNoArg, "False" },
1487 { "-icsAlarmTime", "icsAlarmTime", XrmoptionSepArg, NULL },
1488 { "-useTelnet", "useTelnet", XrmoptionSepArg, NULL },
1489 { "-telnet", "useTelnet", XrmoptionNoArg, "True" },
1490 { "-xtelnet", "useTelnet", XrmoptionNoArg, "False" },
1491 { "-telnetProgram", "telnetProgram", XrmoptionSepArg, NULL },
1492 { "-gateway", "gateway", XrmoptionSepArg, NULL },
1493 { "-loadGameFile", "loadGameFile", XrmoptionSepArg, NULL },
1494 { "-lgf", "loadGameFile", XrmoptionSepArg, NULL },
1495 { "-loadGameIndex", "loadGameIndex", XrmoptionSepArg, NULL },
1496 { "-lgi", "loadGameIndex", XrmoptionSepArg, NULL },
1497 { "-saveGameFile", "saveGameFile", XrmoptionSepArg, NULL },
1498 { "-sgf", "saveGameFile", XrmoptionSepArg, NULL },
1499 { "-autoSaveGames", "autoSaveGames", XrmoptionSepArg, NULL },
1500 { "-autosave", "autoSaveGames", XrmoptionNoArg, "True" },
1501 { "-xautosave", "autoSaveGames", XrmoptionNoArg, "False" },
1502 { "-autoRaiseBoard", "autoRaiseBoard", XrmoptionSepArg, NULL },
1503 { "-autoraise", "autoRaiseBoard", XrmoptionNoArg, "True" },
1504 { "-xautoraise", "autoRaiseBoard", XrmoptionNoArg, "False" },
1505 { "-blindfold", "blindfold", XrmoptionSepArg, NULL },
1506 { "-blind", "blindfold", XrmoptionNoArg, "True" },
1507 { "-xblind", "blindfold", XrmoptionNoArg, "False" },
1508 { "-loadPositionFile", "loadPositionFile", XrmoptionSepArg, NULL },
1509 { "-lpf", "loadPositionFile", XrmoptionSepArg, NULL },
1510 { "-loadPositionIndex", "loadPositionIndex", XrmoptionSepArg, NULL },
1511 { "-lpi", "loadPositionIndex", XrmoptionSepArg, NULL },
1512 { "-savePositionFile", "savePositionFile", XrmoptionSepArg, NULL },
1513 { "-spf", "savePositionFile", XrmoptionSepArg, NULL },
1514 { "-matchMode", "matchMode", XrmoptionSepArg, NULL },
1515 { "-mm", "matchMode", XrmoptionNoArg, "True" },
1516 { "-xmm", "matchMode", XrmoptionNoArg, "False" },
1517 { "-matchGames", "matchGames", XrmoptionSepArg, NULL },
1518 { "-mg", "matchGames", XrmoptionSepArg, NULL },
1519 { "-monoMode", "monoMode", XrmoptionSepArg, NULL },
1520 { "-mono", "monoMode", XrmoptionNoArg, "True" },
1521 { "-xmono", "monoMode", XrmoptionNoArg, "False" },
1522 { "-debugMode", "debugMode", XrmoptionSepArg, NULL },
1523 { "-debug", "debugMode", XrmoptionNoArg, "True" },
1524 { "-xdebug", "debugMode", XrmoptionNoArg, "False" },
1525 { "-clockMode", "clockMode", XrmoptionSepArg, NULL },
1526 { "-clock", "clockMode", XrmoptionNoArg, "True" },
1527 { "-xclock", "clockMode", XrmoptionNoArg, "False" },
1528 { "-boardSize", "boardSize", XrmoptionSepArg, NULL },
1529 { "-size", "boardSize", XrmoptionSepArg, NULL },
1530 { "-searchTime", "searchTime", XrmoptionSepArg, NULL },
1531 { "-st", "searchTime", XrmoptionSepArg, NULL },
1532 { "-searchDepth", "searchDepth", XrmoptionSepArg, NULL },
1533 { "-depth", "searchDepth", XrmoptionSepArg, NULL },
1534 { "-showCoords", "showCoords", XrmoptionSepArg, NULL },
1535 { "-coords", "showCoords", XrmoptionNoArg, "True" },
1536 { "-xcoords", "showCoords", XrmoptionNoArg, "False" },
1538 { "-showJail", "showJail", XrmoptionSepArg, NULL },
1539 { "-jail", "showJail", XrmoptionNoArg, "1" },
1540 { "-sidejail", "showJail", XrmoptionNoArg, "2" },
1541 { "-xjail", "showJail", XrmoptionNoArg, "0" },
1543 { "-showThinking", "showThinking", XrmoptionSepArg, NULL },
1544 { "-thinking", "showThinking", XrmoptionNoArg, "True" },
1545 { "-xthinking", "showThinking", XrmoptionNoArg, "False" },
1546 { "-ponderNextMove", "ponderNextMove", XrmoptionSepArg, NULL },
1547 { "-ponder", "ponderNextMove", XrmoptionNoArg, "True" },
1548 { "-xponder", "ponderNextMove", XrmoptionNoArg, "False" },
1549 { "-periodicUpdates", "periodicUpdates", XrmoptionSepArg, NULL },
1550 { "-periodic", "periodicUpdates", XrmoptionNoArg, "True" },
1551 { "-xperiodic", "periodicUpdates", XrmoptionNoArg, "False" },
1552 { "-clockFont", "clockFont", XrmoptionSepArg, NULL },
1553 { "-coordFont", "coordFont", XrmoptionSepArg, NULL },
1554 { "-font", "font", XrmoptionSepArg, NULL },
1555 { "-ringBellAfterMoves", "ringBellAfterMoves", XrmoptionSepArg, NULL },
1556 { "-bell", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1557 { "-xbell", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1558 { "-movesound", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1559 { "-xmovesound", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1560 { "-autoCallFlag", "autoCallFlag", XrmoptionSepArg, NULL },
1561 { "-autoflag", "autoCallFlag", XrmoptionNoArg, "True" },
1562 { "-xautoflag", "autoCallFlag", XrmoptionNoArg, "False" },
1563 { "-autoFlipView", "autoFlipView", XrmoptionSepArg, NULL },
1564 { "-autoflip", "autoFlipView", XrmoptionNoArg, "True" },
1565 { "-xautoflip", "autoFlipView", XrmoptionNoArg, "False" },
1566 { "-autoObserve", "autoObserve", XrmoptionSepArg, NULL },
1567 { "-autobs", "autoObserve", XrmoptionNoArg, "True" },
1568 { "-xautobs", "autoObserve", XrmoptionNoArg, "False" },
1569 { "-autoComment", "autoComment", XrmoptionSepArg, NULL },
1570 { "-autocomm", "autoComment", XrmoptionNoArg, "True" },
1571 { "-xautocomm", "autoComment", XrmoptionNoArg, "False" },
1572 { "-getMoveList", "getMoveList", XrmoptionSepArg, NULL },
1573 { "-moves", "getMoveList", XrmoptionNoArg, "True" },
1574 { "-xmoves", "getMoveList", XrmoptionNoArg, "False" },
1576 { "-highlightDragging", "highlightDragging", XrmoptionSepArg, NULL },
1577 { "-highdrag", "highlightDragging", XrmoptionNoArg, "True" },
1578 { "-xhighdrag", "highlightDragging", XrmoptionNoArg, "False" },
1580 { "-highlightLastMove", "highlightLastMove", XrmoptionSepArg, NULL },
1581 { "-highlight", "highlightLastMove", XrmoptionNoArg, "True" },
1582 { "-xhighlight", "highlightLastMove", XrmoptionNoArg, "False" },
1583 { "-premove", "premove", XrmoptionSepArg, NULL },
1584 { "-pre", "premove", XrmoptionNoArg, "True" },
1585 { "-xpre", "premove", XrmoptionNoArg, "False" },
1586 { "-testLegality", "testLegality", XrmoptionSepArg, NULL },
1587 { "-legal", "testLegality", XrmoptionNoArg, "True" },
1588 { "-xlegal", "testLegality", XrmoptionNoArg, "False" },
1589 { "-flipView", "flipView", XrmoptionSepArg, NULL },
1590 { "-flip", "flipView", XrmoptionNoArg, "True" },
1591 { "-xflip", "flipView", XrmoptionNoArg, "False" },
1592 { "-cmail", "cmailGameName", XrmoptionSepArg, NULL },
1593 { "-alwaysPromoteToQueen", "alwaysPromoteToQueen",
1594 XrmoptionSepArg, NULL },
1595 { "-queen", "alwaysPromoteToQueen", XrmoptionNoArg, "True" },
1596 { "-xqueen", "alwaysPromoteToQueen", XrmoptionNoArg, "False" },
1597 { "-oldSaveStyle", "oldSaveStyle", XrmoptionSepArg, NULL },
1598 { "-oldsave", "oldSaveStyle", XrmoptionNoArg, "True" },
1599 { "-xoldsave", "oldSaveStyle", XrmoptionNoArg, "False" },
1600 { "-quietPlay", "quietPlay", XrmoptionSepArg, NULL },
1601 { "-quiet", "quietPlay", XrmoptionNoArg, "True" },
1602 { "-xquiet", "quietPlay", XrmoptionNoArg, "False" },
1603 { "-titleInWindow", "titleInWindow", XrmoptionSepArg, NULL },
1604 { "-title", "titleInWindow", XrmoptionNoArg, "True" },
1605 { "-xtitle", "titleInWindow", XrmoptionNoArg, "False" },
1607 { "-zippyTalk", "zippyTalk", XrmoptionSepArg, NULL },
1608 { "-zt", "zippyTalk", XrmoptionNoArg, "True" },
1609 { "-xzt", "zippyTalk", XrmoptionNoArg, "False" },
1610 { "-zippyPlay", "zippyPlay", XrmoptionSepArg, NULL },
1611 { "-zp", "zippyPlay", XrmoptionNoArg, "True" },
1612 { "-xzp", "zippyPlay", XrmoptionNoArg, "False" },
1613 { "-zippyLines", "zippyLines", XrmoptionSepArg, NULL },
1614 { "-zippyPinhead", "zippyPinhead", XrmoptionSepArg, NULL },
1615 { "-zippyPassword", "zippyPassword", XrmoptionSepArg, NULL },
1616 { "-zippyPassword2", "zippyPassword2", XrmoptionSepArg, NULL },
1617 { "-zippyWrongPassword", "zippyWrongPassword", XrmoptionSepArg, NULL },
1618 { "-zippyAcceptOnly", "zippyAcceptOnly", XrmoptionSepArg, NULL },
1619 { "-zippyUseI", "zippyUseI", XrmoptionSepArg, NULL },
1620 { "-zui", "zippyUseI", XrmoptionNoArg, "True" },
1621 { "-xzui", "zippyUseI", XrmoptionNoArg, "False" },
1622 { "-zippyBughouse", "zippyBughouse", XrmoptionSepArg, NULL },
1623 { "-zippyNoplayCrafty", "zippyNoplayCrafty", XrmoptionSepArg, NULL },
1624 { "-znc", "zippyNoplayCrafty", XrmoptionNoArg, "True" },
1625 { "-xznc", "zippyNoplayCrafty", XrmoptionNoArg, "False" },
1626 { "-zippyGameEnd", "zippyGameEnd", XrmoptionSepArg, NULL },
1627 { "-zippyGameStart", "zippyGameStart", XrmoptionSepArg, NULL },
1628 { "-zippyAdjourn", "zippyAdjourn", XrmoptionSepArg, NULL },
1629 { "-zadj", "zippyAdjourn", XrmoptionNoArg, "True" },
1630 { "-xzadj", "zippyAdjourn", XrmoptionNoArg, "False" },
1631 { "-zippyAbort", "zippyAbort", XrmoptionSepArg, NULL },
1632 { "-zab", "zippyAbort", XrmoptionNoArg, "True" },
1633 { "-xzab", "zippyAbort", XrmoptionNoArg, "False" },
1634 { "-zippyVariants", "zippyVariants", XrmoptionSepArg, NULL },
1635 { "-zippyMaxGames", "zippyMaxGames", XrmoptionSepArg, NULL },
1636 { "-zippyReplayTimeout", "zippyReplayTimeout", XrmoptionSepArg, NULL },
1637 { "-zippyShortGame", "zippyShortGame", XrmoptionSepArg, NULL },
1639 { "-flashCount", "flashCount", XrmoptionSepArg, NULL },
1640 { "-flash", "flashCount", XrmoptionNoArg, "3" },
1641 { "-xflash", "flashCount", XrmoptionNoArg, "0" },
1642 { "-flashRate", "flashRate", XrmoptionSepArg, NULL },
1643 { "-pixmapDirectory", "pixmapDirectory", XrmoptionSepArg, NULL },
1644 { "-msLoginDelay", "msLoginDelay", XrmoptionSepArg, NULL },
1645 { "-pixmap", "pixmapDirectory", XrmoptionSepArg, NULL },
1646 { "-colorizeMessages", "colorizeMessages", XrmoptionSepArg, NULL },
1647 { "-colorize", "colorizeMessages", XrmoptionNoArg, "True" },
1648 { "-xcolorize", "colorizeMessages", XrmoptionNoArg, "False" },
1649 { "-colorShout", "colorShout", XrmoptionSepArg, NULL },
1650 { "-colorSShout", "colorSShout", XrmoptionSepArg, NULL },
1651 { "-colorCShout", "colorSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1652 { "-colorChannel1", "colorChannel1", XrmoptionSepArg, NULL },
1653 { "-colorChannel", "colorChannel", XrmoptionSepArg, NULL },
1654 { "-colorKibitz", "colorKibitz", XrmoptionSepArg, NULL },
1655 { "-colorTell", "colorTell", XrmoptionSepArg, NULL },
1656 { "-colorChallenge", "colorChallenge", XrmoptionSepArg, NULL },
1657 { "-colorRequest", "colorRequest", XrmoptionSepArg, NULL },
1658 { "-colorSeek", "colorSeek", XrmoptionSepArg, NULL },
1659 { "-colorNormal", "colorNormal", XrmoptionSepArg, NULL },
1660 { "-soundProgram", "soundProgram", XrmoptionSepArg, NULL },
1661 { "-soundShout", "soundShout", XrmoptionSepArg, NULL },
1662 { "-soundSShout", "soundSShout", XrmoptionSepArg, NULL },
1663 { "-soundCShout", "soundSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1664 { "-soundChannel1", "soundChannel1", XrmoptionSepArg, NULL },
1665 { "-soundChannel", "soundChannel", XrmoptionSepArg, NULL },
1666 { "-soundKibitz", "soundKibitz", XrmoptionSepArg, NULL },
1667 { "-soundTell", "soundTell", XrmoptionSepArg, NULL },
1668 { "-soundChallenge", "soundChallenge", XrmoptionSepArg, NULL },
1669 { "-soundRequest", "soundRequest", XrmoptionSepArg, NULL },
1670 { "-soundSeek", "soundSeek", XrmoptionSepArg, NULL },
1671 { "-soundMove", "soundMove", XrmoptionSepArg, NULL },
1672 { "-soundIcsWin", "soundIcsWin", XrmoptionSepArg, NULL },
1673 { "-soundIcsLoss", "soundIcsLoss", XrmoptionSepArg, NULL },
1674 { "-soundIcsDraw", "soundIcsDraw", XrmoptionSepArg, NULL },
1675 { "-soundIcsUnfinished", "soundIcsUnfinished", XrmoptionSepArg, NULL },
1676 { "-soundIcsAlarm", "soundIcsAlarm", XrmoptionSepArg, NULL },
1677 { "-reuseFirst", "reuseFirst", XrmoptionSepArg, NULL },
1678 { "-reuseChessPrograms", "reuseFirst", XrmoptionSepArg, NULL }, /*compat*/
1679 { "-reuse", "reuseFirst", XrmoptionNoArg, "True" },
1680 { "-xreuse", "reuseFirst", XrmoptionNoArg, "False" },
1681 { "-reuseSecond", "reuseSecond", XrmoptionSepArg, NULL },
1682 { "-reuse2", "reuseSecond", XrmoptionNoArg, "True" },
1683 { "-xreuse2", "reuseSecond", XrmoptionNoArg, "False" },
1684 { "-animateMoving", "animateMoving", XrmoptionSepArg, NULL },
1685 { "-animate", "animateMoving", XrmoptionNoArg, "True" },
1686 { "-xanimate", "animateMoving", XrmoptionNoArg, "False" },
1687 { "-animateDragging", "animateDragging", XrmoptionSepArg, NULL },
1688 { "-drag", "animateDragging", XrmoptionNoArg, "True" },
1689 { "-xdrag", "animateDragging", XrmoptionNoArg, "False" },
1690 { "-animateSpeed", "animateSpeed", XrmoptionSepArg, NULL },
1691 { "-popupExitMessage", "popupExitMessage", XrmoptionSepArg, NULL },
1692 { "-exit", "popupExitMessage", XrmoptionNoArg, "True" },
1693 { "-xexit", "popupExitMessage", XrmoptionNoArg, "False" },
1694 { "-popupMoveErrors", "popupMoveErrors", XrmoptionSepArg, NULL },
1695 { "-popup", "popupMoveErrors", XrmoptionNoArg, "True" },
1696 { "-xpopup", "popupMoveErrors", XrmoptionNoArg, "False" },
1697 { "-fontSizeTolerance", "fontSizeTolerance", XrmoptionSepArg, NULL },
1698 { "-initialMode", "initialMode", XrmoptionSepArg, NULL },
1699 { "-mode", "initialMode", XrmoptionSepArg, NULL },
1700 { "-variant", "variant", XrmoptionSepArg, NULL },
1701 { "-firstProtocolVersion", "firstProtocolVersion", XrmoptionSepArg, NULL },
1702 { "-secondProtocolVersion","secondProtocolVersion",XrmoptionSepArg, NULL },
1703 { "-showButtonBar", "showButtonBar", XrmoptionSepArg, NULL },
1704 { "-buttons", "showButtonBar", XrmoptionNoArg, "True" },
1705 { "-xbuttons", "showButtonBar", XrmoptionNoArg, "False" },
1706 { "-lowTimeWarningColor", "lowTimeWarningColor", XrmoptionSepArg, NULL },
1707 { "-lowTimeWarning", "lowTimeWarning", XrmoptionSepArg, NULL },
1708 /* [AS,HR] New features */
1709 { "-firstScoreAbs", "firstScoreAbs", XrmoptionSepArg, NULL },
1710 { "-secondScoreAbs", "secondScoreAbs", XrmoptionSepArg, NULL },
1711 { "-pgnExtendedInfo", "pgnExtendedInfo", XrmoptionSepArg, NULL },
1712 { "-hideThinkingFromHuman", "hideThinkingFromHuman", XrmoptionSepArg, NULL },
1713 { "-adjudicateLossThreshold", "adjudicateLossThreshold", XrmoptionSepArg, NULL },
1714 { "-adjudicateDrawMoves", "adjudicateDrawMoves", XrmoptionSepArg, NULL },
1715 { "-pgnEventHeader", "pgnEventHeader", XrmoptionSepArg, NULL },
1716 { "-firstIsUCI", "firstIsUCI", XrmoptionSepArg, NULL },
1717 { "-secondIsUCI", "secondIsUCI", XrmoptionSepArg, NULL },
1718 { "-fUCI", "firstIsUCI", XrmoptionNoArg, "True" },
1719 { "-sUCI", "secondIsUCI", XrmoptionNoArg, "True" },
1720 { "-firstHasOwnBookUCI", "firstHasOwnBookUCI", XrmoptionSepArg, NULL },
1721 { "-secondHasOwnBookUCI", "secondHasOwnBookUCI", XrmoptionSepArg, NULL },
1722 { "-fNoOwnBookUCI", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1723 { "-sNoOwnBookUCI", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1724 { "-firstXBook", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1725 { "-secondXBook", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1726 { "-polyglotDir", "polyglotDir", XrmoptionSepArg, NULL },
1727 { "-usePolyglotBook", "usePolyglotBook", XrmoptionSepArg, NULL },
1728 { "-polyglotBook", "polyglotBook", XrmoptionSepArg, NULL },
1729 { "-defaultHashSize", "defaultHashSize", XrmoptionSepArg, NULL },
1730 { "-defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XrmoptionSepArg, NULL },
1731 { "-defaultPathEGTB", "defaultPathEGTB", XrmoptionSepArg, NULL },
1732 { "-defaultFrcPosition", "defaultFrcPosition", XrmoptionSepArg, NULL },
1733 { "-gameListTags", "gameListTags", XrmoptionSepArg, NULL },
1734 // [HGM] I am sure AS added many more options, but we have to fish them out, from the list in winboard.c
1736 /* [HGM,HR] User-selectable board size */
1737 { "-boardWidth", "boardWidth", XrmoptionSepArg, NULL },
1738 { "-boardHeight", "boardHeight", XrmoptionSepArg, NULL },
1739 { "-matchPause", "matchPause", XrmoptionSepArg, NULL },
1741 /* [HGM] new arguments of 4.3.xx. All except first three are back-end options, which should work immediately */
1742 { "-holdingsSize", "holdingsSize", XrmoptionSepArg, NULL }, // requires extensive front-end changes to work
1743 { "-flipBlack", "flipBlack", XrmoptionSepArg, NULL }, // requires front-end changes to work
1744 { "-allWhite", "allWhite", XrmoptionSepArg, NULL }, // requires front-end changes to work
1745 { "-pieceToCharTable", "pieceToCharTable", XrmoptionSepArg, NULL },
1746 { "-alphaRank", "alphaRank", XrmoptionSepArg, NULL },
1747 { "-testClaims", "testClaims", XrmoptionSepArg, NULL },
1748 { "-checkMates", "checkMates", XrmoptionSepArg, NULL },
1749 { "-materialDraws", "materialDraws", XrmoptionSepArg, NULL },
1750 { "-trivialDraws", "trivialDraws", XrmoptionSepArg, NULL },
1751 { "-ruleMoves", "ruleMoves", XrmoptionSepArg, NULL },
1752 { "-repeatsToDraw", "repeatsToDraw", XrmoptionSepArg, NULL },
1753 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1754 { "-userName", "userName", XrmoptionSepArg, NULL },
1755 { "-autoKibitz", "autoKibitz", XrmoptionNoArg, "True" },
1756 { "-firstTimeOdds", "firstTimeOdds", XrmoptionSepArg, NULL },
1757 { "-secondTimeOdds", "secondTimeOdds", XrmoptionSepArg, NULL },
1758 { "-timeOddsMode", "timeOddsMode", XrmoptionSepArg, NULL },
1759 { "-firstAccumulateTC", "firstAccumulateTC", XrmoptionSepArg, NULL },
1760 { "-secondAccumulateTC", "secondAccumulateTC", XrmoptionSepArg, NULL },
1761 { "-firstNPS", "firstNPS", XrmoptionSepArg, NULL },
1762 { "-secondNPS", "secondNPS", XrmoptionSepArg, NULL },
1763 { "-serverMoves", "serverMoves", XrmoptionSepArg, NULL },
1764 { "-serverPause", "serverPause", XrmoptionSepArg, NULL },
1765 { "-suppressLoadMoves", "suppressLoadMoves", XrmoptionSepArg, NULL },
1766 { "-egtFormats", "egtFormats", XrmoptionSepArg, NULL },
1767 { "-userName", "userName", XrmoptionSepArg, NULL },
1768 { "-smpCores", "smpCores", XrmoptionSepArg, NULL },
1769 { "-sameColorGames", "sameColorGames", XrmoptionSepArg, NULL },
1770 { "-rewindIndex", "rewindIndex", XrmoptionSepArg, NULL },
1771 { "-niceEngines", "niceEngines", XrmoptionSepArg, NULL },
1772 { "-delayBeforeQuit", "delayBeforeQuit", XrmoptionSepArg, NULL },
1773 { "-delayAfterQuit", "delayAfterQuit", XrmoptionSepArg, NULL },
1774 { "-nameOfDebugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1775 { "-debugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1776 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1777 { "-noGUI", "noGUI", XrmoptionNoArg, "True" },
1778 { "-firstOptions", "firstOptions", XrmoptionSepArg, NULL },
1779 { "-secondOptions", "secondOptions", XrmoptionSepArg, NULL },
1780 { "-firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1781 { "-secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1782 { "-keepAlive", "keepAlive", XrmoptionSepArg, NULL },
1783 { "-forceIllegalMoves", "forceIllegalMoves", XrmoptionNoArg, "True" },
1787 XtActionsRec boardActions[] = {
1788 { "HandleUserMove", HandleUserMove },
1789 { "AnimateUserMove", AnimateUserMove },
1790 { "FileNameAction", FileNameAction },
1791 { "AskQuestionProc", AskQuestionProc },
1792 { "AskQuestionReplyAction", AskQuestionReplyAction },
1793 { "PieceMenuPopup", PieceMenuPopup },
1794 { "WhiteClock", WhiteClock },
1795 { "BlackClock", BlackClock },
1796 { "Iconify", Iconify },
1797 { "LoadSelectedProc", LoadSelectedProc },
1798 { "LoadPositionProc", LoadPositionProc },
1799 // { "LoadNextPositionProc", LoadNextPositionProc },
1800 // { "LoadPrevPositionProc", LoadPrevPositionProc },
1801 // { "ReloadPositionProc", ReloadPositionProc },
1802 { "CopyPositionProc", CopyPositionProc },
1803 { "PastePositionProc", PastePositionProc },
1804 { "CopyGameProc", CopyGameProc },
1805 { "PasteGameProc", PasteGameProc },
1806 { "SaveGameProc", SaveGameProc },
1807 { "SavePositionProc", SavePositionProc },
1808 { "MailMoveProc", MailMoveProc },
1809 { "ReloadCmailMsgProc", ReloadCmailMsgProc },
1810 // { "MachineWhiteProc", MachineWhiteProc },
1811 // { "MachineBlackProc", MachineBlackProc },
1812 { "AnalysisModeProc", AnalyzeModeProc },
1813 { "AnalyzeFileProc", AnalyzeFileProc },
1814 // { "TwoMachinesProc", TwoMachinesProc },
1815 // { "IcsClientProc", IcsClientProc },
1816 { "EditGameProc", EditGameProc },
1817 { "EditPositionProc", EditPositionProc },
1818 { "TrainingProc", EditPositionProc },
1819 { "EngineOutputProc", EngineOutputProc}, // [HGM] Winboard_x engine-output window
1820 { "ShowGameListProc", ShowGameListProc },
1821 // { "ShowMoveListProc", HistoryShowProc},
1822 { "EditTagsProc", EditCommentProc },
1823 { "EditCommentProc", EditCommentProc },
1824 { "IcsAlarmProc", IcsAlarmProc },
1825 { "IcsInputBoxProc", IcsInputBoxProc },
1826 // { "AcceptProc", AcceptProc },
1827 // { "DeclineProc", DeclineProc },
1828 // { "RematchProc", RematchProc },
1829 // { "CallFlagProc", CallFlagProc },
1830 // { "DrawProc", DrawProc },
1831 // { "AdjournProc", AdjournProc },
1832 // { "AbortProc", AbortProc },
1833 // { "ResignProc", ResignProc },
1834 // { "AdjuWhiteProc", AdjuWhiteProc },
1835 // { "AdjuBlackProc", AdjuBlackProc },
1836 // { "AdjuDrawProc", AdjuDrawProc },
1837 { "EnterKeyProc", EnterKeyProc },
1838 // { "StopObservingProc", StopObservingProc },
1839 // { "StopExaminingProc", StopExaminingProc },
1840 // { "BackwardProc", BackwardProc },
1841 // { "ForwardProc", ForwardProc },
1842 // { "ToStartProc", ToStartProc },
1843 // { "ToEndProc", ToEndProc },
1844 // { "RevertProc", RevertProc },
1845 // { "TruncateGameProc", TruncateGameProc },
1846 // { "MoveNowProc", MoveNowProc },
1847 // { "RetractMoveProc", RetractMoveProc },
1848 { "AlwaysQueenProc", AlwaysQueenProc },
1849 { "AnimateDraggingProc", AnimateDraggingProc },
1850 { "AnimateMovingProc", AnimateMovingProc },
1851 { "AutoflagProc", AutoflagProc },
1852 { "AutoflipProc", AutoflipProc },
1853 { "AutobsProc", AutobsProc },
1854 { "AutoraiseProc", AutoraiseProc },
1855 { "AutosaveProc", AutosaveProc },
1856 { "BlindfoldProc", BlindfoldProc },
1857 { "FlashMovesProc", FlashMovesProc },
1858 // { "FlipViewProc", FlipViewProc },
1859 // { "GetMoveListProc", GetMoveListProc },
1861 { "HighlightDraggingProc", HighlightDraggingProc },
1863 { "HighlightLastMoveProc", HighlightLastMoveProc },
1864 { "IcsAlarmProc", IcsAlarmProc },
1865 { "MoveSoundProc", MoveSoundProc },
1866 { "OldSaveStyleProc", OldSaveStyleProc },
1867 { "PeriodicUpdatesProc", PeriodicUpdatesProc },
1868 { "PonderNextMoveProc", PonderNextMoveProc },
1869 { "PopupExitMessageProc", PopupExitMessageProc },
1870 { "PopupMoveErrorsProc", PopupMoveErrorsProc },
1871 { "PremoveProc", PremoveProc },
1872 { "QuietPlayProc", QuietPlayProc },
1873 // { "ShowThinkingProc", ShowThinkingProc },
1874 // { "HideThinkingProc", HideThinkingProc },
1875 { "TestLegalityProc", TestLegalityProc },
1876 // { "InfoProc", InfoProc },
1877 // { "ManProc", ManProc },
1878 // { "HintProc", HintProc },
1879 // { "BookProc", BookProc },
1880 { "AboutGameProc", AboutGameProc },
1881 { "DebugProc", DebugProc },
1882 { "NothingProc", NothingProc },
1883 { "CommentPopDown", (XtActionProc) CommentPopDown },
1884 { "EditCommentPopDown", (XtActionProc) EditCommentPopDown },
1885 { "TagsPopDown", (XtActionProc) TagsPopDown },
1886 { "ErrorPopDown", (XtActionProc) ErrorPopDown },
1887 { "ICSInputBoxPopDown", (XtActionProc) ICSInputBoxPopDown },
1888 { "AnalysisPopDown", (XtActionProc) AnalysisPopDown },
1889 { "FileNamePopDown", (XtActionProc) FileNamePopDown },
1890 { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown },
1891 { "GameListPopDown", (XtActionProc) GameListPopDown },
1892 { "PromotionPopDown", (XtActionProc) PromotionPopDown },
1893 // { "HistoryPopDown", (XtActionProc) HistoryPopDown },
1894 { "EngineOutputPopDown", (XtActionProc) EngineOutputPopDown },
1895 { "ShufflePopDown", (XtActionProc) ShufflePopDown },
1896 { "EnginePopDown", (XtActionProc) EnginePopDown },
1897 { "UciPopDown", (XtActionProc) UciPopDown },
1898 { "TimeControlPopDown", (XtActionProc) TimeControlPopDown },
1899 { "NewVariantPopDown", (XtActionProc) NewVariantPopDown },
1900 { "SettingsPopDown", (XtActionProc) SettingsPopDown },
1904 char ICSInputTranslations[] =
1905 "<Key>Return: EnterKeyProc() \n";
1907 String xboardResources[] = {
1908 "*fileName*value.translations: #override\\n <Key>Return: FileNameAction()",
1909 "*question*value.translations: #override\\n <Key>Return: AskQuestionReplyAction()",
1910 "*errorpopup*translations: #override\\n <Key>Return: ErrorPopDown()",
1914 static char *cnames[9] = { "black", "red", "green", "yellow", "blue",
1915 "magenta", "cyan", "white" };
1919 TextColors textColors[(int)NColorClasses];
1921 /* String is: "fg, bg, attr". Which is 0, 1, 2 */
1923 parse_color(str, which)
1927 char *p, buf[100], *d;
1930 if (strlen(str) > 99) /* watch bounds on buf */
1935 for (i=0; i<which; ++i) {
1942 /* Could be looking at something like:
1944 .. in which case we want to stop on a comma also */
1945 while (*p && *p != ',' && !isalpha(*p) && !isdigit(*p))
1949 return -1; /* Use default for empty field */
1952 if (which == 2 || isdigit(*p))
1955 while (*p && isalpha(*p))
1960 for (i=0; i<8; ++i) {
1961 if (!StrCaseCmp(buf, cnames[i]))
1962 return which? (i+40) : (i+30);
1964 if (!StrCaseCmp(buf, "default")) return -1;
1966 fprintf(stderr, _("%s: unrecognized color %s\n"), programName, buf);
1971 parse_cpair(cc, str)
1975 if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {
1976 fprintf(stderr, _("%s: can't parse foreground color in `%s'\n"),
1981 /* bg and attr are optional */
1982 textColors[(int)cc].bg = parse_color(str, 1);
1983 if ((textColors[(int)cc].attr = parse_color(str, 2)) < 0) {
1984 textColors[(int)cc].attr = 0;
1990 /* Arrange to catch delete-window events */
1991 Atom wm_delete_window;
1993 CatchDeleteWindow(Widget w, String procname)
1996 XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
1997 snprintf(buf, sizeof(buf), "<Message>WM_PROTOCOLS: %s() \n", procname);
1998 XtAugmentTranslations(w, XtParseTranslationTable(buf));
2004 /* this should raise the board to the top */
2005 gtk_window_present(GTK_WINDOW(GUI_Window));
2009 #define BoardSize int
2010 void InitDrawingSizes(BoardSize boardSize, int flags)
2011 { // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
2012 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2014 XtGeometryResult gres;
2017 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2018 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2020 timerWidth = (boardWidth - sep) / 2;
2022 if (appData.titleInWindow)
2027 w = boardWidth - 2*bor;
2031 w = boardWidth - w - sep - 2*bor - 2; // WIDTH_FUDGE
2035 if(!formWidget) return;
2038 * Inhibit shell resizing.
2041 // [HGM] pieces: tailor piece bitmaps to needs of specific variant
2044 for(i=0; i<4; i++) {
2046 for(p=0; p<=(int)WhiteKing; p++)
2047 xpmPieceBitmap[i][p] = xpmPieceBitmap2[i][p]; // defaults
2048 if(gameInfo.variant == VariantShogi) {
2049 xpmPieceBitmap[i][(int)WhiteCannon] = xpmPieceBitmap2[i][(int)WhiteKing+1];
2050 xpmPieceBitmap[i][(int)WhiteNightrider] = xpmPieceBitmap2[i][(int)WhiteKing+2];
2051 xpmPieceBitmap[i][(int)WhiteSilver] = xpmPieceBitmap2[i][(int)WhiteKing+3];
2052 xpmPieceBitmap[i][(int)WhiteGrasshopper] = xpmPieceBitmap2[i][(int)WhiteKing+4];
2053 xpmPieceBitmap[i][(int)WhiteQueen] = xpmPieceBitmap2[i][(int)WhiteLance];
2056 if(gameInfo.variant == VariantGothic) {
2057 xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteSilver];
2061 // [HGM] why are thee ximMasks used at all? the ximPieceBitmaps seem to be never used!
2062 for(p=0; p<=(int)WhiteKing; p++)
2063 ximMaskPm[p] = ximMaskPm2[p]; // defaults
2064 if(gameInfo.variant == VariantShogi) {
2065 ximMaskPm[(int)WhiteCannon] = ximMaskPm2[(int)WhiteKing+1];
2066 ximMaskPm[(int)WhiteNightrider] = ximMaskPm2[(int)WhiteKing+2];
2067 ximMaskPm[(int)WhiteSilver] = ximMaskPm2[(int)WhiteKing+3];
2068 ximMaskPm[(int)WhiteGrasshopper] = ximMaskPm2[(int)WhiteKing+4];
2069 ximMaskPm[(int)WhiteQueen] = ximMaskPm2[(int)WhiteLance];
2072 if(gameInfo.variant == VariantGothic) {
2073 ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[(int)WhiteSilver];
2079 for(i=0; i<2; i++) {
2081 for(p=0; p<=(int)WhiteKing; p++)
2082 pieceBitmap[i][p] = pieceBitmap2[i][p]; // defaults
2083 if(gameInfo.variant == VariantShogi) {
2084 pieceBitmap[i][(int)WhiteCannon] = pieceBitmap2[i][(int)WhiteKing+1];
2085 pieceBitmap[i][(int)WhiteNightrider] = pieceBitmap2[i][(int)WhiteKing+2];
2086 pieceBitmap[i][(int)WhiteSilver] = pieceBitmap2[i][(int)WhiteKing+3];
2087 pieceBitmap[i][(int)WhiteGrasshopper] = pieceBitmap2[i][(int)WhiteKing+4];
2088 pieceBitmap[i][(int)WhiteQueen] = pieceBitmap2[i][(int)WhiteLance];
2091 if(gameInfo.variant == VariantGothic) {
2092 pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteSilver];
2102 void EscapeExpand(char *p, char *q)
2103 { // [HGM] initstring: routine to shape up string arguments
2104 while(*p++ = *q++) if(p[-1] == '\\')
2106 case 'n': p[-1] = '\n'; break;
2107 case 'r': p[-1] = '\r'; break;
2108 case 't': p[-1] = '\t'; break;
2109 case '\\': p[-1] = '\\'; break;
2110 case 0: *p = 0; return;
2111 default: p[-1] = q[-1]; break;
2120 int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
2121 XSetWindowAttributes window_attributes;
2123 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2124 XrmValue vFrom, vTo;
2125 XtGeometryResult gres;
2128 int forceMono = False;
2132 // [HGM] before anything else, expand any indirection files amongst options
2133 char *argvCopy[1000]; // 1000 seems enough
2134 char newArgs[10000]; // holds actual characters
2137 srandom(time(0)); // [HGM] book: make random truly random
2140 for(i=0; i<argc; i++) {
2141 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2142 //fprintf(stderr, "arg %s\n", argv[i]);
2143 if(argv[i][0] != '@') argvCopy[j++] = argv[i]; else {
2145 FILE *f = fopen(argv[i]+1, "rb");
2146 if(f == NULL) { fprintf(stderr, _("ignore %s\n"), argv[i]); continue; } // do not expand non-existing
2147 argvCopy[j++] = newArgs + k; // get ready for first argument from file
2148 while((c = fgetc(f)) != EOF) { // each line of file inserts 1 argument in the list
2150 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2151 newArgs[k++] = 0; // terminate current arg
2152 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2153 argvCopy[j++] = newArgs + k; // get ready for next
2155 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2169 setbuf(stdout, NULL);
2170 setbuf(stderr, NULL);
2173 programName = strrchr(argv[0], '/');
2174 if (programName == NULL)
2175 programName = argv[0];
2180 XtSetLanguageProc(NULL, NULL, NULL);
2181 bindtextdomain(PACKAGE, LOCALEDIR);
2182 textdomain(PACKAGE);
2186 XtAppInitialize(&appContext, "XBoard", shellOptions,
2187 XtNumber(shellOptions),
2188 &argc, argv, xboardResources, NULL, 0);
2191 gtk_init (&argc, &argv);
2193 /* parse glade file to build widgets */
2195 builder = gtk_builder_new ();
2196 gtk_builder_add_from_file (builder, "gtk-interface.xml", NULL);
2198 /* test if everything worked ok */
2200 GUI_Window = GTK_WIDGET (gtk_builder_get_object (builder, "MainWindow"));
2201 if(!GUI_Window) printf("Error: gtk_builder didn't work!\n");
2203 GUI_History = GTK_WIDGET (gtk_builder_get_object (builder, "MoveHistory"));
2204 if(!GUI_History) printf("Error: gtk_builder didn't work!\n");
2206 GUI_Menubar = GTK_WIDGET (gtk_builder_get_object (builder, "MenuBar"));
2207 if(!GUI_Menubar) printf("Error: gtk_builder didn't work!\n");
2208 GUI_Timer = GTK_WIDGET (gtk_builder_get_object (builder, "Timer"));
2209 if(!GUI_Timer) printf("Error: gtk_builder didn't work!\n");
2210 GUI_Buttonbar = GTK_WIDGET (gtk_builder_get_object (builder, "ButtonBar"));
2211 if(!GUI_Buttonbar) printf("Error: gtk_builder didn't work!\n");
2212 GUI_Board = GTK_WIDGET (gtk_builder_get_object (builder, "Board"));
2213 if(!GUI_Board) printf("Error: gtk_builder didn't work!\n");
2215 GUI_Whiteclock = GTK_WIDGET (gtk_builder_get_object (builder, "WhiteClock"));
2216 if(!GUI_Whiteclock) printf("Error: gtk_builder didn't work!\n");
2218 GUI_Blackclock = GTK_WIDGET (gtk_builder_get_object (builder, "BlackClock"));
2219 if(!GUI_Blackclock) printf("Error: gtk_builder didn't work!\n");
2221 LIST_MoveHistory = GTK_LIST_STORE (gtk_builder_get_object (builder, "MoveHistoryStore"));
2222 if(!LIST_MoveHistory) printf("Error: gtk_builder didn't work!\n");
2225 gtk_builder_connect_signals (builder, NULL);
2227 // don't unref the builder, since we use it to get references to widgets
2228 // g_object_unref (G_OBJECT (builder));
2230 /* end parse glade file */
2234 fprintf(stderr, _("%s: unrecognized argument %s\n"),
2235 programName, argv[1]);
2237 fprintf(stderr, "Recognized options:\n");
2238 for(i = 0; i < XtNumber(shellOptions); i++)
2240 /* print first column */
2241 j = fprintf(stderr, " %s%s", shellOptions[i].option,
2242 (shellOptions[i].argKind == XrmoptionSepArg
2244 /* print second column and end line */
2245 if (++i < XtNumber(shellOptions))
2247 fprintf(stderr, "%*c%s%s\n", 40 - j, ' ',
2248 shellOptions[i].option,
2249 (shellOptions[i].argKind == XrmoptionSepArg
2254 fprintf(stderr, "\n");
2261 if (p == NULL) p = "/tmp";
2262 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
2263 gameCopyFilename = (char*) malloc(i);
2264 gamePasteFilename = (char*) malloc(i);
2265 snprintf(gameCopyFilename,i, "%s/.xboard%05uc.pgn", p, getpid());
2266 snprintf(gamePasteFilename,i, "%s/.xboard%05up.pgn", p, getpid());
2268 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
2269 clientResources, XtNumber(clientResources),
2272 { // [HGM] initstring: kludge to fix bad bug. expand '\n' characters in init string and computer string.
2273 static char buf[MSG_SIZ];
2274 EscapeExpand(buf, appData.initString);
2275 appData.initString = strdup(buf);
2276 EscapeExpand(buf, appData.secondInitString);
2277 appData.secondInitString = strdup(buf);
2278 EscapeExpand(buf, appData.firstComputerString);
2279 appData.firstComputerString = strdup(buf);
2280 EscapeExpand(buf, appData.secondComputerString);
2281 appData.secondComputerString = strdup(buf);
2284 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
2287 if (chdir(chessDir) != 0) {
2288 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
2294 if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) {
2295 /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */
2296 if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL) {
2297 printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile);
2300 setbuf(debugFP, NULL);
2303 /* [HGM,HR] make sure board size is acceptable */
2304 if(appData.NrFiles > BOARD_SIZE ||
2305 appData.NrRanks > BOARD_SIZE )
2306 DisplayFatalError(_("Recompile with BOARD_SIZE > 12, to support this size"), 0, 2);
2309 /* This feature does not work; animation needs a rewrite */
2310 appData.highlightDragging = FALSE;
2314 xDisplay = XtDisplay(shellWidget);
2315 xScreen = DefaultScreen(xDisplay);
2316 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
2318 gameInfo.variant = StringToVariant(appData.variant);
2319 InitPosition(FALSE);
2321 /* calc board size */
2322 if (isdigit(appData.boardSize[0]))
2324 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
2325 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
2326 &fontPxlSize, &smallLayout, &tinyLayout);
2329 fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
2330 programName, appData.boardSize);
2335 /* Find some defaults; use the nearest known size */
2336 SizeDefaults *szd, *nearest;
2337 int distance = 99999;
2338 nearest = szd = sizeDefaults;
2339 while (szd->name != NULL)
2341 if (abs(szd->squareSize - squareSize) < distance)
2344 distance = abs(szd->squareSize - squareSize);
2345 if (distance == 0) break;
2349 if (i < 2) lineGap = nearest->lineGap;
2350 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
2351 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
2352 if (i < 5) fontPxlSize = nearest->fontPxlSize;
2353 if (i < 6) smallLayout = nearest->smallLayout;
2354 if (i < 7) tinyLayout = nearest->tinyLayout;
2359 SizeDefaults *szd = sizeDefaults;
2360 if (*appData.boardSize == NULLCHAR)
2362 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize
2363 || DisplayHeight(xDisplay, xScreen) < szd->minScreenSize)
2367 if (szd->name == NULL) szd--;
2371 while (szd->name != NULL
2372 && StrCaseCmp(szd->name, appData.boardSize) != 0)
2374 if (szd->name == NULL)
2376 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
2377 programName, appData.boardSize);
2381 squareSize = szd->squareSize;
2382 lineGap = szd->lineGap;
2383 clockFontPxlSize = szd->clockFontPxlSize;
2384 coordFontPxlSize = szd->coordFontPxlSize;
2385 fontPxlSize = szd->fontPxlSize;
2386 smallLayout = szd->smallLayout;
2387 tinyLayout = szd->tinyLayout;
2389 /* end figuring out what size to use */
2391 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2392 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2395 * Determine what fonts to use.
2397 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
2398 clockFontID = XLoadFont(xDisplay, appData.clockFont);
2399 clockFontStruct = XQueryFont(xDisplay, clockFontID);
2400 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
2401 coordFontID = XLoadFont(xDisplay, appData.coordFont);
2402 coordFontStruct = XQueryFont(xDisplay, coordFontID);
2403 appData.font = FindFont(appData.font, fontPxlSize);
2404 countFontID = XLoadFont(xDisplay, appData.coordFont); // [HGM] holdings
2405 countFontStruct = XQueryFont(xDisplay, countFontID);
2406 // appData.font = FindFont(appData.font, fontPxlSize);
2408 xdb = XtDatabase(xDisplay);
2409 XrmPutStringResource(&xdb, "*font", appData.font);
2412 * Detect if there are not enough colors available and adapt.
2414 if (DefaultDepth(xDisplay, xScreen) <= 2) {
2415 appData.monoMode = True;
2418 if (!appData.monoMode) {
2419 vFrom.addr = (caddr_t) appData.lightSquareColor;
2420 vFrom.size = strlen(appData.lightSquareColor);
2421 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2422 if (vTo.addr == NULL) {
2423 appData.monoMode = True;
2426 lightSquareColor = *(Pixel *) vTo.addr;
2429 if (!appData.monoMode) {
2430 vFrom.addr = (caddr_t) appData.darkSquareColor;
2431 vFrom.size = strlen(appData.darkSquareColor);
2432 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2433 if (vTo.addr == NULL) {
2434 appData.monoMode = True;
2437 darkSquareColor = *(Pixel *) vTo.addr;
2440 if (!appData.monoMode) {
2441 vFrom.addr = (caddr_t) appData.whitePieceColor;
2442 vFrom.size = strlen(appData.whitePieceColor);
2443 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2444 if (vTo.addr == NULL) {
2445 appData.monoMode = True;
2448 whitePieceColor = *(Pixel *) vTo.addr;
2451 if (!appData.monoMode) {
2452 vFrom.addr = (caddr_t) appData.blackPieceColor;
2453 vFrom.size = strlen(appData.blackPieceColor);
2454 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2455 if (vTo.addr == NULL) {
2456 appData.monoMode = True;
2459 blackPieceColor = *(Pixel *) vTo.addr;
2463 if (!appData.monoMode) {
2464 vFrom.addr = (caddr_t) appData.highlightSquareColor;
2465 vFrom.size = strlen(appData.highlightSquareColor);
2466 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2467 if (vTo.addr == NULL) {
2468 appData.monoMode = True;
2471 highlightSquareColor = *(Pixel *) vTo.addr;
2475 if (!appData.monoMode) {
2476 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
2477 vFrom.size = strlen(appData.premoveHighlightColor);
2478 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2479 if (vTo.addr == NULL) {
2480 appData.monoMode = True;
2483 premoveHighlightColor = *(Pixel *) vTo.addr;
2488 fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2491 if (appData.bitmapDirectory == NULL ||
2492 appData.bitmapDirectory[0] == NULLCHAR)
2493 appData.bitmapDirectory = DEF_BITMAP_DIR;
2496 if (appData.lowTimeWarning && !appData.monoMode) {
2497 vFrom.addr = (caddr_t) appData.lowTimeWarningColor;
2498 vFrom.size = strlen(appData.lowTimeWarningColor);
2499 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2500 if (vTo.addr == NULL)
2501 appData.monoMode = True;
2503 lowTimeWarningColor = *(Pixel *) vTo.addr;
2506 if (appData.monoMode && appData.debugMode) {
2507 fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2508 (unsigned long) XWhitePixel(xDisplay, xScreen),
2509 (unsigned long) XBlackPixel(xDisplay, xScreen));
2512 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
2513 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
2514 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
2515 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
2516 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
2517 parse_cpair(ColorTell, appData.colorTell) < 0 ||
2518 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
2519 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
2520 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
2521 parse_cpair(ColorNormal, appData.colorNormal) < 0)
2523 if (appData.colorize) {
2525 _("%s: can't parse color names; disabling colorization\n"),
2528 appData.colorize = FALSE;
2530 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2531 textColors[ColorNone].attr = 0;
2533 // XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2539 layoutName = "tinyLayout";
2540 } else if (smallLayout) {
2541 layoutName = "smallLayout";
2543 layoutName = "normalLayout";
2546 if (appData.titleInWindow) {
2547 /* todo check what this appdata does */
2550 if (appData.showButtonBar) {
2551 /* TODO hide button bar if requested */
2555 if (appData.titleInWindow)
2560 if (appData.showButtonBar)
2567 if (appData.showButtonBar)
2577 /* set some checkboxes in the menu according to appData */
2579 if (appData.alwaysPromoteToQueen)
2580 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Always Queen")),TRUE);
2582 if (appData.animateDragging)
2583 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Animate Dragging")),TRUE);
2585 if (appData.animate)
2586 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Animate Moving")),TRUE);
2588 if (appData.autoComment)
2589 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Comment")),TRUE);
2591 if (appData.autoCallFlag)
2592 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Flag")),TRUE);
2594 if (appData.autoFlipView)
2595 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Flip View")),TRUE);
2597 if (appData.autoObserve)
2598 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Observe")),TRUE);
2600 if (appData.autoRaiseBoard)
2601 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Raise Board")),TRUE);
2603 if (appData.autoSaveGames)
2604 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Save")),TRUE);
2606 if (appData.saveGameFile[0] != NULLCHAR)
2608 /* Can't turn this off from menu */
2609 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Save")),TRUE);
2610 gtk_action_set_sensitive(GTK_ACTION (gtk_builder_get_object (builder, "menuOptions.Auto Save")),FALSE);
2613 if (appData.blindfold)
2614 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Blindfold")),TRUE);
2616 if (appData.flashCount > 0)
2617 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Flash Moves")),TRUE);
2619 if (appData.getMoveList)
2620 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Get Move List")),TRUE);
2623 if (appData.highlightDragging)
2624 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Highlight Dragging")),TRUE);
2627 if (appData.highlightLastMove)
2628 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Highlight Last Move")),TRUE);
2630 if (appData.icsAlarm)
2631 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.ICS Alarm")),TRUE);
2633 if (appData.ringBellAfterMoves)
2634 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Move Sound")),TRUE);
2636 if (appData.oldSaveStyle)
2637 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Old Save Style")),TRUE);
2639 if (appData.periodicUpdates)
2640 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Periodic Updates")),TRUE);
2642 if (appData.ponderNextMove)
2643 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Ponder Next Move")),TRUE);
2645 if (appData.popupExitMessage)
2646 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Popup Exit Message")),TRUE);
2648 if (appData.popupMoveErrors)
2649 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Popup Move Errors")),TRUE);
2651 if (appData.premove)
2652 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Premove")),TRUE);
2654 if (appData.quietPlay)
2655 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Quit Play")),TRUE);
2657 if (appData.showCoords)
2658 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Show Coords")),TRUE);
2660 if (appData.showThinking)
2661 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Show Thinking")),TRUE);
2663 if (appData.testLegality)
2664 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Test Legality")),TRUE);
2666 /* end setting check boxes */
2668 /* load square colors */
2669 SVGLightSquare = load_pixbuf("svg/LightSquare.svg",squareSize);
2670 SVGDarkSquare = load_pixbuf("svg/DarkSquare.svg",squareSize);
2671 SVGNeutralSquare = load_pixbuf("svg/NeutralSquare.svg",squareSize);
2673 /* use two icons to indicate if it is white's or black's turn */
2674 WhiteIcon = load_pixbuf("svg/icon_white.svg",0);
2675 BlackIcon = load_pixbuf("svg/icon_black.svg",0);
2676 WindowIcon = WhiteIcon;
2677 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
2680 /* realize window */
2681 gtk_widget_show (GUI_Window);
2683 /* recalc boardsize */
2688 if (appData.animate || appData.animateDragging)
2693 if (errorExitStatus == -1) {
2694 if (appData.icsActive) {
2695 /* We now wait until we see "login:" from the ICS before
2696 sending the logon script (problems with timestamp otherwise) */
2697 /*ICSInitScript();*/
2698 if (appData.icsInputBox) ICSInputBoxPopUp();
2701 signal(SIGINT, IntSigHandler);
2702 signal(SIGTERM, IntSigHandler);
2703 if (*appData.cmailGameName != NULLCHAR) {
2704 signal(SIGUSR1, CmailSigHandler);
2707 gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes()
2711 * Create a cursor for the board widget.
2712 * (This needs to be called after the window has been created to have access to board-window)
2715 BoardCursor = gdk_cursor_new(GDK_HAND2);
2716 gdk_window_set_cursor(GUI_Board->window, BoardCursor);
2717 gdk_cursor_destroy(BoardCursor);
2722 if (appData.debugMode) fclose(debugFP); // [DM] debug
2729 if (appData.icsActive && oldICSInteractionTitle != NULL) {
2730 DisplayIcsInteractionTitle(oldICSInteractionTitle);
2732 unlink(gameCopyFilename);
2733 unlink(gamePasteFilename);
2744 CmailSigHandler(sig)
2750 signal(SIGUSR1, SIG_IGN); /* suspend handler */
2752 /* Activate call-back function CmailSigHandlerCallBack() */
2753 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
2755 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
2759 CmailSigHandlerCallBack(isr, closure, message, count, error)
2767 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
2769 /**** end signal code ****/
2779 f = fopen(appData.icsLogon, "r");
2785 strcat(buf, appData.icsLogon);
2786 f = fopen(buf, "r");
2790 ProcessICSInitScript(f);
2797 EditCommentPopDown();
2803 SetMenuEnables(enab)
2808 if (!builder) return;
2809 while (enab->name != NULL) {
2810 o = gtk_builder_get_object(builder, enab->name);
2811 if(GTK_IS_WIDGET(o))
2812 gtk_widget_set_sensitive(GTK_WIDGET (o),enab->value);
2815 if(GTK_IS_ACTION(o))
2816 gtk_action_set_sensitive(GTK_ACTION (o),enab->value);
2818 DisplayError(enab->name, 0);
2826 SetMenuEnables(icsEnables);
2829 if (appData.zippyPlay && !appData.noChessProgram) /* [DM] icsEngineAnalyze */
2830 {}; // XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
2837 SetMenuEnables(ncpEnables);
2843 SetMenuEnables(gnuEnables);
2849 SetMenuEnables(cmailEnables);
2855 SetMenuEnables(trainingOnEnables);
2856 if (appData.showButtonBar) {
2857 // XtSetSensitive(buttonBarWidget, False);
2863 SetTrainingModeOff()
2865 SetMenuEnables(trainingOffEnables);
2866 if (appData.showButtonBar) {
2867 // XtSetSensitive(buttonBarWidget, True);
2872 SetUserThinkingEnables()
2874 if (appData.noChessProgram) return;
2875 SetMenuEnables(userThinkingEnables);
2879 SetMachineThinkingEnables()
2881 if (appData.noChessProgram) return;
2882 SetMenuEnables(machineThinkingEnables);
2884 case MachinePlaysBlack:
2885 case MachinePlaysWhite:
2886 case TwoMachinesPlay:
2887 // XtSetSensitive(XtNameToWidget(menuBarWidget,
2888 // ModeToWidgetName(gameMode)), True);
2895 #define Abs(n) ((n)<0 ? -(n) : (n))
2898 * Find a font that matches "pattern" that is as close as
2899 * possible to the targetPxlSize. Prefer fonts that are k
2900 * pixels smaller to fonts that are k pixels larger. The
2901 * pattern must be in the X Consortium standard format,
2902 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
2903 * The return value should be freed with XtFree when no
2906 char *FindFont(pattern, targetPxlSize)
2910 char **fonts, *p, *best, *scalable, *scalableTail;
2911 int i, j, nfonts, minerr, err, pxlSize;
2914 char **missing_list;
2916 char *def_string, *base_fnt_lst, strInt[3];
2918 XFontStruct **fnt_list;
2920 base_fnt_lst = calloc(1, strlen(pattern) + 3);
2921 sprintf(strInt, "%d", targetPxlSize);
2922 p = strstr(pattern, "--");
2923 strncpy(base_fnt_lst, pattern, p - pattern + 2);
2924 strcat(base_fnt_lst, strInt);
2925 strcat(base_fnt_lst, strchr(p + 2, '-'));
2927 if ((fntSet = XCreateFontSet(xDisplay,
2931 &def_string)) == NULL) {
2933 fprintf(stderr, _("Unable to create font set.\n"));
2937 nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
2939 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
2941 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
2942 programName, pattern);
2950 for (i=0; i<nfonts; i++) {
2953 if (*p != '-') continue;
2955 if (*p == NULLCHAR) break;
2956 if (*p++ == '-') j++;
2958 if (j < 7) continue;
2961 scalable = fonts[i];
2964 err = pxlSize - targetPxlSize;
2965 if (Abs(err) < Abs(minerr) ||
2966 (minerr > 0 && err < 0 && -err == minerr)) {
2972 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
2973 /* If the error is too big and there is a scalable font,
2974 use the scalable font. */
2975 int headlen = scalableTail - scalable;
2976 p = (char *) XtMalloc(strlen(scalable) + 10);
2977 while (isdigit(*scalableTail)) scalableTail++;
2978 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
2980 p = (char *) XtMalloc(strlen(best) + 1);
2983 if (appData.debugMode) {
2984 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
2985 pattern, targetPxlSize, p);
2988 if (missing_count > 0)
2989 XFreeStringList(missing_list);
2990 XFreeFontSet(xDisplay, fntSet);
2992 XFreeFontNames(fonts);
2999 /* 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*/
3001 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
3002 | GCBackground | GCFunction | GCPlaneMask;
3003 XGCValues gc_values;
3006 gc_values.plane_mask = AllPlanes;
3007 gc_values.line_width = lineGap;
3008 gc_values.line_style = LineSolid;
3009 gc_values.function = GXcopy;
3011 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3012 gc_values.background = XWhitePixel(xDisplay, xScreen);
3013 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
3014 XSetFont(xDisplay, coordGC, coordFontID);
3016 if (appData.monoMode) {
3017 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3018 gc_values.background = XBlackPixel(xDisplay, xScreen);
3019 lightSquareGC = wbPieceGC
3020 = XtGetGC(shellWidget, value_mask, &gc_values);
3022 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3023 gc_values.background = XWhitePixel(xDisplay, xScreen);
3024 darkSquareGC = bwPieceGC
3025 = XtGetGC(shellWidget, value_mask, &gc_values);
3027 if (DefaultDepth(xDisplay, xScreen) == 1) {
3028 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3029 gc_values.function = GXcopyInverted;
3030 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3031 gc_values.function = GXcopy;
3032 if (XBlackPixel(xDisplay, xScreen) == 1) {
3033 bwPieceGC = darkSquareGC;
3034 wbPieceGC = copyInvertedGC;
3036 bwPieceGC = copyInvertedGC;
3037 wbPieceGC = lightSquareGC;
3041 gc_values.foreground = lightSquareColor;
3042 gc_values.background = darkSquareColor;
3043 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3045 gc_values.foreground = darkSquareColor;
3046 gc_values.background = lightSquareColor;
3047 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3049 gc_values.foreground = jailSquareColor;
3050 gc_values.background = jailSquareColor;
3051 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3053 gc_values.foreground = whitePieceColor;
3054 gc_values.background = darkSquareColor;
3055 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3057 gc_values.foreground = whitePieceColor;
3058 gc_values.background = lightSquareColor;
3059 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3061 gc_values.foreground = whitePieceColor;
3062 gc_values.background = jailSquareColor;
3063 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3065 gc_values.foreground = blackPieceColor;
3066 gc_values.background = darkSquareColor;
3067 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3069 gc_values.foreground = blackPieceColor;
3070 gc_values.background = lightSquareColor;
3071 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3073 gc_values.foreground = blackPieceColor;
3074 gc_values.background = jailSquareColor;
3075 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3084 for(i=0;i<MAXPIECES;i++)
3088 g_free(SVGpieces[i]);
3095 SVGLightSquare = load_pixbuf("svg/LightSquare.svg",squareSize);
3096 SVGDarkSquare = load_pixbuf("svg/DarkSquare.svg",squareSize);
3097 SVGNeutralSquare = load_pixbuf("svg/NeutralSquare.svg",squareSize);
3100 /* get some defaults going */
3101 for(i=WhitePawn; i<DemotePiece+1; i++)
3102 SVGpieces[i] = load_pixbuf("svg/NeutralSquare.svg",squareSize);
3104 SVGpieces[WhitePawn] = load_pixbuf("svg/WhitePawn.svg",squareSize);
3105 SVGpieces[WhiteKnight] = load_pixbuf("svg/WhiteKnight.svg",squareSize);
3106 SVGpieces[WhiteBishop] = load_pixbuf("svg/WhiteBishop.svg",squareSize);
3107 SVGpieces[WhiteRook] = load_pixbuf("svg/WhiteRook.svg",squareSize);
3108 SVGpieces[WhiteQueen] = load_pixbuf("svg/WhiteQueen.svg",squareSize);
3109 SVGpieces[WhiteKing] = load_pixbuf("svg/WhiteKing.svg",squareSize);
3111 SVGpieces[BlackPawn] = load_pixbuf("svg/BlackPawn.svg",squareSize);
3112 SVGpieces[BlackKnight] = load_pixbuf("svg/BlackKnight.svg",squareSize);
3113 SVGpieces[BlackBishop] = load_pixbuf("svg/BlackBishop.svg",squareSize);
3114 SVGpieces[BlackRook] = load_pixbuf("svg/BlackRook.svg",squareSize);
3115 SVGpieces[BlackQueen] = load_pixbuf("svg/BlackQueen.svg",squareSize);
3116 SVGpieces[BlackKing] = load_pixbuf("svg/BlackKing.svg",squareSize);
3122 static void MenuBarSelect(w, addr, index)
3127 XtActionProc proc = (XtActionProc) addr;
3129 (proc)(NULL, NULL, NULL, NULL);
3132 void CreateMenuBarPopup(parent, name, mb)
3142 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3145 XtSetArg(args[j], XtNleftMargin, 20); j++;
3146 XtSetArg(args[j], XtNrightMargin, 20); j++;
3148 while (mi->string != NULL) {
3149 if (strcmp(mi->string, "----") == 0) {
3150 entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
3153 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string)));
3154 entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass,
3156 XtAddCallback(entry, XtNcallback,
3157 (XtCallbackProc) MenuBarSelect,
3158 (caddr_t) mi->proc);
3164 Widget CreateMenuBar(mb)
3168 Widget anchor, menuBar;
3170 char menuName[MSG_SIZ];
3173 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3174 XtSetArg(args[j], XtNvSpace, 0); j++;
3175 XtSetArg(args[j], XtNborderWidth, 0); j++;
3176 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
3177 formWidget, args, j);
3179 while (mb->name != NULL) {
3180 strcpy(menuName, "menu");
3181 strcat(menuName, mb->name);
3183 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
3186 shortName[0] = _(mb->name)[0];
3187 shortName[1] = NULLCHAR;
3188 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
3191 XtSetArg(args[j], XtNlabel, XtNewString(_(mb->name))); j++;
3194 XtSetArg(args[j], XtNborderWidth, 0); j++;
3195 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
3197 CreateMenuBarPopup(menuBar, menuName, mb);
3205 CreatePieceMenu(name, color)
3212 ChessSquare selection;
3214 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3215 boardWidget, args, 0);
3217 for (i = 0; i < PIECE_MENU_SIZE; i++) {
3218 String item = pieceMenuStrings[color][i];
3220 if (strcmp(item, "----") == 0) {
3221 entry = XtCreateManagedWidget(item, smeLineObjectClass,
3224 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3225 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3227 selection = pieceMenuTranslation[color][i];
3228 XtAddCallback(entry, XtNcallback,
3229 (XtCallbackProc) PieceMenuSelect,
3230 (caddr_t) selection);
3231 if (selection == WhitePawn || selection == BlackPawn) {
3232 XtSetArg(args[0], XtNpopupOnEntry, entry);
3233 XtSetValues(menu, args, 1);
3246 ChessSquare selection;
3248 // whitePieceMenu = CreatePieceMenu("menuW", 0);
3249 // blackPieceMenu = CreatePieceMenu("menuB", 1);
3251 // XtRegisterGrabAction(PieceMenuPopup, True,
3252 // (unsigned)(ButtonPressMask|ButtonReleaseMask),
3253 // GrabModeAsync, GrabModeAsync);
3255 // XtSetArg(args[0], XtNlabel, _("Drop"));
3256 // dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
3257 // boardWidget, args, 1);
3258 // for (i = 0; i < DROP_MENU_SIZE; i++) {
3259 // String item = dropMenuStrings[i];
3261 // if (strcmp(item, "----") == 0) {
3262 // entry = XtCreateManagedWidget(item, smeLineObjectClass,
3263 // dropMenu, NULL, 0);
3265 // XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3266 // entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3267 // dropMenu, args, 1);
3268 // selection = dropMenuTranslation[i];
3269 // XtAddCallback(entry, XtNcallback,
3270 // (XtCallbackProc) DropMenuSelect,
3271 // (caddr_t) selection);
3276 void SetupDropMenu()
3284 for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
3285 entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
3286 p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
3287 dmEnables[i].piece);
3288 XtSetSensitive(entry, p != NULL || !appData.testLegality
3289 /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
3290 && !appData.icsActive));
3292 while (p && *p++ == dmEnables[i].piece) count++;
3293 snprintf(label, sizeof(label), "%s %d", dmEnables[i].widget, count);
3295 XtSetArg(args[j], XtNlabel, label); j++;
3296 XtSetValues(entry, args, j);
3300 void PieceMenuPopup(w, event, params, num_params)
3304 Cardinal *num_params;
3307 if (event->type != ButtonPress) return;
3308 if (errorUp) ErrorPopDown();
3312 whichMenu = params[0];
3314 case IcsPlayingWhite:
3315 case IcsPlayingBlack:
3317 case MachinePlaysWhite:
3318 case MachinePlaysBlack:
3319 if (appData.testLegality &&
3320 gameInfo.variant != VariantBughouse &&
3321 gameInfo.variant != VariantCrazyhouse) return;
3323 whichMenu = "menuD";
3329 if (((pmFromX = EventToSquare(event->xbutton.x, BOARD_WIDTH)) < 0) ||
3330 ((pmFromY = EventToSquare(event->xbutton.y, BOARD_HEIGHT)) < 0)) {
3331 pmFromX = pmFromY = -1;
3335 pmFromX = BOARD_WIDTH - 1 - pmFromX;
3337 pmFromY = BOARD_HEIGHT - 1 - pmFromY;
3339 XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
3342 static void PieceMenuSelect(w, piece, junk)
3347 if (pmFromX < 0 || pmFromY < 0) return;
3348 EditPositionMenuEvent(piece, pmFromX, pmFromY);
3351 static void DropMenuSelect(w, piece, junk)
3356 if (pmFromX < 0 || pmFromY < 0) return;
3357 DropMenuEvent(piece, pmFromX, pmFromY);
3360 void WhiteClock(w, event, prms, nprms)
3366 if (gameMode == EditPosition || gameMode == IcsExamining) {
3367 SetWhiteToPlayEvent();
3368 } else if (gameMode == IcsPlayingBlack || gameMode == MachinePlaysWhite) {
3373 void BlackClock(w, event, prms, nprms)
3379 if (gameMode == EditPosition || gameMode == IcsExamining) {
3380 SetBlackToPlayEvent();
3381 } else if (gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) {
3388 * If the user selects on a border boundary, return -1; if off the board,
3389 * return -2. Otherwise map the event coordinate to the square.
3391 int EventToSquare(x, limit)
3399 if ((x % (squareSize + lineGap)) >= squareSize)
3401 x /= (squareSize + lineGap);
3407 static void do_flash_delay(msec)
3413 static void drawHighlight(file, rank, line_type)
3414 int file, rank, line_type;
3419 if (lineGap == 0 || appData.blindfold) return;
3423 x = lineGap/2 + ((BOARD_WIDTH-1)-file) *
3424 (squareSize + lineGap);
3425 y = lineGap/2 + rank * (squareSize + lineGap);
3429 x = lineGap/2 + file * (squareSize + lineGap);
3430 y = lineGap/2 + ((BOARD_HEIGHT-1)-rank) *
3431 (squareSize + lineGap);
3435 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3437 /* draw the highlight */
3438 cairo_move_to (cr, x, y);
3439 cairo_rel_line_to (cr, 0,squareSize+lineGap);
3440 cairo_rel_line_to (cr, squareSize+lineGap,0);
3441 cairo_rel_line_to (cr, 0,-squareSize-lineGap);
3442 cairo_close_path (cr);
3444 cairo_set_line_width (cr, lineGap);
3447 /* TODO: use appdata colors */
3448 case LINE_TYPE_HIGHLIGHT:
3449 cairo_set_source_rgba (cr, 1, 1, 0, 1.0);
3452 cairo_set_source_rgba (cr, 1, 0, 0, 1.0);
3454 case LINE_TYPE_NORMAL:
3456 cairo_set_source_rgba (cr, 0, 1, 0, 1.0);
3467 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
3468 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
3471 SetHighlights(fromX, fromY, toX, toY)
3472 int fromX, fromY, toX, toY;
3474 if (hi1X != fromX || hi1Y != fromY)
3476 if (hi1X >= 0 && hi1Y >= 0)
3478 drawHighlight(hi1X, hi1Y, LINE_TYPE_NORMAL);
3480 if (fromX >= 0 && fromY >= 0)
3482 drawHighlight(fromX, fromY, LINE_TYPE_HIGHLIGHT);
3485 if (hi2X != toX || hi2Y != toY)
3487 if (hi2X >= 0 && hi2Y >= 0)
3489 drawHighlight(hi2X, hi2Y, LINE_TYPE_NORMAL);
3491 if (toX >= 0 && toY >= 0)
3493 drawHighlight(toX, toY, LINE_TYPE_HIGHLIGHT);
3507 SetHighlights(-1, -1, -1, -1);
3512 SetPremoveHighlights(fromX, fromY, toX, toY)
3513 int fromX, fromY, toX, toY;
3515 if (pm1X != fromX || pm1Y != fromY)
3517 if (pm1X >= 0 && pm1Y >= 0)
3519 drawHighlight(pm1X, pm1Y, LINE_TYPE_NORMAL);
3521 if (fromX >= 0 && fromY >= 0)
3523 drawHighlight(fromX, fromY, LINE_TYPE_PRE);
3526 if (pm2X != toX || pm2Y != toY)
3528 if (pm2X >= 0 && pm2Y >= 0)
3530 drawHighlight(pm2X, pm2Y, LINE_TYPE_NORMAL);
3532 if (toX >= 0 && toY >= 0)
3534 drawHighlight(toX, toY, LINE_TYPE_PRE);
3547 ClearPremoveHighlights()
3549 SetPremoveHighlights(-1, -1, -1, -1);
3552 static void BlankSquare(x, y, color, piece, dest)
3565 pb = SVGLightSquare;
3567 case 2: /* neutral */
3569 pb = SVGNeutralSquare;
3572 gdk_draw_pixbuf(GDK_WINDOW(GUI_Board->window),NULL,pb,0,0,x,y,-1,-1, GDK_RGB_DITHER_NORMAL, 0, 0);
3576 static void DrawPiece(piece, square_color, x, y, dest)
3578 int square_color, x, y;
3581 /* redraw background, since piece might be transparent in some areas */
3582 BlankSquare(x,y,square_color,piece,dest);
3585 gdk_draw_pixbuf(GDK_WINDOW(GUI_Board->window),NULL,
3586 GDK_PIXBUF(SVGpieces[piece]),0,0,x,y,-1,-1,
3587 GDK_RGB_DITHER_NORMAL, 0, 0);
3591 /* [HR] determine square color depending on chess variant. */
3592 static int SquareColor(row, column)
3597 if (gameInfo.variant == VariantXiangqi) {
3598 if (column >= 3 && column <= 5 && row >= 0 && row <= 2) {
3600 } else if (column >= 3 && column <= 5 && row >= 7 && row <= 9) {
3602 } else if (row <= 4) {
3608 square_color = ((column + row) % 2) == 1;
3611 /* [hgm] holdings: next line makes all holdings squares light */
3612 if(column < BOARD_LEFT || column >= BOARD_RGHT) square_color = 1;
3614 return square_color;
3617 void DrawSquare(row, column, piece, do_flash)
3618 int row, column, do_flash;
3621 int square_color, x, y;
3626 /* Calculate delay in milliseconds (2-delays per complete flash) */
3627 flash_delay = 500 / appData.flashRate;
3629 /* calculate x and y coordinates from row and column */
3632 x = lineGap + ((BOARD_WIDTH-1)-column) *
3633 (squareSize + lineGap);
3634 y = lineGap + row * (squareSize + lineGap);
3638 x = lineGap + column * (squareSize + lineGap);
3639 y = lineGap + ((BOARD_HEIGHT-1)-row) *
3640 (squareSize + lineGap);
3643 square_color = SquareColor(row, column);
3645 // [HGM] holdings: blank out area between board and holdings
3646 if ( column == BOARD_LEFT-1 || column == BOARD_RGHT
3647 || (column == BOARD_LEFT-2 && row < BOARD_HEIGHT-gameInfo.holdingsSize)
3648 || (column == BOARD_RGHT+1 && row >= gameInfo.holdingsSize) )
3650 BlankSquare(x, y, 2, EmptySquare, xBoardWindow);
3652 // [HGM] print piece counts next to holdings
3653 string[1] = NULLCHAR;
3656 cairo_text_extents_t extents;
3661 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3663 string[0] = '0' + piece;
3665 /* TODO this has to go into the font-selection */
3666 cairo_select_font_face (cr, "Sans",
3667 CAIRO_FONT_SLANT_NORMAL,
3668 CAIRO_FONT_WEIGHT_NORMAL);
3670 cairo_set_font_size (cr, 12.0);
3671 cairo_text_extents (cr, string, &extents);
3673 if (column == (flipView ? BOARD_LEFT-1 : BOARD_RGHT) )
3675 xpos= x + squareSize - extents.width - 2;
3676 ypos= y + extents.y_bearing + 1;
3678 if (column == (flipView ? BOARD_RGHT : BOARD_LEFT-1) && piece > 1)
3681 ypos = y + extents.y_bearing + 1;
3684 /* TODO mono mode? */
3685 cairo_move_to (cr, xpos, ypos);
3686 cairo_text_path (cr, string);
3687 cairo_set_source_rgb (cr, 1.0, 1.0, 1);
3688 cairo_fill_preserve (cr);
3689 cairo_set_source_rgb (cr, 0, 0, 0);
3690 cairo_set_line_width (cr, 0.1);
3699 /* square on the board */
3700 if (piece == EmptySquare || appData.blindfold)
3702 BlankSquare(x, y, square_color, piece, xBoardWindow);
3706 if (do_flash && appData.flashCount > 0)
3708 for (i=0; i<appData.flashCount; ++i)
3711 DrawPiece(piece, square_color, x, y, xBoardWindow);
3712 do_flash_delay(flash_delay);
3714 BlankSquare(x, y, square_color, piece, xBoardWindow);
3715 do_flash_delay(flash_delay);
3718 DrawPiece(piece, square_color, x, y, xBoardWindow);
3722 /* show coordinates if necessary */
3723 if(appData.showCoords)
3725 cairo_text_extents_t extents;
3729 /* TODO this has to go into the font-selection */
3730 cairo_select_font_face (cr, "Sans",
3731 CAIRO_FONT_SLANT_NORMAL,
3732 CAIRO_FONT_WEIGHT_NORMAL);
3733 cairo_set_font_size (cr, 12.0);
3735 string[1] = NULLCHAR;
3738 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3740 if (row == (flipView ? BOARD_HEIGHT-1 : 0) &&
3741 column >= BOARD_LEFT && column < BOARD_RGHT)
3743 string[0] = 'a' + column - BOARD_LEFT;
3744 cairo_text_extents (cr, string, &extents);
3746 xpos = x + squareSize - extents.width - 2;
3747 ypos = y + squareSize - extents.height - extents.y_bearing - 1;
3749 if (appData.monoMode)
3756 cairo_move_to (cr, xpos, ypos);
3757 cairo_text_path (cr, string);
3758 cairo_set_source_rgb (cr, 0.0, 0.0, 0);
3759 cairo_fill_preserve (cr);
3760 cairo_set_source_rgb (cr, 0, 1.0, 0);
3761 cairo_set_line_width (cr, 0.1);
3764 if ( column == (flipView ? BOARD_RGHT-1 : BOARD_LEFT))
3767 string[0] = ONE + row;
3768 cairo_text_extents (cr, string, &extents);
3771 ypos = y + extents.height + 1;
3773 if (appData.monoMode)
3780 cairo_move_to (cr, xpos, ypos);
3781 cairo_text_path (cr, string);
3782 cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
3783 cairo_fill_preserve (cr);
3784 cairo_set_source_rgb (cr, 0, 0, 1.0);
3785 cairo_set_line_width (cr, 0.1);
3797 /* Returns 1 if there are "too many" differences between b1 and b2
3798 (i.e. more than 1 move was made) */
3799 static int too_many_diffs(b1, b2)
3805 for (i=0; i<BOARD_HEIGHT; ++i) {
3806 for (j=0; j<BOARD_WIDTH; ++j) {
3807 if (b1[i][j] != b2[i][j]) {
3808 if (++c > 4) /* Castling causes 4 diffs */
3817 /* Matrix describing castling maneuvers */
3818 /* Row, ColRookFrom, ColKingFrom, ColRookTo, ColKingTo */
3819 static int castling_matrix[4][5] = {
3820 { 0, 0, 4, 3, 2 }, /* 0-0-0, white */
3821 { 0, 7, 4, 5, 6 }, /* 0-0, white */
3822 { 7, 0, 4, 3, 2 }, /* 0-0-0, black */
3823 { 7, 7, 4, 5, 6 } /* 0-0, black */
3826 /* Checks whether castling occurred. If it did, *rrow and *rcol
3827 are set to the destination (row,col) of the rook that moved.
3829 Returns 1 if castling occurred, 0 if not.
3831 Note: Only handles a max of 1 castling move, so be sure
3832 to call too_many_diffs() first.
3834 static int check_castle_draw(newb, oldb, rrow, rcol)
3841 /* For each type of castling... */
3842 for (i=0; i<4; ++i) {
3843 r = castling_matrix[i];
3845 /* Check the 4 squares involved in the castling move */
3847 for (j=1; j<=4; ++j) {
3848 if (newb[r[0]][r[j]] == oldb[r[0]][r[j]]) {
3855 /* All 4 changed, so it must be a castling move */
3864 static int damage[BOARD_SIZE][BOARD_SIZE];
3867 * event handler for redrawing the board
3869 void DrawPosition( repaint, board)
3870 /*Boolean*/int repaint;
3874 static int lastFlipView = 0;
3875 static int lastBoardValid = 0;
3876 static Board lastBoard;
3879 if (board == NULL) {
3880 if (!lastBoardValid) return;
3883 if (!lastBoardValid || lastFlipView != flipView) {
3884 // XtSetArg(args[0], XtNleftBitmap, (flipView ? xMarkPixmap : None));
3885 // XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flip View"),
3890 * It would be simpler to clear the window with XClearWindow()
3891 * but this causes a very distracting flicker.
3894 if (!repaint && lastBoardValid && lastFlipView == flipView)
3896 /* If too much changes (begin observing new game, etc.), don't
3898 do_flash = too_many_diffs(board, lastBoard) ? 0 : 1;
3900 /* Special check for castling so we don't flash both the king
3901 and the rook (just flash the king). */
3904 if (check_castle_draw(board, lastBoard, &rrow, &rcol))
3906 /* Draw rook with NO flashing. King will be drawn flashing later */
3907 DrawSquare(rrow, rcol, board[rrow][rcol], 0);
3908 lastBoard[rrow][rcol] = board[rrow][rcol];
3912 /* First pass -- Draw (newly) empty squares and repair damage.
3913 This prevents you from having a piece show up twice while it
3914 is flashing on its new square */
3915 for (i = 0; i < BOARD_HEIGHT; i++)
3916 for (j = 0; j < BOARD_WIDTH; j++)
3917 if ((board[i][j] != lastBoard[i][j] && board[i][j] == EmptySquare)
3920 DrawSquare(i, j, board[i][j], 0);
3921 damage[i][j] = False;
3924 /* Second pass -- Draw piece(s) in new position and flash them */
3925 for (i = 0; i < BOARD_HEIGHT; i++)
3926 for (j = 0; j < BOARD_WIDTH; j++)
3927 if (board[i][j] != lastBoard[i][j])
3929 DrawSquare(i, j, board[i][j], do_flash);
3941 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3943 cairo_set_line_width (cr, lineGap);
3945 /* TODO: use appdata colors */
3946 cairo_set_source_rgba (cr, 0, 1, 0, 1.0);
3950 for (i = 0; i < BOARD_HEIGHT + 1; i++)
3953 x2 = lineGap + BOARD_WIDTH * (squareSize + lineGap);
3954 y1 = y2 = lineGap / 2 + (i * (squareSize + lineGap));
3956 cairo_move_to (cr, x1, y1);
3957 cairo_rel_line_to (cr, x2,0);
3961 for (j = 0; j < BOARD_WIDTH + 1; j++)
3964 y2 = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
3965 x1 = x2 = lineGap / 2 + (j * (squareSize + lineGap));
3967 cairo_move_to (cr, x1, y1);
3968 cairo_rel_line_to (cr, 0, y2);
3977 for (i = 0; i < BOARD_HEIGHT; i++)
3978 for (j = 0; j < BOARD_WIDTH; j++)
3980 DrawSquare(i, j, board[i][j], 0);
3981 damage[i][j] = False;
3985 CopyBoard(lastBoard, board);
3987 lastFlipView = flipView;
3989 /* Draw highlights */
3990 if (pm1X >= 0 && pm1Y >= 0)
3992 drawHighlight(pm1X, pm1Y, LINE_TYPE_PRE);
3994 if (pm2X >= 0 && pm2Y >= 0)
3996 drawHighlight(pm2X, pm2Y, LINE_TYPE_PRE);
3998 if (hi1X >= 0 && hi1Y >= 0)
4000 drawHighlight(hi1X, hi1Y, LINE_TYPE_HIGHLIGHT);
4002 if (hi2X >= 0 && hi2Y >= 0)
4004 drawHighlight(hi2X, hi2Y, LINE_TYPE_HIGHLIGHT);
4007 /* If piece being dragged around board, must redraw that too */
4014 * event handler for parsing user moves
4016 // [HGM] This routine will need quite some reworking. Although the backend still supports the old
4017 // way of doing things, by calling UserMoveEvent() to test the legality of the move and then perform
4018 // it at the end, and doing all kind of preliminary tests here (e.g. to weed out self-captures), it
4019 // should be made to use the new way, of calling UserMoveTest early to determine the legality of the
4020 // move, (which will weed out the illegal selfcaptures and moves into the holdings, and flag promotions),
4021 // and at the end FinishMove() to perform the move after optional promotion popups.
4022 // For now I patched it to allow self-capture with King, and suppress clicks between board and holdings.
4023 void HandleUserMove(w, event, prms, nprms)
4030 Boolean saveAnimate;
4031 static int second = 0, promotionChoice = 0;
4034 if (w != boardWidget || errorExitStatus != -1) return;
4036 x = EventToSquare(event->xbutton.x, BOARD_WIDTH);
4037 y = EventToSquare(event->xbutton.y, BOARD_HEIGHT);
4038 if (!flipView && y >= 0) {
4039 y = BOARD_HEIGHT - 1 - y;
4041 if (flipView && x >= 0) {
4042 x = BOARD_WIDTH - 1 - x;
4045 if(promotionChoice) { // we are waiting for a click to indicate promotion piece
4046 if(event->type == ButtonRelease) return; // ignore upclick of click-click destination
4047 promotionChoice = FALSE; // only one chance: if click not OK it is interpreted as cancel
4048 if(appData.debugMode) fprintf(debugFP, "promotion click, x=%d, y=%d\n", x, y);
4049 if(gameInfo.holdingsWidth &&
4050 (WhiteOnMove(currentMove)
4051 ? x == BOARD_WIDTH-1 && y < gameInfo.holdingsSize && y > 0
4052 : x == 0 && y >= BOARD_HEIGHT - gameInfo.holdingsSize && y < BOARD_HEIGHT-1) ) {
4053 // click in right holdings, for determining promotion piece
4054 ChessSquare p = boards[currentMove][y][x];
4055 if(appData.debugMode) fprintf(debugFP, "square contains %d\n", (int)p);
4056 if(p != EmptySquare) {
4057 FinishMove(NormalMove, fromX, fromY, toX, toY, ToLower(PieceToChar(p)));
4062 DrawPosition(FALSE, boards[currentMove]);
4065 if (event->type == ButtonPress) ErrorPopDown();
4068 if (event->type == ButtonPress) {
4069 // XtPopdown(promotionShell);
4070 // XtDestroyWidget(promotionShell);
4071 promotionUp = False;
4079 /* [HGM] holdings: next 5 lines: ignore all clicks between board and holdings */
4080 if(event->type == ButtonPress
4081 && ( x == BOARD_LEFT-1 ||
4083 (x == BOARD_LEFT-2 && y < BOARD_HEIGHT-gameInfo.holdingsSize ) ||
4084 (x == BOARD_RGHT+1 && y >= gameInfo.holdingsSize)) )
4088 if (event->type == ButtonPress) {
4089 /* First square, prepare to drag */
4090 if (OKToStartUserMove(x, y)) {
4094 DragPieceBegin(event->xbutton.x, event->xbutton.y);
4095 if (appData.highlightDragging) {
4096 SetHighlights(x, y, -1, -1);
4104 if (event->type == ButtonRelease && x == fromX && y == fromY) {
4105 /* Click on single square in stead of drag-drop */
4106 DragPieceEnd(event->xbutton.x, event->xbutton.y);
4107 if (appData.animateDragging) {
4108 /* Undo animation damage if any */
4109 DrawPosition(FALSE, NULL);
4112 /* Second up/down in same square; just abort move */
4117 ClearPremoveHighlights();
4119 /* First upclick in same square; start click-click mode */
4120 SetHighlights(x, y, -1, -1);
4125 moveType = UserMoveTest(fromX, fromY, x, y, NULLCHAR, event->type == ButtonRelease);
4127 if (moveType == Comment) { // kludge for indicating capture-own on Press
4128 /* Clicked again on same color piece -- changed his mind */
4129 /* note that re-clicking same square always hits same color piece */
4130 second = (x == fromX && y == fromY);
4131 if (appData.highlightDragging) {
4132 SetHighlights(x, y, -1, -1);
4136 if (OKToStartUserMove(x, y)) {
4139 DragPieceBegin(event->xbutton.x, event->xbutton.y);
4144 if(moveType == AmbiguousMove) { // kludge to indicate edit-position move
4147 DragPieceEnd(event->xbutton.x, event->xbutton.y);
4148 DrawPosition(FALSE, boards[currentMove]);
4152 /* Complete move; (x,y) is now different from (fromX, fromY) on both Press and Release */
4155 saveAnimate = appData.animate;
4156 if (event->type == ButtonPress) {
4157 /* Finish clickclick move */
4158 if (appData.animate || appData.highlightLastMove) {
4159 SetHighlights(fromX, fromY, toX, toY);
4164 /* Finish drag move */
4165 if (appData.highlightLastMove) {
4166 SetHighlights(fromX, fromY, toX, toY);
4170 DragPieceEnd(event->xbutton.x, event->xbutton.y);
4171 /* Don't animate move and drag both */
4172 appData.animate = FALSE;
4174 if (moveType == WhitePromotionKnight || moveType == BlackPromotionKnight ||
4175 (moveType == WhitePromotionQueen || moveType == BlackPromotionQueen) &&
4176 appData.alwaysPromoteToQueen) { // promotion, but no choice
4177 FinishMove(moveType, fromX, fromY, toX, toY, 'q');
4179 if (moveType == WhitePromotionQueen || moveType == BlackPromotionQueen ) {
4180 SetHighlights(fromX, fromY, toX, toY);
4181 if(gameInfo.variant == VariantSuper || gameInfo.variant == VariantGreat) {
4182 // [HGM] super: promotion to captured piece selected from holdings
4183 ChessSquare p = boards[currentMove][fromY][fromX], q = boards[currentMove][toY][toX];
4184 promotionChoice = TRUE;
4185 // kludge follows to temporarily execute move on display, without promoting yet
4186 boards[currentMove][fromY][fromX] = EmptySquare; // move Pawn to 8th rank
4187 boards[currentMove][toY][toX] = p;
4188 DrawPosition(FALSE, boards[currentMove]);
4189 boards[currentMove][fromY][fromX] = p; // take back, but display stays
4190 boards[currentMove][toY][toX] = q;
4191 DisplayMessage("Click in holdings to choose piece", "");
4195 goto skipClearingFrom; // the skipped stuff is done asynchronously by PromotionCallback
4197 if(moveType != ImpossibleMove) { // valid move, but no promotion
4198 FinishMove(moveType, fromX, fromY, toX, toY, NULLCHAR);
4199 } else { // invalid move; could have set premove
4202 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
4203 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
4206 appData.animate = saveAnimate;
4207 if (appData.animate || appData.animateDragging) {
4208 /* Undo animation damage if needed */
4209 DrawPosition(FALSE, NULL);
4213 void AnimateUserMove (Widget w, XEvent * event,
4214 String * params, Cardinal * nParams)
4216 DragPieceMove(event->xmotion.x, event->xmotion.y);
4219 Widget CommentCreate(name, text, mutable, callback, lines)
4221 int /*Boolean*/ mutable;
4222 XtCallbackProc callback;
4226 Widget shell, layout, form, edit, b_ok, b_cancel, b_clear, b_close, b_edit;
4231 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4232 XtGetValues(boardWidget, args, j);
4235 XtSetArg(args[j], XtNresizable, True); j++;
4238 XtCreatePopupShell(name, topLevelShellWidgetClass,
4239 shellWidget, args, j);
4242 XtCreatePopupShell(name, transientShellWidgetClass,
4243 shellWidget, args, j);
4246 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
4247 layoutArgs, XtNumber(layoutArgs));
4249 XtCreateManagedWidget("form", formWidgetClass, layout,
4250 formArgs, XtNumber(formArgs));
4254 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
4255 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
4257 XtSetArg(args[j], XtNstring, text); j++;
4258 XtSetArg(args[j], XtNtop, XtChainTop); j++;
4259 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4260 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4261 XtSetArg(args[j], XtNright, XtChainRight); j++;
4262 XtSetArg(args[j], XtNresizable, True); j++;
4263 XtSetArg(args[j], XtNwidth, bw_width); j++; /*force wider than buttons*/
4264 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
4265 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
4266 XtSetArg(args[j], XtNautoFill, True); j++;
4267 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
4269 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
4273 XtSetArg(args[j], XtNfromVert, edit); j++;
4274 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4275 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4276 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4277 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4279 XtCreateManagedWidget(_("ok"), commandWidgetClass, form, args, j);
4280 XtAddCallback(b_ok, XtNcallback, callback, (XtPointer) 0);
4283 XtSetArg(args[j], XtNfromVert, edit); j++;
4284 XtSetArg(args[j], XtNfromHoriz, b_ok); j++;
4285 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4286 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4287 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4288 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4290 XtCreateManagedWidget(_("cancel"), commandWidgetClass, form, args, j);
4291 XtAddCallback(b_cancel, XtNcallback, callback, (XtPointer) 0);
4294 XtSetArg(args[j], XtNfromVert, edit); j++;
4295 XtSetArg(args[j], XtNfromHoriz, b_cancel); j++;
4296 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4297 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4298 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4299 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4301 XtCreateManagedWidget(_("clear"), commandWidgetClass, form, args, j);
4302 XtAddCallback(b_clear, XtNcallback, callback, (XtPointer) 0);
4305 XtSetArg(args[j], XtNfromVert, edit); j++;
4306 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4307 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4308 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4309 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4311 XtCreateManagedWidget(_("close"), commandWidgetClass, form, args, j);
4312 XtAddCallback(b_close, XtNcallback, callback, (XtPointer) 0);
4315 XtSetArg(args[j], XtNfromVert, edit); j++;
4316 XtSetArg(args[j], XtNfromHoriz, b_close); j++;
4317 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4318 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4319 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4320 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4322 XtCreateManagedWidget(_("edit"), commandWidgetClass, form, args, j);
4323 XtAddCallback(b_edit, XtNcallback, callback, (XtPointer) 0);
4326 XtRealizeWidget(shell);
4328 if (commentX == -1) {
4331 Dimension pw_height;
4332 Dimension ew_height;
4335 XtSetArg(args[j], XtNheight, &ew_height); j++;
4336 XtGetValues(edit, args, j);
4339 XtSetArg(args[j], XtNheight, &pw_height); j++;
4340 XtGetValues(shell, args, j);
4341 commentH = pw_height + (lines - 1) * ew_height;
4342 commentW = bw_width - 16;
4344 XSync(xDisplay, False);
4346 /* This code seems to tickle an X bug if it is executed too soon
4347 after xboard starts up. The coordinates get transformed as if
4348 the main window was positioned at (0, 0).
4350 XtTranslateCoords(shellWidget,
4351 (bw_width - commentW) / 2, 0 - commentH / 2,
4352 &commentX, &commentY);
4354 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
4355 RootWindowOfScreen(XtScreen(shellWidget)),
4356 (bw_width - commentW) / 2, 0 - commentH / 2,
4361 if (commentY < 0) commentY = 0; /*avoid positioning top offscreen*/
4364 XtSetArg(args[j], XtNheight, commentH); j++;
4365 XtSetArg(args[j], XtNwidth, commentW); j++;
4366 XtSetArg(args[j], XtNx, commentX); j++;
4367 XtSetArg(args[j], XtNy, commentY); j++;
4368 XtSetValues(shell, args, j);
4369 XtSetKeyboardFocus(shell, edit);
4374 /* Used for analysis window and ICS input window */
4375 Widget MiscCreate(name, text, mutable, callback, lines)
4377 int /*Boolean*/ mutable;
4378 XtCallbackProc callback;
4382 Widget shell, layout, form, edit;
4384 Dimension bw_width, pw_height, ew_height, w, h;
4390 XtSetArg(args[j], XtNresizable, True); j++;
4393 XtCreatePopupShell(name, topLevelShellWidgetClass,
4394 shellWidget, args, j);
4397 XtCreatePopupShell(name, transientShellWidgetClass,
4398 shellWidget, args, j);
4401 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
4402 layoutArgs, XtNumber(layoutArgs));
4404 XtCreateManagedWidget("form", formWidgetClass, layout,
4405 formArgs, XtNumber(formArgs));
4409 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
4410 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
4412 XtSetArg(args[j], XtNstring, text); j++;
4413 XtSetArg(args[j], XtNtop, XtChainTop); j++;
4414 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4415 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4416 XtSetArg(args[j], XtNright, XtChainRight); j++;
4417 XtSetArg(args[j], XtNresizable, True); j++;
4418 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
4419 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
4420 XtSetArg(args[j], XtNautoFill, True); j++;
4421 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
4423 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
4425 XtRealizeWidget(shell);
4428 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4429 XtGetValues(boardWidget, args, j);
4432 XtSetArg(args[j], XtNheight, &ew_height); j++;
4433 XtGetValues(edit, args, j);
4436 XtSetArg(args[j], XtNheight, &pw_height); j++;
4437 XtGetValues(shell, args, j);
4438 h = pw_height + (lines - 1) * ew_height;
4441 XSync(xDisplay, False);
4443 /* This code seems to tickle an X bug if it is executed too soon
4444 after xboard starts up. The coordinates get transformed as if
4445 the main window was positioned at (0, 0).
4447 XtTranslateCoords(shellWidget, (bw_width - w) / 2, 0 - h / 2, &x, &y);
4449 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
4450 RootWindowOfScreen(XtScreen(shellWidget)),
4451 (bw_width - w) / 2, 0 - h / 2, &xx, &yy, &junk);
4455 if (y < 0) y = 0; /*avoid positioning top offscreen*/
4458 XtSetArg(args[j], XtNheight, h); j++;
4459 XtSetArg(args[j], XtNwidth, w); j++;
4460 XtSetArg(args[j], XtNx, x); j++;
4461 XtSetArg(args[j], XtNy, y); j++;
4462 XtSetValues(shell, args, j);
4468 static int savedIndex; /* gross that this is global */
4470 void EditCommentPopUp(index, title, text)
4479 if (text == NULL) text = "";
4481 if (editShell == NULL) {
4483 CommentCreate(title, text, True, EditCommentCallback, 4);
4484 XtRealizeWidget(editShell);
4485 CatchDeleteWindow(editShell, "EditCommentPopDown");
4487 edit = XtNameToWidget(editShell, "*form.text");
4489 XtSetArg(args[j], XtNstring, text); j++;
4490 XtSetValues(edit, args, j);
4492 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4493 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4494 XtSetValues(editShell, args, j);
4497 XtPopup(editShell, XtGrabNone);
4501 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
4502 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
4506 void EditCommentCallback(w, client_data, call_data)
4508 XtPointer client_data, call_data;
4516 XtSetArg(args[j], XtNlabel, &name); j++;
4517 XtGetValues(w, args, j);
4519 if (strcmp(name, _("ok")) == 0) {
4520 edit = XtNameToWidget(editShell, "*form.text");
4522 XtSetArg(args[j], XtNstring, &val); j++;
4523 XtGetValues(edit, args, j);
4524 ReplaceComment(savedIndex, val);
4525 EditCommentPopDown();
4526 } else if (strcmp(name, _("cancel")) == 0) {
4527 EditCommentPopDown();
4528 } else if (strcmp(name, _("clear")) == 0) {
4529 edit = XtNameToWidget(editShell, "*form.text");
4530 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
4531 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
4535 void EditCommentPopDown()
4540 if (!editUp) return;
4542 XtSetArg(args[j], XtNx, &commentX); j++;
4543 XtSetArg(args[j], XtNy, &commentY); j++;
4544 XtSetArg(args[j], XtNheight, &commentH); j++;
4545 XtSetArg(args[j], XtNwidth, &commentW); j++;
4546 XtGetValues(editShell, args, j);
4547 XtPopdown(editShell);
4550 XtSetArg(args[j], XtNleftBitmap, None); j++;
4551 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
4555 void ICSInputBoxPopUp()
4560 char *title = _("ICS Input");
4563 if (ICSInputShell == NULL) {
4564 ICSInputShell = MiscCreate(title, "", True, NULL, 1);
4565 tr = XtParseTranslationTable(ICSInputTranslations);
4566 edit = XtNameToWidget(ICSInputShell, "*form.text");
4567 XtOverrideTranslations(edit, tr);
4568 XtRealizeWidget(ICSInputShell);
4569 CatchDeleteWindow(ICSInputShell, "ICSInputBoxPopDown");
4572 edit = XtNameToWidget(ICSInputShell, "*form.text");
4574 XtSetArg(args[j], XtNstring, ""); j++;
4575 XtSetValues(edit, args, j);
4577 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4578 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4579 XtSetValues(ICSInputShell, args, j);
4582 XtPopup(ICSInputShell, XtGrabNone);
4583 XtSetKeyboardFocus(ICSInputShell, edit);
4585 ICSInputBoxUp = True;
4587 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
4588 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
4592 void ICSInputSendText()
4599 edit = XtNameToWidget(ICSInputShell, "*form.text");
4601 XtSetArg(args[j], XtNstring, &val); j++;
4602 XtGetValues(edit, args, j);
4603 SendMultiLineToICS(val);
4604 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
4605 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
4608 void ICSInputBoxPopDown()
4613 if (!ICSInputBoxUp) return;
4615 XtPopdown(ICSInputShell);
4616 ICSInputBoxUp = False;
4618 XtSetArg(args[j], XtNleftBitmap, None); j++;
4619 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
4623 void CommentPopUp(title, text)
4630 if (commentShell == NULL) {
4632 CommentCreate(title, text, False, CommentCallback, 4);
4633 XtRealizeWidget(commentShell);
4634 CatchDeleteWindow(commentShell, "CommentPopDown");
4636 edit = XtNameToWidget(commentShell, "*form.text");
4638 XtSetArg(args[j], XtNstring, text); j++;
4639 XtSetValues(edit, args, j);
4641 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4642 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4643 XtSetValues(commentShell, args, j);
4646 XtPopup(commentShell, XtGrabNone);
4647 XSync(xDisplay, False);
4652 void AnalysisPopUp(title, text)
4659 if (analysisShell == NULL) {
4660 analysisShell = MiscCreate(title, text, False, NULL, 4);
4661 XtRealizeWidget(analysisShell);
4662 CatchDeleteWindow(analysisShell, "AnalysisPopDown");
4665 edit = XtNameToWidget(analysisShell, "*form.text");
4667 XtSetArg(args[j], XtNstring, text); j++;
4668 XtSetValues(edit, args, j);
4670 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4671 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4672 XtSetValues(analysisShell, args, j);
4676 XtPopup(analysisShell, XtGrabNone);
4678 XSync(xDisplay, False);
4683 void CommentCallback(w, client_data, call_data)
4685 XtPointer client_data, call_data;
4692 XtSetArg(args[j], XtNlabel, &name); j++;
4693 XtGetValues(w, args, j);
4695 if (strcmp(name, _("close")) == 0) {
4697 } else if (strcmp(name, _("edit")) == 0) {
4704 void CommentPopDown()
4709 if (!commentUp) return;
4711 XtSetArg(args[j], XtNx, &commentX); j++;
4712 XtSetArg(args[j], XtNy, &commentY); j++;
4713 XtSetArg(args[j], XtNwidth, &commentW); j++;
4714 XtSetArg(args[j], XtNheight, &commentH); j++;
4715 XtGetValues(commentShell, args, j);
4716 XtPopdown(commentShell);
4717 XSync(xDisplay, False);
4721 void AnalysisPopDown()
4723 if (!analysisUp) return;
4724 XtPopdown(analysisShell);
4725 XSync(xDisplay, False);
4727 if (appData.icsEngineAnalyze) ExitAnalyzeMode(); /* [DM] icsEngineAnalyze */
4731 void FileNamePopUp(label, def, proc, openMode)
4738 Widget popup, layout, dialog, edit;
4744 fileProc = proc; /* I can't see a way not */
4745 fileOpenMode = openMode; /* to use globals here */
4748 XtSetArg(args[i], XtNresizable, True); i++;
4749 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
4750 XtSetArg(args[i], XtNtitle, XtNewString(_("File name prompt"))); i++;
4751 fileNameShell = popup =
4752 XtCreatePopupShell("File name prompt", transientShellWidgetClass,
4753 shellWidget, args, i);
4756 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
4757 layoutArgs, XtNumber(layoutArgs));
4760 XtSetArg(args[i], XtNlabel, label); i++;
4761 XtSetArg(args[i], XtNvalue, def); i++;
4762 XtSetArg(args[i], XtNborderWidth, 0); i++;
4763 dialog = XtCreateManagedWidget("fileName", dialogWidgetClass,
4766 XawDialogAddButton(dialog, _("ok"), FileNameCallback, (XtPointer) dialog);
4767 XawDialogAddButton(dialog, _("cancel"), FileNameCallback,
4768 (XtPointer) dialog);
4770 XtRealizeWidget(popup);
4771 CatchDeleteWindow(popup, "FileNamePopDown");
4773 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
4774 &x, &y, &win_x, &win_y, &mask);
4776 XtSetArg(args[0], XtNx, x - 10);
4777 XtSetArg(args[1], XtNy, y - 30);
4778 XtSetValues(popup, args, 2);
4780 XtPopup(popup, XtGrabExclusive);
4783 edit = XtNameToWidget(dialog, "*value");
4784 XtSetKeyboardFocus(popup, edit);
4787 void FileNamePopDown()
4789 if (!filenameUp) return;
4790 XtPopdown(fileNameShell);
4791 XtDestroyWidget(fileNameShell);
4796 void FileNameCallback(w, client_data, call_data)
4798 XtPointer client_data, call_data;
4803 XtSetArg(args[0], XtNlabel, &name);
4804 XtGetValues(w, args, 1);
4806 if (strcmp(name, _("cancel")) == 0) {
4811 FileNameAction(w, NULL, NULL, NULL);
4814 void FileNameAction(w, event, prms, nprms)
4826 name = XawDialogGetValueString(w = XtParent(w));
4828 if ((name != NULL) && (*name != NULLCHAR)) {
4830 XtPopdown(w = XtParent(XtParent(w)));
4834 p = strrchr(buf, ' ');
4841 fullname = ExpandPathName(buf);
4843 ErrorPopUp(_("Error"), _("Can't open file"), FALSE);
4846 f = fopen(fullname, fileOpenMode);
4848 DisplayError(_("Failed to open file"), errno);
4850 (void) (*fileProc)(f, index, buf);
4857 XtPopdown(w = XtParent(XtParent(w)));
4863 void PromotionPopUp()
4866 Widget dialog, layout;
4868 Dimension bw_width, pw_width;
4872 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4873 XtGetValues(boardWidget, args, j);
4876 XtSetArg(args[j], XtNresizable, True); j++;
4877 XtSetArg(args[j], XtNtitle, XtNewString(_("Promotion"))); j++;
4879 XtCreatePopupShell("Promotion", transientShellWidgetClass,
4880 shellWidget, args, j);
4882 XtCreateManagedWidget(layoutName, formWidgetClass, promotionShell,
4883 layoutArgs, XtNumber(layoutArgs));
4886 XtSetArg(args[j], XtNlabel, _("Promote to what?")); j++;
4887 XtSetArg(args[j], XtNborderWidth, 0); j++;
4888 dialog = XtCreateManagedWidget("promotion", dialogWidgetClass,
4891 if(gameInfo.variant != VariantShogi) {
4892 XawDialogAddButton(dialog, _("Queen"), PromotionCallback,
4893 (XtPointer) dialog);
4894 XawDialogAddButton(dialog, _("Rook"), PromotionCallback,
4895 (XtPointer) dialog);
4896 XawDialogAddButton(dialog, _("Bishop"), PromotionCallback,
4897 (XtPointer) dialog);
4898 XawDialogAddButton(dialog, _("Knight"), PromotionCallback,
4899 (XtPointer) dialog);
4900 if (!appData.testLegality || gameInfo.variant == VariantSuicide ||
4901 gameInfo.variant == VariantGiveaway) {
4902 XawDialogAddButton(dialog, _("King"), PromotionCallback,
4903 (XtPointer) dialog);
4905 if(gameInfo.variant == VariantCapablanca ||
4906 gameInfo.variant == VariantGothic ||
4907 gameInfo.variant == VariantCapaRandom) {
4908 XawDialogAddButton(dialog, _("Archbishop"), PromotionCallback,
4909 (XtPointer) dialog);
4910 XawDialogAddButton(dialog, _("Chancellor"), PromotionCallback,
4911 (XtPointer) dialog);
4913 } else // [HGM] shogi
4915 XawDialogAddButton(dialog, _("Promote"), PromotionCallback,
4916 (XtPointer) dialog);
4917 XawDialogAddButton(dialog, _("Defer"), PromotionCallback,
4918 (XtPointer) dialog);
4920 XawDialogAddButton(dialog, _("cancel"), PromotionCallback,
4921 (XtPointer) dialog);
4923 XtRealizeWidget(promotionShell);
4924 CatchDeleteWindow(promotionShell, "PromotionPopDown");
4927 XtSetArg(args[j], XtNwidth, &pw_width); j++;
4928 XtGetValues(promotionShell, args, j);
4930 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
4931 lineGap + squareSize/3 +
4932 ((toY == BOARD_HEIGHT-1) ^ (flipView) ?
4933 0 : 6*(squareSize + lineGap)), &x, &y);
4936 XtSetArg(args[j], XtNx, x); j++;
4937 XtSetArg(args[j], XtNy, y); j++;
4938 XtSetValues(promotionShell, args, j);
4940 XtPopup(promotionShell, XtGrabNone);
4945 void PromotionPopDown()
4947 if (!promotionUp) return;
4948 XtPopdown(promotionShell);
4949 XtDestroyWidget(promotionShell);
4950 promotionUp = False;
4953 void PromotionCallback(w, client_data, call_data)
4955 XtPointer client_data, call_data;
4961 XtSetArg(args[0], XtNlabel, &name);
4962 XtGetValues(w, args, 1);
4966 if (fromX == -1) return;
4968 if (strcmp(name, _("cancel")) == 0) {
4972 } else if (strcmp(name, _("Knight")) == 0) {
4974 } else if (strcmp(name, _("Promote")) == 0) {
4976 } else if (strcmp(name, _("Defer")) == 0) {
4979 promoChar = ToLower(name[0]);
4982 FinishMove(NormalMove, fromX, fromY, toX, toY, promoChar);
4984 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
4985 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
4990 void ErrorCallback(w, client_data, call_data)
4992 XtPointer client_data, call_data;
4995 XtPopdown(w = XtParent(XtParent(XtParent(w))));
4997 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5003 if (!errorUp) return;
5007 gtk_widget_destroy(GTK_WIDGET(GUI_Error));
5009 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5014 void ErrorPopUp(title, label, modal)
5015 char *title, *label;
5018 GUI_Error = gtk_message_dialog_new(GTK_WINDOW(GUI_Window),
5019 GTK_DIALOG_DESTROY_WITH_PARENT,
5024 gtk_window_set_title(GTK_WINDOW(GUI_Error),(gchar *) title);
5027 gtk_dialog_run(GTK_DIALOG(GUI_Error));
5028 gtk_widget_destroy(GTK_WIDGET(GUI_Error));
5032 g_signal_connect_swapped (GUI_Error, "response",
5033 G_CALLBACK (ErrorPopDownProc),
5036 gtk_widget_show(GTK_WIDGET(GUI_Error));
5042 /* Disable all user input other than deleting the window */
5043 static int frozen = 0;
5047 /* Grab by a widget that doesn't accept input */
5048 // XtAddGrab(messageWidget, TRUE, FALSE);
5052 /* Undo a FreezeUI */
5055 if (!frozen) return;
5056 // XtRemoveGrab(messageWidget);
5060 char *ModeToWidgetName(mode)
5064 case BeginningOfGame:
5065 if (appData.icsActive)
5066 return "menuMode.ICS Client";
5067 else if (appData.noChessProgram ||
5068 *appData.cmailGameName != NULLCHAR)
5069 return "menuMode.Edit Game";
5071 return "menuMode.Machine Black";
5072 case MachinePlaysBlack:
5073 return "menuMode.Machine Black";
5074 case MachinePlaysWhite:
5075 return "menuMode.Machine White";
5077 return "menuMode.Analysis Mode";
5079 return "menuMode.Analyze File";
5080 case TwoMachinesPlay:
5081 return "menuMode.Two Machines";
5083 return "menuMode.Edit Game";
5084 case PlayFromGameFile:
5085 return "menuFile.Load Game";
5087 return "menuMode.Edit Position";
5089 return "menuMode.Training";
5090 case IcsPlayingWhite:
5091 case IcsPlayingBlack:
5095 return "menuMode.ICS Client";
5102 void ModeHighlight()
5104 static int oldPausing = FALSE;
5105 static GameMode oldmode = (GameMode) -1;
5108 // todo this toggling of the pause button doesn't seem to work?
5109 // e.g. select pause from buttonbar doesn't activate menumode.pause
5111 // if (!boardWidget || !XtIsRealized(boardWidget)) return;
5113 if (pausing != oldPausing) {
5114 oldPausing = pausing;
5115 gtk_button_set_relief(GTK_BUTTON (gtk_builder_get_object (builder, "menuMode.Pause")),pausing?GTK_RELIEF_NORMAL:GTK_RELIEF_NONE);
5116 /* toggle background color in showbuttonbar */
5117 if (appData.showButtonBar) {
5119 gtk_button_pressed(GTK_BUTTON (gtk_builder_get_object (builder, "buttonbar.Pause")));
5121 gtk_button_released(GTK_BUTTON (gtk_builder_get_object (builder, "buttonbar.Pause")));
5126 wname = ModeToWidgetName(oldmode);
5128 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, wname)),True);
5132 /* Maybe all the enables should be handled here, not just this one */
5133 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuMode.Training")),
5134 gameMode == Training || gameMode == PlayFromGameFile);
5139 * Button/menu procedures
5142 int LoadGamePopUp(f, gameNumber, title)
5147 cmailMsgLoaded = FALSE;
5149 if (gameNumber == 0)
5151 int error = GameListBuild(f);
5155 DisplayError(_("Cannot build game list"), error);
5157 else if (!ListEmpty(&gameList)
5158 && ((ListGame *) gameList.tailPred)->number > 1)
5160 GameListPopUp(f, title);
5168 return LoadGame(f, gameNumber, title, FALSE);
5171 void LoadPositionProc(w, event, prms, nprms)
5177 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
5180 FileNamePopUp(_("Load position file name?"), "", LoadPosition, "rb");
5183 void SaveGameProc(w, event, prms, nprms)
5189 FileNamePopUp(_("Save game file name?"),
5190 DefaultFileName(appData.oldSaveStyle ? "game" : "pgn"),
5194 void SavePositionProc(w, event, prms, nprms)
5200 FileNamePopUp(_("Save position file name?"),
5201 DefaultFileName(appData.oldSaveStyle ? "pos" : "fen"),
5205 void ReloadCmailMsgProc(w, event, prms, nprms)
5211 ReloadCmailMsgEvent(FALSE);
5214 void MailMoveProc(w, event, prms, nprms)
5223 /* this variable is shared between CopyPositionProc and SendPositionSelection */
5224 static char *selected_fen_position=NULL;
5227 SendPositionSelection(Widget w, Atom *selection, Atom *target,
5228 Atom *type_return, XtPointer *value_return,
5229 unsigned long *length_return, int *format_return)
5231 char *selection_tmp;
5233 if (!selected_fen_position) return False; /* should never happen */
5234 if (*target == XA_STRING){
5235 /* note: since no XtSelectionDoneProc was registered, Xt will
5236 * automatically call XtFree on the value returned. So have to
5237 * make a copy of it allocated with XtMalloc */
5238 selection_tmp= XtMalloc(strlen(selected_fen_position)+16);
5239 strcpy(selection_tmp, selected_fen_position);
5241 *value_return=selection_tmp;
5242 *length_return=strlen(selection_tmp);
5243 *type_return=XA_STRING;
5244 *format_return = 8; /* bits per byte */
5251 /* note: when called from menu all parameters are NULL, so no clue what the
5252 * Widget which was clicked on was, or what the click event was
5254 void CopyPositionProc(w, event, prms, nprms)
5262 if (selected_fen_position) free(selected_fen_position);
5263 selected_fen_position = (char *)PositionToFEN(currentMove, NULL);
5264 if (!selected_fen_position) return;
5265 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
5267 SendPositionSelection,
5268 NULL/* lose_ownership_proc */ ,
5269 NULL/* transfer_done_proc */);
5271 free(selected_fen_position);
5272 selected_fen_position=NULL;
5276 /* function called when the data to Paste is ready */
5278 PastePositionCB(Widget w, XtPointer client_data, Atom *selection,
5279 Atom *type, XtPointer value, unsigned long *len, int *format)
5282 if (value==NULL || *len==0) return; /* nothing had been selected to copy */
5283 fenstr[*len]='\0'; /* normally this string is terminated, but be safe */
5284 EditPositionPasteFEN(fenstr);
5288 /* called when Paste Position button is pressed,
5289 * all parameters will be NULL */
5290 void PastePositionProc(w, event, prms, nprms)
5296 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
5297 /* (XtSelectionCallbackProc) */ PastePositionCB,
5298 NULL, /* client_data passed to PastePositionCB */
5300 /* better to use the time field from the event that triggered the
5301 * call to this function, but that isn't trivial to get
5309 SendGameSelection(Widget w, Atom *selection, Atom *target,
5310 Atom *type_return, XtPointer *value_return,
5311 unsigned long *length_return, int *format_return)
5313 char *selection_tmp;
5315 if (*target == XA_STRING){
5316 FILE* f = fopen(gameCopyFilename, "r");
5319 if (f == NULL) return False;
5323 selection_tmp = XtMalloc(len + 1);
5324 count = fread(selection_tmp, 1, len, f);
5326 XtFree(selection_tmp);
5329 selection_tmp[len] = NULLCHAR;
5330 *value_return = selection_tmp;
5331 *length_return = len;
5332 *type_return = XA_STRING;
5333 *format_return = 8; /* bits per byte */
5340 /* note: when called from menu all parameters are NULL, so no clue what the
5341 * Widget which was clicked on was, or what the click event was
5343 void CopyGameProc(w, event, prms, nprms)
5351 ret = SaveGameToFile(gameCopyFilename, FALSE);
5354 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
5357 NULL/* lose_ownership_proc */ ,
5358 NULL/* transfer_done_proc */);
5361 /* function called when the data to Paste is ready */
5363 PasteGameCB(Widget w, XtPointer client_data, Atom *selection,
5364 Atom *type, XtPointer value, unsigned long *len, int *format)
5367 if (value == NULL || *len == 0) {
5368 return; /* nothing had been selected to copy */
5370 f = fopen(gamePasteFilename, "w");
5372 DisplayError(_("Can't open temp file"), errno);
5375 fwrite(value, 1, *len, f);
5378 LoadGameFromFile(gamePasteFilename, 0, gamePasteFilename, TRUE);
5381 /* called when Paste Game button is pressed,
5382 * all parameters will be NULL */
5383 void PasteGameProc(w, event, prms, nprms)
5389 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
5390 /* (XtSelectionCallbackProc) */ PasteGameCB,
5391 NULL, /* client_data passed to PasteGameCB */
5393 /* better to use the time field from the event that triggered the
5394 * call to this function, but that isn't trivial to get
5404 SaveGameProc(NULL, NULL, NULL, NULL);
5407 void AnalyzeModeProc(w, event, prms, nprms)
5415 if (!first.analysisSupport) {
5416 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
5417 DisplayError(buf, 0);
5420 /* [DM] icsEngineAnalyze [HGM] This is horrible code; reverse the gameMode and isEngineAnalyze tests! */
5421 if (appData.icsActive) {
5422 if (gameMode != IcsObserving) {
5423 sprintf(buf,_("You are not observing a game"));
5424 DisplayError(buf, 0);
5426 if (appData.icsEngineAnalyze) {
5427 if (appData.debugMode)
5428 fprintf(debugFP, _("Found unexpected active ICS engine analyze \n"));
5434 /* if enable, use want disable icsEngineAnalyze */
5435 if (appData.icsEngineAnalyze) {
5440 appData.icsEngineAnalyze = TRUE;
5441 if (appData.debugMode)
5442 fprintf(debugFP, _("ICS engine analyze starting... \n"));
5444 if (!appData.showThinking)
5445 ShowThinkingProc(NULL,NULL);
5450 void AnalyzeFileProc(w, event, prms, nprms)
5456 if (!first.analysisSupport) {
5458 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
5459 DisplayError(buf, 0);
5464 if (!appData.showThinking)
5465 ShowThinkingProc(NULL,NULL);
5468 FileNamePopUp(_("File to analyze"), "", LoadGamePopUp, "rb");
5469 AnalysisPeriodicEvent(1);
5473 void EditGameProc(w, event, prms, nprms)
5482 void EditPositionProc(w, event, prms, nprms)
5488 EditPositionEvent();
5491 void TrainingProc(w, event, prms, nprms)
5500 void EditCommentProc(w, event, prms, nprms)
5507 EditCommentPopDown();
5513 void IcsInputBoxProc(w, event, prms, nprms)
5519 if (ICSInputBoxUp) {
5520 ICSInputBoxPopDown();
5527 void EnterKeyProc(w, event, prms, nprms)
5533 if (ICSInputBoxUp == True)
5537 void AlwaysQueenProc(w, event, prms, nprms)
5545 appData.alwaysPromoteToQueen = !appData.alwaysPromoteToQueen;
5547 if (appData.alwaysPromoteToQueen) {
5548 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5550 XtSetArg(args[0], XtNleftBitmap, None);
5552 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
5556 void AnimateDraggingProc(w, event, prms, nprms)
5564 appData.animateDragging = !appData.animateDragging;
5566 if (appData.animateDragging) {
5567 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5570 XtSetArg(args[0], XtNleftBitmap, None);
5572 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Dragging"),
5576 void AnimateMovingProc(w, event, prms, nprms)
5584 appData.animate = !appData.animate;
5586 if (appData.animate) {
5587 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5590 XtSetArg(args[0], XtNleftBitmap, None);
5592 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
5596 void AutocommProc(w, event, prms, nprms)
5604 appData.autoComment = !appData.autoComment;
5606 if (appData.autoComment) {
5607 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5609 XtSetArg(args[0], XtNleftBitmap, None);
5611 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
5616 void AutoflagProc(w, event, prms, nprms)
5624 appData.autoCallFlag = !appData.autoCallFlag;
5626 if (appData.autoCallFlag) {
5627 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5629 XtSetArg(args[0], XtNleftBitmap, None);
5631 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
5635 void AutoflipProc(w, event, prms, nprms)
5643 appData.autoFlipView = !appData.autoFlipView;
5645 if (appData.autoFlipView) {
5646 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5648 XtSetArg(args[0], XtNleftBitmap, None);
5650 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flip View"),
5654 void AutobsProc(w, event, prms, nprms)
5662 appData.autoObserve = !appData.autoObserve;
5664 if (appData.autoObserve) {
5665 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5667 XtSetArg(args[0], XtNleftBitmap, None);
5669 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
5673 void AutoraiseProc(w, event, prms, nprms)
5681 appData.autoRaiseBoard = !appData.autoRaiseBoard;
5683 if (appData.autoRaiseBoard) {
5684 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5686 XtSetArg(args[0], XtNleftBitmap, None);
5688 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Raise Board"),
5692 void AutosaveProc(w, event, prms, nprms)
5700 appData.autoSaveGames = !appData.autoSaveGames;
5702 if (appData.autoSaveGames) {
5703 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5705 XtSetArg(args[0], XtNleftBitmap, None);
5707 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
5711 void BlindfoldProc(w, event, prms, nprms)
5719 appData.blindfold = !appData.blindfold;
5721 if (appData.blindfold) {
5722 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5724 XtSetArg(args[0], XtNleftBitmap, None);
5726 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Blindfold"),
5729 DrawPosition(True, NULL);
5732 void TestLegalityProc(w, event, prms, nprms)
5740 appData.testLegality = !appData.testLegality;
5742 if (appData.testLegality) {
5743 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5745 XtSetArg(args[0], XtNleftBitmap, None);
5747 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Test Legality"),
5752 void FlashMovesProc(w, event, prms, nprms)
5760 if (appData.flashCount == 0) {
5761 appData.flashCount = 3;
5763 appData.flashCount = -appData.flashCount;
5766 if (appData.flashCount > 0) {
5767 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5769 XtSetArg(args[0], XtNleftBitmap, None);
5771 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flash Moves"),
5776 void HighlightDraggingProc(w, event, prms, nprms)
5784 appData.highlightDragging = !appData.highlightDragging;
5786 if (appData.highlightDragging) {
5787 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5789 XtSetArg(args[0], XtNleftBitmap, None);
5791 XtSetValues(XtNameToWidget(menuBarWidget,
5792 "menuOptions.Highlight Dragging"), args, 1);
5796 void HighlightLastMoveProc(w, event, prms, nprms)
5804 appData.highlightLastMove = !appData.highlightLastMove;
5806 if (appData.highlightLastMove) {
5807 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5809 XtSetArg(args[0], XtNleftBitmap, None);
5811 XtSetValues(XtNameToWidget(menuBarWidget,
5812 "menuOptions.Highlight Last Move"), args, 1);
5815 void IcsAlarmProc(w, event, prms, nprms)
5823 appData.icsAlarm = !appData.icsAlarm;
5825 if (appData.icsAlarm) {
5826 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5828 XtSetArg(args[0], XtNleftBitmap, None);
5830 XtSetValues(XtNameToWidget(menuBarWidget,
5831 "menuOptions.ICS Alarm"), args, 1);
5834 void MoveSoundProc(w, event, prms, nprms)
5842 appData.ringBellAfterMoves = !appData.ringBellAfterMoves;
5844 if (appData.ringBellAfterMoves) {
5845 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5847 XtSetArg(args[0], XtNleftBitmap, None);
5849 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
5854 void OldSaveStyleProc(w, event, prms, nprms)
5862 appData.oldSaveStyle = !appData.oldSaveStyle;
5864 if (appData.oldSaveStyle) {
5865 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5867 XtSetArg(args[0], XtNleftBitmap, None);
5869 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Old Save Style"),
5873 void PeriodicUpdatesProc(w, event, prms, nprms)
5881 PeriodicUpdatesEvent(!appData.periodicUpdates);
5883 if (appData.periodicUpdates) {
5884 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5886 XtSetArg(args[0], XtNleftBitmap, None);
5888 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Periodic Updates"),
5892 void PonderNextMoveProc(w, event, prms, nprms)
5900 PonderNextMoveEvent(!appData.ponderNextMove);
5902 if (appData.ponderNextMove) {
5903 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5905 XtSetArg(args[0], XtNleftBitmap, None);
5907 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Ponder Next Move"),
5911 void PopupExitMessageProc(w, event, prms, nprms)
5919 appData.popupExitMessage = !appData.popupExitMessage;
5921 if (appData.popupExitMessage) {
5922 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5924 XtSetArg(args[0], XtNleftBitmap, None);
5926 XtSetValues(XtNameToWidget(menuBarWidget,
5927 "menuOptions.Popup Exit Message"), args, 1);
5930 void PopupMoveErrorsProc(w, event, prms, nprms)
5938 appData.popupMoveErrors = !appData.popupMoveErrors;
5940 if (appData.popupMoveErrors) {
5941 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5943 XtSetArg(args[0], XtNleftBitmap, None);
5945 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Popup Move Errors"),
5949 void PremoveProc(w, event, prms, nprms)
5957 appData.premove = !appData.premove;
5959 if (appData.premove) {
5960 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5962 XtSetArg(args[0], XtNleftBitmap, None);
5964 XtSetValues(XtNameToWidget(menuBarWidget,
5965 "menuOptions.Premove"), args, 1);
5968 void QuietPlayProc(w, event, prms, nprms)
5976 appData.quietPlay = !appData.quietPlay;
5978 if (appData.quietPlay) {
5979 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5981 XtSetArg(args[0], XtNleftBitmap, None);
5983 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Quiet Play"),
5987 void DebugProc(w, event, prms, nprms)
5993 appData.debugMode = !appData.debugMode;
5996 void AboutGameProc(w, event, prms, nprms)
6005 void NothingProc(w, event, prms, nprms)
6014 void Iconify(w, event, prms, nprms)
6023 XtSetArg(args[0], XtNiconic, True);
6024 XtSetValues(shellWidget, args, 1);
6027 void DisplayMessage(message, extMessage)
6028 gchar *message, *extMessage;
6035 snprintf(buf, sizeof(buf), "%s %s", message, extMessage);
6038 message = extMessage;
6041 gtk_label_set_text( GTK_LABEL(gtk_builder_get_object (builder, "Messages")),message);
6046 void DisplayTitle(text)
6049 gchar title[MSG_SIZ];
6051 if (text == NULL) text = "";
6053 if (appData.titleInWindow)
6058 if (*text != NULLCHAR)
6060 strcpy(title, text);
6062 else if (appData.icsActive)
6064 snprintf(title, sizeof(title), "%s: %s", programName, appData.icsHost);
6066 else if (appData.cmailGameName[0] != NULLCHAR)
6068 snprintf(title,sizeof(title), "%s: %s", programName, "CMail");
6070 // [HGM] license: This stuff should really be done in back-end, but WinBoard already had a pop-up for it
6072 else if (gameInfo.variant == VariantGothic)
6074 strcpy(title, GOTHIC);
6078 else if (gameInfo.variant == VariantFalcon)
6080 strcpy(title, FALCON);
6083 else if (appData.noChessProgram)
6085 strcpy(title, programName);
6089 snprintf(title,sizeof(title), "%s: %s", programName, first.tidy);
6091 gtk_window_set_title(GTK_WINDOW(GUI_Window),title);
6097 void DisplayError(message, error)
6104 if (appData.debugMode || appData.matchMode) {
6105 fprintf(stderr, "%s: %s\n", programName, message);
6108 if (appData.debugMode || appData.matchMode) {
6109 fprintf(stderr, "%s: %s: %s\n",
6110 programName, message, strerror(error));
6112 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
6115 ErrorPopUp(_("Error"), message, FALSE);
6119 void DisplayMoveError(message)
6124 DrawPosition(FALSE, NULL);
6125 if (appData.debugMode || appData.matchMode) {
6126 fprintf(stderr, "%s: %s\n", programName, message);
6128 if (appData.popupMoveErrors) {
6129 ErrorPopUp(_("Error"), message, FALSE);
6131 DisplayMessage(message, "");
6136 void DisplayFatalError(message, error, status)
6142 errorExitStatus = status;
6144 fprintf(stderr, "%s: %s\n", programName, message);
6146 fprintf(stderr, "%s: %s: %s\n",
6147 programName, message, strerror(error));
6148 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
6151 if (appData.popupExitMessage && boardWidget && XtIsRealized(boardWidget)) {
6152 ErrorPopUp(status ? _("Fatal Error") : _("Exiting"), message, TRUE);
6158 void DisplayInformation(message)
6162 ErrorPopUp(_("Information"), message, TRUE);
6165 void DisplayNote(message)
6169 ErrorPopUp(_("Note"), message, FALSE);
6173 NullXErrorCheck(dpy, error_event)
6175 XErrorEvent *error_event;
6180 void DisplayIcsInteractionTitle(message)
6183 if (oldICSInteractionTitle == NULL) {
6184 /* Magic to find the old window title, adapted from vim */
6185 char *wina = getenv("WINDOWID");
6187 Window win = (Window) atoi(wina);
6188 Window root, parent, *children;
6189 unsigned int nchildren;
6190 int (*oldHandler)() = XSetErrorHandler(NullXErrorCheck);
6192 if (XFetchName(xDisplay, win, &oldICSInteractionTitle)) break;
6193 if (!XQueryTree(xDisplay, win, &root, &parent,
6194 &children, &nchildren)) break;
6195 if (children) XFree((void *)children);
6196 if (parent == root || parent == 0) break;
6199 XSetErrorHandler(oldHandler);
6201 if (oldICSInteractionTitle == NULL) {
6202 oldICSInteractionTitle = "xterm";
6205 printf("\033]0;%s\007", message);
6209 char pendingReplyPrefix[MSG_SIZ];
6210 ProcRef pendingReplyPR;
6212 void AskQuestionProc(w, event, prms, nprms)
6219 fprintf(stderr, _("AskQuestionProc needed 4 parameters, got %d\n"),
6223 AskQuestionEvent(prms[0], prms[1], prms[2], prms[3]);
6226 void AskQuestionPopDown()
6228 if (!askQuestionUp) return;
6229 XtPopdown(askQuestionShell);
6230 XtDestroyWidget(askQuestionShell);
6231 askQuestionUp = False;
6234 void AskQuestionReplyAction(w, event, prms, nprms)
6244 reply = XawDialogGetValueString(w = XtParent(w));
6245 strcpy(buf, pendingReplyPrefix);
6246 if (*buf) strcat(buf, " ");
6249 OutputToProcess(pendingReplyPR, buf, strlen(buf), &err);
6250 AskQuestionPopDown();
6252 if (err) DisplayFatalError(_("Error writing to chess program"), err, 0);
6255 void AskQuestionCallback(w, client_data, call_data)
6257 XtPointer client_data, call_data;
6262 XtSetArg(args[0], XtNlabel, &name);
6263 XtGetValues(w, args, 1);
6265 if (strcmp(name, _("cancel")) == 0) {
6266 AskQuestionPopDown();
6268 AskQuestionReplyAction(w, NULL, NULL, NULL);
6272 void AskQuestion(title, question, replyPrefix, pr)
6273 char *title, *question, *replyPrefix;
6277 Widget popup, layout, dialog, edit;
6283 strcpy(pendingReplyPrefix, replyPrefix);
6284 pendingReplyPR = pr;
6287 XtSetArg(args[i], XtNresizable, True); i++;
6288 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
6289 askQuestionShell = popup =
6290 XtCreatePopupShell(title, transientShellWidgetClass,
6291 shellWidget, args, i);
6294 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
6295 layoutArgs, XtNumber(layoutArgs));
6298 XtSetArg(args[i], XtNlabel, question); i++;
6299 XtSetArg(args[i], XtNvalue, ""); i++;
6300 XtSetArg(args[i], XtNborderWidth, 0); i++;
6301 dialog = XtCreateManagedWidget("question", dialogWidgetClass,
6304 XawDialogAddButton(dialog, _("enter"), AskQuestionCallback,
6305 (XtPointer) dialog);
6306 XawDialogAddButton(dialog, _("cancel"), AskQuestionCallback,
6307 (XtPointer) dialog);
6309 XtRealizeWidget(popup);
6310 CatchDeleteWindow(popup, "AskQuestionPopDown");
6312 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
6313 &x, &y, &win_x, &win_y, &mask);
6315 XtSetArg(args[0], XtNx, x - 10);
6316 XtSetArg(args[1], XtNy, y - 30);
6317 XtSetValues(popup, args, 2);
6319 XtPopup(popup, XtGrabExclusive);
6320 askQuestionUp = True;
6322 edit = XtNameToWidget(dialog, "*value");
6323 XtSetKeyboardFocus(popup, edit);
6331 if (*name == NULLCHAR) {
6333 } else if (strcmp(name, "$") == 0) {
6334 putc(BELLCHAR, stderr);
6337 snprintf(buf, sizeof(buf), "%s '%s' &", appData.soundProgram, name);
6345 PlaySound(appData.soundMove);
6351 PlaySound(appData.soundIcsWin);
6357 PlaySound(appData.soundIcsLoss);
6363 PlaySound(appData.soundIcsDraw);
6367 PlayIcsUnfinishedSound()
6369 PlaySound(appData.soundIcsUnfinished);
6375 PlaySound(appData.soundIcsAlarm);
6381 system("stty echo");
6387 system("stty -echo");
6391 Colorize(cc, continuation)
6396 int count, outCount, error;
6398 if (textColors[(int)cc].bg > 0) {
6399 if (textColors[(int)cc].fg > 0) {
6400 sprintf(buf, "\033[0;%d;%d;%dm", textColors[(int)cc].attr,
6401 textColors[(int)cc].fg, textColors[(int)cc].bg);
6403 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
6404 textColors[(int)cc].bg);
6407 if (textColors[(int)cc].fg > 0) {
6408 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
6409 textColors[(int)cc].fg);
6411 sprintf(buf, "\033[0;%dm", textColors[(int)cc].attr);
6414 count = strlen(buf);
6415 outCount = OutputToProcess(NoProc, buf, count, &error);
6416 if (outCount < count) {
6417 DisplayFatalError(_("Error writing to display"), error, 1);
6420 if (continuation) return;
6423 PlaySound(appData.soundShout);
6426 PlaySound(appData.soundSShout);
6429 PlaySound(appData.soundChannel1);
6432 PlaySound(appData.soundChannel);
6435 PlaySound(appData.soundKibitz);
6438 PlaySound(appData.soundTell);
6440 case ColorChallenge:
6441 PlaySound(appData.soundChallenge);
6444 PlaySound(appData.soundRequest);
6447 PlaySound(appData.soundSeek);
6458 return getpwuid(getuid())->pw_name;
6461 static char *ExpandPathName(path)
6464 static char static_buf[2000];
6465 char *d, *s, buf[2000];
6471 while (*s && isspace(*s))
6480 if (*(s+1) == '/') {
6481 strcpy(d, getpwuid(getuid())->pw_dir);
6486 *strchr(buf, '/') = 0;
6487 pwd = getpwnam(buf);
6490 fprintf(stderr, _("ERROR: Unknown user %s (in path %s)\n"),
6494 strcpy(d, pwd->pw_dir);
6495 strcat(d, strchr(s+1, '/'));
6506 static char host_name[MSG_SIZ];
6508 #if HAVE_GETHOSTNAME
6509 gethostname(host_name, MSG_SIZ);
6511 #else /* not HAVE_GETHOSTNAME */
6512 # if HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H
6513 sysinfo(SI_HOSTNAME, host_name, MSG_SIZ);
6515 # else /* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
6517 # endif/* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
6518 #endif /* not HAVE_GETHOSTNAME */
6521 guint delayedEventTimerTag = 0;
6522 DelayedEventCallback delayedEventCallback = 0;
6525 FireDelayedEvent(data)
6529 g_source_remove(delayedEventTimerTag);
6530 delayedEventTimerTag = 0;
6533 delayedEventCallback();
6539 ScheduleDelayedEvent(cb, millisec)
6540 DelayedEventCallback cb; guint millisec;
6542 if(delayedEventTimerTag && delayedEventCallback == cb)
6543 // [HGM] alive: replace, rather than add or flush identical event
6544 g_source_remove(delayedEventTimerTag);
6545 delayedEventCallback = cb;
6546 delayedEventTimerTag = g_timeout_add(millisec,(GSourceFunc) FireDelayedEvent, NULL);
6550 DelayedEventCallback
6553 if (delayedEventTimerTag)
6555 return delayedEventCallback;
6564 CancelDelayedEvent()
6566 if (delayedEventTimerTag)
6568 g_source_remove(delayedEventTimerTag);
6569 delayedEventTimerTag = 0;
6575 guint loadGameTimerTag = 0;
6577 int LoadGameTimerRunning()
6579 return loadGameTimerTag != 0;
6582 int StopLoadGameTimer()
6584 if (loadGameTimerTag != 0) {
6585 g_source_remove(loadGameTimerTag);
6586 loadGameTimerTag = 0;
6594 LoadGameTimerCallback(data)
6598 g_source_remove(loadGameTimerTag);
6599 loadGameTimerTag = 0;
6606 StartLoadGameTimer(millisec)
6610 g_timeout_add( millisec, (GSourceFunc) LoadGameTimerCallback, NULL);
6614 guint analysisClockTag = 0;
6617 AnalysisClockCallback(data)
6620 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile
6621 || appData.icsEngineAnalyze)
6623 AnalysisPeriodicEvent(0);
6624 return 1; /* keep on going */
6626 return 0; /* stop timer */
6630 StartAnalysisClock()
6633 g_timeout_add( 2000,(GSourceFunc) AnalysisClockCallback, NULL);
6637 guint clockTimerTag = 0;
6639 int ClockTimerRunning()
6641 return clockTimerTag != 0;
6644 int StopClockTimer()
6646 if (clockTimerTag != 0)
6648 g_source_remove(clockTimerTag);
6659 ClockTimerCallback(data)
6663 g_source_remove(clockTimerTag);
6671 StartClockTimer(millisec)
6674 clockTimerTag = g_timeout_add(millisec,(GSourceFunc) ClockTimerCallback,NULL);
6679 DisplayTimerLabel(w, color, timer, highlight)
6688 if (appData.clockMode) {
6689 sprintf(buf, "%s: %s", color, TimeString(timer));
6691 sprintf(buf, "%s ", color);
6693 gtk_label_set_text(GTK_LABEL(w),buf);
6695 /* check for low time warning */
6696 // Pixel foregroundOrWarningColor = timerForegroundPixel;
6699 // appData.lowTimeWarning &&
6700 // (timer / 1000) < appData.icsAlarmTime)
6701 // foregroundOrWarningColor = lowTimeWarningColor;
6703 // if (appData.clockMode) {
6704 // sprintf(buf, "%s: %s", color, TimeString(timer));
6705 // XtSetArg(args[0], XtNlabel, buf);
6707 // sprintf(buf, "%s ", color);
6708 // XtSetArg(args[0], XtNlabel, buf);
6713 // XtSetArg(args[1], XtNbackground, foregroundOrWarningColor);
6714 // XtSetArg(args[2], XtNforeground, timerBackgroundPixel);
6716 // XtSetArg(args[1], XtNbackground, timerBackgroundPixel);
6717 // XtSetArg(args[2], XtNforeground, foregroundOrWarningColor);
6720 // XtSetValues(w, args, 3);
6725 DisplayWhiteClock(timeRemaining, highlight)
6729 if(appData.noGUI) return;
6731 DisplayTimerLabel(GUI_Whiteclock, _("White"), timeRemaining, highlight);
6732 if (highlight && WindowIcon == BlackIcon)
6734 WindowIcon = WhiteIcon;
6735 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
6740 DisplayBlackClock(timeRemaining, highlight)
6744 if(appData.noGUI) return;
6746 DisplayTimerLabel(GUI_Blackclock, _("Black"), timeRemaining, highlight);
6747 if (highlight && WindowIcon == WhiteIcon)
6749 WindowIcon = BlackIcon;
6750 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
6768 int StartChildProcess(cmdLine, dir, pr)
6775 int to_prog[2], from_prog[2];
6779 if (appData.debugMode) {
6780 fprintf(stderr, "StartChildProcess (dir=\"%s\") %s\n",dir, cmdLine);
6783 /* We do NOT feed the cmdLine to the shell; we just
6784 parse it into blank-separated arguments in the
6785 most simple-minded way possible.
6788 strcpy(buf, cmdLine);
6793 if (p == NULL) break;
6798 SetUpChildIO(to_prog, from_prog);
6800 if ((pid = fork()) == 0) {
6802 // [HGM] PSWBTM: made order resistant against case where fd of created pipe was 0 or 1
6803 close(to_prog[1]); // first close the unused pipe ends
6804 close(from_prog[0]);
6805 dup2(to_prog[0], 0); // to_prog was created first, nd is the only one to use 0 or 1
6806 dup2(from_prog[1], 1);
6807 if(to_prog[0] >= 2) close(to_prog[0]); // if 0 or 1, the dup2 already cosed the original
6808 close(from_prog[1]); // and closing again loses one of the pipes!
6809 if(fileno(stderr) >= 2) // better safe than sorry...
6810 dup2(1, fileno(stderr)); /* force stderr to the pipe */
6812 if (dir[0] != NULLCHAR && chdir(dir) != 0) {
6817 nice(appData.niceEngines); // [HGM] nice: adjust priority of engine proc
6819 execvp(argv[0], argv);
6821 /* If we get here, exec failed */
6826 /* Parent process */
6828 close(from_prog[1]);
6830 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
6833 cp->fdFrom = from_prog[0];
6834 cp->fdTo = to_prog[1];
6839 // [HGM] kill: implement the 'hard killing' of AS's Winboard_x
6840 static RETSIGTYPE AlarmCallBack(int n)
6846 DestroyChildProcess(pr, signalType)
6850 ChildProc *cp = (ChildProc *) pr;
6852 if (cp->kind != CPReal) return;
6854 if (signalType == 10) { // [HGM] kill: if it does not terminate in 3 sec, kill
6855 signal(SIGALRM, AlarmCallBack);
6857 if(wait((int *) 0) == -1) { // process does not terminate on its own accord
6858 kill(cp->pid, SIGKILL); // kill it forcefully
6859 wait((int *) 0); // and wait again
6863 kill(cp->pid, signalType == 9 ? SIGKILL : SIGTERM); // [HGM] kill: use hard kill if so requested
6865 /* Process is exiting either because of the kill or because of
6866 a quit command sent by the backend; either way, wait for it to die.
6875 InterruptChildProcess(pr)
6878 ChildProc *cp = (ChildProc *) pr;
6880 if (cp->kind != CPReal) return;
6881 (void) kill(cp->pid, SIGINT); /* stop it thinking */
6884 int OpenTelnet(host, port, pr)
6889 char cmdLine[MSG_SIZ];
6891 if (port[0] == NULLCHAR) {
6892 snprintf(cmdLine, sizeof(cmdLine), "%s %s", appData.telnetProgram, host);
6894 snprintf(cmdLine, sizeof(cmdLine), "%s %s %s", appData.telnetProgram, host, port);
6896 return StartChildProcess(cmdLine, "", pr);
6899 int OpenTCP(host, port, pr)
6905 DisplayFatalError(_("Socket support is not configured in"), 0, 2);
6906 #else /* !OMIT_SOCKETS */
6908 struct sockaddr_in sa;
6910 unsigned short uport;
6913 if ((s = socket(AF_INET, SOCK_STREAM, 6)) < 0) {
6917 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
6918 sa.sin_family = AF_INET;
6919 sa.sin_addr.s_addr = INADDR_ANY;
6920 uport = (unsigned short) 0;
6921 sa.sin_port = htons(uport);
6922 if (bind(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)) < 0) {
6926 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
6927 if (!(hp = gethostbyname(host))) {
6929 if (sscanf(host, "%d.%d.%d.%d", &b0, &b1, &b2, &b3) == 4) {
6930 hp = (struct hostent *) calloc(1, sizeof(struct hostent));
6931 hp->h_addrtype = AF_INET;
6933 hp->h_addr_list = (char **) calloc(2, sizeof(char *));
6934 hp->h_addr_list[0] = (char *) malloc(4);
6935 hp->h_addr_list[0][0] = b0;
6936 hp->h_addr_list[0][1] = b1;
6937 hp->h_addr_list[0][2] = b2;
6938 hp->h_addr_list[0][3] = b3;
6943 sa.sin_family = hp->h_addrtype;
6944 uport = (unsigned short) atoi(port);
6945 sa.sin_port = htons(uport);
6946 memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);
6948 if (connect(s, (struct sockaddr *) &sa,
6949 sizeof(struct sockaddr_in)) < 0) {
6953 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
6960 #endif /* !OMIT_SOCKETS */
6965 int OpenCommPort(name, pr)
6972 fd = open(name, 2, 0);
6973 if (fd < 0) return errno;
6975 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
6985 int OpenLoopback(pr)
6991 SetUpChildIO(to, from);
6993 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
6996 cp->fdFrom = to[0]; /* note not from[0]; we are doing a loopback */
7003 int OpenRcmd(host, user, cmd, pr)
7004 char *host, *user, *cmd;
7007 DisplayFatalError(_("internal rcmd not implemented for Unix"), 0, 1);
7011 #define INPUT_SOURCE_BUF_SIZE 8192
7020 char buf[INPUT_SOURCE_BUF_SIZE];
7025 DoInputCallback(io,cond,data)
7030 /* read input from one of the input source (for example a chess program, ICS, etc).
7031 * and call a function that will handle the input
7034 int count; /* how many bytes did we read */
7038 /* All information (callback function, file descriptor, etc) is
7039 * saved in an InputSource structure
7041 InputSource *is = (InputSource *) data;
7045 count = read(is->fd, is->unused,
7046 INPUT_SOURCE_BUF_SIZE - (is->unused - is->buf));
7050 (is->func)(is, is->closure, is->buf, count, count ? errno : 0);
7053 is->unused += count;
7055 /* break input into lines and call the callback function on each
7058 while (p < is->unused)
7060 q = memchr(p, '\n', is->unused - p);
7061 if (q == NULL) break;
7063 (is->func)(is, is->closure, p, q - p, 0);
7066 /* remember not yet used part of the buffer */
7068 while (p < is->unused)
7076 /* read maximum length of input buffer and send the whole buffer
7077 * to the callback function
7079 count = read(is->fd, is->buf, INPUT_SOURCE_BUF_SIZE);
7084 (is->func)(is, is->closure, is->buf, count, error);
7090 InputSourceRef AddInputSource(pr, lineByLine, func, closure)
7097 GIOChannel *channel;
7098 ChildProc *cp = (ChildProc *) pr;
7100 is = (InputSource *) calloc(1, sizeof(InputSource));
7101 is->lineByLine = lineByLine;
7105 is->fd = fileno(stdin);
7107 is->kind = cp->kind;
7108 is->fd = cp->fdFrom;
7111 is->unused = is->buf;
7115 // is->xid = XtAppAddInput(appContext, is->fd,
7116 // (XtPointer) (XtInputReadMask),
7117 // (XtInputCallbackProc) DoInputCallback,
7121 /* TODO: will this work on windows?*/
7122 printf("DEBUG: fd=%d %d\n",is->fd,is);
7124 channel = g_io_channel_unix_new(is->fd);
7125 g_io_channel_set_close_on_unref (channel, TRUE);
7126 is->sid = g_io_add_watch(channel, G_IO_IN,(GIOFunc) DoInputCallback, is);
7127 is->closure = closure;
7128 return (InputSourceRef) is;
7132 RemoveInputSource(isr)
7135 InputSource *is = (InputSource *) isr;
7137 if (is->sid == 0) return;
7138 g_source_remove(is->sid);
7143 int OutputToProcess(pr, message, count, outError)
7149 ChildProc *cp = (ChildProc *) pr;
7153 outCount = fwrite(message, 1, count, stdout);
7155 outCount = write(cp->fdTo, message, count);
7165 /* Output message to process, with "ms" milliseconds of delay
7166 between each character. This is needed when sending the logon
7167 script to ICC, which for some reason doesn't like the
7168 instantaneous send. */
7169 int OutputToProcessDelayed(pr, message, count, outError, msdelay)
7176 ChildProc *cp = (ChildProc *) pr;
7181 r = write(cp->fdTo, message++, 1);
7194 /**** Animation code by Hugh Fisher, DCS, ANU.
7196 Known problem: if a window overlapping the board is
7197 moved away while a piece is being animated underneath,
7198 the newly exposed area won't be updated properly.
7199 I can live with this.
7201 Known problem: if you look carefully at the animation
7202 of pieces in mono mode, they are being drawn as solid
7203 shapes without interior detail while moving. Fixing
7204 this would be a major complication for minimal return.
7207 /* Masks for XPM pieces. Black and white pieces can have
7208 different shapes, but in the interest of retaining my
7209 sanity pieces must have the same outline on both light
7210 and dark squares, and all pieces must use the same
7211 background square colors/images. */
7213 static int xpmDone = 0;
7216 CreateAnimMasks (pieceDepth)
7223 unsigned long plane;
7226 /* just return for gtk at the moment */
7229 /* Need a bitmap just to get a GC with right depth */
7230 buf = XCreatePixmap(xDisplay, xBoardWindow,
7232 values.foreground = 1;
7233 values.background = 0;
7234 /* Don't use XtGetGC, not read only */
7235 maskGC = XCreateGC(xDisplay, buf,
7236 GCForeground | GCBackground, &values);
7237 XFreePixmap(xDisplay, buf);
7239 buf = XCreatePixmap(xDisplay, xBoardWindow,
7240 squareSize, squareSize, pieceDepth);
7241 values.foreground = XBlackPixel(xDisplay, xScreen);
7242 values.background = XWhitePixel(xDisplay, xScreen);
7243 bufGC = XCreateGC(xDisplay, buf,
7244 GCForeground | GCBackground, &values);
7246 for (piece = WhitePawn; piece <= BlackKing; piece++) {
7247 /* Begin with empty mask */
7248 if(!xpmDone) // [HGM] pieces: keep using existing
7249 xpmMask[piece] = XCreatePixmap(xDisplay, xBoardWindow,
7250 squareSize, squareSize, 1);
7251 XSetFunction(xDisplay, maskGC, GXclear);
7252 XFillRectangle(xDisplay, xpmMask[piece], maskGC,
7253 0, 0, squareSize, squareSize);
7255 /* Take a copy of the piece */
7260 XSetFunction(xDisplay, bufGC, GXcopy);
7261 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn],
7263 0, 0, squareSize, squareSize, 0, 0);
7265 /* XOR the background (light) over the piece */
7266 XSetFunction(xDisplay, bufGC, GXxor);
7268 XCopyArea(xDisplay, xpmLightSquare, buf, bufGC,
7269 0, 0, squareSize, squareSize, 0, 0);
7271 XSetForeground(xDisplay, bufGC, lightSquareColor);
7272 XFillRectangle(xDisplay, buf, bufGC, 0, 0, squareSize, squareSize);
7275 /* We now have an inverted piece image with the background
7276 erased. Construct mask by just selecting all the non-zero
7277 pixels - no need to reconstruct the original image. */
7278 XSetFunction(xDisplay, maskGC, GXor);
7280 /* Might be quicker to download an XImage and create bitmap
7281 data from it rather than this N copies per piece, but it
7282 only takes a fraction of a second and there is a much
7283 longer delay for loading the pieces. */
7284 for (n = 0; n < pieceDepth; n ++) {
7285 XCopyPlane(xDisplay, buf, xpmMask[piece], maskGC,
7286 0, 0, squareSize, squareSize,
7292 XFreePixmap(xDisplay, buf);
7293 XFreeGC(xDisplay, bufGC);
7294 XFreeGC(xDisplay, maskGC);
7298 InitAnimState (anim, info)
7300 XWindowAttributes * info;
7305 /* Each buffer is square size, same depth as window */
7306 // anim->saveBuf = XCreatePixmap(xDisplay, xBoardWindow,
7307 // squareSize, squareSize, info->depth);
7308 // anim->newBuf = XCreatePixmap(xDisplay, xBoardWindow,
7309 // squareSize, squareSize, info->depth);
7311 // /* Create a plain GC for blitting */
7312 // mask = GCForeground | GCBackground | GCFunction |
7313 // GCPlaneMask | GCGraphicsExposures;
7314 // values.foreground = XBlackPixel(xDisplay, xScreen);
7315 // values.background = XWhitePixel(xDisplay, xScreen);
7316 // values.function = GXcopy;
7317 // values.plane_mask = AllPlanes;
7318 // values.graphics_exposures = False;
7319 // anim->blitGC = XCreateGC(xDisplay, xBoardWindow, mask, &values);
7321 // /* Piece will be copied from an existing context at
7322 // the start of each new animation/drag. */
7323 // anim->pieceGC = XCreateGC(xDisplay, xBoardWindow, 0, &values);
7325 // /* Outline will be a read-only copy of an existing */
7326 // anim->outlineGC = None;
7332 static VariantClass old = (VariantClass) -1; // [HGM] pieces: redo every time variant changes
7333 XWindowAttributes info;
7335 /* for gtk at the moment just ... */
7338 if (xpmDone && gameInfo.variant == old) return;
7339 if(xpmDone) old = gameInfo.variant; // first time pieces might not be created yet
7340 // XGetWindowAttributes(xDisplay, xBoardWindow, &info);
7342 // InitAnimState(&game, &info);
7343 // InitAnimState(&player, &info);
7345 /* For XPM pieces, we need bitmaps to use as masks. */
7347 // CreateAnimMasks(info.depth);
7353 static Boolean frameWaiting;
7355 static RETSIGTYPE FrameAlarm (sig)
7358 frameWaiting = False;
7359 /* In case System-V style signals. Needed?? */
7360 signal(SIGALRM, FrameAlarm);
7367 struct itimerval delay;
7369 XSync(xDisplay, False);
7372 frameWaiting = True;
7373 signal(SIGALRM, FrameAlarm);
7374 delay.it_interval.tv_sec =
7375 delay.it_value.tv_sec = time / 1000;
7376 delay.it_interval.tv_usec =
7377 delay.it_value.tv_usec = (time % 1000) * 1000;
7378 setitimer(ITIMER_REAL, &delay, NULL);
7379 while (frameWaiting) pause();
7380 delay.it_interval.tv_sec = delay.it_value.tv_sec = 0;
7381 delay.it_interval.tv_usec = delay.it_value.tv_usec = 0;
7382 setitimer(ITIMER_REAL, &delay, NULL);
7392 // XSync(xDisplay, False);
7394 usleep(time * 1000);
7399 /* Convert board position to corner of screen rect and color */
7402 ScreenSquare(column, row, pt, color)
7403 int column; int row; XPoint * pt; int * color;
7406 pt->x = lineGap + ((BOARD_WIDTH-1)-column) * (squareSize + lineGap);
7407 pt->y = lineGap + row * (squareSize + lineGap);
7409 pt->x = lineGap + column * (squareSize + lineGap);
7410 pt->y = lineGap + ((BOARD_HEIGHT-1)-row) * (squareSize + lineGap);
7412 *color = SquareColor(row, column);
7415 /* Convert window coords to square */
7418 BoardSquare(x, y, column, row)
7419 int x; int y; int * column; int * row;
7421 *column = EventToSquare(x, BOARD_WIDTH);
7422 if (flipView && *column >= 0)
7423 *column = BOARD_WIDTH - 1 - *column;
7424 *row = EventToSquare(y, BOARD_HEIGHT);
7425 if (!flipView && *row >= 0)
7426 *row = BOARD_HEIGHT - 1 - *row;
7431 #undef Max /* just in case */
7433 #define Max(a, b) ((a) > (b) ? (a) : (b))
7434 #define Min(a, b) ((a) < (b) ? (a) : (b))
7437 SetRect(rect, x, y, width, height)
7438 XRectangle * rect; int x; int y; int width; int height;
7442 rect->width = width;
7443 rect->height = height;
7446 /* Test if two frames overlap. If they do, return
7447 intersection rect within old and location of
7448 that rect within new. */
7451 Intersect(old, new, size, area, pt)
7452 XPoint * old; XPoint * new;
7453 int size; XRectangle * area; XPoint * pt;
7455 if (old->x > new->x + size || new->x > old->x + size ||
7456 old->y > new->y + size || new->y > old->y + size) {
7459 SetRect(area, Max(new->x - old->x, 0), Max(new->y - old->y, 0),
7460 size - abs(old->x - new->x), size - abs(old->y - new->y));
7461 pt->x = Max(old->x - new->x, 0);
7462 pt->y = Max(old->y - new->y, 0);
7467 /* For two overlapping frames, return the rect(s)
7468 in the old that do not intersect with the new. */
7471 CalcUpdateRects(old, new, size, update, nUpdates)
7472 XPoint * old; XPoint * new; int size;
7473 XRectangle update[]; int * nUpdates;
7477 /* If old = new (shouldn't happen) then nothing to draw */
7478 if (old->x == new->x && old->y == new->y) {
7482 /* Work out what bits overlap. Since we know the rects
7483 are the same size we don't need a full intersect calc. */
7485 /* Top or bottom edge? */
7486 if (new->y > old->y) {
7487 SetRect(&(update[count]), old->x, old->y, size, new->y - old->y);
7489 } else if (old->y > new->y) {
7490 SetRect(&(update[count]), old->x, old->y + size - (old->y - new->y),
7491 size, old->y - new->y);
7494 /* Left or right edge - don't overlap any update calculated above. */
7495 if (new->x > old->x) {
7496 SetRect(&(update[count]), old->x, Max(new->y, old->y),
7497 new->x - old->x, size - abs(new->y - old->y));
7499 } else if (old->x > new->x) {
7500 SetRect(&(update[count]), new->x + size, Max(new->y, old->y),
7501 old->x - new->x, size - abs(new->y - old->y));
7508 /* Generate a series of frame coords from start->mid->finish.
7509 The movement rate doubles until the half way point is
7510 reached, then halves back down to the final destination,
7511 which gives a nice slow in/out effect. The algorithmn
7512 may seem to generate too many intermediates for short
7513 moves, but remember that the purpose is to attract the
7514 viewers attention to the piece about to be moved and
7515 then to where it ends up. Too few frames would be less
7519 Tween(start, mid, finish, factor, frames, nFrames)
7520 XPoint * start; XPoint * mid;
7521 XPoint * finish; int factor;
7522 XPoint frames[]; int * nFrames;
7524 int fraction, n, count;
7528 /* Slow in, stepping 1/16th, then 1/8th, ... */
7530 for (n = 0; n < factor; n++)
7532 for (n = 0; n < factor; n++) {
7533 frames[count].x = start->x + (mid->x - start->x) / fraction;
7534 frames[count].y = start->y + (mid->y - start->y) / fraction;
7536 fraction = fraction / 2;
7540 frames[count] = *mid;
7543 /* Slow out, stepping 1/2, then 1/4, ... */
7545 for (n = 0; n < factor; n++) {
7546 frames[count].x = finish->x - (finish->x - mid->x) / fraction;
7547 frames[count].y = finish->y - (finish->y - mid->y) / fraction;
7549 fraction = fraction * 2;
7554 /* Draw a piece on the screen without disturbing what's there */
7557 SelectGCMask(piece, clip, outline, mask)
7558 ChessSquare piece; GC * clip; GC * outline; Pixmap * mask;
7562 /* Bitmap for piece being moved. */
7563 if (appData.monoMode) {
7564 *mask = *pieceToSolid(piece);
7565 } else if (useImages) {
7567 *mask = xpmMask[piece];
7569 *mask = ximMaskPm[piece];
7572 *mask = *pieceToSolid(piece);
7575 /* GC for piece being moved. Square color doesn't matter, but
7576 since it gets modified we make a copy of the original. */
7578 if (appData.monoMode)
7583 if (appData.monoMode)
7588 // XCopyGC(xDisplay, source, 0xFFFFFFFF, *clip);
7590 /* Outline only used in mono mode and is not modified */
7592 *outline = bwPieceGC;
7594 *outline = wbPieceGC;
7598 OverlayPiece(piece, clip, outline, dest)
7599 ChessSquare piece; GC clip; GC outline; Drawable dest;
7604 /* Draw solid rectangle which will be clipped to shape of piece */
7605 // XFillRectangle(xDisplay, dest, clip,
7606 // 0, 0, squareSize, squareSize)
7608 if (appData.monoMode)
7609 /* Also draw outline in contrasting color for black
7610 on black / white on white cases */
7611 // XCopyPlane(xDisplay, *pieceToOutline(piece), dest, outline,
7612 // 0, 0, squareSize, squareSize, 0, 0, 1)
7615 /* Copy the piece */
7620 // XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
7622 // 0, 0, squareSize, squareSize,
7627 /* Animate the movement of a single piece */
7630 BeginAnimation(anim, piece, startColor, start)
7638 /* The old buffer is initialised with the start square (empty) */
7639 BlankSquare(0, 0, startColor, EmptySquare, anim->saveBuf);
7640 anim->prevFrame = *start;
7642 /* The piece will be drawn using its own bitmap as a matte */
7643 // SelectGCMask(piece, &anim->pieceGC, &anim->outlineGC, &mask);
7644 // XSetClipMask(xDisplay, anim->pieceGC, mask);
7648 AnimationFrame(anim, frame, piece)
7653 XRectangle updates[4];
7658 /* Save what we are about to draw into the new buffer */
7659 // XCopyArea(xDisplay, xBoardWindow, anim->newBuf, anim->blitGC,
7660 // frame->x, frame->y, squareSize, squareSize,
7663 /* Erase bits of the previous frame */
7664 if (Intersect(&anim->prevFrame, frame, squareSize, &overlap, &pt)) {
7665 /* Where the new frame overlapped the previous,
7666 the contents in newBuf are wrong. */
7667 // XCopyArea(xDisplay, anim->saveBuf, anim->newBuf, anim->blitGC,
7668 // overlap.x, overlap.y,
7669 // overlap.width, overlap.height,
7671 /* Repaint the areas in the old that don't overlap new */
7672 CalcUpdateRects(&anim->prevFrame, frame, squareSize, updates, &count);
7673 for (i = 0; i < count; i++)
7674 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
7675 // updates[i].x - anim->prevFrame.x,
7676 // updates[i].y - anim->prevFrame.y,
7677 // updates[i].width, updates[i].height,
7678 // updates[i].x, updates[i].y)
7681 /* Easy when no overlap */
7682 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
7683 // 0, 0, squareSize, squareSize,
7684 // anim->prevFrame.x, anim->prevFrame.y);
7687 /* Save this frame for next time round */
7688 // XCopyArea(xDisplay, anim->newBuf, anim->saveBuf, anim->blitGC,
7689 // 0, 0, squareSize, squareSize,
7691 anim->prevFrame = *frame;
7693 /* Draw piece over original screen contents, not current,
7694 and copy entire rect. Wipes out overlapping piece images. */
7695 OverlayPiece(piece, anim->pieceGC, anim->outlineGC, anim->newBuf);
7696 // XCopyArea(xDisplay, anim->newBuf, xBoardWindow, anim->blitGC,
7697 // 0, 0, squareSize, squareSize,
7698 // frame->x, frame->y);
7702 EndAnimation (anim, finish)
7706 XRectangle updates[4];
7711 /* The main code will redraw the final square, so we
7712 only need to erase the bits that don't overlap. */
7713 if (Intersect(&anim->prevFrame, finish, squareSize, &overlap, &pt)) {
7714 CalcUpdateRects(&anim->prevFrame, finish, squareSize, updates, &count);
7715 for (i = 0; i < count; i++)
7716 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
7717 // updates[i].x - anim->prevFrame.x,
7718 // updates[i].y - anim->prevFrame.y,
7719 // updates[i].width, updates[i].height,
7720 // updates[i].x, updates[i].y)
7723 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
7724 // 0, 0, squareSize, squareSize,
7725 // anim->prevFrame.x, anim->prevFrame.y);
7730 FrameSequence(anim, piece, startColor, start, finish, frames, nFrames)
7732 ChessSquare piece; int startColor;
7733 XPoint * start; XPoint * finish;
7734 XPoint frames[]; int nFrames;
7738 BeginAnimation(anim, piece, startColor, start);
7739 for (n = 0; n < nFrames; n++) {
7740 AnimationFrame(anim, &(frames[n]), piece);
7741 FrameDelay(appData.animSpeed);
7743 EndAnimation(anim, finish);
7746 /* Main control logic for deciding what to animate and how */
7749 AnimateMove(board, fromX, fromY, toX, toY)
7758 XPoint start, finish, mid;
7759 XPoint frames[kFactor * 2 + 1];
7760 int nFrames, startColor, endColor;
7762 /* Are we animating? */
7763 if (!appData.animate || appData.blindfold)
7766 if(board[toY][toX] == WhiteRook && board[fromY][fromX] == WhiteKing ||
7767 board[toY][toX] == BlackRook && board[fromY][fromX] == BlackKing)
7768 return; // [HGM] FRC: no animtion of FRC castlings, as to-square is not true to-square
7770 if (fromY < 0 || fromX < 0 || toX < 0 || toY < 0) return;
7771 piece = board[fromY][fromX];
7772 if (piece >= EmptySquare) return;
7777 hop = (piece == WhiteKnight || piece == BlackKnight);
7780 if (appData.debugMode) {
7781 fprintf(debugFP, hop ? _("AnimateMove: piece %d hops from %d,%d to %d,%d \n") :
7782 _("AnimateMove: piece %d slides from %d,%d to %d,%d \n"),
7783 piece, fromX, fromY, toX, toY); }
7785 ScreenSquare(fromX, fromY, &start, &startColor);
7786 ScreenSquare(toX, toY, &finish, &endColor);
7789 /* Knight: make diagonal movement then straight */
7790 if (abs(toY - fromY) < abs(toX - fromX)) {
7791 mid.x = start.x + (finish.x - start.x) / 2;
7795 mid.y = start.y + (finish.y - start.y) / 2;
7798 mid.x = start.x + (finish.x - start.x) / 2;
7799 mid.y = start.y + (finish.y - start.y) / 2;
7802 /* Don't use as many frames for very short moves */
7803 if (abs(toY - fromY) + abs(toX - fromX) <= 2)
7804 Tween(&start, &mid, &finish, kFactor - 1, frames, &nFrames);
7806 Tween(&start, &mid, &finish, kFactor, frames, &nFrames);
7807 FrameSequence(&game, piece, startColor, &start, &finish, frames, nFrames);
7809 /* Be sure end square is redrawn */
7810 damage[toY][toX] = True;
7814 DragPieceBegin(x, y)
7817 int boardX, boardY, color;
7820 /* Are we animating? */
7821 if (!appData.animateDragging || appData.blindfold)
7824 /* Figure out which square we start in and the
7825 mouse position relative to top left corner. */
7826 BoardSquare(x, y, &boardX, &boardY);
7827 player.startBoardX = boardX;
7828 player.startBoardY = boardY;
7829 ScreenSquare(boardX, boardY, &corner, &color);
7830 player.startSquare = corner;
7831 player.startColor = color;
7832 /* As soon as we start dragging, the piece will jump slightly to
7833 be centered over the mouse pointer. */
7834 player.mouseDelta.x = squareSize/2;
7835 player.mouseDelta.y = squareSize/2;
7836 /* Initialise animation */
7837 player.dragPiece = PieceForSquare(boardX, boardY);
7839 if (player.dragPiece >= 0 && player.dragPiece < EmptySquare) {
7840 player.dragActive = True;
7841 BeginAnimation(&player, player.dragPiece, color, &corner);
7842 /* Mark this square as needing to be redrawn. Note that
7843 we don't remove the piece though, since logically (ie
7844 as seen by opponent) the move hasn't been made yet. */
7845 if(boardX == BOARD_RGHT+1 && PieceForSquare(boardX-1, boardY) > 1 ||
7846 boardX == BOARD_LEFT-2 && PieceForSquare(boardX+1, boardY) > 1)
7847 // XCopyArea(xDisplay, xBoardWindow, player.saveBuf, player.blitGC,
7848 // corner.x, corner.y, squareSize, squareSize,
7849 // 0, 0); // [HGM] zh: unstack in stead of grab
7850 damage[boardY][boardX] = True;
7852 player.dragActive = False;
7862 /* Are we animating? */
7863 if (!appData.animateDragging || appData.blindfold)
7867 if (! player.dragActive)
7869 /* Move piece, maintaining same relative position
7870 of mouse within square */
7871 corner.x = x - player.mouseDelta.x;
7872 corner.y = y - player.mouseDelta.y;
7873 AnimationFrame(&player, &corner, player.dragPiece);
7875 if (appData.highlightDragging) {
7877 BoardSquare(x, y, &boardX, &boardY);
7878 SetHighlights(fromX, fromY, boardX, boardY);
7887 int boardX, boardY, color;
7890 /* Are we animating? */
7891 if (!appData.animateDragging || appData.blindfold)
7895 if (! player.dragActive)
7897 /* Last frame in sequence is square piece is
7898 placed on, which may not match mouse exactly. */
7899 BoardSquare(x, y, &boardX, &boardY);
7900 ScreenSquare(boardX, boardY, &corner, &color);
7901 EndAnimation(&player, &corner);
7903 /* Be sure end square is redrawn */
7904 damage[boardY][boardX] = True;
7906 /* This prevents weird things happening with fast successive
7907 clicks which on my Sun at least can cause motion events
7908 without corresponding press/release. */
7909 player.dragActive = False;
7912 /* Handle expose event while piece being dragged */
7917 if (!player.dragActive || appData.blindfold)
7920 /* What we're doing: logically, the move hasn't been made yet,
7921 so the piece is still in it's original square. But visually
7922 it's being dragged around the board. So we erase the square
7923 that the piece is on and draw it at the last known drag point. */
7924 BlankSquare(player.startSquare.x, player.startSquare.y,
7925 player.startColor, EmptySquare, xBoardWindow);
7926 AnimationFrame(&player, &player.prevFrame, player.dragPiece);
7927 damage[player.startBoardY][player.startBoardX] = TRUE;
7931 SetProgramStats( FrontEndProgramStats * stats )
7934 // [HGM] done, but perhaps backend should call this directly?
7935 EngineOutputUpdate( stats );