2 * xboard.c -- X front end for XBoard
4 * Copyright 1991 by Digital Equipment Corporation, Maynard,
7 * Enhancements Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006,
8 * 2007, 2008, 2009 Free Software Foundation, Inc.
10 * The following terms apply to Digital Equipment Corporation's copyright
12 * ------------------------------------------------------------------------
15 * Permission to use, copy, modify, and distribute this software and its
16 * documentation for any purpose and without fee is hereby granted,
17 * provided that the above copyright notice appear in all copies and that
18 * both that copyright notice and this permission notice appear in
19 * supporting documentation, and that the name of Digital not be
20 * used in advertising or publicity pertaining to distribution of the
21 * software without specific, written prior permission.
23 * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
24 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
25 * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
26 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
27 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
28 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
30 * ------------------------------------------------------------------------
32 * The following terms apply to the enhanced version of XBoard
33 * distributed by the Free Software Foundation:
34 * ------------------------------------------------------------------------
36 * GNU XBoard is free software: you can redistribute it and/or modify
37 * it under the terms of the GNU General Public License as published by
38 * the Free Software Foundation, either version 3 of the License, or (at
39 * your option) any later version.
41 * GNU XBoard is distributed in the hope that it will be useful, but
42 * WITHOUT ANY WARRANTY; without even the implied warranty of
43 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
44 * General Public License for more details.
46 * You should have received a copy of the GNU General Public License
47 * along with this program. If not, see http://www.gnu.org/licenses/. *
49 *------------------------------------------------------------------------
50 ** See the file ChangeLog for a revision history. */
58 #include <sys/types.h>
63 # if HAVE_SYS_SOCKET_H
64 # include <sys/socket.h>
65 # include <netinet/in.h>
67 # else /* not HAVE_SYS_SOCKET_H */
68 # if HAVE_LAN_SOCKET_H
69 # include <lan/socket.h>
71 # include <lan/netdb.h>
72 # else /* not HAVE_LAN_SOCKET_H */
73 # define OMIT_SOCKETS 1
74 # endif /* not HAVE_LAN_SOCKET_H */
75 # endif /* not HAVE_SYS_SOCKET_H */
76 #endif /* !OMIT_SOCKETS */
81 #else /* not STDC_HEADERS */
82 extern char *getenv();
85 # else /* not HAVE_STRING_H */
87 # endif /* not HAVE_STRING_H */
88 #endif /* not STDC_HEADERS */
91 # include <sys/fcntl.h>
92 #else /* not HAVE_SYS_FCNTL_H */
95 # endif /* HAVE_FCNTL_H */
96 #endif /* not HAVE_SYS_FCNTL_H */
98 #if HAVE_SYS_SYSTEMINFO_H
99 # include <sys/systeminfo.h>
100 #endif /* HAVE_SYS_SYSTEMINFO_H */
102 #if TIME_WITH_SYS_TIME
103 # include <sys/time.h>
107 # include <sys/time.h>
118 # include <sys/wait.h>
123 # define NAMLEN(dirent) strlen((dirent)->d_name)
124 # define HAVE_DIR_STRUCT
126 # define dirent direct
127 # define NAMLEN(dirent) (dirent)->d_namlen
129 # include <sys/ndir.h>
130 # define HAVE_DIR_STRUCT
133 # include <sys/dir.h>
134 # define HAVE_DIR_STRUCT
138 # define HAVE_DIR_STRUCT
142 #include <X11/Intrinsic.h>
143 #include <X11/StringDefs.h>
144 #include <X11/Shell.h>
145 #include <X11/cursorfont.h>
146 #include <X11/Xatom.h>
148 #include <X11/Xaw3d/Dialog.h>
149 #include <X11/Xaw3d/Form.h>
150 #include <X11/Xaw3d/List.h>
151 #include <X11/Xaw3d/Label.h>
152 #include <X11/Xaw3d/SimpleMenu.h>
153 #include <X11/Xaw3d/SmeBSB.h>
154 #include <X11/Xaw3d/SmeLine.h>
155 #include <X11/Xaw3d/Box.h>
156 #include <X11/Xaw3d/MenuButton.h>
157 #include <X11/Xaw3d/Text.h>
158 #include <X11/Xaw3d/AsciiText.h>
160 #include <X11/Xaw/Dialog.h>
161 #include <X11/Xaw/Form.h>
162 #include <X11/Xaw/List.h>
163 #include <X11/Xaw/Label.h>
164 #include <X11/Xaw/SimpleMenu.h>
165 #include <X11/Xaw/SmeBSB.h>
166 #include <X11/Xaw/SmeLine.h>
167 #include <X11/Xaw/Box.h>
168 #include <X11/Xaw/MenuButton.h>
169 #include <X11/Xaw/Text.h>
170 #include <X11/Xaw/AsciiText.h>
173 // [HGM] bitmaps: put before incuding the bitmaps / pixmaps, to know how many piece types there are.
178 #include "pixmaps/pixmaps.h"
179 #define IMAGE_EXT "xpm"
181 #define IMAGE_EXT "xim"
182 #include "bitmaps/bitmaps.h"
187 #include <gdk-pixbuf/gdk-pixbuf.h>
189 #include "bitmaps/icon_white.bm"
190 #include "bitmaps/icon_black.bm"
191 #include "bitmaps/checkmark.bm"
193 #include "frontend.h"
198 #include "xgamelist.h"
199 #include "xhistory.h"
200 #include "xedittags.h"
202 #include "callback.h"
203 #include "interface.h"
205 // must be moved to xengineoutput.h
207 void EngineOutputProc P((Widget w, XEvent *event,
208 String *prms, Cardinal *nprms));
210 void EngineOutputPopDown();
217 #define usleep(t) _sleep2(((t)+500)/1000)
221 # define _(s) gettext (s)
222 # define N_(s) gettext_noop (s)
245 int main P((int argc, char **argv));
246 RETSIGTYPE CmailSigHandler P((int sig));
247 RETSIGTYPE IntSigHandler P((int sig));
248 void CreateGCs P((void));
249 void CreateXIMPieces P((void));
250 void CreateXPMPieces P((void));
251 void CreatePieces P((void));
252 void CreatePieceMenus P((void));
253 Widget CreateMenuBar P((Menu *mb));
254 Widget CreateButtonBar P ((MenuItem *mi));
255 char *FindFont P((char *pattern, int targetPxlSize));
256 void PieceMenuPopup P((Widget w, XEvent *event,
257 String *params, Cardinal *num_params));
258 static void PieceMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
259 static void DropMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
260 int EventToSquare P((int x, int limit));
261 void DrawSquare P((int row, int column, ChessSquare piece, int do_flash));
262 void HandleUserMove P((Widget w, XEvent *event,
263 String *prms, Cardinal *nprms));
264 void AnimateUserMove P((Widget w, XEvent * event,
265 String * params, Cardinal * nParams));
266 void WhiteClock P((Widget w, XEvent *event,
267 String *prms, Cardinal *nprms));
268 void BlackClock P((Widget w, XEvent *event,
269 String *prms, Cardinal *nprms));
270 void CommentPopUp P((char *title, char *label));
271 void CommentPopDown P((void));
272 void CommentCallback P((Widget w, XtPointer client_data,
273 XtPointer call_data));
274 void ICSInputBoxPopUp P((void));
275 void ICSInputBoxPopDown P((void));
276 void FileNamePopUp P((char *label, char *def,
277 FileProc proc, char *openMode));
278 void FileNamePopDown P((void));
279 void FileNameCallback P((Widget w, XtPointer client_data,
280 XtPointer call_data));
281 void FileNameAction P((Widget w, XEvent *event,
282 String *prms, Cardinal *nprms));
283 void AskQuestionReplyAction P((Widget w, XEvent *event,
284 String *prms, Cardinal *nprms));
285 void AskQuestionProc P((Widget w, XEvent *event,
286 String *prms, Cardinal *nprms));
287 void AskQuestionPopDown P((void));
288 void PromotionPopUp P((void));
289 void PromotionPopDown P((void));
290 void PromotionCallback P((Widget w, XtPointer client_data,
291 XtPointer call_data));
292 void EditCommentPopDown P((void));
293 void EditCommentCallback P((Widget w, XtPointer client_data,
294 XtPointer call_data));
295 void SelectCommand P((Widget w, XtPointer client_data, XtPointer call_data));
296 void LoadPositionProc P((Widget w, XEvent *event,
297 String *prms, Cardinal *nprms));
298 void LoadNextPositionProc P((Widget w, XEvent *event, String *prms,
300 void LoadPrevPositionProc P((Widget w, XEvent *event, String *prms,
302 void ReloadPositionProc P((Widget w, XEvent *event, String *prms,
304 void CopyPositionProc P((Widget w, XEvent *event, String *prms,
306 void PastePositionProc P((Widget w, XEvent *event, String *prms,
308 void CopyGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
309 void PasteGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
310 void SaveGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
311 void SavePositionProc P((Widget w, XEvent *event,
312 String *prms, Cardinal *nprms));
313 void MailMoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
314 void ReloadCmailMsgProc P((Widget w, XEvent *event, String *prms,
316 void AnalyzeModeProc P((Widget w, XEvent *event,
317 String *prms, Cardinal *nprms));
318 void AnalyzeFileProc P((Widget w, XEvent *event,
319 String *prms, Cardinal *nprms));
320 void EditGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
321 void EditPositionProc P((Widget w, XEvent *event,
322 String *prms, Cardinal *nprms));
323 void TrainingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
324 void EditCommentProc P((Widget w, XEvent *event,
325 String *prms, Cardinal *nprms));
326 void IcsInputBoxProc P((Widget w, XEvent *event,
327 String *prms, Cardinal *nprms));
328 void EnterKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
329 void AlwaysQueenProc P((Widget w, XEvent *event, String *prms,
331 void AnimateDraggingProc P((Widget w, XEvent *event, String *prms,
333 void AnimateMovingProc P((Widget w, XEvent *event, String *prms,
335 void AutocommProc P((Widget w, XEvent *event, String *prms,
337 void AutoflagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
338 void AutoflipProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
339 void AutobsProc P((Widget w, XEvent *event, String *prms,
341 void AutoraiseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
342 void AutosaveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
343 void BlindfoldProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
344 void FlashMovesProc P((Widget w, XEvent *event, String *prms,
346 void GetMoveListProc P((Widget w, XEvent *event, String *prms,
348 void HighlightDraggingProc P((Widget w, XEvent *event, String *prms,
350 void HighlightLastMoveProc P((Widget w, XEvent *event, String *prms,
352 void MoveSoundProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
353 void IcsAlarmProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
354 void OldSaveStyleProc P((Widget w, XEvent *event, String *prms,
356 void PeriodicUpdatesProc P((Widget w, XEvent *event, String *prms,
358 void PonderNextMoveProc P((Widget w, XEvent *event, String *prms,
360 void PopupMoveErrorsProc P((Widget w, XEvent *event, String *prms,
362 void PopupExitMessageProc P((Widget w, XEvent *event, String *prms,
364 void PremoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
365 void QuietPlayProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
366 void ShowThinkingProc P((Widget w, XEvent *event, String *prms,
368 void HideThinkingProc P((Widget w, XEvent *event, String *prms,
370 void TestLegalityProc P((Widget w, XEvent *event, String *prms,
372 void AboutGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
373 void DebugProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
374 void NothingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
375 void Iconify P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
376 void DisplayMove P((int moveNumber));
377 void DisplayTitle P((char *title));
378 void ICSInitScript P((void));
379 int LoadGamePopUp P((FILE *f, int gameNumber, char *title));
380 void ErrorPopUp P((char *title, char *text, int modal));
381 void ErrorPopDown P((void));
382 static char *ExpandPathName P((char *path));
383 static void CreateAnimVars P((void));
384 void DragPieceBegin P((int x, int y));
385 static void DragPieceMove P((int x, int y));
386 void DragPieceEnd P((int x, int y));
387 static void DrawDragPiece P((void));
388 char *ModeToWidgetName P((GameMode mode));
389 void EngineOutputUpdate( FrontEndProgramStats * stats );
390 void ShuffleMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
391 void EngineMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
392 void UciMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
393 void TimeControlProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
394 void NewVariantProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
395 void FirstSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
396 void SecondSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
397 void ShufflePopDown P(());
398 void EnginePopDown P(());
399 void UciPopDown P(());
400 void TimeControlPopDown P(());
401 void NewVariantPopDown P(());
402 void SettingsPopDown P(());
403 void SetMenuEnables P((Enables *enab));
406 * XBoard depends on Xt R4 or higher
408 int xtVersion = XtSpecificationRelease;
413 Pixel lightSquareColor, darkSquareColor, whitePieceColor, blackPieceColor,
414 jailSquareColor, highlightSquareColor, premoveHighlightColor;
415 Pixel lowTimeWarningColor;
417 #define LINE_TYPE_NORMAL 0
418 #define LINE_TYPE_HIGHLIGHT 1
419 #define LINE_TYPE_PRE 2
422 GC lightSquareGC, darkSquareGC, jailSquareGC, wdPieceGC, wlPieceGC,
423 bdPieceGC, blPieceGC, wbPieceGC, bwPieceGC, coordGC,
424 wjPieceGC, bjPieceGC;
425 Pixmap iconPixmap, wIconPixmap, bIconPixmap, xMarkPixmap;
426 Widget shellWidget, layoutWidget, formWidget, boardWidget, messageWidget,
427 whiteTimerWidget, blackTimerWidget, titleWidget, widgetList[16],
428 commentShell, promotionShell, whitePieceMenu, blackPieceMenu, dropMenu,
429 menuBarWidget, buttonBarWidget, editShell, errorShell, analysisShell,
430 ICSInputShell, fileNameShell, askQuestionShell;
431 Font clockFontID, coordFontID, countFontID;
432 XFontStruct *clockFontStruct, *coordFontStruct, *countFontStruct;
433 XtAppContext appContext;
435 char *oldICSInteractionTitle;
439 char installDir[] = "."; // [HGM] UCI: needed for UCI; probably needs run-time initializtion
441 Position commentX = -1, commentY = -1;
442 Dimension commentW, commentH;
444 int squareSize, smallLayout = 0, tinyLayout = 0,
445 marginW, marginH, // [HGM] for run-time resizing
446 fromX = -1, fromY = -1, toX, toY, commentUp = False, analysisUp = False,
447 ICSInputBoxUp = False, askQuestionUp = False,
448 filenameUp = False, promotionUp = False, pmFromX = -1, pmFromY = -1,
449 editUp = False, errorUp = False, errorExitStatus = -1, lineGap;
450 Pixel timerForegroundPixel, timerBackgroundPixel;
451 Pixel buttonForegroundPixel, buttonBackgroundPixel;
452 char *chessDir, *programName, *programVersion,
453 *gameCopyFilename, *gamePasteFilename;
457 Pixmap pieceBitmap[2][(int)BlackPawn];
458 Pixmap pieceBitmap2[2][(int)BlackPawn+4]; /* [HGM] pieces */
459 Pixmap xpmPieceBitmap[4][(int)BlackPawn]; /* LL, LD, DL, DD actually used*/
460 Pixmap xpmPieceBitmap2[4][(int)BlackPawn+4]; /* LL, LD, DL, DD set to select from */
461 Pixmap xpmLightSquare, xpmDarkSquare, xpmJailSquare;
462 int useImages=0, useImageSqs;
463 XImage *ximPieceBitmap[4][(int)BlackPawn+4]; /* LL, LD, DL, DD */
464 Pixmap ximMaskPm[(int)BlackPawn]; /* clipmasks, used for XIM pieces */
465 Pixmap ximMaskPm2[(int)BlackPawn+4]; /* clipmasks, used for XIM pieces */
466 XImage *ximLightSquare, *ximDarkSquare;
469 #define pieceToSolid(piece) &pieceBitmap[SOLID][(piece) % (int)BlackPawn]
470 #define pieceToOutline(piece) &pieceBitmap[OUTLINE][(piece) % (int)BlackPawn]
472 #define White(piece) ((int)(piece) < (int)BlackPawn)
474 /* Variables for doing smooth animation. This whole thing
475 would be much easier if the board was double-buffered,
476 but that would require a fairly major rewrite. */
481 GC blitGC, pieceGC, outlineGC;
482 XPoint startSquare, prevFrame, mouseDelta;
486 int startBoardX, startBoardY;
489 /* There can be two pieces being animated at once: a player
490 can begin dragging a piece before the remote opponent has moved. */
492 static AnimState game, player;
494 /* Bitmaps for use as masks when drawing XPM pieces.
495 Need one for each black and white piece. */
496 static Pixmap xpmMask[BlackKing + 1];
498 /* This magic number is the number of intermediate frames used
499 in each half of the animation. For short moves it's reduced
500 by 1. The total number of frames will be factor * 2 + 1. */
503 SizeDefaults sizeDefaults[] = SIZE_DEFAULTS;
505 Enables icsEnables[] = {
506 { "menuFile.Mail Move", False },
507 { "menuFile.Reload CMail Message", False },
508 { "menuMode.Machine Black", False },
509 { "menuMode.Machine White", False },
510 { "menuMode.Analysis Mode", False },
511 { "menuMode.Analyze File", False },
512 { "menuMode.Two Machines", False },
514 { "menuHelp.Hint", False },
515 { "menuHelp.Book", False },
516 { "menuStep.Move Now", False },
517 { "menuOptions.Periodic Updates", False },
518 { "menuOptions.Hide Thinking", False },
519 { "menuOptions.Ponder Next Move", False },
524 Enables ncpEnables[] = {
525 { "menuFile.Mail Move", False },
526 { "menuFile.Reload CMail Message", False },
527 { "menuMode.Machine White", False },
528 { "menuMode.Machine Black", False },
529 { "menuMode.Analysis Mode", False },
530 { "menuMode.Analyze File", False },
531 { "menuMode.Two Machines", False },
532 { "menuMode.ICS Client", False },
533 { "menuMode.ICS Input Box", False },
535 { "menuStep.Revert", False },
536 { "menuStep.Move Now", False },
537 { "menuStep.Retract Move", False },
538 { "menuOptions.Auto Comment", False },
539 { "menuOptions.Auto Flag", False },
540 { "menuOptions.Auto Flip View", False },
541 { "menuOptions.Auto Observe", False },
542 { "menuOptions.Auto Raise Board", False },
543 { "menuOptions.Get Move List", False },
544 { "menuOptions.ICS Alarm", False },
545 { "menuOptions.Move Sound", False },
546 { "menuOptions.Quiet Play", False },
547 { "menuOptions.Hide Thinking", False },
548 { "menuOptions.Periodic Updates", False },
549 { "menuOptions.Ponder Next Move", False },
550 { "menuHelp.Hint", False },
551 { "menuHelp.Book", False },
555 Enables gnuEnables[] = {
556 { "menuMode.ICS Client", False },
557 { "menuMode.ICS Input Box", False },
558 { "menuAction.Accept", False },
559 { "menuAction.Decline", False },
560 { "menuAction.Rematch", False },
561 { "menuAction.Adjourn", False },
562 { "menuAction.Stop Examining", False },
563 { "menuAction.Stop Observing", False },
564 { "menuStep.Revert", False },
565 { "menuOptions.Auto Comment", False },
566 { "menuOptions.Auto Observe", False },
567 { "menuOptions.Auto Raise Board", False },
568 { "menuOptions.Get Move List", False },
569 { "menuOptions.Premove", False },
570 { "menuOptions.Quiet Play", False },
572 /* The next two options rely on SetCmailMode being called *after* */
573 /* SetGNUMode so that when GNU is being used to give hints these */
574 /* menu options are still available */
576 { "menuFile.Mail Move", False },
577 { "menuFile.Reload CMail Message", False },
581 Enables cmailEnables[] = {
583 { "menuAction.Call Flag", False },
584 { "menuAction.Draw", True },
585 { "menuAction.Adjourn", False },
586 { "menuAction.Abort", False },
587 { "menuAction.Stop Observing", False },
588 { "menuAction.Stop Examining", False },
589 { "menuFile.Mail Move", True },
590 { "menuFile.Reload CMail Message", True },
594 Enables trainingOnEnables[] = {
595 { "menuMode.Edit Comment", False },
596 { "menuMode.Pause", False },
597 { "menuStep.Forward", False },
598 { "menuStep.Backward", False },
599 { "menuStep.Forward to End", False },
600 { "menuStep.Back to Start", False },
601 { "menuStep.Move Now", False },
602 { "menuStep.Truncate Game", False },
606 Enables trainingOffEnables[] = {
607 { "menuMode.Edit Comment", True },
608 { "menuMode.Pause", True },
609 { "menuStep.Forward", True },
610 { "menuStep.Backward", True },
611 { "menuStep.Forward to End", True },
612 { "menuStep.Back to Start", True },
613 { "menuStep.Move Now", True },
614 { "menuStep.Truncate Game", True },
618 Enables machineThinkingEnables[] = {
619 { "menuFile.Load Game", False },
620 { "menuFile.Load Next Game", False },
621 { "menuFile.Load Previous Game", False },
622 { "menuFile.Reload Same Game", False },
623 { "menuFile.Paste Game", False },
624 { "menuFile.Load Position", False },
625 { "menuFile.Load Next Position", False },
626 { "menuFile.Load Previous Position", False },
627 { "menuFile.Reload Same Position", False },
628 { "menuFile.Paste Position", False },
629 { "menuMode.Machine White", False },
630 { "menuMode.Machine Black", False },
631 { "menuMode.Two Machines", False },
632 { "menuStep.Retract Move", False },
636 Enables userThinkingEnables[] = {
637 { "menuFile.Load Game", True },
638 { "menuFile.Load Next Game", True },
639 { "menuFile.Load Previous Game", True },
640 { "menuFile.Reload Same Game", True },
641 { "menuFile.Paste Game", True },
642 { "menuFile.Load Position", True },
643 { "menuFile.Load Next Position", True },
644 { "menuFile.Load Previous Position", True },
645 { "menuFile.Reload Same Position", True },
646 { "menuFile.Paste Position", True },
647 { "menuMode.Machine White", True },
648 { "menuMode.Machine Black", True },
649 { "menuMode.Two Machines", True },
650 { "menuStep.Retract Move", True },
656 MenuItem fileMenu[] = {
657 {N_("New Shuffle Game ..."), ShuffleMenuProc},
658 {N_("New Variant ..."), NewVariantProc}, // [HGM] variant: not functional yet
659 {"----", NothingProc},
660 {N_("Save Game"), SaveGameProc},
661 {"----", NothingProc},
662 {N_("Copy Game"), CopyGameProc},
663 {N_("Paste Game"), PasteGameProc},
664 {"----", NothingProc},
665 {N_("Load Position"), LoadPositionProc},
666 {N_("Load Next Position"), LoadNextPositionProc},
667 {N_("Load Previous Position"), LoadPrevPositionProc},
668 {N_("Reload Same Position"), ReloadPositionProc},
669 {N_("Save Position"), SavePositionProc},
670 {"----", NothingProc},
671 {N_("Copy Position"), CopyPositionProc},
672 {N_("Paste Position"), PastePositionProc},
673 {"----", NothingProc},
674 {N_("Mail Move"), MailMoveProc},
675 {N_("Reload CMail Message"), ReloadCmailMsgProc},
676 {"----", NothingProc},
680 MenuItem modeMenu[] = {
681 // {N_("Machine White"), MachineWhiteProc},
682 // {N_("Machine Black"), MachineBlackProc},
683 // {N_("Two Machines"), TwoMachinesProc},
684 {N_("Analysis Mode"), AnalyzeModeProc},
685 {N_("Analyze File"), AnalyzeFileProc },
686 // {N_("ICS Client"), IcsClientProc},
687 {N_("Edit Game"), EditGameProc},
688 {N_("Edit Position"), EditPositionProc},
689 {N_("Training"), TrainingProc},
690 {"----", NothingProc},
691 {N_("Show Engine Output"), EngineOutputProc},
692 {N_("Show Evaluation Graph"), NothingProc}, // [HGM] evalgr: not functional yet
693 {N_("Show Game List"), ShowGameListProc},
694 {"Show Move History", HistoryShowProc}, // [HGM] hist: activate 4.2.7 code
695 {"----", NothingProc},
696 {N_("Edit Tags"), EditTagsProc},
697 {N_("Edit Comment"), EditCommentProc},
698 {N_("ICS Input Box"), IcsInputBoxProc},
702 MenuItem optionsMenu[] = {
703 // {N_("Flip View"), FlipViewProc},
704 // {"----", NothingProc},
705 {N_("Adjudications ..."), EngineMenuProc},
706 {N_("General Settings ..."), UciMenuProc},
707 {N_("Engine #1 Settings ..."), FirstSettingsProc},
708 {N_("Engine #2 Settings ..."), SecondSettingsProc},
709 {N_("Time Control ..."), TimeControlProc},
710 {"----", NothingProc},
711 {N_("Always Queen"), AlwaysQueenProc},
712 {N_("Animate Dragging"), AnimateDraggingProc},
713 {N_("Animate Moving"), AnimateMovingProc},
714 {N_("Auto Comment"), AutocommProc},
715 {N_("Auto Flag"), AutoflagProc},
716 {N_("Auto Flip View"), AutoflipProc},
717 {N_("Auto Observe"), AutobsProc},
718 {N_("Auto Raise Board"), AutoraiseProc},
719 {N_("Auto Save"), AutosaveProc},
720 {N_("Blindfold"), BlindfoldProc},
721 {N_("Flash Moves"), FlashMovesProc},
722 {N_("Get Move List"), GetMoveListProc},
724 {N_("Highlight Dragging"), HighlightDraggingProc},
726 {N_("Highlight Last Move"), HighlightLastMoveProc},
727 {N_("Move Sound"), MoveSoundProc},
728 {N_("ICS Alarm"), IcsAlarmProc},
729 {N_("Old Save Style"), OldSaveStyleProc},
730 {N_("Periodic Updates"), PeriodicUpdatesProc},
731 {N_("Ponder Next Move"), PonderNextMoveProc},
732 {N_("Popup Exit Message"), PopupExitMessageProc},
733 {N_("Popup Move Errors"), PopupMoveErrorsProc},
734 {N_("Premove"), PremoveProc},
735 {N_("Quiet Play"), QuietPlayProc},
736 {N_("Hide Thinking"), HideThinkingProc},
737 {N_("Test Legality"), TestLegalityProc},
742 {N_("File"), fileMenu},
743 {N_("Mode"), modeMenu},
744 {N_("Options"), optionsMenu},
748 #define PAUSE_BUTTON N_("P")
749 MenuItem buttonBar[] = {
750 // {"<<", ToStartProc},
751 // {"<", BackwardProc},
752 // {PAUSE_BUTTON, PauseProc},
753 // {">", ForwardProc},
754 // {">>", ToEndProc},
758 #define PIECE_MENU_SIZE 18
759 String pieceMenuStrings[2][PIECE_MENU_SIZE] = {
760 { N_("White"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
761 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
762 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
763 N_("Empty square"), N_("Clear board") },
764 { N_("Black"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
765 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
766 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
767 N_("Empty square"), N_("Clear board") }
769 /* must be in same order as PieceMenuStrings! */
770 ChessSquare pieceMenuTranslation[2][PIECE_MENU_SIZE] = {
771 { WhitePlay, (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
772 WhiteRook, WhiteQueen, WhiteKing, (ChessSquare) 0, WhiteAlfil,
773 WhiteCannon, WhiteAngel, WhiteMarshall, (ChessSquare) 0,
774 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
775 { BlackPlay, (ChessSquare) 0, BlackPawn, BlackKnight, BlackBishop,
776 BlackRook, BlackQueen, BlackKing, (ChessSquare) 0, BlackAlfil,
777 BlackCannon, BlackAngel, BlackMarshall, (ChessSquare) 0,
778 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
781 #define DROP_MENU_SIZE 6
782 String dropMenuStrings[DROP_MENU_SIZE] = {
783 "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"), N_("Queen")
785 /* must be in same order as PieceMenuStrings! */
786 ChessSquare dropMenuTranslation[DROP_MENU_SIZE] = {
787 (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
788 WhiteRook, WhiteQueen
796 DropMenuEnables dmEnables[] = {
805 { XtNborderWidth, 0 },
806 { XtNdefaultDistance, 0 },
810 { XtNborderWidth, 0 },
811 { XtNresizable, (XtArgVal) True },
815 { XtNborderWidth, 0 },
820 XtResource clientResources[] = {
821 { "whitePieceColor", "whitePieceColor", XtRString, sizeof(String),
822 XtOffset(AppDataPtr, whitePieceColor), XtRString,
824 { "blackPieceColor", "blackPieceColor", XtRString, sizeof(String),
825 XtOffset(AppDataPtr, blackPieceColor), XtRString,
827 { "lightSquareColor", "lightSquareColor", XtRString,
828 sizeof(String), XtOffset(AppDataPtr, lightSquareColor),
829 XtRString, LIGHT_SQUARE_COLOR },
830 { "darkSquareColor", "darkSquareColor", XtRString, sizeof(String),
831 XtOffset(AppDataPtr, darkSquareColor), XtRString,
833 { "highlightSquareColor", "highlightSquareColor", XtRString,
834 sizeof(String), XtOffset(AppDataPtr, highlightSquareColor),
835 XtRString, HIGHLIGHT_SQUARE_COLOR },
836 { "premoveHighlightColor", "premoveHighlightColor", XtRString,
837 sizeof(String), XtOffset(AppDataPtr, premoveHighlightColor),
838 XtRString, PREMOVE_HIGHLIGHT_COLOR },
839 { "movesPerSession", "movesPerSession", XtRInt, sizeof(int),
840 XtOffset(AppDataPtr, movesPerSession), XtRImmediate,
841 (XtPointer) MOVES_PER_SESSION },
842 { "timeIncrement", "timeIncrement", XtRInt, sizeof(int),
843 XtOffset(AppDataPtr, timeIncrement), XtRImmediate,
844 (XtPointer) TIME_INCREMENT },
845 { "initString", "initString", XtRString, sizeof(String),
846 XtOffset(AppDataPtr, initString), XtRString, INIT_STRING },
847 { "secondInitString", "secondInitString", XtRString, sizeof(String),
848 XtOffset(AppDataPtr, secondInitString), XtRString, INIT_STRING },
849 { "firstComputerString", "firstComputerString", XtRString,
850 sizeof(String), XtOffset(AppDataPtr, firstComputerString), XtRString,
852 { "secondComputerString", "secondComputerString", XtRString,
853 sizeof(String), XtOffset(AppDataPtr, secondComputerString), XtRString,
855 { "firstChessProgram", "firstChessProgram", XtRString,
856 sizeof(String), XtOffset(AppDataPtr, firstChessProgram),
857 XtRString, FIRST_CHESS_PROGRAM },
858 { "secondChessProgram", "secondChessProgram", XtRString,
859 sizeof(String), XtOffset(AppDataPtr, secondChessProgram),
860 XtRString, SECOND_CHESS_PROGRAM },
861 { "firstPlaysBlack", "firstPlaysBlack", XtRBoolean,
862 sizeof(Boolean), XtOffset(AppDataPtr, firstPlaysBlack),
863 XtRImmediate, (XtPointer) False },
864 { "noChessProgram", "noChessProgram", XtRBoolean,
865 sizeof(Boolean), XtOffset(AppDataPtr, noChessProgram),
866 XtRImmediate, (XtPointer) False },
867 { "firstHost", "firstHost", XtRString, sizeof(String),
868 XtOffset(AppDataPtr, firstHost), XtRString, FIRST_HOST },
869 { "secondHost", "secondHost", XtRString, sizeof(String),
870 XtOffset(AppDataPtr, secondHost), XtRString, SECOND_HOST },
871 { "firstDirectory", "firstDirectory", XtRString, sizeof(String),
872 XtOffset(AppDataPtr, firstDirectory), XtRString, "." },
873 { "secondDirectory", "secondDirectory", XtRString, sizeof(String),
874 XtOffset(AppDataPtr, secondDirectory), XtRString, "." },
875 { "bitmapDirectory", "bitmapDirectory", XtRString,
876 sizeof(String), XtOffset(AppDataPtr, bitmapDirectory),
878 { "remoteShell", "remoteShell", XtRString, sizeof(String),
879 XtOffset(AppDataPtr, remoteShell), XtRString, REMOTE_SHELL },
880 { "remoteUser", "remoteUser", XtRString, sizeof(String),
881 XtOffset(AppDataPtr, remoteUser), XtRString, "" },
882 { "timeDelay", "timeDelay", XtRFloat, sizeof(float),
883 XtOffset(AppDataPtr, timeDelay), XtRString,
884 (XtPointer) TIME_DELAY_QUOTE },
885 { "timeControl", "timeControl", XtRString, sizeof(String),
886 XtOffset(AppDataPtr, timeControl), XtRString,
887 (XtPointer) TIME_CONTROL },
888 { "internetChessServerMode", "internetChessServerMode",
889 XtRBoolean, sizeof(Boolean),
890 XtOffset(AppDataPtr, icsActive), XtRImmediate,
892 { "internetChessServerHost", "internetChessServerHost",
893 XtRString, sizeof(String),
894 XtOffset(AppDataPtr, icsHost),
895 XtRString, (XtPointer) ICS_HOST },
896 { "internetChessServerPort", "internetChessServerPort",
897 XtRString, sizeof(String),
898 XtOffset(AppDataPtr, icsPort), XtRString,
899 (XtPointer) ICS_PORT },
900 { "internetChessServerCommPort", "internetChessServerCommPort",
901 XtRString, sizeof(String),
902 XtOffset(AppDataPtr, icsCommPort), XtRString,
904 { "internetChessServerLogonScript", "internetChessServerLogonScript",
905 XtRString, sizeof(String),
906 XtOffset(AppDataPtr, icsLogon), XtRString,
908 { "internetChessServerHelper", "internetChessServerHelper",
909 XtRString, sizeof(String),
910 XtOffset(AppDataPtr, icsHelper), XtRString, "" },
911 { "internetChessServerInputBox", "internetChessServerInputBox",
912 XtRBoolean, sizeof(Boolean),
913 XtOffset(AppDataPtr, icsInputBox), XtRImmediate,
915 { "icsAlarm", "icsAlarm",
916 XtRBoolean, sizeof(Boolean),
917 XtOffset(AppDataPtr, icsAlarm), XtRImmediate,
919 { "icsAlarmTime", "icsAlarmTime",
921 XtOffset(AppDataPtr, icsAlarmTime), XtRImmediate,
923 { "useTelnet", "useTelnet", XtRBoolean, sizeof(Boolean),
924 XtOffset(AppDataPtr, useTelnet), XtRImmediate,
926 { "telnetProgram", "telnetProgram", XtRString, sizeof(String),
927 XtOffset(AppDataPtr, telnetProgram), XtRString, TELNET_PROGRAM },
928 { "gateway", "gateway", XtRString, sizeof(String),
929 XtOffset(AppDataPtr, gateway), XtRString, "" },
930 { "loadGameFile", "loadGameFile", XtRString, sizeof(String),
931 XtOffset(AppDataPtr, loadGameFile), XtRString, "" },
932 { "loadGameIndex", "loadGameIndex",
934 XtOffset(AppDataPtr, loadGameIndex), XtRImmediate,
936 { "saveGameFile", "saveGameFile", XtRString, sizeof(String),
937 XtOffset(AppDataPtr, saveGameFile), XtRString, "" },
938 { "autoRaiseBoard", "autoRaiseBoard", XtRBoolean,
939 sizeof(Boolean), XtOffset(AppDataPtr, autoRaiseBoard),
940 XtRImmediate, (XtPointer) True },
941 { "autoSaveGames", "autoSaveGames", XtRBoolean,
942 sizeof(Boolean), XtOffset(AppDataPtr, autoSaveGames),
943 XtRImmediate, (XtPointer) False },
944 { "blindfold", "blindfold", XtRBoolean,
945 sizeof(Boolean), XtOffset(AppDataPtr, blindfold),
946 XtRImmediate, (XtPointer) False },
947 { "loadPositionFile", "loadPositionFile", XtRString,
948 sizeof(String), XtOffset(AppDataPtr, loadPositionFile),
950 { "loadPositionIndex", "loadPositionIndex",
952 XtOffset(AppDataPtr, loadPositionIndex), XtRImmediate,
954 { "savePositionFile", "savePositionFile", XtRString,
955 sizeof(String), XtOffset(AppDataPtr, savePositionFile),
957 { "matchMode", "matchMode", XtRBoolean, sizeof(Boolean),
958 XtOffset(AppDataPtr, matchMode), XtRImmediate, (XtPointer) False },
959 { "matchGames", "matchGames", XtRInt, sizeof(int),
960 XtOffset(AppDataPtr, matchGames), XtRImmediate,
962 { "monoMode", "monoMode", XtRBoolean, sizeof(Boolean),
963 XtOffset(AppDataPtr, monoMode), XtRImmediate,
965 { "debugMode", "debugMode", XtRBoolean, sizeof(Boolean),
966 XtOffset(AppDataPtr, debugMode), XtRImmediate,
968 { "clockMode", "clockMode", XtRBoolean, sizeof(Boolean),
969 XtOffset(AppDataPtr, clockMode), XtRImmediate,
971 { "boardSize", "boardSize", XtRString, sizeof(String),
972 XtOffset(AppDataPtr, boardSize), XtRString, "" },
973 { "searchTime", "searchTime", XtRString, sizeof(String),
974 XtOffset(AppDataPtr, searchTime), XtRString,
976 { "searchDepth", "searchDepth", XtRInt, sizeof(int),
977 XtOffset(AppDataPtr, searchDepth), XtRImmediate,
979 { "showCoords", "showCoords", XtRBoolean, sizeof(Boolean),
980 XtOffset(AppDataPtr, showCoords), XtRImmediate,
982 { "showJail", "showJail", XtRInt, sizeof(int),
983 XtOffset(AppDataPtr, showJail), XtRImmediate,
985 { "showThinking", "showThinking", XtRBoolean, sizeof(Boolean),
986 XtOffset(AppDataPtr, showThinking), XtRImmediate,
988 { "ponderNextMove", "ponderNextMove", XtRBoolean, sizeof(Boolean),
989 XtOffset(AppDataPtr, ponderNextMove), XtRImmediate,
991 { "periodicUpdates", "periodicUpdates", XtRBoolean, sizeof(Boolean),
992 XtOffset(AppDataPtr, periodicUpdates), XtRImmediate,
994 { "clockFont", "clockFont", XtRString, sizeof(String),
995 XtOffset(AppDataPtr, clockFont), XtRString, CLOCK_FONT },
996 { "coordFont", "coordFont", XtRString, sizeof(String),
997 XtOffset(AppDataPtr, coordFont), XtRString, COORD_FONT },
998 { "font", "font", XtRString, sizeof(String),
999 XtOffset(AppDataPtr, font), XtRString, DEFAULT_FONT },
1000 { "ringBellAfterMoves", "ringBellAfterMoves",
1001 XtRBoolean, sizeof(Boolean),
1002 XtOffset(AppDataPtr, ringBellAfterMoves),
1003 XtRImmediate, (XtPointer) False },
1004 { "autoCallFlag", "autoCallFlag", XtRBoolean,
1005 sizeof(Boolean), XtOffset(AppDataPtr, autoCallFlag),
1006 XtRImmediate, (XtPointer) False },
1007 { "autoFlipView", "autoFlipView", XtRBoolean,
1008 sizeof(Boolean), XtOffset(AppDataPtr, autoFlipView),
1009 XtRImmediate, (XtPointer) True },
1010 { "autoObserve", "autoObserve", XtRBoolean,
1011 sizeof(Boolean), XtOffset(AppDataPtr, autoObserve),
1012 XtRImmediate, (XtPointer) False },
1013 { "autoComment", "autoComment", XtRBoolean,
1014 sizeof(Boolean), XtOffset(AppDataPtr, autoComment),
1015 XtRImmediate, (XtPointer) False },
1016 { "getMoveList", "getMoveList", XtRBoolean,
1017 sizeof(Boolean), XtOffset(AppDataPtr, getMoveList),
1018 XtRImmediate, (XtPointer) True },
1020 { "highlightDragging", "highlightDragging", XtRBoolean,
1021 sizeof(Boolean), XtOffset(AppDataPtr, highlightDragging),
1022 XtRImmediate, (XtPointer) False },
1024 { "highlightLastMove", "highlightLastMove", XtRBoolean,
1025 sizeof(Boolean), XtOffset(AppDataPtr, highlightLastMove),
1026 XtRImmediate, (XtPointer) False },
1027 { "premove", "premove", XtRBoolean,
1028 sizeof(Boolean), XtOffset(AppDataPtr, premove),
1029 XtRImmediate, (XtPointer) True },
1030 { "testLegality", "testLegality", XtRBoolean,
1031 sizeof(Boolean), XtOffset(AppDataPtr, testLegality),
1032 XtRImmediate, (XtPointer) True },
1033 { "flipView", "flipView", XtRBoolean,
1034 sizeof(Boolean), XtOffset(AppDataPtr, flipView),
1035 XtRImmediate, (XtPointer) False },
1036 { "cmail", "cmailGameName", XtRString, sizeof(String),
1037 XtOffset(AppDataPtr, cmailGameName), XtRString, "" },
1038 { "alwaysPromoteToQueen", "alwaysPromoteToQueen", XtRBoolean,
1039 sizeof(Boolean), XtOffset(AppDataPtr, alwaysPromoteToQueen),
1040 XtRImmediate, (XtPointer) False },
1041 { "oldSaveStyle", "oldSaveStyle", XtRBoolean,
1042 sizeof(Boolean), XtOffset(AppDataPtr, oldSaveStyle),
1043 XtRImmediate, (XtPointer) False },
1044 { "quietPlay", "quietPlay", XtRBoolean,
1045 sizeof(Boolean), XtOffset(AppDataPtr, quietPlay),
1046 XtRImmediate, (XtPointer) False },
1047 { "titleInWindow", "titleInWindow", XtRBoolean,
1048 sizeof(Boolean), XtOffset(AppDataPtr, titleInWindow),
1049 XtRImmediate, (XtPointer) False },
1050 { "localLineEditing", "localLineEditing", XtRBoolean,
1051 sizeof(Boolean), XtOffset(AppDataPtr, localLineEditing),
1052 XtRImmediate, (XtPointer) True }, /* not implemented, must be True */
1054 { "zippyTalk", "zippyTalk", XtRBoolean,
1055 sizeof(Boolean), XtOffset(AppDataPtr, zippyTalk),
1056 XtRImmediate, (XtPointer) ZIPPY_TALK },
1057 { "zippyPlay", "zippyPlay", XtRBoolean,
1058 sizeof(Boolean), XtOffset(AppDataPtr, zippyPlay),
1059 XtRImmediate, (XtPointer) ZIPPY_PLAY },
1060 { "zippyLines", "zippyLines", XtRString, sizeof(String),
1061 XtOffset(AppDataPtr, zippyLines), XtRString, ZIPPY_LINES },
1062 { "zippyPinhead", "zippyPinhead", XtRString, sizeof(String),
1063 XtOffset(AppDataPtr, zippyPinhead), XtRString, ZIPPY_PINHEAD },
1064 { "zippyPassword", "zippyPassword", XtRString, sizeof(String),
1065 XtOffset(AppDataPtr, zippyPassword), XtRString, ZIPPY_PASSWORD },
1066 { "zippyPassword2", "zippyPassword2", XtRString, sizeof(String),
1067 XtOffset(AppDataPtr, zippyPassword2), XtRString, ZIPPY_PASSWORD2 },
1068 { "zippyWrongPassword", "zippyWrongPassword", XtRString, sizeof(String),
1069 XtOffset(AppDataPtr, zippyWrongPassword), XtRString,
1070 ZIPPY_WRONG_PASSWORD },
1071 { "zippyAcceptOnly", "zippyAcceptOnly", XtRString, sizeof(String),
1072 XtOffset(AppDataPtr, zippyAcceptOnly), XtRString, ZIPPY_ACCEPT_ONLY },
1073 { "zippyUseI", "zippyUseI", XtRBoolean,
1074 sizeof(Boolean), XtOffset(AppDataPtr, zippyUseI),
1075 XtRImmediate, (XtPointer) ZIPPY_USE_I },
1076 { "zippyBughouse", "zippyBughouse", XtRInt,
1077 sizeof(int), XtOffset(AppDataPtr, zippyBughouse),
1078 XtRImmediate, (XtPointer) ZIPPY_BUGHOUSE },
1079 { "zippyNoplayCrafty", "zippyNoplayCrafty", XtRBoolean,
1080 sizeof(Boolean), XtOffset(AppDataPtr, zippyNoplayCrafty),
1081 XtRImmediate, (XtPointer) ZIPPY_NOPLAY_CRAFTY },
1082 { "zippyGameEnd", "zippyGameEnd", XtRString, sizeof(String),
1083 XtOffset(AppDataPtr, zippyGameEnd), XtRString, ZIPPY_GAME_END },
1084 { "zippyGameStart", "zippyGameStart", XtRString, sizeof(String),
1085 XtOffset(AppDataPtr, zippyGameStart), XtRString, ZIPPY_GAME_START },
1086 { "zippyAdjourn", "zippyAdjourn", XtRBoolean,
1087 sizeof(Boolean), XtOffset(AppDataPtr, zippyAdjourn),
1088 XtRImmediate, (XtPointer) ZIPPY_ADJOURN },
1089 { "zippyAbort", "zippyAbort", XtRBoolean,
1090 sizeof(Boolean), XtOffset(AppDataPtr, zippyAbort),
1091 XtRImmediate, (XtPointer) ZIPPY_ABORT },
1092 { "zippyVariants", "zippyVariants", XtRString, sizeof(String),
1093 XtOffset(AppDataPtr, zippyVariants), XtRString, ZIPPY_VARIANTS },
1094 { "zippyMaxGames", "zippyMaxGames", XtRInt, sizeof(int),
1095 XtOffset(AppDataPtr, zippyMaxGames), XtRImmediate,
1096 (XtPointer) ZIPPY_MAX_GAMES },
1097 { "zippyReplayTimeout", "zippyReplayTimeout", XtRInt, sizeof(int),
1098 XtOffset(AppDataPtr, zippyReplayTimeout), XtRImmediate,
1099 (XtPointer) ZIPPY_REPLAY_TIMEOUT },
1100 { "zippyShortGame", "zippyShortGame", XtRInt, sizeof(int),
1101 XtOffset(AppDataPtr, zippyShortGame), XtRImmediate,
1104 { "flashCount", "flashCount", XtRInt, sizeof(int),
1105 XtOffset(AppDataPtr, flashCount), XtRImmediate,
1106 (XtPointer) FLASH_COUNT },
1107 { "flashRate", "flashRate", XtRInt, sizeof(int),
1108 XtOffset(AppDataPtr, flashRate), XtRImmediate,
1109 (XtPointer) FLASH_RATE },
1110 { "pixmapDirectory", "pixmapDirectory", XtRString,
1111 sizeof(String), XtOffset(AppDataPtr, pixmapDirectory),
1113 { "msLoginDelay", "msLoginDelay", XtRInt, sizeof(int),
1114 XtOffset(AppDataPtr, msLoginDelay), XtRImmediate,
1115 (XtPointer) MS_LOGIN_DELAY },
1116 { "colorizeMessages", "colorizeMessages", XtRBoolean,
1117 sizeof(Boolean), XtOffset(AppDataPtr, colorize),
1118 XtRImmediate, (XtPointer) False },
1119 { "colorShout", "colorShout", XtRString,
1120 sizeof(String), XtOffset(AppDataPtr, colorShout),
1121 XtRString, COLOR_SHOUT },
1122 { "colorSShout", "colorSShout", XtRString,
1123 sizeof(String), XtOffset(AppDataPtr, colorSShout),
1124 XtRString, COLOR_SSHOUT },
1125 { "colorChannel1", "colorChannel1", XtRString,
1126 sizeof(String), XtOffset(AppDataPtr, colorChannel1),
1127 XtRString, COLOR_CHANNEL1 },
1128 { "colorChannel", "colorChannel", XtRString,
1129 sizeof(String), XtOffset(AppDataPtr, colorChannel),
1130 XtRString, COLOR_CHANNEL },
1131 { "colorKibitz", "colorKibitz", XtRString,
1132 sizeof(String), XtOffset(AppDataPtr, colorKibitz),
1133 XtRString, COLOR_KIBITZ },
1134 { "colorTell", "colorTell", XtRString,
1135 sizeof(String), XtOffset(AppDataPtr, colorTell),
1136 XtRString, COLOR_TELL },
1137 { "colorChallenge", "colorChallenge", XtRString,
1138 sizeof(String), XtOffset(AppDataPtr, colorChallenge),
1139 XtRString, COLOR_CHALLENGE },
1140 { "colorRequest", "colorRequest", XtRString,
1141 sizeof(String), XtOffset(AppDataPtr, colorRequest),
1142 XtRString, COLOR_REQUEST },
1143 { "colorSeek", "colorSeek", XtRString,
1144 sizeof(String), XtOffset(AppDataPtr, colorSeek),
1145 XtRString, COLOR_SEEK },
1146 { "colorNormal", "colorNormal", XtRString,
1147 sizeof(String), XtOffset(AppDataPtr, colorNormal),
1148 XtRString, COLOR_NORMAL },
1149 { "soundProgram", "soundProgram", XtRString,
1150 sizeof(String), XtOffset(AppDataPtr, soundProgram),
1151 XtRString, "play" },
1152 { "soundShout", "soundShout", XtRString,
1153 sizeof(String), XtOffset(AppDataPtr, soundShout),
1155 { "soundSShout", "soundSShout", XtRString,
1156 sizeof(String), XtOffset(AppDataPtr, soundSShout),
1158 { "soundChannel1", "soundChannel1", XtRString,
1159 sizeof(String), XtOffset(AppDataPtr, soundChannel1),
1161 { "soundChannel", "soundChannel", XtRString,
1162 sizeof(String), XtOffset(AppDataPtr, soundChannel),
1164 { "soundKibitz", "soundKibitz", XtRString,
1165 sizeof(String), XtOffset(AppDataPtr, soundKibitz),
1167 { "soundTell", "soundTell", XtRString,
1168 sizeof(String), XtOffset(AppDataPtr, soundTell),
1170 { "soundChallenge", "soundChallenge", XtRString,
1171 sizeof(String), XtOffset(AppDataPtr, soundChallenge),
1173 { "soundRequest", "soundRequest", XtRString,
1174 sizeof(String), XtOffset(AppDataPtr, soundRequest),
1176 { "soundSeek", "soundSeek", XtRString,
1177 sizeof(String), XtOffset(AppDataPtr, soundSeek),
1179 { "soundMove", "soundMove", XtRString,
1180 sizeof(String), XtOffset(AppDataPtr, soundMove),
1182 { "soundIcsWin", "soundIcsWin", XtRString,
1183 sizeof(String), XtOffset(AppDataPtr, soundIcsWin),
1185 { "soundIcsLoss", "soundIcsLoss", XtRString,
1186 sizeof(String), XtOffset(AppDataPtr, soundIcsLoss),
1188 { "soundIcsDraw", "soundIcsDraw", XtRString,
1189 sizeof(String), XtOffset(AppDataPtr, soundIcsDraw),
1191 { "soundIcsUnfinished", "soundIcsUnfinished", XtRString,
1192 sizeof(String), XtOffset(AppDataPtr, soundIcsUnfinished),
1194 { "soundIcsAlarm", "soundIcsAlarm", XtRString,
1195 sizeof(String), XtOffset(AppDataPtr, soundIcsAlarm),
1197 { "reuseFirst", "reuseFirst", XtRBoolean,
1198 sizeof(Boolean), XtOffset(AppDataPtr, reuseFirst),
1199 XtRImmediate, (XtPointer) True },
1200 { "reuseSecond", "reuseSecond", XtRBoolean,
1201 sizeof(Boolean), XtOffset(AppDataPtr, reuseSecond),
1202 XtRImmediate, (XtPointer) True },
1203 { "animateDragging", "animateDragging", XtRBoolean,
1204 sizeof(Boolean), XtOffset(AppDataPtr, animateDragging),
1205 XtRImmediate, (XtPointer) True },
1206 { "animateMoving", "animateMoving", XtRBoolean,
1207 sizeof(Boolean), XtOffset(AppDataPtr, animate),
1208 XtRImmediate, (XtPointer) True },
1209 { "animateSpeed", "animateSpeed", XtRInt,
1210 sizeof(int), XtOffset(AppDataPtr, animSpeed),
1211 XtRImmediate, (XtPointer)10 },
1212 { "popupExitMessage", "popupExitMessage", XtRBoolean,
1213 sizeof(Boolean), XtOffset(AppDataPtr, popupExitMessage),
1214 XtRImmediate, (XtPointer) True },
1215 { "popupMoveErrors", "popupMoveErrors", XtRBoolean,
1216 sizeof(Boolean), XtOffset(AppDataPtr, popupMoveErrors),
1217 XtRImmediate, (XtPointer) False },
1218 { "fontSizeTolerance", "fontSizeTolerance", XtRInt,
1219 sizeof(int), XtOffset(AppDataPtr, fontSizeTolerance),
1220 XtRImmediate, (XtPointer)4 },
1221 { "initialMode", "initialMode", XtRString,
1222 sizeof(String), XtOffset(AppDataPtr, initialMode),
1223 XtRImmediate, (XtPointer) "" },
1224 { "variant", "variant", XtRString,
1225 sizeof(String), XtOffset(AppDataPtr, variant),
1226 XtRImmediate, (XtPointer) "normal" },
1227 { "firstProtocolVersion", "firstProtocolVersion", XtRInt,
1228 sizeof(int), XtOffset(AppDataPtr, firstProtocolVersion),
1229 XtRImmediate, (XtPointer)PROTOVER },
1230 { "secondProtocolVersion", "secondProtocolVersion", XtRInt,
1231 sizeof(int), XtOffset(AppDataPtr, secondProtocolVersion),
1232 XtRImmediate, (XtPointer)PROTOVER },
1233 { "showButtonBar", "showButtonBar", XtRBoolean,
1234 sizeof(Boolean), XtOffset(AppDataPtr, showButtonBar),
1235 XtRImmediate, (XtPointer) True },
1236 { "lowTimeWarningColor", "lowTimeWarningColor", XtRString,
1237 sizeof(String), XtOffset(AppDataPtr, lowTimeWarningColor),
1238 XtRString, COLOR_LOWTIMEWARNING },
1239 { "lowTimeWarning", "lowTimeWarning", XtRBoolean,
1240 sizeof(Boolean), XtOffset(AppDataPtr, lowTimeWarning),
1241 XtRImmediate, (XtPointer) False },
1242 {"icsEngineAnalyze", "icsEngineAnalyze", XtRBoolean, /* [DM] icsEngineAnalyze */
1243 sizeof(Boolean), XtOffset(AppDataPtr, icsEngineAnalyze),
1244 XtRImmediate, (XtPointer) False },
1245 { "firstScoreAbs", "firstScoreAbs", XtRBoolean,
1246 sizeof(Boolean), XtOffset(AppDataPtr, firstScoreIsAbsolute),
1247 XtRImmediate, (XtPointer) False },
1248 { "secondScoreAbs", "secondScoreAbs", XtRBoolean,
1249 sizeof(Boolean), XtOffset(AppDataPtr, secondScoreIsAbsolute),
1250 XtRImmediate, (XtPointer) False },
1251 { "pgnExtendedInfo", "pgnExtendedInfo", XtRBoolean,
1252 sizeof(Boolean), XtOffset(AppDataPtr, saveExtendedInfoInPGN),
1253 XtRImmediate, (XtPointer) False },
1254 { "hideThinkingFromHuman", "hideThinkingFromHuman", XtRBoolean,
1255 sizeof(Boolean), XtOffset(AppDataPtr, hideThinkingFromHuman),
1256 XtRImmediate, (XtPointer) True },
1257 { "adjudicateLossThreshold", "adjudicateLossThreshold", XtRInt,
1258 sizeof(int), XtOffset(AppDataPtr, adjudicateLossThreshold),
1259 XtRImmediate, (XtPointer) 0},
1260 { "pgnEventHeader", "pgnEventHeader", XtRString,
1261 sizeof(String), XtOffset(AppDataPtr, pgnEventHeader),
1262 XtRImmediate, (XtPointer) "Computer Chess Game" },
1263 { "defaultFrcPosition", "defaultFrcPositon", XtRInt,
1264 sizeof(int), XtOffset(AppDataPtr, defaultFrcPosition),
1265 XtRImmediate, (XtPointer) -1},
1266 { "gameListTags", "gameListTags", XtRString,
1267 sizeof(String), XtOffset(AppDataPtr, gameListTags),
1268 XtRImmediate, (XtPointer) GLT_DEFAULT_TAGS },
1270 // [HGM] 4.3.xx options
1271 { "boardWidth", "boardWidth", XtRInt,
1272 sizeof(int), XtOffset(AppDataPtr, NrFiles),
1273 XtRImmediate, (XtPointer) -1},
1274 { "boardHeight", "boardHeight", XtRInt,
1275 sizeof(int), XtOffset(AppDataPtr, NrRanks),
1276 XtRImmediate, (XtPointer) -1},
1277 { "matchPause", "matchPause", XtRInt,
1278 sizeof(int), XtOffset(AppDataPtr, matchPause),
1279 XtRImmediate, (XtPointer) 10000},
1280 { "holdingsSize", "holdingsSize", XtRInt,
1281 sizeof(int), XtOffset(AppDataPtr, holdingsSize),
1282 XtRImmediate, (XtPointer) -1},
1283 { "flipBlack", "flipBlack", XtRBoolean,
1284 sizeof(Boolean), XtOffset(AppDataPtr, upsideDown),
1285 XtRImmediate, (XtPointer) False},
1286 { "allWhite", "allWhite", XtRBoolean,
1287 sizeof(Boolean), XtOffset(AppDataPtr, allWhite),
1288 XtRImmediate, (XtPointer) False},
1289 { "pieceToCharTable", "pieceToCharTable", XtRString,
1290 sizeof(String), XtOffset(AppDataPtr, pieceToCharTable),
1291 XtRImmediate, (XtPointer) 0},
1292 { "alphaRank", "alphaRank", XtRBoolean,
1293 sizeof(Boolean), XtOffset(AppDataPtr, alphaRank),
1294 XtRImmediate, (XtPointer) False},
1295 { "testClaims", "testClaims", XtRBoolean,
1296 sizeof(Boolean), XtOffset(AppDataPtr, testClaims),
1297 XtRImmediate, (XtPointer) True},
1298 { "checkMates", "checkMates", XtRBoolean,
1299 sizeof(Boolean), XtOffset(AppDataPtr, checkMates),
1300 XtRImmediate, (XtPointer) True},
1301 { "materialDraws", "materialDraws", XtRBoolean,
1302 sizeof(Boolean), XtOffset(AppDataPtr, materialDraws),
1303 XtRImmediate, (XtPointer) True},
1304 { "trivialDraws", "trivialDraws", XtRBoolean,
1305 sizeof(Boolean), XtOffset(AppDataPtr, trivialDraws),
1306 XtRImmediate, (XtPointer) False},
1307 { "ruleMoves", "ruleMoves", XtRInt,
1308 sizeof(int), XtOffset(AppDataPtr, ruleMoves),
1309 XtRImmediate, (XtPointer) 51},
1310 { "repeatsToDraw", "repeatsToDraw", XtRInt,
1311 sizeof(int), XtOffset(AppDataPtr, drawRepeats),
1312 XtRImmediate, (XtPointer) 6},
1313 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1314 sizeof(int), XtOffset(AppDataPtr, engineComments),
1315 XtRImmediate, (XtPointer) 1},
1316 { "userName", "userName", XtRString,
1317 sizeof(int), XtOffset(AppDataPtr, userName),
1318 XtRImmediate, (XtPointer) 0},
1319 { "autoKibitz", "autoKibitz", XtRBoolean,
1320 sizeof(Boolean), XtOffset(AppDataPtr, autoKibitz),
1321 XtRImmediate, (XtPointer) False},
1322 { "firstTimeOdds", "firstTimeOdds", XtRInt,
1323 sizeof(int), XtOffset(AppDataPtr, firstTimeOdds),
1324 XtRImmediate, (XtPointer) 1},
1325 { "secondTimeOdds", "secondTimeOdds", XtRInt,
1326 sizeof(int), XtOffset(AppDataPtr, secondTimeOdds),
1327 XtRImmediate, (XtPointer) 1},
1328 { "timeOddsMode", "timeOddsMode", XtRInt,
1329 sizeof(int), XtOffset(AppDataPtr, timeOddsMode),
1330 XtRImmediate, (XtPointer) 0},
1331 { "firstAccumulateTC", "firstAccumulateTC", XtRInt,
1332 sizeof(int), XtOffset(AppDataPtr, firstAccumulateTC),
1333 XtRImmediate, (XtPointer) 1},
1334 { "secondAccumulateTC", "secondAccumulateTC", XtRInt,
1335 sizeof(int), XtOffset(AppDataPtr, secondAccumulateTC),
1336 XtRImmediate, (XtPointer) 1},
1337 { "firstNPS", "firstNPS", XtRInt,
1338 sizeof(int), XtOffset(AppDataPtr, firstNPS),
1339 XtRImmediate, (XtPointer) -1},
1340 { "secondNPS", "secondNPS", XtRInt,
1341 sizeof(int), XtOffset(AppDataPtr, secondNPS),
1342 XtRImmediate, (XtPointer) -1},
1343 { "serverMoves", "serverMoves", XtRString,
1344 sizeof(String), XtOffset(AppDataPtr, serverMovesName),
1345 XtRImmediate, (XtPointer) 0},
1346 { "serverPause", "serverPause", XtRInt,
1347 sizeof(int), XtOffset(AppDataPtr, serverPause),
1348 XtRImmediate, (XtPointer) 0},
1349 { "suppressLoadMoves", "suppressLoadMoves", XtRBoolean,
1350 sizeof(Boolean), XtOffset(AppDataPtr, suppressLoadMoves),
1351 XtRImmediate, (XtPointer) False},
1352 { "userName", "userName", XtRString,
1353 sizeof(String), XtOffset(AppDataPtr, userName),
1354 XtRImmediate, (XtPointer) 0},
1355 { "egtFormats", "egtFormats", XtRString,
1356 sizeof(String), XtOffset(AppDataPtr, egtFormats),
1357 XtRImmediate, (XtPointer) 0},
1358 { "rewindIndex", "rewindIndex", XtRInt,
1359 sizeof(int), XtOffset(AppDataPtr, rewindIndex),
1360 XtRImmediate, (XtPointer) 0},
1361 { "sameColorGames", "sameColorGames", XtRInt,
1362 sizeof(int), XtOffset(AppDataPtr, sameColorGames),
1363 XtRImmediate, (XtPointer) 0},
1364 { "smpCores", "smpCores", XtRInt,
1365 sizeof(int), XtOffset(AppDataPtr, smpCores),
1366 XtRImmediate, (XtPointer) 1},
1367 { "niceEngines", "niceEngines", XtRInt,
1368 sizeof(int), XtOffset(AppDataPtr, niceEngines),
1369 XtRImmediate, (XtPointer) 0},
1370 { "nameOfDebugFile", "nameOfDebugFile", XtRString,
1371 sizeof(String), XtOffset(AppDataPtr, nameOfDebugFile),
1372 XtRImmediate, (XtPointer) "xboard.debug"},
1373 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1374 sizeof(int), XtOffset(AppDataPtr, engineComments),
1375 XtRImmediate, (XtPointer) 0},
1376 { "noGUI", "noGUI", XtRBoolean,
1377 sizeof(Boolean), XtOffset(AppDataPtr, noGUI),
1378 XtRImmediate, (XtPointer) 0},
1379 { "firstOptions", "firstOptions", XtRString,
1380 sizeof(String), XtOffset(AppDataPtr, firstOptions),
1381 XtRImmediate, (XtPointer) "" },
1382 { "secondOptions", "secondOptions", XtRString,
1383 sizeof(String), XtOffset(AppDataPtr, secondOptions),
1384 XtRImmediate, (XtPointer) "" },
1385 { "firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XtRString,
1386 sizeof(String), XtOffset(AppDataPtr, fenOverride1),
1387 XtRImmediate, (XtPointer) 0 },
1388 { "secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XtRString,
1389 sizeof(String), XtOffset(AppDataPtr, fenOverride2),
1390 XtRImmediate, (XtPointer) 0 },
1392 // [HGM] Winboard_x UCI options
1393 { "firstIsUCI", "firstIsUCI", XtRBoolean,
1394 sizeof(Boolean), XtOffset(AppDataPtr, firstIsUCI),
1395 XtRImmediate, (XtPointer) False},
1396 { "secondIsUCI", "secondIsUCI", XtRBoolean,
1397 sizeof(Boolean), XtOffset(AppDataPtr, secondIsUCI),
1398 XtRImmediate, (XtPointer) False},
1399 { "firstHasOwnBookUCI", "firstHasOwnBookUCI", XtRBoolean,
1400 sizeof(Boolean), XtOffset(AppDataPtr, firstHasOwnBookUCI),
1401 XtRImmediate, (XtPointer) True},
1402 { "secondHasOwnBookUCI", "secondHasOwnBookUCI", XtRBoolean,
1403 sizeof(Boolean), XtOffset(AppDataPtr, secondHasOwnBookUCI),
1404 XtRImmediate, (XtPointer) True},
1405 { "usePolyglotBook", "usePolyglotBook", XtRBoolean,
1406 sizeof(Boolean), XtOffset(AppDataPtr, usePolyglotBook),
1407 XtRImmediate, (XtPointer) False},
1408 { "defaultHashSize", "defaultHashSize", XtRInt,
1409 sizeof(int), XtOffset(AppDataPtr, defaultHashSize),
1410 XtRImmediate, (XtPointer) 64},
1411 { "defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XtRInt,
1412 sizeof(int), XtOffset(AppDataPtr, defaultCacheSizeEGTB),
1413 XtRImmediate, (XtPointer) 4},
1414 { "polyglotDir", "polyglotDir", XtRString,
1415 sizeof(String), XtOffset(AppDataPtr, polyglotDir),
1416 XtRImmediate, (XtPointer) "." },
1417 { "polyglotBook", "polyglotBook", XtRString,
1418 sizeof(String), XtOffset(AppDataPtr, polyglotBook),
1419 XtRImmediate, (XtPointer) "" },
1420 { "defaultPathEGTB", "defaultPathEGTB", XtRString,
1421 sizeof(String), XtOffset(AppDataPtr, defaultPathEGTB),
1422 XtRImmediate, (XtPointer) "/usr/local/share/egtb"},
1423 { "delayBeforeQuit", "delayBeforeQuit", XtRInt,
1424 sizeof(int), XtOffset(AppDataPtr, delayBeforeQuit),
1425 XtRImmediate, (XtPointer) 0},
1426 { "delayAfterQuit", "delayAfterQuit", XtRInt,
1427 sizeof(int), XtOffset(AppDataPtr, delayAfterQuit),
1428 XtRImmediate, (XtPointer) 0},
1431 XrmOptionDescRec shellOptions[] = {
1432 { "-whitePieceColor", "whitePieceColor", XrmoptionSepArg, NULL },
1433 { "-blackPieceColor", "blackPieceColor", XrmoptionSepArg, NULL },
1434 { "-lightSquareColor", "lightSquareColor", XrmoptionSepArg, NULL },
1435 { "-darkSquareColor", "darkSquareColor", XrmoptionSepArg, NULL },
1436 { "-highlightSquareColor", "highlightSquareColor", XrmoptionSepArg, NULL },
1437 { "-premoveHighlightColor", "premoveHighlightColor", XrmoptionSepArg,NULL},
1438 { "-movesPerSession", "movesPerSession", XrmoptionSepArg, NULL },
1439 { "-mps", "movesPerSession", XrmoptionSepArg, NULL },
1440 { "-timeIncrement", "timeIncrement", XrmoptionSepArg, NULL },
1441 { "-inc", "timeIncrement", XrmoptionSepArg, NULL },
1442 { "-initString", "initString", XrmoptionSepArg, NULL },
1443 { "-firstInitString", "initString", XrmoptionSepArg, NULL },
1444 { "-secondInitString", "secondInitString", XrmoptionSepArg, NULL },
1445 { "-firstComputerString", "firstComputerString", XrmoptionSepArg, NULL },
1446 { "-secondComputerString", "secondComputerString", XrmoptionSepArg, NULL },
1447 { "-firstChessProgram", "firstChessProgram", XrmoptionSepArg, NULL },
1448 { "-fcp", "firstChessProgram", XrmoptionSepArg, NULL },
1449 { "-secondChessProgram", "secondChessProgram", XrmoptionSepArg, NULL },
1450 { "-scp", "secondChessProgram", XrmoptionSepArg, NULL },
1451 { "-firstPlaysBlack", "firstPlaysBlack", XrmoptionSepArg, NULL },
1452 { "-fb", "firstPlaysBlack", XrmoptionNoArg, "True" },
1453 { "-xfb", "firstPlaysBlack", XrmoptionNoArg, "False" },
1454 { "-noChessProgram", "noChessProgram", XrmoptionSepArg, NULL },
1455 { "-ncp", "noChessProgram", XrmoptionNoArg, "True" },
1456 { "-xncp", "noChessProgram", XrmoptionNoArg, "False" },
1457 { "-firstHost", "firstHost", XrmoptionSepArg, NULL },
1458 { "-fh", "firstHost", XrmoptionSepArg, NULL },
1459 { "-secondHost", "secondHost", XrmoptionSepArg, NULL },
1460 { "-sh", "secondHost", XrmoptionSepArg, NULL },
1461 { "-firstDirectory", "firstDirectory", XrmoptionSepArg, NULL },
1462 { "-fd", "firstDirectory", XrmoptionSepArg, NULL },
1463 { "-secondDirectory", "secondDirectory", XrmoptionSepArg, NULL },
1464 { "-sd", "secondDirectory", XrmoptionSepArg, NULL },
1465 { "-bitmapDirectory", "bitmapDirectory", XrmoptionSepArg, NULL },
1466 { "-bm", "bitmapDirectory", XrmoptionSepArg, NULL },
1467 { "-remoteShell", "remoteShell", XrmoptionSepArg, NULL },
1468 { "-rsh", "remoteShell", XrmoptionSepArg, NULL },
1469 { "-remoteUser", "remoteUser", XrmoptionSepArg, NULL },
1470 { "-ruser", "remoteUser", XrmoptionSepArg, NULL },
1471 { "-timeDelay", "timeDelay", XrmoptionSepArg, NULL },
1472 { "-td", "timeDelay", XrmoptionSepArg, NULL },
1473 { "-timeControl", "timeControl", XrmoptionSepArg, NULL },
1474 { "-tc", "timeControl", XrmoptionSepArg, NULL },
1475 { "-internetChessServerMode", "internetChessServerMode",
1476 XrmoptionSepArg, NULL },
1477 { "-ics", "internetChessServerMode", XrmoptionNoArg, "True" },
1478 { "-xics", "internetChessServerMode", XrmoptionNoArg, "False" },
1479 { "-internetChessServerHost", "internetChessServerHost",
1480 XrmoptionSepArg, NULL },
1481 { "-icshost", "internetChessServerHost", XrmoptionSepArg, NULL },
1482 { "-internetChessServerPort", "internetChessServerPort",
1483 XrmoptionSepArg, NULL },
1484 { "-icsport", "internetChessServerPort", XrmoptionSepArg, NULL },
1485 { "-internetChessServerCommPort", "internetChessServerCommPort",
1486 XrmoptionSepArg, NULL },
1487 { "-icscomm", "internetChessServerCommPort", XrmoptionSepArg, NULL },
1488 { "-internetChessServerLogonScript", "internetChessServerLogonScript",
1489 XrmoptionSepArg, NULL },
1490 { "-icslogon", "internetChessServerLogonScript", XrmoptionSepArg, NULL },
1491 { "-internetChessServerHelper", "internetChessServerHelper",
1492 XrmoptionSepArg, NULL },
1493 { "-icshelper", "internetChessServerHelper", XrmoptionSepArg, NULL },
1494 { "-internetChessServerInputBox", "internetChessServerInputBox",
1495 XrmoptionSepArg, NULL },
1496 { "-icsinput", "internetChessServerInputBox", XrmoptionNoArg, "True" },
1497 { "-xicsinput", "internetChessServerInputBox", XrmoptionNoArg, "False" },
1498 { "-icsAlarm", "icsAlarm", XrmoptionSepArg, NULL },
1499 { "-alarm", "icsAlarm", XrmoptionNoArg, "True" },
1500 { "-xalarm", "icsAlarm", XrmoptionNoArg, "False" },
1501 { "-icsAlarmTime", "icsAlarmTime", XrmoptionSepArg, NULL },
1502 { "-useTelnet", "useTelnet", XrmoptionSepArg, NULL },
1503 { "-telnet", "useTelnet", XrmoptionNoArg, "True" },
1504 { "-xtelnet", "useTelnet", XrmoptionNoArg, "False" },
1505 { "-telnetProgram", "telnetProgram", XrmoptionSepArg, NULL },
1506 { "-gateway", "gateway", XrmoptionSepArg, NULL },
1507 { "-loadGameFile", "loadGameFile", XrmoptionSepArg, NULL },
1508 { "-lgf", "loadGameFile", XrmoptionSepArg, NULL },
1509 { "-loadGameIndex", "loadGameIndex", XrmoptionSepArg, NULL },
1510 { "-lgi", "loadGameIndex", XrmoptionSepArg, NULL },
1511 { "-saveGameFile", "saveGameFile", XrmoptionSepArg, NULL },
1512 { "-sgf", "saveGameFile", XrmoptionSepArg, NULL },
1513 { "-autoSaveGames", "autoSaveGames", XrmoptionSepArg, NULL },
1514 { "-autosave", "autoSaveGames", XrmoptionNoArg, "True" },
1515 { "-xautosave", "autoSaveGames", XrmoptionNoArg, "False" },
1516 { "-autoRaiseBoard", "autoRaiseBoard", XrmoptionSepArg, NULL },
1517 { "-autoraise", "autoRaiseBoard", XrmoptionNoArg, "True" },
1518 { "-xautoraise", "autoRaiseBoard", XrmoptionNoArg, "False" },
1519 { "-blindfold", "blindfold", XrmoptionSepArg, NULL },
1520 { "-blind", "blindfold", XrmoptionNoArg, "True" },
1521 { "-xblind", "blindfold", XrmoptionNoArg, "False" },
1522 { "-loadPositionFile", "loadPositionFile", XrmoptionSepArg, NULL },
1523 { "-lpf", "loadPositionFile", XrmoptionSepArg, NULL },
1524 { "-loadPositionIndex", "loadPositionIndex", XrmoptionSepArg, NULL },
1525 { "-lpi", "loadPositionIndex", XrmoptionSepArg, NULL },
1526 { "-savePositionFile", "savePositionFile", XrmoptionSepArg, NULL },
1527 { "-spf", "savePositionFile", XrmoptionSepArg, NULL },
1528 { "-matchMode", "matchMode", XrmoptionSepArg, NULL },
1529 { "-mm", "matchMode", XrmoptionNoArg, "True" },
1530 { "-xmm", "matchMode", XrmoptionNoArg, "False" },
1531 { "-matchGames", "matchGames", XrmoptionSepArg, NULL },
1532 { "-mg", "matchGames", XrmoptionSepArg, NULL },
1533 { "-monoMode", "monoMode", XrmoptionSepArg, NULL },
1534 { "-mono", "monoMode", XrmoptionNoArg, "True" },
1535 { "-xmono", "monoMode", XrmoptionNoArg, "False" },
1536 { "-debugMode", "debugMode", XrmoptionSepArg, NULL },
1537 { "-debug", "debugMode", XrmoptionNoArg, "True" },
1538 { "-xdebug", "debugMode", XrmoptionNoArg, "False" },
1539 { "-clockMode", "clockMode", XrmoptionSepArg, NULL },
1540 { "-clock", "clockMode", XrmoptionNoArg, "True" },
1541 { "-xclock", "clockMode", XrmoptionNoArg, "False" },
1542 { "-boardSize", "boardSize", XrmoptionSepArg, NULL },
1543 { "-size", "boardSize", XrmoptionSepArg, NULL },
1544 { "-searchTime", "searchTime", XrmoptionSepArg, NULL },
1545 { "-st", "searchTime", XrmoptionSepArg, NULL },
1546 { "-searchDepth", "searchDepth", XrmoptionSepArg, NULL },
1547 { "-depth", "searchDepth", XrmoptionSepArg, NULL },
1548 { "-showCoords", "showCoords", XrmoptionSepArg, NULL },
1549 { "-coords", "showCoords", XrmoptionNoArg, "True" },
1550 { "-xcoords", "showCoords", XrmoptionNoArg, "False" },
1552 { "-showJail", "showJail", XrmoptionSepArg, NULL },
1553 { "-jail", "showJail", XrmoptionNoArg, "1" },
1554 { "-sidejail", "showJail", XrmoptionNoArg, "2" },
1555 { "-xjail", "showJail", XrmoptionNoArg, "0" },
1557 { "-showThinking", "showThinking", XrmoptionSepArg, NULL },
1558 { "-thinking", "showThinking", XrmoptionNoArg, "True" },
1559 { "-xthinking", "showThinking", XrmoptionNoArg, "False" },
1560 { "-ponderNextMove", "ponderNextMove", XrmoptionSepArg, NULL },
1561 { "-ponder", "ponderNextMove", XrmoptionNoArg, "True" },
1562 { "-xponder", "ponderNextMove", XrmoptionNoArg, "False" },
1563 { "-periodicUpdates", "periodicUpdates", XrmoptionSepArg, NULL },
1564 { "-periodic", "periodicUpdates", XrmoptionNoArg, "True" },
1565 { "-xperiodic", "periodicUpdates", XrmoptionNoArg, "False" },
1566 { "-clockFont", "clockFont", XrmoptionSepArg, NULL },
1567 { "-coordFont", "coordFont", XrmoptionSepArg, NULL },
1568 { "-font", "font", XrmoptionSepArg, NULL },
1569 { "-ringBellAfterMoves", "ringBellAfterMoves", XrmoptionSepArg, NULL },
1570 { "-bell", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1571 { "-xbell", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1572 { "-movesound", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1573 { "-xmovesound", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1574 { "-autoCallFlag", "autoCallFlag", XrmoptionSepArg, NULL },
1575 { "-autoflag", "autoCallFlag", XrmoptionNoArg, "True" },
1576 { "-xautoflag", "autoCallFlag", XrmoptionNoArg, "False" },
1577 { "-autoFlipView", "autoFlipView", XrmoptionSepArg, NULL },
1578 { "-autoflip", "autoFlipView", XrmoptionNoArg, "True" },
1579 { "-xautoflip", "autoFlipView", XrmoptionNoArg, "False" },
1580 { "-autoObserve", "autoObserve", XrmoptionSepArg, NULL },
1581 { "-autobs", "autoObserve", XrmoptionNoArg, "True" },
1582 { "-xautobs", "autoObserve", XrmoptionNoArg, "False" },
1583 { "-autoComment", "autoComment", XrmoptionSepArg, NULL },
1584 { "-autocomm", "autoComment", XrmoptionNoArg, "True" },
1585 { "-xautocomm", "autoComment", XrmoptionNoArg, "False" },
1586 { "-getMoveList", "getMoveList", XrmoptionSepArg, NULL },
1587 { "-moves", "getMoveList", XrmoptionNoArg, "True" },
1588 { "-xmoves", "getMoveList", XrmoptionNoArg, "False" },
1590 { "-highlightDragging", "highlightDragging", XrmoptionSepArg, NULL },
1591 { "-highdrag", "highlightDragging", XrmoptionNoArg, "True" },
1592 { "-xhighdrag", "highlightDragging", XrmoptionNoArg, "False" },
1594 { "-highlightLastMove", "highlightLastMove", XrmoptionSepArg, NULL },
1595 { "-highlight", "highlightLastMove", XrmoptionNoArg, "True" },
1596 { "-xhighlight", "highlightLastMove", XrmoptionNoArg, "False" },
1597 { "-premove", "premove", XrmoptionSepArg, NULL },
1598 { "-pre", "premove", XrmoptionNoArg, "True" },
1599 { "-xpre", "premove", XrmoptionNoArg, "False" },
1600 { "-testLegality", "testLegality", XrmoptionSepArg, NULL },
1601 { "-legal", "testLegality", XrmoptionNoArg, "True" },
1602 { "-xlegal", "testLegality", XrmoptionNoArg, "False" },
1603 { "-flipView", "flipView", XrmoptionSepArg, NULL },
1604 { "-flip", "flipView", XrmoptionNoArg, "True" },
1605 { "-xflip", "flipView", XrmoptionNoArg, "False" },
1606 { "-cmail", "cmailGameName", XrmoptionSepArg, NULL },
1607 { "-alwaysPromoteToQueen", "alwaysPromoteToQueen",
1608 XrmoptionSepArg, NULL },
1609 { "-queen", "alwaysPromoteToQueen", XrmoptionNoArg, "True" },
1610 { "-xqueen", "alwaysPromoteToQueen", XrmoptionNoArg, "False" },
1611 { "-oldSaveStyle", "oldSaveStyle", XrmoptionSepArg, NULL },
1612 { "-oldsave", "oldSaveStyle", XrmoptionNoArg, "True" },
1613 { "-xoldsave", "oldSaveStyle", XrmoptionNoArg, "False" },
1614 { "-quietPlay", "quietPlay", XrmoptionSepArg, NULL },
1615 { "-quiet", "quietPlay", XrmoptionNoArg, "True" },
1616 { "-xquiet", "quietPlay", XrmoptionNoArg, "False" },
1617 { "-titleInWindow", "titleInWindow", XrmoptionSepArg, NULL },
1618 { "-title", "titleInWindow", XrmoptionNoArg, "True" },
1619 { "-xtitle", "titleInWindow", XrmoptionNoArg, "False" },
1621 { "-zippyTalk", "zippyTalk", XrmoptionSepArg, NULL },
1622 { "-zt", "zippyTalk", XrmoptionNoArg, "True" },
1623 { "-xzt", "zippyTalk", XrmoptionNoArg, "False" },
1624 { "-zippyPlay", "zippyPlay", XrmoptionSepArg, NULL },
1625 { "-zp", "zippyPlay", XrmoptionNoArg, "True" },
1626 { "-xzp", "zippyPlay", XrmoptionNoArg, "False" },
1627 { "-zippyLines", "zippyLines", XrmoptionSepArg, NULL },
1628 { "-zippyPinhead", "zippyPinhead", XrmoptionSepArg, NULL },
1629 { "-zippyPassword", "zippyPassword", XrmoptionSepArg, NULL },
1630 { "-zippyPassword2", "zippyPassword2", XrmoptionSepArg, NULL },
1631 { "-zippyWrongPassword", "zippyWrongPassword", XrmoptionSepArg, NULL },
1632 { "-zippyAcceptOnly", "zippyAcceptOnly", XrmoptionSepArg, NULL },
1633 { "-zippyUseI", "zippyUseI", XrmoptionSepArg, NULL },
1634 { "-zui", "zippyUseI", XrmoptionNoArg, "True" },
1635 { "-xzui", "zippyUseI", XrmoptionNoArg, "False" },
1636 { "-zippyBughouse", "zippyBughouse", XrmoptionSepArg, NULL },
1637 { "-zippyNoplayCrafty", "zippyNoplayCrafty", XrmoptionSepArg, NULL },
1638 { "-znc", "zippyNoplayCrafty", XrmoptionNoArg, "True" },
1639 { "-xznc", "zippyNoplayCrafty", XrmoptionNoArg, "False" },
1640 { "-zippyGameEnd", "zippyGameEnd", XrmoptionSepArg, NULL },
1641 { "-zippyGameStart", "zippyGameStart", XrmoptionSepArg, NULL },
1642 { "-zippyAdjourn", "zippyAdjourn", XrmoptionSepArg, NULL },
1643 { "-zadj", "zippyAdjourn", XrmoptionNoArg, "True" },
1644 { "-xzadj", "zippyAdjourn", XrmoptionNoArg, "False" },
1645 { "-zippyAbort", "zippyAbort", XrmoptionSepArg, NULL },
1646 { "-zab", "zippyAbort", XrmoptionNoArg, "True" },
1647 { "-xzab", "zippyAbort", XrmoptionNoArg, "False" },
1648 { "-zippyVariants", "zippyVariants", XrmoptionSepArg, NULL },
1649 { "-zippyMaxGames", "zippyMaxGames", XrmoptionSepArg, NULL },
1650 { "-zippyReplayTimeout", "zippyReplayTimeout", XrmoptionSepArg, NULL },
1651 { "-zippyShortGame", "zippyShortGame", XrmoptionSepArg, NULL },
1653 { "-flashCount", "flashCount", XrmoptionSepArg, NULL },
1654 { "-flash", "flashCount", XrmoptionNoArg, "3" },
1655 { "-xflash", "flashCount", XrmoptionNoArg, "0" },
1656 { "-flashRate", "flashRate", XrmoptionSepArg, NULL },
1657 { "-pixmapDirectory", "pixmapDirectory", XrmoptionSepArg, NULL },
1658 { "-msLoginDelay", "msLoginDelay", XrmoptionSepArg, NULL },
1659 { "-pixmap", "pixmapDirectory", XrmoptionSepArg, NULL },
1660 { "-colorizeMessages", "colorizeMessages", XrmoptionSepArg, NULL },
1661 { "-colorize", "colorizeMessages", XrmoptionNoArg, "True" },
1662 { "-xcolorize", "colorizeMessages", XrmoptionNoArg, "False" },
1663 { "-colorShout", "colorShout", XrmoptionSepArg, NULL },
1664 { "-colorSShout", "colorSShout", XrmoptionSepArg, NULL },
1665 { "-colorCShout", "colorSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1666 { "-colorChannel1", "colorChannel1", XrmoptionSepArg, NULL },
1667 { "-colorChannel", "colorChannel", XrmoptionSepArg, NULL },
1668 { "-colorKibitz", "colorKibitz", XrmoptionSepArg, NULL },
1669 { "-colorTell", "colorTell", XrmoptionSepArg, NULL },
1670 { "-colorChallenge", "colorChallenge", XrmoptionSepArg, NULL },
1671 { "-colorRequest", "colorRequest", XrmoptionSepArg, NULL },
1672 { "-colorSeek", "colorSeek", XrmoptionSepArg, NULL },
1673 { "-colorNormal", "colorNormal", XrmoptionSepArg, NULL },
1674 { "-soundProgram", "soundProgram", XrmoptionSepArg, NULL },
1675 { "-soundShout", "soundShout", XrmoptionSepArg, NULL },
1676 { "-soundSShout", "soundSShout", XrmoptionSepArg, NULL },
1677 { "-soundCShout", "soundSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1678 { "-soundChannel1", "soundChannel1", XrmoptionSepArg, NULL },
1679 { "-soundChannel", "soundChannel", XrmoptionSepArg, NULL },
1680 { "-soundKibitz", "soundKibitz", XrmoptionSepArg, NULL },
1681 { "-soundTell", "soundTell", XrmoptionSepArg, NULL },
1682 { "-soundChallenge", "soundChallenge", XrmoptionSepArg, NULL },
1683 { "-soundRequest", "soundRequest", XrmoptionSepArg, NULL },
1684 { "-soundSeek", "soundSeek", XrmoptionSepArg, NULL },
1685 { "-soundMove", "soundMove", XrmoptionSepArg, NULL },
1686 { "-soundIcsWin", "soundIcsWin", XrmoptionSepArg, NULL },
1687 { "-soundIcsLoss", "soundIcsLoss", XrmoptionSepArg, NULL },
1688 { "-soundIcsDraw", "soundIcsDraw", XrmoptionSepArg, NULL },
1689 { "-soundIcsUnfinished", "soundIcsUnfinished", XrmoptionSepArg, NULL },
1690 { "-soundIcsAlarm", "soundIcsAlarm", XrmoptionSepArg, NULL },
1691 { "-reuseFirst", "reuseFirst", XrmoptionSepArg, NULL },
1692 { "-reuseChessPrograms", "reuseFirst", XrmoptionSepArg, NULL }, /*compat*/
1693 { "-reuse", "reuseFirst", XrmoptionNoArg, "True" },
1694 { "-xreuse", "reuseFirst", XrmoptionNoArg, "False" },
1695 { "-reuseSecond", "reuseSecond", XrmoptionSepArg, NULL },
1696 { "-reuse2", "reuseSecond", XrmoptionNoArg, "True" },
1697 { "-xreuse2", "reuseSecond", XrmoptionNoArg, "False" },
1698 { "-animateMoving", "animateMoving", XrmoptionSepArg, NULL },
1699 { "-animate", "animateMoving", XrmoptionNoArg, "True" },
1700 { "-xanimate", "animateMoving", XrmoptionNoArg, "False" },
1701 { "-animateDragging", "animateDragging", XrmoptionSepArg, NULL },
1702 { "-drag", "animateDragging", XrmoptionNoArg, "True" },
1703 { "-xdrag", "animateDragging", XrmoptionNoArg, "False" },
1704 { "-animateSpeed", "animateSpeed", XrmoptionSepArg, NULL },
1705 { "-popupExitMessage", "popupExitMessage", XrmoptionSepArg, NULL },
1706 { "-exit", "popupExitMessage", XrmoptionNoArg, "True" },
1707 { "-xexit", "popupExitMessage", XrmoptionNoArg, "False" },
1708 { "-popupMoveErrors", "popupMoveErrors", XrmoptionSepArg, NULL },
1709 { "-popup", "popupMoveErrors", XrmoptionNoArg, "True" },
1710 { "-xpopup", "popupMoveErrors", XrmoptionNoArg, "False" },
1711 { "-fontSizeTolerance", "fontSizeTolerance", XrmoptionSepArg, NULL },
1712 { "-initialMode", "initialMode", XrmoptionSepArg, NULL },
1713 { "-mode", "initialMode", XrmoptionSepArg, NULL },
1714 { "-variant", "variant", XrmoptionSepArg, NULL },
1715 { "-firstProtocolVersion", "firstProtocolVersion", XrmoptionSepArg, NULL },
1716 { "-secondProtocolVersion","secondProtocolVersion",XrmoptionSepArg, NULL },
1717 { "-showButtonBar", "showButtonBar", XrmoptionSepArg, NULL },
1718 { "-buttons", "showButtonBar", XrmoptionNoArg, "True" },
1719 { "-xbuttons", "showButtonBar", XrmoptionNoArg, "False" },
1720 { "-lowTimeWarningColor", "lowTimeWarningColor", XrmoptionSepArg, NULL },
1721 { "-lowTimeWarning", "lowTimeWarning", XrmoptionSepArg, NULL },
1722 /* [AS,HR] New features */
1723 { "-firstScoreAbs", "firstScoreAbs", XrmoptionSepArg, NULL },
1724 { "-secondScoreAbs", "secondScoreAbs", XrmoptionSepArg, NULL },
1725 { "-pgnExtendedInfo", "pgnExtendedInfo", XrmoptionSepArg, NULL },
1726 { "-hideThinkingFromHuman", "hideThinkingFromHuman", XrmoptionSepArg, NULL },
1727 { "-adjudicateLossThreshold", "adjudicateLossThreshold", XrmoptionSepArg, NULL },
1728 { "-pgnEventHeader", "pgnEventHeader", XrmoptionSepArg, NULL },
1729 { "-firstIsUCI", "firstIsUCI", XrmoptionSepArg, NULL },
1730 { "-secondIsUCI", "secondIsUCI", XrmoptionSepArg, NULL },
1731 { "-fUCI", "firstIsUCI", XrmoptionNoArg, "True" },
1732 { "-sUCI", "secondIsUCI", XrmoptionNoArg, "True" },
1733 { "-firstHasOwnBookUCI", "firstHasOwnBookUCI", XrmoptionSepArg, NULL },
1734 { "-secondHasOwnBookUCI", "secondHasOwnBookUCI", XrmoptionSepArg, NULL },
1735 { "-fNoOwnBookUCI", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1736 { "-sNoOwnBookUCI", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1737 { "-firstXBook", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1738 { "-secondXBook", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1739 { "-polyglotDir", "polyglotDir", XrmoptionSepArg, NULL },
1740 { "-usePolyglotBook", "usePolyglotBook", XrmoptionSepArg, NULL },
1741 { "-polyglotBook", "polyglotBook", XrmoptionSepArg, NULL },
1742 { "-defaultHashSize", "defaultHashSize", XrmoptionSepArg, NULL },
1743 { "-defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XrmoptionSepArg, NULL },
1744 { "-defaultPathEGTB", "defaultPathEGTB", XrmoptionSepArg, NULL },
1745 { "-defaultFrcPosition", "defaultFrcPosition", XrmoptionSepArg, NULL },
1746 { "-gameListTags", "gameListTags", XrmoptionSepArg, NULL },
1747 // [HGM] I am sure AS added many more options, but we have to fish them out, from the list in winboard.c
1749 /* [HGM,HR] User-selectable board size */
1750 { "-boardWidth", "boardWidth", XrmoptionSepArg, NULL },
1751 { "-boardHeight", "boardHeight", XrmoptionSepArg, NULL },
1752 { "-matchPause", "matchPause", XrmoptionSepArg, NULL },
1754 /* [HGM] new arguments of 4.3.xx. All except first three are back-end options, which should work immediately */
1755 { "-holdingsSize", "holdingsSize", XrmoptionSepArg, NULL }, // requires extensive front-end changes to work
1756 { "-flipBlack", "flipBlack", XrmoptionSepArg, NULL }, // requires front-end changes to work
1757 { "-allWhite", "allWhite", XrmoptionSepArg, NULL }, // requires front-end changes to work
1758 { "-pieceToCharTable", "pieceToCharTable", XrmoptionSepArg, NULL },
1759 { "-alphaRank", "alphaRank", XrmoptionSepArg, NULL },
1760 { "-testClaims", "testClaims", XrmoptionSepArg, NULL },
1761 { "-checkMates", "checkMates", XrmoptionSepArg, NULL },
1762 { "-materialDraws", "materialDraws", XrmoptionSepArg, NULL },
1763 { "-trivialDraws", "trivialDraws", XrmoptionSepArg, NULL },
1764 { "-ruleMoves", "ruleMoves", XrmoptionSepArg, NULL },
1765 { "-repeatsToDraw", "repeatsToDraw", XrmoptionSepArg, NULL },
1766 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1767 { "-userName", "userName", XrmoptionSepArg, NULL },
1768 { "-autoKibitz", "autoKibitz", XrmoptionNoArg, "True" },
1769 { "-firstTimeOdds", "firstTimeOdds", XrmoptionSepArg, NULL },
1770 { "-secondTimeOdds", "secondTimeOdds", XrmoptionSepArg, NULL },
1771 { "-timeOddsMode", "timeOddsMode", XrmoptionSepArg, NULL },
1772 { "-firstAccumulateTC", "firstAccumulateTC", XrmoptionSepArg, NULL },
1773 { "-secondAccumulateTC", "secondAccumulateTC", XrmoptionSepArg, NULL },
1774 { "-firstNPS", "firstNPS", XrmoptionSepArg, NULL },
1775 { "-secondNPS", "secondNPS", XrmoptionSepArg, NULL },
1776 { "-serverMoves", "serverMoves", XrmoptionSepArg, NULL },
1777 { "-serverPause", "serverPause", XrmoptionSepArg, NULL },
1778 { "-suppressLoadMoves", "suppressLoadMoves", XrmoptionSepArg, NULL },
1779 { "-egtFormats", "egtFormats", XrmoptionSepArg, NULL },
1780 { "-userName", "userName", XrmoptionSepArg, NULL },
1781 { "-smpCores", "smpCores", XrmoptionSepArg, NULL },
1782 { "-sameColorGames", "sameColorGames", XrmoptionSepArg, NULL },
1783 { "-rewindIndex", "rewindIndex", XrmoptionSepArg, NULL },
1784 { "-niceEngines", "niceEngines", XrmoptionSepArg, NULL },
1785 { "-delayBeforeQuit", "delayBeforeQuit", XrmoptionSepArg, NULL },
1786 { "-delayAfterQuit", "delayAfterQuit", XrmoptionSepArg, NULL },
1787 { "-nameOfDebugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1788 { "-debugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1789 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1790 { "-noGUI", "noGUI", XrmoptionNoArg, "True" },
1791 { "-firstOptions", "firstOptions", XrmoptionSepArg, NULL },
1792 { "-secondOptions", "secondOptions", XrmoptionSepArg, NULL },
1793 { "-firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1794 { "-secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1798 XtActionsRec boardActions[] = {
1799 { "HandleUserMove", HandleUserMove },
1800 { "AnimateUserMove", AnimateUserMove },
1801 { "FileNameAction", FileNameAction },
1802 { "AskQuestionProc", AskQuestionProc },
1803 { "AskQuestionReplyAction", AskQuestionReplyAction },
1804 { "PieceMenuPopup", PieceMenuPopup },
1805 { "WhiteClock", WhiteClock },
1806 { "BlackClock", BlackClock },
1807 { "Iconify", Iconify },
1808 { "LoadSelectedProc", LoadSelectedProc },
1809 { "LoadPositionProc", LoadPositionProc },
1810 { "LoadNextPositionProc", LoadNextPositionProc },
1811 { "LoadPrevPositionProc", LoadPrevPositionProc },
1812 { "ReloadPositionProc", ReloadPositionProc },
1813 { "CopyPositionProc", CopyPositionProc },
1814 { "PastePositionProc", PastePositionProc },
1815 { "CopyGameProc", CopyGameProc },
1816 { "PasteGameProc", PasteGameProc },
1817 { "SaveGameProc", SaveGameProc },
1818 { "SavePositionProc", SavePositionProc },
1819 { "MailMoveProc", MailMoveProc },
1820 { "ReloadCmailMsgProc", ReloadCmailMsgProc },
1821 // { "MachineWhiteProc", MachineWhiteProc },
1822 // { "MachineBlackProc", MachineBlackProc },
1823 { "AnalysisModeProc", AnalyzeModeProc },
1824 { "AnalyzeFileProc", AnalyzeFileProc },
1825 // { "TwoMachinesProc", TwoMachinesProc },
1826 // { "IcsClientProc", IcsClientProc },
1827 { "EditGameProc", EditGameProc },
1828 { "EditPositionProc", EditPositionProc },
1829 { "TrainingProc", EditPositionProc },
1830 { "EngineOutputProc", EngineOutputProc}, // [HGM] Winboard_x engine-output window
1831 { "ShowGameListProc", ShowGameListProc },
1832 { "ShowMoveListProc", HistoryShowProc},
1833 { "EditTagsProc", EditCommentProc },
1834 { "EditCommentProc", EditCommentProc },
1835 { "IcsAlarmProc", IcsAlarmProc },
1836 { "IcsInputBoxProc", IcsInputBoxProc },
1837 // { "AcceptProc", AcceptProc },
1838 // { "DeclineProc", DeclineProc },
1839 // { "RematchProc", RematchProc },
1840 // { "CallFlagProc", CallFlagProc },
1841 // { "DrawProc", DrawProc },
1842 // { "AdjournProc", AdjournProc },
1843 // { "AbortProc", AbortProc },
1844 // { "ResignProc", ResignProc },
1845 // { "AdjuWhiteProc", AdjuWhiteProc },
1846 // { "AdjuBlackProc", AdjuBlackProc },
1847 // { "AdjuDrawProc", AdjuDrawProc },
1848 { "EnterKeyProc", EnterKeyProc },
1849 // { "StopObservingProc", StopObservingProc },
1850 // { "StopExaminingProc", StopExaminingProc },
1851 // { "BackwardProc", BackwardProc },
1852 // { "ForwardProc", ForwardProc },
1853 // { "ToStartProc", ToStartProc },
1854 // { "ToEndProc", ToEndProc },
1855 // { "RevertProc", RevertProc },
1856 // { "TruncateGameProc", TruncateGameProc },
1857 // { "MoveNowProc", MoveNowProc },
1858 // { "RetractMoveProc", RetractMoveProc },
1859 { "AlwaysQueenProc", AlwaysQueenProc },
1860 { "AnimateDraggingProc", AnimateDraggingProc },
1861 { "AnimateMovingProc", AnimateMovingProc },
1862 { "AutoflagProc", AutoflagProc },
1863 { "AutoflipProc", AutoflipProc },
1864 { "AutobsProc", AutobsProc },
1865 { "AutoraiseProc", AutoraiseProc },
1866 { "AutosaveProc", AutosaveProc },
1867 { "BlindfoldProc", BlindfoldProc },
1868 { "FlashMovesProc", FlashMovesProc },
1869 // { "FlipViewProc", FlipViewProc },
1870 { "GetMoveListProc", GetMoveListProc },
1872 { "HighlightDraggingProc", HighlightDraggingProc },
1874 { "HighlightLastMoveProc", HighlightLastMoveProc },
1875 { "IcsAlarmProc", IcsAlarmProc },
1876 { "MoveSoundProc", MoveSoundProc },
1877 { "OldSaveStyleProc", OldSaveStyleProc },
1878 { "PeriodicUpdatesProc", PeriodicUpdatesProc },
1879 { "PonderNextMoveProc", PonderNextMoveProc },
1880 { "PopupExitMessageProc", PopupExitMessageProc },
1881 { "PopupMoveErrorsProc", PopupMoveErrorsProc },
1882 { "PremoveProc", PremoveProc },
1883 { "QuietPlayProc", QuietPlayProc },
1884 { "ShowThinkingProc", ShowThinkingProc },
1885 { "HideThinkingProc", HideThinkingProc },
1886 { "TestLegalityProc", TestLegalityProc },
1887 // { "InfoProc", InfoProc },
1888 // { "ManProc", ManProc },
1889 // { "HintProc", HintProc },
1890 // { "BookProc", BookProc },
1891 { "AboutGameProc", AboutGameProc },
1892 { "DebugProc", DebugProc },
1893 { "NothingProc", NothingProc },
1894 { "CommentPopDown", (XtActionProc) CommentPopDown },
1895 { "EditCommentPopDown", (XtActionProc) EditCommentPopDown },
1896 { "TagsPopDown", (XtActionProc) TagsPopDown },
1897 { "ErrorPopDown", (XtActionProc) ErrorPopDown },
1898 { "ICSInputBoxPopDown", (XtActionProc) ICSInputBoxPopDown },
1899 { "AnalysisPopDown", (XtActionProc) AnalysisPopDown },
1900 { "FileNamePopDown", (XtActionProc) FileNamePopDown },
1901 { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown },
1902 { "GameListPopDown", (XtActionProc) GameListPopDown },
1903 { "PromotionPopDown", (XtActionProc) PromotionPopDown },
1904 { "HistoryPopDown", (XtActionProc) HistoryPopDown },
1905 { "EngineOutputPopDown", (XtActionProc) EngineOutputPopDown },
1906 { "ShufflePopDown", (XtActionProc) ShufflePopDown },
1907 { "EnginePopDown", (XtActionProc) EnginePopDown },
1908 { "UciPopDown", (XtActionProc) UciPopDown },
1909 { "TimeControlPopDown", (XtActionProc) TimeControlPopDown },
1910 { "NewVariantPopDown", (XtActionProc) NewVariantPopDown },
1911 { "SettingsPopDown", (XtActionProc) SettingsPopDown },
1915 char ICSInputTranslations[] =
1916 "<Key>Return: EnterKeyProc() \n";
1918 String xboardResources[] = {
1919 "*fileName*value.translations: #override\\n <Key>Return: FileNameAction()",
1920 "*question*value.translations: #override\\n <Key>Return: AskQuestionReplyAction()",
1921 "*errorpopup*translations: #override\\n <Key>Return: ErrorPopDown()",
1925 static char *cnames[9] = { "black", "red", "green", "yellow", "blue",
1926 "magenta", "cyan", "white" };
1930 TextColors textColors[(int)NColorClasses];
1932 /* String is: "fg, bg, attr". Which is 0, 1, 2 */
1934 parse_color(str, which)
1938 char *p, buf[100], *d;
1941 if (strlen(str) > 99) /* watch bounds on buf */
1946 for (i=0; i<which; ++i) {
1953 /* Could be looking at something like:
1955 .. in which case we want to stop on a comma also */
1956 while (*p && *p != ',' && !isalpha(*p) && !isdigit(*p))
1960 return -1; /* Use default for empty field */
1963 if (which == 2 || isdigit(*p))
1966 while (*p && isalpha(*p))
1971 for (i=0; i<8; ++i) {
1972 if (!StrCaseCmp(buf, cnames[i]))
1973 return which? (i+40) : (i+30);
1975 if (!StrCaseCmp(buf, "default")) return -1;
1977 fprintf(stderr, _("%s: unrecognized color %s\n"), programName, buf);
1982 parse_cpair(cc, str)
1986 if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {
1987 fprintf(stderr, _("%s: can't parse foreground color in `%s'\n"),
1992 /* bg and attr are optional */
1993 textColors[(int)cc].bg = parse_color(str, 1);
1994 if ((textColors[(int)cc].attr = parse_color(str, 2)) < 0) {
1995 textColors[(int)cc].attr = 0;
2001 /* Arrange to catch delete-window events */
2002 Atom wm_delete_window;
2004 CatchDeleteWindow(Widget w, String procname)
2007 XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
2008 snprintf(buf, sizeof(buf), "<Message>WM_PROTOCOLS: %s() \n", procname);
2009 XtAugmentTranslations(w, XtParseTranslationTable(buf));
2015 /* this should raise the board to the top */
2016 gtk_window_present(GTK_WINDOW(GUI_Window));
2021 // eventually, all layout determining code should go into a subroutine, but until then IDSIZE remains undefined
2023 #define BoardSize int
2024 void InitDrawingSizes(BoardSize boardSize, int flags)
2025 { // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
2026 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2028 XtGeometryResult gres;
2031 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2032 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2034 timerWidth = (boardWidth - sep) / 2;
2036 if (appData.titleInWindow)
2041 w = boardWidth - 2*bor;
2045 w = boardWidth - w - sep - 2*bor - 2; // WIDTH_FUDGE
2049 if(!formWidget) return;
2052 * Inhibit shell resizing.
2055 // [HGM] pieces: tailor piece bitmaps to needs of specific variant
2058 for(i=0; i<4; i++) {
2060 for(p=0; p<=(int)WhiteKing; p++)
2061 xpmPieceBitmap[i][p] = xpmPieceBitmap2[i][p]; // defaults
2062 if(gameInfo.variant == VariantShogi) {
2063 xpmPieceBitmap[i][(int)WhiteCannon] = xpmPieceBitmap2[i][(int)WhiteKing+1];
2064 xpmPieceBitmap[i][(int)WhiteNightrider] = xpmPieceBitmap2[i][(int)WhiteKing+2];
2065 xpmPieceBitmap[i][(int)WhiteSilver] = xpmPieceBitmap2[i][(int)WhiteKing+3];
2066 xpmPieceBitmap[i][(int)WhiteGrasshopper] = xpmPieceBitmap2[i][(int)WhiteKing+4];
2067 xpmPieceBitmap[i][(int)WhiteQueen] = xpmPieceBitmap2[i][(int)WhiteLance];
2070 if(gameInfo.variant == VariantGothic) {
2071 xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteSilver];
2075 // [HGM] why are thee ximMasks used at all? the ximPieceBitmaps seem to be never used!
2076 for(p=0; p<=(int)WhiteKing; p++)
2077 ximMaskPm[p] = ximMaskPm2[p]; // defaults
2078 if(gameInfo.variant == VariantShogi) {
2079 ximMaskPm[(int)WhiteCannon] = ximMaskPm2[(int)WhiteKing+1];
2080 ximMaskPm[(int)WhiteNightrider] = ximMaskPm2[(int)WhiteKing+2];
2081 ximMaskPm[(int)WhiteSilver] = ximMaskPm2[(int)WhiteKing+3];
2082 ximMaskPm[(int)WhiteGrasshopper] = ximMaskPm2[(int)WhiteKing+4];
2083 ximMaskPm[(int)WhiteQueen] = ximMaskPm2[(int)WhiteLance];
2086 if(gameInfo.variant == VariantGothic) {
2087 ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[i][(int)WhiteSilver];
2093 for(i=0; i<2; i++) {
2095 for(p=0; p<=(int)WhiteKing; p++)
2096 pieceBitmap[i][p] = pieceBitmap2[i][p]; // defaults
2097 if(gameInfo.variant == VariantShogi) {
2098 pieceBitmap[i][(int)WhiteCannon] = pieceBitmap2[i][(int)WhiteKing+1];
2099 pieceBitmap[i][(int)WhiteNightrider] = pieceBitmap2[i][(int)WhiteKing+2];
2100 pieceBitmap[i][(int)WhiteSilver] = pieceBitmap2[i][(int)WhiteKing+3];
2101 pieceBitmap[i][(int)WhiteGrasshopper] = pieceBitmap2[i][(int)WhiteKing+4];
2102 pieceBitmap[i][(int)WhiteQueen] = pieceBitmap2[i][(int)WhiteLance];
2105 if(gameInfo.variant == VariantGothic) {
2106 pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteSilver];
2122 int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
2123 XSetWindowAttributes window_attributes;
2125 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2126 XrmValue vFrom, vTo;
2127 XtGeometryResult gres;
2130 int forceMono = False;
2134 // [HGM] before anything else, expand any indirection files amongst options
2135 char *argvCopy[1000]; // 1000 seems enough
2136 char newArgs[10000]; // holds actual characters
2139 srandom(time(0)); // [HGM] book: make random truly random
2142 for(i=0; i<argc; i++) {
2143 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2144 //fprintf(stderr, "arg %s\n", argv[i]);
2145 if(argv[i][0] != '@') argvCopy[j++] = argv[i]; else {
2147 FILE *f = fopen(argv[i]+1, "rb");
2148 if(f == NULL) { fprintf(stderr, _("ignore %s\n"), argv[i]); continue; } // do not expand non-existing
2149 argvCopy[j++] = newArgs + k; // get ready for first argument from file
2150 while((c = fgetc(f)) != EOF) { // each line of file inserts 1 argument in the list
2152 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2153 newArgs[k++] = 0; // terminate current arg
2154 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2155 argvCopy[j++] = newArgs + k; // get ready for next
2157 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2170 if(appData.debugMode,1) { // OK, appData is not initialized here yet...
2171 for(i=0; i<argc; i++) fprintf(stderr, "argv[%2d] = '%s'\n", i, argv[i]);
2177 setbuf(stdout, NULL);
2178 setbuf(stderr, NULL);
2181 programName = strrchr(argv[0], '/');
2182 if (programName == NULL)
2183 programName = argv[0];
2188 XtSetLanguageProc(NULL, NULL, NULL);
2189 bindtextdomain(PACKAGE, LOCALEDIR);
2190 textdomain(PACKAGE);
2194 XtAppInitialize(&appContext, "XBoard", shellOptions,
2195 XtNumber(shellOptions),
2196 &argc, argv, xboardResources, NULL, 0);
2200 gtk_init (&argc, &argv);
2202 /* parse glade file to build widgets */
2204 builder = gtk_builder_new ();
2205 gtk_builder_add_from_file (builder, "gtk-interface.xml", NULL);
2207 /* test if everything worked ok */
2209 GUI_Window = GTK_WIDGET (gtk_builder_get_object (builder, "MainWindow"));
2210 if(!GUI_Window) printf("Error: gtk_builder didn't work!\n");
2211 GUI_Board = GTK_WIDGET (gtk_builder_get_object (builder, "Board"));
2212 if(!GUI_Board) printf("Error: gtk_builder didn't work!\n");
2213 GUI_Whiteclock = GTK_WIDGET (gtk_builder_get_object (builder, "WhiteClock"));
2214 if(!GUI_Whiteclock) printf("Error: gtk_builder didn't work!\n");
2215 GUI_Blackclock = GTK_WIDGET (gtk_builder_get_object (builder, "BlackClock"));
2216 if(!GUI_Blackclock) printf("Error: gtk_builder didn't work!\n");
2218 gtk_builder_connect_signals (builder, NULL);
2220 // don't unref the builder, since we use it to get references to widgets
2221 // g_object_unref (G_OBJECT (builder));
2223 /* end parse glade file */
2227 fprintf(stderr, _("%s: unrecognized argument %s\n"),
2228 programName, argv[1]);
2229 fprintf(stderr, "Recognized options:\n");
2230 for(i = 0; i < XtNumber(shellOptions); i++)
2232 j = fprintf(stderr, " %s%s", shellOptions[i].option,
2233 (shellOptions[i].argKind == XrmoptionSepArg
2235 if (i++ < XtNumber(shellOptions))
2237 fprintf(stderr, "%*c%s%s\n", 40 - j, ' ',
2238 shellOptions[i].option,
2239 (shellOptions[i].argKind == XrmoptionSepArg
2244 fprintf(stderr, "\n");
2250 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL)
2256 if (chdir(chessDir) != 0)
2258 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
2265 if (p == NULL) p = "/tmp";
2266 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
2267 gameCopyFilename = (char*) malloc(i);
2268 gamePasteFilename = (char*) malloc(i);
2269 snprintf(gameCopyFilename,i, "%s/.xboard%05uc.pgn", p, getpid());
2270 snprintf(gamePasteFilename,i, "%s/.xboard%05up.pgn", p, getpid());
2272 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
2273 clientResources, XtNumber(clientResources),
2276 if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) {
2277 /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */
2278 if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL) {
2279 printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile);
2282 setbuf(debugFP, NULL);
2285 /* [HGM,HR] make sure board size is acceptable */
2286 if(appData.NrFiles > BOARD_SIZE ||
2287 appData.NrRanks > BOARD_SIZE )
2288 DisplayFatalError(_("Recompile with BOARD_SIZE > 12, to support this size"), 0, 2);
2291 /* This feature does not work; animation needs a rewrite */
2292 appData.highlightDragging = FALSE;
2296 xDisplay = XtDisplay(shellWidget);
2297 xScreen = DefaultScreen(xDisplay);
2298 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
2300 gameInfo.variant = StringToVariant(appData.variant);
2301 InitPosition(FALSE);
2305 * Determine boardSize
2307 gameInfo.boardWidth = gameInfo.boardHeight = 8; // [HGM] boardsize: make sure we start as 8x8
2310 // [HGM] as long as we have not created the possibility to change size while running, start with requested size
2311 gameInfo.boardWidth = appData.NrFiles > 0 ? appData.NrFiles : 8;
2312 gameInfo.boardHeight = appData.NrRanks > 0 ? appData.NrRanks : 8;
2313 gameInfo.holdingsWidth = appData.holdingsSize > 0 ? 2 : 0;
2318 InitDrawingSizes(-1, 0); // [HGM] initsize: make this into a subroutine
2320 if (isdigit(appData.boardSize[0])) {
2321 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
2322 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
2323 &fontPxlSize, &smallLayout, &tinyLayout);
2325 fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
2326 programName, appData.boardSize);
2330 /* Find some defaults; use the nearest known size */
2331 SizeDefaults *szd, *nearest;
2332 int distance = 99999;
2333 nearest = szd = sizeDefaults;
2334 while (szd->name != NULL) {
2335 if (abs(szd->squareSize - squareSize) < distance) {
2337 distance = abs(szd->squareSize - squareSize);
2338 if (distance == 0) break;
2342 if (i < 2) lineGap = nearest->lineGap;
2343 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
2344 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
2345 if (i < 5) fontPxlSize = nearest->fontPxlSize;
2346 if (i < 6) smallLayout = nearest->smallLayout;
2347 if (i < 7) tinyLayout = nearest->tinyLayout;
2350 SizeDefaults *szd = sizeDefaults;
2351 if (*appData.boardSize == NULLCHAR) {
2352 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize ||
2353 DisplayHeight(xDisplay, xScreen) < szd->minScreenSize) {
2356 if (szd->name == NULL) szd--;
2358 while (szd->name != NULL &&
2359 StrCaseCmp(szd->name, appData.boardSize) != 0) szd++;
2360 if (szd->name == NULL) {
2361 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
2362 programName, appData.boardSize);
2366 squareSize = szd->squareSize;
2367 lineGap = szd->lineGap;
2368 clockFontPxlSize = szd->clockFontPxlSize;
2369 coordFontPxlSize = szd->coordFontPxlSize;
2370 fontPxlSize = szd->fontPxlSize;
2371 smallLayout = szd->smallLayout;
2372 tinyLayout = szd->tinyLayout;
2375 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2376 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2377 if (appData.showJail == 1) {
2378 /* Jail on top and bottom */
2379 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2380 XtSetArg(boardArgs[2], XtNheight,
2381 boardHeight + 2*(lineGap + squareSize));
2382 } else if (appData.showJail == 2) {
2384 XtSetArg(boardArgs[1], XtNwidth,
2385 boardWidth + 2*(lineGap + squareSize));
2386 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2389 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2390 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2394 * Determine what fonts to use.
2396 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
2397 clockFontID = XLoadFont(xDisplay, appData.clockFont);
2398 clockFontStruct = XQueryFont(xDisplay, clockFontID);
2399 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
2400 coordFontID = XLoadFont(xDisplay, appData.coordFont);
2401 coordFontStruct = XQueryFont(xDisplay, coordFontID);
2402 appData.font = FindFont(appData.font, fontPxlSize);
2403 countFontID = XLoadFont(xDisplay, appData.coordFont); // [HGM] holdings
2404 countFontStruct = XQueryFont(xDisplay, countFontID);
2405 // appData.font = FindFont(appData.font, fontPxlSize);
2407 xdb = XtDatabase(xDisplay);
2408 XrmPutStringResource(&xdb, "*font", appData.font);
2411 * Detect if there are not enough colors available and adapt.
2413 if (DefaultDepth(xDisplay, xScreen) <= 2) {
2414 appData.monoMode = True;
2417 if (!appData.monoMode) {
2418 vFrom.addr = (caddr_t) appData.lightSquareColor;
2419 vFrom.size = strlen(appData.lightSquareColor);
2420 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2421 if (vTo.addr == NULL) {
2422 appData.monoMode = True;
2425 lightSquareColor = *(Pixel *) vTo.addr;
2428 if (!appData.monoMode) {
2429 vFrom.addr = (caddr_t) appData.darkSquareColor;
2430 vFrom.size = strlen(appData.darkSquareColor);
2431 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2432 if (vTo.addr == NULL) {
2433 appData.monoMode = True;
2436 darkSquareColor = *(Pixel *) vTo.addr;
2439 if (!appData.monoMode) {
2440 vFrom.addr = (caddr_t) appData.whitePieceColor;
2441 vFrom.size = strlen(appData.whitePieceColor);
2442 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2443 if (vTo.addr == NULL) {
2444 appData.monoMode = True;
2447 whitePieceColor = *(Pixel *) vTo.addr;
2450 if (!appData.monoMode) {
2451 vFrom.addr = (caddr_t) appData.blackPieceColor;
2452 vFrom.size = strlen(appData.blackPieceColor);
2453 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2454 if (vTo.addr == NULL) {
2455 appData.monoMode = True;
2458 blackPieceColor = *(Pixel *) vTo.addr;
2462 if (!appData.monoMode) {
2463 vFrom.addr = (caddr_t) appData.highlightSquareColor;
2464 vFrom.size = strlen(appData.highlightSquareColor);
2465 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2466 if (vTo.addr == NULL) {
2467 appData.monoMode = True;
2470 highlightSquareColor = *(Pixel *) vTo.addr;
2474 if (!appData.monoMode) {
2475 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
2476 vFrom.size = strlen(appData.premoveHighlightColor);
2477 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2478 if (vTo.addr == NULL) {
2479 appData.monoMode = True;
2482 premoveHighlightColor = *(Pixel *) vTo.addr;
2487 fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2490 if (appData.bitmapDirectory == NULL ||
2491 appData.bitmapDirectory[0] == NULLCHAR)
2492 appData.bitmapDirectory = DEF_BITMAP_DIR;
2495 if (appData.lowTimeWarning && !appData.monoMode) {
2496 vFrom.addr = (caddr_t) appData.lowTimeWarningColor;
2497 vFrom.size = strlen(appData.lowTimeWarningColor);
2498 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2499 if (vTo.addr == NULL)
2500 appData.monoMode = True;
2502 lowTimeWarningColor = *(Pixel *) vTo.addr;
2505 if (appData.monoMode && appData.debugMode) {
2506 fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2507 (unsigned long) XWhitePixel(xDisplay, xScreen),
2508 (unsigned long) XBlackPixel(xDisplay, xScreen));
2511 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
2512 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
2513 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
2514 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
2515 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
2516 parse_cpair(ColorTell, appData.colorTell) < 0 ||
2517 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
2518 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
2519 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
2520 parse_cpair(ColorNormal, appData.colorNormal) < 0)
2522 if (appData.colorize) {
2524 _("%s: can't parse color names; disabling colorization\n"),
2527 appData.colorize = FALSE;
2529 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2530 textColors[ColorNone].attr = 0;
2532 // XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2538 layoutName = "tinyLayout";
2539 } else if (smallLayout) {
2540 layoutName = "smallLayout";
2542 layoutName = "normalLayout";
2545 if (appData.titleInWindow) {
2546 /* todo check what this appdata does */
2549 if (appData.showButtonBar) {
2550 /* TODO hide button bar if requested */
2554 * gtk set properties of widgets
2557 /* set board size */
2558 gtk_widget_set_size_request(GTK_WIDGET(GUI_Board),
2559 boardWidth,boardHeight);
2561 /* end gtk set properties of widgets */
2563 if (appData.titleInWindow)
2568 if (appData.showButtonBar)
2575 if (appData.showButtonBar)
2584 // [HGM] it seems the layout code ends here, but perhaps the color stuff is size independent and would
2585 // not need to go into InitDrawingSizes().
2588 /* set some checkboxes in the menu according to appData */
2590 if (appData.alwaysPromoteToQueen)
2591 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Always Queen")),TRUE);
2593 if (appData.animateDragging)
2594 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Animate Dragging")),TRUE);
2596 if (appData.animate)
2597 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Animate Moving")),TRUE);
2599 if (appData.autoComment)
2600 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Comment")),TRUE);
2602 if (appData.autoCallFlag)
2603 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Flag")),TRUE);
2605 if (appData.autoFlipView)
2606 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Flip View")),TRUE);
2608 if (appData.autoObserve)
2609 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Observe")),TRUE);
2611 if (appData.autoRaiseBoard)
2612 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Raise Board")),TRUE);
2614 if (appData.autoSaveGames)
2615 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Save")),TRUE);
2617 if (appData.saveGameFile[0] != NULLCHAR)
2619 /* Can't turn this off from menu */
2620 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Save")),TRUE);
2621 gtk_action_set_sensitive(GTK_ACTION (gtk_builder_get_object (builder, "menuOptions.Auto Save")),FALSE);
2624 if (appData.blindfold)
2625 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Blindfold")),TRUE);
2627 if (appData.flashCount > 0)
2628 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Flash Moves")),TRUE);
2630 if (appData.getMoveList)
2631 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Get Move List")),TRUE);
2634 if (appData.highlightDragging)
2635 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Highlight Dragging")),TRUE);
2638 if (appData.highlightLastMove)
2639 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Highlight Last Move")),TRUE);
2641 if (appData.icsAlarm)
2642 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.ICS Alarm")),TRUE);
2644 if (appData.ringBellAfterMoves)
2645 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Move Sound")),TRUE);
2647 if (appData.oldSaveStyle)
2648 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Old Save Style")),TRUE);
2650 if (appData.periodicUpdates)
2651 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Periodic Updates")),TRUE);
2653 if (appData.ponderNextMove)
2654 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Ponder Next Move")),TRUE);
2656 if (appData.popupExitMessage)
2657 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Popup Exit Message")),TRUE);
2659 if (appData.popupMoveErrors)
2660 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Popup Move Errors")),TRUE);
2662 if (appData.premove)
2663 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Premove")),TRUE);
2665 if (appData.quietPlay)
2666 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Quit Play")),TRUE);
2668 if (appData.showCoords)
2669 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Show Coords")),TRUE);
2671 if (appData.showThinking)
2672 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Show Thinking")),TRUE);
2674 if (appData.testLegality)
2675 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Test Legality")),TRUE);
2677 /* end setting check boxes */
2680 /* load square colors */
2681 SVGLightSquare = load_pixbuf("svg/LightSquare.svg",squareSize);
2682 SVGDarkSquare = load_pixbuf("svg/DarkSquare.svg",squareSize);
2683 SVGNeutralSquare = load_pixbuf("svg/NeutralSquare.svg",squareSize);
2685 /* use two icons to indicate if it is white's or black's turn */
2686 WhiteIcon = load_pixbuf("svg/icon_white.svg",0);
2687 BlackIcon = load_pixbuf("svg/icon_black.svg",0);
2688 WindowIcon = WhiteIcon;
2689 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
2691 /* do resizing to a fixed aspect ratio */
2696 GUI_SetAspectRatio(0.7);
2698 /* realize window */
2699 gtk_widget_show (GUI_Window);
2705 if (appData.animate || appData.animateDragging)
2710 if (errorExitStatus == -1) {
2711 if (appData.icsActive) {
2712 /* We now wait until we see "login:" from the ICS before
2713 sending the logon script (problems with timestamp otherwise) */
2714 /*ICSInitScript();*/
2715 if (appData.icsInputBox) ICSInputBoxPopUp();
2718 signal(SIGINT, IntSigHandler);
2719 signal(SIGTERM, IntSigHandler);
2720 if (*appData.cmailGameName != NULLCHAR) {
2721 signal(SIGUSR1, CmailSigHandler);
2724 gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes()
2728 * Create a cursor for the board widget.
2729 * (This needs to be called after the window has been created to have access to board-window)
2732 BoardCursor = gdk_cursor_new(GDK_HAND2);
2733 gdk_window_set_cursor(GUI_Board->window, BoardCursor);
2734 gdk_cursor_destroy(BoardCursor);
2739 if (appData.debugMode) fclose(debugFP); // [DM] debug
2746 if (appData.icsActive && oldICSInteractionTitle != NULL) {
2747 DisplayIcsInteractionTitle(oldICSInteractionTitle);
2749 unlink(gameCopyFilename);
2750 unlink(gamePasteFilename);
2761 CmailSigHandler(sig)
2767 signal(SIGUSR1, SIG_IGN); /* suspend handler */
2769 /* Activate call-back function CmailSigHandlerCallBack() */
2770 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
2772 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
2776 CmailSigHandlerCallBack(isr, closure, message, count, error)
2784 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
2786 /**** end signal code ****/
2796 f = fopen(appData.icsLogon, "r");
2802 strcat(buf, appData.icsLogon);
2803 f = fopen(buf, "r");
2807 ProcessICSInitScript(f);
2814 EditCommentPopDown();
2820 SetMenuEnables(enab)
2825 if (!builder) return;
2826 while (enab->name != NULL) {
2827 o = gtk_builder_get_object(builder, enab->name);
2828 if(GTK_IS_WIDGET(o))
2829 gtk_widget_set_sensitive(GTK_WIDGET (o),enab->value);
2832 if(GTK_IS_ACTION(o))
2833 gtk_action_set_sensitive(GTK_ACTION (o),enab->value);
2835 DisplayError(enab->name, 0);
2843 SetMenuEnables(icsEnables);
2846 if (appData.zippyPlay && !appData.noChessProgram) /* [DM] icsEngineAnalyze */
2847 {}; // XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
2854 SetMenuEnables(ncpEnables);
2860 SetMenuEnables(gnuEnables);
2866 SetMenuEnables(cmailEnables);
2872 SetMenuEnables(trainingOnEnables);
2873 if (appData.showButtonBar) {
2874 // XtSetSensitive(buttonBarWidget, False);
2880 SetTrainingModeOff()
2882 SetMenuEnables(trainingOffEnables);
2883 if (appData.showButtonBar) {
2884 // XtSetSensitive(buttonBarWidget, True);
2889 SetUserThinkingEnables()
2891 if (appData.noChessProgram) return;
2892 SetMenuEnables(userThinkingEnables);
2896 SetMachineThinkingEnables()
2898 if (appData.noChessProgram) return;
2899 SetMenuEnables(machineThinkingEnables);
2901 case MachinePlaysBlack:
2902 case MachinePlaysWhite:
2903 case TwoMachinesPlay:
2904 // XtSetSensitive(XtNameToWidget(menuBarWidget,
2905 // ModeToWidgetName(gameMode)), True);
2912 #define Abs(n) ((n)<0 ? -(n) : (n))
2915 * Find a font that matches "pattern" that is as close as
2916 * possible to the targetPxlSize. Prefer fonts that are k
2917 * pixels smaller to fonts that are k pixels larger. The
2918 * pattern must be in the X Consortium standard format,
2919 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
2920 * The return value should be freed with XtFree when no
2923 char *FindFont(pattern, targetPxlSize)
2927 char **fonts, *p, *best, *scalable, *scalableTail;
2928 int i, j, nfonts, minerr, err, pxlSize;
2931 char **missing_list;
2933 char *def_string, *base_fnt_lst, strInt[3];
2935 XFontStruct **fnt_list;
2937 base_fnt_lst = calloc(1, strlen(pattern) + 3);
2938 sprintf(strInt, "%d", targetPxlSize);
2939 p = strstr(pattern, "--");
2940 strncpy(base_fnt_lst, pattern, p - pattern + 2);
2941 strcat(base_fnt_lst, strInt);
2942 strcat(base_fnt_lst, strchr(p + 2, '-'));
2944 if ((fntSet = XCreateFontSet(xDisplay,
2948 &def_string)) == NULL) {
2950 fprintf(stderr, _("Unable to create font set.\n"));
2954 nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
2956 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
2958 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
2959 programName, pattern);
2967 for (i=0; i<nfonts; i++) {
2970 if (*p != '-') continue;
2972 if (*p == NULLCHAR) break;
2973 if (*p++ == '-') j++;
2975 if (j < 7) continue;
2978 scalable = fonts[i];
2981 err = pxlSize - targetPxlSize;
2982 if (Abs(err) < Abs(minerr) ||
2983 (minerr > 0 && err < 0 && -err == minerr)) {
2989 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
2990 /* If the error is too big and there is a scalable font,
2991 use the scalable font. */
2992 int headlen = scalableTail - scalable;
2993 p = (char *) XtMalloc(strlen(scalable) + 10);
2994 while (isdigit(*scalableTail)) scalableTail++;
2995 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
2997 p = (char *) XtMalloc(strlen(best) + 1);
3000 if (appData.debugMode) {
3001 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
3002 pattern, targetPxlSize, p);
3005 if (missing_count > 0)
3006 XFreeStringList(missing_list);
3007 XFreeFontSet(xDisplay, fntSet);
3009 XFreeFontNames(fonts);
3016 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
3017 | GCBackground | GCFunction | GCPlaneMask;
3018 XGCValues gc_values;
3021 gc_values.plane_mask = AllPlanes;
3022 gc_values.line_width = lineGap;
3023 gc_values.line_style = LineSolid;
3024 gc_values.function = GXcopy;
3026 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3027 gc_values.background = XWhitePixel(xDisplay, xScreen);
3028 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
3029 XSetFont(xDisplay, coordGC, coordFontID);
3031 if (appData.monoMode) {
3032 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3033 gc_values.background = XBlackPixel(xDisplay, xScreen);
3034 lightSquareGC = wbPieceGC
3035 = XtGetGC(shellWidget, value_mask, &gc_values);
3037 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3038 gc_values.background = XWhitePixel(xDisplay, xScreen);
3039 darkSquareGC = bwPieceGC
3040 = XtGetGC(shellWidget, value_mask, &gc_values);
3042 if (DefaultDepth(xDisplay, xScreen) == 1) {
3043 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3044 gc_values.function = GXcopyInverted;
3045 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3046 gc_values.function = GXcopy;
3047 if (XBlackPixel(xDisplay, xScreen) == 1) {
3048 bwPieceGC = darkSquareGC;
3049 wbPieceGC = copyInvertedGC;
3051 bwPieceGC = copyInvertedGC;
3052 wbPieceGC = lightSquareGC;
3056 gc_values.foreground = lightSquareColor;
3057 gc_values.background = darkSquareColor;
3058 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3060 gc_values.foreground = darkSquareColor;
3061 gc_values.background = lightSquareColor;
3062 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3064 gc_values.foreground = jailSquareColor;
3065 gc_values.background = jailSquareColor;
3066 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3068 gc_values.foreground = whitePieceColor;
3069 gc_values.background = darkSquareColor;
3070 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3072 gc_values.foreground = whitePieceColor;
3073 gc_values.background = lightSquareColor;
3074 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3076 gc_values.foreground = whitePieceColor;
3077 gc_values.background = jailSquareColor;
3078 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3080 gc_values.foreground = blackPieceColor;
3081 gc_values.background = darkSquareColor;
3082 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3084 gc_values.foreground = blackPieceColor;
3085 gc_values.background = lightSquareColor;
3086 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3088 gc_values.foreground = blackPieceColor;
3089 gc_values.background = jailSquareColor;
3090 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3097 WhitePawn, WhiteKnight, WhiteBishop, WhiteRook, WhiteQueen, WhiteKing,
3098 BlackPawn, BlackKnight, BlackBishop, BlackRook, BlackQueen, BlackKing,
3102 /* get some defaults going */
3103 for(i=WhitePawn; i<DemotePiece+1; i++)
3104 SVGpieces[i] = load_pixbuf("svg/NeutralSquare.svg",squareSize);
3107 SVGpieces[WhitePawn] = load_pixbuf("svg/WhitePawn.svg",squareSize);
3108 SVGpieces[WhiteKnight] = load_pixbuf("svg/WhiteKnight.svg",squareSize);
3109 SVGpieces[WhiteBishop] = load_pixbuf("svg/WhiteBishop.svg",squareSize);
3110 SVGpieces[WhiteRook] = load_pixbuf("svg/WhiteRook.svg",squareSize);
3111 SVGpieces[WhiteQueen] = load_pixbuf("svg/WhiteQueen.svg",squareSize);
3112 SVGpieces[WhiteKing] = load_pixbuf("svg/WhiteKing.svg",squareSize);
3114 SVGpieces[BlackPawn] = load_pixbuf("svg/BlackPawn.svg",squareSize);
3115 SVGpieces[BlackKnight] = load_pixbuf("svg/BlackKnight.svg",squareSize);
3116 SVGpieces[BlackBishop] = load_pixbuf("svg/BlackBishop.svg",squareSize);
3117 SVGpieces[BlackRook] = load_pixbuf("svg/BlackRook.svg",squareSize);
3118 SVGpieces[BlackQueen] = load_pixbuf("svg/BlackQueen.svg",squareSize);
3119 SVGpieces[BlackKing] = load_pixbuf("svg/BlackKing.svg",squareSize);
3125 static void MenuBarSelect(w, addr, index)
3130 XtActionProc proc = (XtActionProc) addr;
3132 (proc)(NULL, NULL, NULL, NULL);
3135 void CreateMenuBarPopup(parent, name, mb)
3145 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3148 XtSetArg(args[j], XtNleftMargin, 20); j++;
3149 XtSetArg(args[j], XtNrightMargin, 20); j++;
3151 while (mi->string != NULL) {
3152 if (strcmp(mi->string, "----") == 0) {
3153 entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
3156 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string)));
3157 entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass,
3159 XtAddCallback(entry, XtNcallback,
3160 (XtCallbackProc) MenuBarSelect,
3161 (caddr_t) mi->proc);
3167 Widget CreateMenuBar(mb)
3171 Widget anchor, menuBar;
3173 char menuName[MSG_SIZ];
3176 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3177 XtSetArg(args[j], XtNvSpace, 0); j++;
3178 XtSetArg(args[j], XtNborderWidth, 0); j++;
3179 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
3180 formWidget, args, j);
3182 while (mb->name != NULL) {
3183 strcpy(menuName, "menu");
3184 strcat(menuName, mb->name);
3186 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
3189 shortName[0] = _(mb->name)[0];
3190 shortName[1] = NULLCHAR;
3191 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
3194 XtSetArg(args[j], XtNlabel, XtNewString(_(mb->name))); j++;
3197 XtSetArg(args[j], XtNborderWidth, 0); j++;
3198 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
3200 CreateMenuBarPopup(menuBar, menuName, mb);
3206 Widget CreateButtonBar(mi)
3210 Widget button, buttonBar;
3214 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3216 XtSetArg(args[j], XtNhSpace, 0); j++;
3218 XtSetArg(args[j], XtNborderWidth, 0); j++;
3219 XtSetArg(args[j], XtNvSpace, 0); j++;
3220 buttonBar = XtCreateWidget("buttonBar", boxWidgetClass,
3221 formWidget, args, j);
3223 while (mi->string != NULL) {
3226 XtSetArg(args[j], XtNinternalWidth, 2); j++;
3227 XtSetArg(args[j], XtNborderWidth, 0); j++;
3229 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string))); j++;
3230 button = XtCreateManagedWidget(mi->string, commandWidgetClass,
3231 buttonBar, args, j);
3232 XtAddCallback(button, XtNcallback,
3233 (XtCallbackProc) MenuBarSelect,
3234 (caddr_t) mi->proc);
3241 CreatePieceMenu(name, color)
3248 ChessSquare selection;
3250 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3251 boardWidget, args, 0);
3253 for (i = 0; i < PIECE_MENU_SIZE; i++) {
3254 String item = pieceMenuStrings[color][i];
3256 if (strcmp(item, "----") == 0) {
3257 entry = XtCreateManagedWidget(item, smeLineObjectClass,
3260 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3261 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3263 selection = pieceMenuTranslation[color][i];
3264 XtAddCallback(entry, XtNcallback,
3265 (XtCallbackProc) PieceMenuSelect,
3266 (caddr_t) selection);
3267 if (selection == WhitePawn || selection == BlackPawn) {
3268 XtSetArg(args[0], XtNpopupOnEntry, entry);
3269 XtSetValues(menu, args, 1);
3282 ChessSquare selection;
3284 // whitePieceMenu = CreatePieceMenu("menuW", 0);
3285 // blackPieceMenu = CreatePieceMenu("menuB", 1);
3287 // XtRegisterGrabAction(PieceMenuPopup, True,
3288 // (unsigned)(ButtonPressMask|ButtonReleaseMask),
3289 // GrabModeAsync, GrabModeAsync);
3291 // XtSetArg(args[0], XtNlabel, _("Drop"));
3292 // dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
3293 // boardWidget, args, 1);
3294 // for (i = 0; i < DROP_MENU_SIZE; i++) {
3295 // String item = dropMenuStrings[i];
3297 // if (strcmp(item, "----") == 0) {
3298 // entry = XtCreateManagedWidget(item, smeLineObjectClass,
3299 // dropMenu, NULL, 0);
3301 // XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3302 // entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3303 // dropMenu, args, 1);
3304 // selection = dropMenuTranslation[i];
3305 // XtAddCallback(entry, XtNcallback,
3306 // (XtCallbackProc) DropMenuSelect,
3307 // (caddr_t) selection);
3312 void SetupDropMenu()
3320 for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
3321 entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
3322 p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
3323 dmEnables[i].piece);
3324 XtSetSensitive(entry, p != NULL || !appData.testLegality
3325 /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
3326 && !appData.icsActive));
3328 while (p && *p++ == dmEnables[i].piece) count++;
3329 snprintf(label, sizeof(label), "%s %d", dmEnables[i].widget, count);
3331 XtSetArg(args[j], XtNlabel, label); j++;
3332 XtSetValues(entry, args, j);
3336 void PieceMenuPopup(w, event, params, num_params)
3340 Cardinal *num_params;
3343 if (event->type != ButtonPress) return;
3344 if (errorUp) ErrorPopDown();
3348 whichMenu = params[0];
3350 case IcsPlayingWhite:
3351 case IcsPlayingBlack:
3353 case MachinePlaysWhite:
3354 case MachinePlaysBlack:
3355 if (appData.testLegality &&
3356 gameInfo.variant != VariantBughouse &&
3357 gameInfo.variant != VariantCrazyhouse) return;
3359 whichMenu = "menuD";
3365 if (((pmFromX = EventToSquare(event->xbutton.x, BOARD_WIDTH)) < 0) ||
3366 ((pmFromY = EventToSquare(event->xbutton.y, BOARD_HEIGHT)) < 0)) {
3367 pmFromX = pmFromY = -1;
3371 pmFromX = BOARD_WIDTH - 1 - pmFromX;
3373 pmFromY = BOARD_HEIGHT - 1 - pmFromY;
3375 XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
3378 static void PieceMenuSelect(w, piece, junk)
3383 if (pmFromX < 0 || pmFromY < 0) return;
3384 EditPositionMenuEvent(piece, pmFromX, pmFromY);
3387 static void DropMenuSelect(w, piece, junk)
3392 if (pmFromX < 0 || pmFromY < 0) return;
3393 DropMenuEvent(piece, pmFromX, pmFromY);
3396 void WhiteClock(w, event, prms, nprms)
3402 if (gameMode == EditPosition || gameMode == IcsExamining) {
3403 SetWhiteToPlayEvent();
3404 } else if (gameMode == IcsPlayingBlack || gameMode == MachinePlaysWhite) {
3409 void BlackClock(w, event, prms, nprms)
3415 if (gameMode == EditPosition || gameMode == IcsExamining) {
3416 SetBlackToPlayEvent();
3417 } else if (gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) {
3424 * If the user selects on a border boundary, return -1; if off the board,
3425 * return -2. Otherwise map the event coordinate to the square.
3427 int EventToSquare(x, limit)
3435 if ((x % (squareSize + lineGap)) >= squareSize)
3437 x /= (squareSize + lineGap);
3443 static void do_flash_delay(msec)
3449 static void drawHighlight(file, rank, line_type)
3450 int file, rank, line_type;
3455 if (lineGap == 0 || appData.blindfold) return;
3459 x = lineGap/2 + ((BOARD_WIDTH-1)-file) *
3460 (squareSize + lineGap);
3461 y = lineGap/2 + rank * (squareSize + lineGap);
3465 x = lineGap/2 + file * (squareSize + lineGap);
3466 y = lineGap/2 + ((BOARD_HEIGHT-1)-rank) *
3467 (squareSize + lineGap);
3471 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3473 /* draw the highlight */
3474 cairo_move_to (cr, x, y);
3475 cairo_rel_line_to (cr, 0,squareSize+lineGap);
3476 cairo_rel_line_to (cr, squareSize+lineGap,0);
3477 cairo_rel_line_to (cr, 0,-squareSize-lineGap);
3478 cairo_close_path (cr);
3480 cairo_set_line_width (cr, lineGap);
3483 /* TODO: use appdata colors */
3484 case LINE_TYPE_HIGHLIGHT:
3485 cairo_set_source_rgba (cr, 1, 1, 0, 1.0);
3488 cairo_set_source_rgba (cr, 1, 0, 0, 1.0);
3490 case LINE_TYPE_NORMAL:
3492 cairo_set_source_rgba (cr, 0, 1, 0, 1.0);
3503 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
3504 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
3507 SetHighlights(fromX, fromY, toX, toY)
3508 int fromX, fromY, toX, toY;
3510 if (hi1X != fromX || hi1Y != fromY)
3512 if (hi1X >= 0 && hi1Y >= 0)
3514 drawHighlight(hi1X, hi1Y, LINE_TYPE_NORMAL);
3516 if (fromX >= 0 && fromY >= 0)
3518 drawHighlight(fromX, fromY, LINE_TYPE_HIGHLIGHT);
3521 if (hi2X != toX || hi2Y != toY)
3523 if (hi2X >= 0 && hi2Y >= 0)
3525 drawHighlight(hi2X, hi2Y, LINE_TYPE_NORMAL);
3527 if (toX >= 0 && toY >= 0)
3529 drawHighlight(toX, toY, LINE_TYPE_HIGHLIGHT);
3543 SetHighlights(-1, -1, -1, -1);
3548 SetPremoveHighlights(fromX, fromY, toX, toY)
3549 int fromX, fromY, toX, toY;
3551 if (pm1X != fromX || pm1Y != fromY)
3553 if (pm1X >= 0 && pm1Y >= 0)
3555 drawHighlight(pm1X, pm1Y, LINE_TYPE_NORMAL);
3557 if (fromX >= 0 && fromY >= 0)
3559 drawHighlight(fromX, fromY, LINE_TYPE_PRE);
3562 if (pm2X != toX || pm2Y != toY)
3564 if (pm2X >= 0 && pm2Y >= 0)
3566 drawHighlight(pm2X, pm2Y, LINE_TYPE_NORMAL);
3568 if (toX >= 0 && toY >= 0)
3570 drawHighlight(toX, toY, LINE_TYPE_PRE);
3583 ClearPremoveHighlights()
3585 SetPremoveHighlights(-1, -1, -1, -1);
3588 static void BlankSquare(x, y, color, piece, dest)
3601 pb = SVGLightSquare;
3603 case 2: /* neutral */
3605 pb = SVGNeutralSquare;
3608 gdk_draw_pixbuf(GDK_WINDOW(GUI_Board->window),NULL,pb,0,0,x,y,-1,-1, GDK_RGB_DITHER_NORMAL, 0, 0);
3612 static void DrawPiece(piece, square_color, x, y, dest)
3614 int square_color, x, y;
3617 /* redraw background, since piece might be transparent in some areas */
3618 BlankSquare(x,y,square_color,piece,dest);
3621 gdk_draw_pixbuf(GDK_WINDOW(GUI_Board->window),NULL,
3622 GDK_PIXBUF(SVGpieces[piece]),0,0,x,y,-1,-1,
3623 GDK_RGB_DITHER_NORMAL, 0, 0);
3627 /* [HR] determine square color depending on chess variant. */
3628 static int SquareColor(row, column)
3633 if (gameInfo.variant == VariantXiangqi) {
3634 if (column >= 3 && column <= 5 && row >= 0 && row <= 2) {
3636 } else if (column >= 3 && column <= 5 && row >= 7 && row <= 9) {
3638 } else if (row <= 4) {
3644 square_color = ((column + row) % 2) == 1;
3647 /* [hgm] holdings: next line makes all holdings squares light */
3648 if(column < BOARD_LEFT || column >= BOARD_RGHT) square_color = 1;
3650 return square_color;
3653 void DrawSquare(row, column, piece, do_flash)
3654 int row, column, do_flash;
3657 int square_color, x, y;
3662 /* Calculate delay in milliseconds (2-delays per complete flash) */
3663 flash_delay = 500 / appData.flashRate;
3665 /* calculate x and y coordinates from row and column */
3668 x = lineGap + ((BOARD_WIDTH-1)-column) *
3669 (squareSize + lineGap);
3670 y = lineGap + row * (squareSize + lineGap);
3674 x = lineGap + column * (squareSize + lineGap);
3675 y = lineGap + ((BOARD_HEIGHT-1)-row) *
3676 (squareSize + lineGap);
3679 square_color = SquareColor(row, column);
3681 // [HGM] holdings: blank out area between board and holdings
3682 if ( column == BOARD_LEFT-1 || column == BOARD_RGHT
3683 || (column == BOARD_LEFT-2 && row < BOARD_HEIGHT-gameInfo.holdingsSize)
3684 || (column == BOARD_RGHT+1 && row >= gameInfo.holdingsSize) )
3686 BlankSquare(x, y, 2, EmptySquare, xBoardWindow);
3688 // [HGM] print piece counts next to holdings
3689 string[1] = NULLCHAR;
3692 cairo_text_extents_t extents;
3697 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3699 string[0] = '0' + piece;
3701 /* TODO this has to go into the font-selection */
3702 cairo_select_font_face (cr, "Sans",
3703 CAIRO_FONT_SLANT_NORMAL,
3704 CAIRO_FONT_WEIGHT_NORMAL);
3706 cairo_set_font_size (cr, 12.0);
3707 cairo_text_extents (cr, string, &extents);
3709 if (column == (flipView ? BOARD_LEFT-1 : BOARD_RGHT) )
3711 xpos= x + squareSize - extents.width - 2;
3712 ypos= y + extents.y_bearing + 1;
3714 if (column == (flipView ? BOARD_RGHT : BOARD_LEFT-1) && piece > 1)
3717 ypos = y + extents.y_bearing + 1;
3720 /* TODO mono mode? */
3721 cairo_move_to (cr, xpos, ypos);
3722 cairo_text_path (cr, string);
3723 cairo_set_source_rgb (cr, 1.0, 1.0, 1);
3724 cairo_fill_preserve (cr);
3725 cairo_set_source_rgb (cr, 0, 0, 0);
3726 cairo_set_line_width (cr, 0.1);
3735 /* square on the board */
3736 if (piece == EmptySquare || appData.blindfold)
3738 BlankSquare(x, y, square_color, piece, xBoardWindow);
3742 if (do_flash && appData.flashCount > 0)
3744 for (i=0; i<appData.flashCount; ++i)
3747 DrawPiece(piece, square_color, x, y, xBoardWindow);
3748 do_flash_delay(flash_delay);
3750 BlankSquare(x, y, square_color, piece, xBoardWindow);
3751 do_flash_delay(flash_delay);
3754 DrawPiece(piece, square_color, x, y, xBoardWindow);
3758 /* show coordinates if necessary */
3759 if(appData.showCoords)
3761 cairo_text_extents_t extents;
3765 /* TODO this has to go into the font-selection */
3766 cairo_select_font_face (cr, "Sans",
3767 CAIRO_FONT_SLANT_NORMAL,
3768 CAIRO_FONT_WEIGHT_NORMAL);
3769 cairo_set_font_size (cr, 12.0);
3771 string[1] = NULLCHAR;
3774 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3776 if (row == (flipView ? BOARD_HEIGHT-1 : 0) &&
3777 column >= BOARD_LEFT && column < BOARD_RGHT)
3779 string[0] = 'a' + column - BOARD_LEFT;
3780 cairo_text_extents (cr, string, &extents);
3782 xpos = x + squareSize - extents.width - 2;
3783 ypos = y + squareSize - extents.height - extents.y_bearing - 1;
3785 if (appData.monoMode)
3792 cairo_move_to (cr, xpos, ypos);
3793 cairo_text_path (cr, string);
3794 cairo_set_source_rgb (cr, 0.0, 0.0, 0);
3795 cairo_fill_preserve (cr);
3796 cairo_set_source_rgb (cr, 0, 1.0, 0);
3797 cairo_set_line_width (cr, 0.1);
3800 if ( column == (flipView ? BOARD_RGHT-1 : BOARD_LEFT))
3803 string[0] = ONE + row;
3804 cairo_text_extents (cr, string, &extents);
3807 ypos = y + extents.height + 1;
3809 if (appData.monoMode)
3816 cairo_move_to (cr, xpos, ypos);
3817 cairo_text_path (cr, string);
3818 cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
3819 cairo_fill_preserve (cr);
3820 cairo_set_source_rgb (cr, 0, 0, 1.0);
3821 cairo_set_line_width (cr, 0.1);
3833 /* Returns 1 if there are "too many" differences between b1 and b2
3834 (i.e. more than 1 move was made) */
3835 static int too_many_diffs(b1, b2)
3841 for (i=0; i<BOARD_HEIGHT; ++i) {
3842 for (j=0; j<BOARD_WIDTH; ++j) {
3843 if (b1[i][j] != b2[i][j]) {
3844 if (++c > 4) /* Castling causes 4 diffs */
3853 /* Matrix describing castling maneuvers */
3854 /* Row, ColRookFrom, ColKingFrom, ColRookTo, ColKingTo */
3855 static int castling_matrix[4][5] = {
3856 { 0, 0, 4, 3, 2 }, /* 0-0-0, white */
3857 { 0, 7, 4, 5, 6 }, /* 0-0, white */
3858 { 7, 0, 4, 3, 2 }, /* 0-0-0, black */
3859 { 7, 7, 4, 5, 6 } /* 0-0, black */
3862 /* Checks whether castling occurred. If it did, *rrow and *rcol
3863 are set to the destination (row,col) of the rook that moved.
3865 Returns 1 if castling occurred, 0 if not.
3867 Note: Only handles a max of 1 castling move, so be sure
3868 to call too_many_diffs() first.
3870 static int check_castle_draw(newb, oldb, rrow, rcol)
3877 /* For each type of castling... */
3878 for (i=0; i<4; ++i) {
3879 r = castling_matrix[i];
3881 /* Check the 4 squares involved in the castling move */
3883 for (j=1; j<=4; ++j) {
3884 if (newb[r[0]][r[j]] == oldb[r[0]][r[j]]) {
3891 /* All 4 changed, so it must be a castling move */
3900 static int damage[BOARD_SIZE][BOARD_SIZE];
3903 * event handler for redrawing the board
3905 void DrawPosition( repaint, board)
3906 /*Boolean*/int repaint;
3910 static int lastFlipView = 0;
3911 static int lastBoardValid = 0;
3912 static Board lastBoard;
3915 if (board == NULL) {
3916 if (!lastBoardValid) return;
3919 if (!lastBoardValid || lastFlipView != flipView) {
3920 // XtSetArg(args[0], XtNleftBitmap, (flipView ? xMarkPixmap : None));
3921 // XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flip View"),
3926 * It would be simpler to clear the window with XClearWindow()
3927 * but this causes a very distracting flicker.
3930 if (!repaint && lastBoardValid && lastFlipView == flipView)
3932 /* If too much changes (begin observing new game, etc.), don't
3934 do_flash = too_many_diffs(board, lastBoard) ? 0 : 1;
3936 /* Special check for castling so we don't flash both the king
3937 and the rook (just flash the king). */
3940 if (check_castle_draw(board, lastBoard, &rrow, &rcol))
3942 /* Draw rook with NO flashing. King will be drawn flashing later */
3943 DrawSquare(rrow, rcol, board[rrow][rcol], 0);
3944 lastBoard[rrow][rcol] = board[rrow][rcol];
3948 /* First pass -- Draw (newly) empty squares and repair damage.
3949 This prevents you from having a piece show up twice while it
3950 is flashing on its new square */
3951 for (i = 0; i < BOARD_HEIGHT; i++)
3952 for (j = 0; j < BOARD_WIDTH; j++)
3953 if ((board[i][j] != lastBoard[i][j] && board[i][j] == EmptySquare)
3956 DrawSquare(i, j, board[i][j], 0);
3957 damage[i][j] = False;
3960 /* Second pass -- Draw piece(s) in new position and flash them */
3961 for (i = 0; i < BOARD_HEIGHT; i++)
3962 for (j = 0; j < BOARD_WIDTH; j++)
3963 if (board[i][j] != lastBoard[i][j])
3965 DrawSquare(i, j, board[i][j], do_flash);
3977 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3979 cairo_set_line_width (cr, lineGap);
3981 /* TODO: use appdata colors */
3982 cairo_set_source_rgba (cr, 0, 1, 0, 1.0);
3986 for (i = 0; i < BOARD_HEIGHT + 1; i++)
3989 x2 = lineGap + BOARD_WIDTH * (squareSize + lineGap);
3990 y1 = y2 = lineGap / 2 + (i * (squareSize + lineGap));
3992 cairo_move_to (cr, x1, y1);
3993 cairo_rel_line_to (cr, x2,0);
3997 for (j = 0; j < BOARD_WIDTH + 1; j++)
4000 y2 = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
4001 x1 = x2 = lineGap / 2 + (j * (squareSize + lineGap));
4003 cairo_move_to (cr, x1, y1);
4004 cairo_rel_line_to (cr, 0, y2);
4013 for (i = 0; i < BOARD_HEIGHT; i++)
4014 for (j = 0; j < BOARD_WIDTH; j++)
4016 DrawSquare(i, j, board[i][j], 0);
4017 damage[i][j] = False;
4021 CopyBoard(lastBoard, board);
4023 lastFlipView = flipView;
4025 /* Draw highlights */
4026 if (pm1X >= 0 && pm1Y >= 0)
4028 drawHighlight(pm1X, pm1Y, LINE_TYPE_PRE);
4030 if (pm2X >= 0 && pm2Y >= 0)
4032 drawHighlight(pm2X, pm2Y, LINE_TYPE_PRE);
4034 if (hi1X >= 0 && hi1Y >= 0)
4036 drawHighlight(hi1X, hi1Y, LINE_TYPE_HIGHLIGHT);
4038 if (hi2X >= 0 && hi2Y >= 0)
4040 drawHighlight(hi2X, hi2Y, LINE_TYPE_HIGHLIGHT);
4043 /* If piece being dragged around board, must redraw that too */
4050 * event handler for parsing user moves
4052 // [HGM] This routine will need quite some reworking. Although the backend still supports the old
4053 // way of doing things, by calling UserMoveEvent() to test the legality of the move and then perform
4054 // it at the end, and doing all kind of preliminary tests here (e.g. to weed out self-captures), it
4055 // should be made to use the new way, of calling UserMoveTest early to determine the legality of the
4056 // move, (which will weed out the illegal selfcaptures and moves into the holdings, and flag promotions),
4057 // and at the end FinishMove() to perform the move after optional promotion popups.
4058 // For now I patched it to allow self-capture with King, and suppress clicks between board and holdings.
4059 void HandleUserMove(w, event, prms, nprms)
4066 Boolean saveAnimate;
4067 static int second = 0;
4069 if (w != boardWidget || errorExitStatus != -1) return;
4071 if (event->type == ButtonPress) ErrorPopDown();
4074 if (event->type == ButtonPress) {
4075 // XtPopdown(promotionShell);
4076 // XtDestroyWidget(promotionShell);
4077 promotionUp = False;
4085 x = EventToSquare(event->xbutton.x, BOARD_WIDTH);
4086 y = EventToSquare(event->xbutton.y, BOARD_HEIGHT);
4087 if (!flipView && y >= 0) {
4088 y = BOARD_HEIGHT - 1 - y;
4090 if (flipView && x >= 0) {
4091 x = BOARD_WIDTH - 1 - x;
4094 /* [HGM] holdings: next 5 lines: ignore all clicks between board and holdings */
4095 if(event->type == ButtonPress
4096 && ( x == BOARD_LEFT-1 ||
4098 (x == BOARD_LEFT-2 && y < BOARD_HEIGHT-gameInfo.holdingsSize ) ||
4099 (x == BOARD_RGHT+1 && y >= gameInfo.holdingsSize)) )
4103 if (event->type == ButtonPress) {
4105 if (OKToStartUserMove(x, y)) {
4109 DragPieceBegin(event->xbutton.x, event->xbutton.y);
4110 if (appData.highlightDragging) {
4111 SetHighlights(x, y, -1, -1);
4119 if (event->type == ButtonPress && gameMode != EditPosition &&
4124 /* Check if clicking again on the same color piece */
4125 fromP = boards[currentMove][fromY][fromX];
4126 toP = boards[currentMove][y][x];
4127 if ((WhitePawn <= fromP && fromP < WhiteKing && // [HGM] this test should go, as UserMoveTest now does it.
4128 WhitePawn <= toP && toP <= WhiteKing) || // For now I made it less critical by exempting King
4129 (BlackPawn <= fromP && fromP < BlackKing && // moves, to not interfere with FRC castlings.
4130 BlackPawn <= toP && toP <= BlackKing)) {
4131 /* Clicked again on same color piece -- changed his mind */
4132 second = (x == fromX && y == fromY);
4133 if (appData.highlightDragging) {
4134 SetHighlights(x, y, -1, -1);
4138 if (OKToStartUserMove(x, y)) {
4141 DragPieceBegin(event->xbutton.x, event->xbutton.y);
4147 if (event->type == ButtonRelease && x == fromX && y == fromY) {
4148 DragPieceEnd(event->xbutton.x, event->xbutton.y);
4149 if (appData.animateDragging) {
4150 /* Undo animation damage if any */
4151 DrawPosition(FALSE, NULL);
4154 /* Second up/down in same square; just abort move */
4159 ClearPremoveHighlights();
4161 /* First upclick in same square; start click-click mode */
4162 SetHighlights(x, y, -1, -1);
4167 /* Completed move */
4170 saveAnimate = appData.animate;
4171 if (event->type == ButtonPress) {
4172 /* Finish clickclick move */
4173 if (appData.animate || appData.highlightLastMove) {
4174 SetHighlights(fromX, fromY, toX, toY);
4179 /* Finish drag move */
4180 if (appData.highlightLastMove) {
4181 SetHighlights(fromX, fromY, toX, toY);
4185 DragPieceEnd(event->xbutton.x, event->xbutton.y);
4186 /* Don't animate move and drag both */
4187 appData.animate = FALSE;
4189 if (IsPromotion(fromX, fromY, toX, toY)) {
4190 if (appData.alwaysPromoteToQueen) {
4191 UserMoveEvent(fromX, fromY, toX, toY, 'q');
4192 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
4193 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
4196 SetHighlights(fromX, fromY, toX, toY);
4200 UserMoveEvent(fromX, fromY, toX, toY, NULLCHAR);
4201 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
4202 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
4205 appData.animate = saveAnimate;
4206 if (appData.animate || appData.animateDragging) {
4207 /* Undo animation damage if needed */
4208 DrawPosition(FALSE, NULL);
4212 void AnimateUserMove (Widget w, XEvent * event,
4213 String * params, Cardinal * nParams)
4215 DragPieceMove(event->xmotion.x, event->xmotion.y);
4218 Widget CommentCreate(name, text, mutable, callback, lines)
4220 int /*Boolean*/ mutable;
4221 XtCallbackProc callback;
4225 Widget shell, layout, form, edit, b_ok, b_cancel, b_clear, b_close, b_edit;
4230 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4231 XtGetValues(boardWidget, args, j);
4234 XtSetArg(args[j], XtNresizable, True); j++;
4237 XtCreatePopupShell(name, topLevelShellWidgetClass,
4238 shellWidget, args, j);
4241 XtCreatePopupShell(name, transientShellWidgetClass,
4242 shellWidget, args, j);
4245 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
4246 layoutArgs, XtNumber(layoutArgs));
4248 XtCreateManagedWidget("form", formWidgetClass, layout,
4249 formArgs, XtNumber(formArgs));
4253 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
4254 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
4256 XtSetArg(args[j], XtNstring, text); j++;
4257 XtSetArg(args[j], XtNtop, XtChainTop); j++;
4258 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4259 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4260 XtSetArg(args[j], XtNright, XtChainRight); j++;
4261 XtSetArg(args[j], XtNresizable, True); j++;
4262 XtSetArg(args[j], XtNwidth, bw_width); j++; /*force wider than buttons*/
4264 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
4266 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
4267 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
4269 XtSetArg(args[j], XtNautoFill, True); j++;
4270 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
4272 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
4276 XtSetArg(args[j], XtNfromVert, edit); j++;
4277 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4278 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4279 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4280 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4282 XtCreateManagedWidget(_("ok"), commandWidgetClass, form, args, j);
4283 XtAddCallback(b_ok, XtNcallback, callback, (XtPointer) 0);
4286 XtSetArg(args[j], XtNfromVert, edit); j++;
4287 XtSetArg(args[j], XtNfromHoriz, b_ok); j++;
4288 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4289 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4290 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4291 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4293 XtCreateManagedWidget(_("cancel"), commandWidgetClass, form, args, j);
4294 XtAddCallback(b_cancel, XtNcallback, callback, (XtPointer) 0);
4297 XtSetArg(args[j], XtNfromVert, edit); j++;
4298 XtSetArg(args[j], XtNfromHoriz, b_cancel); j++;
4299 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4300 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4301 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4302 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4304 XtCreateManagedWidget(_("clear"), commandWidgetClass, form, args, j);
4305 XtAddCallback(b_clear, XtNcallback, callback, (XtPointer) 0);
4308 XtSetArg(args[j], XtNfromVert, edit); j++;
4309 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4310 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4311 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4312 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4314 XtCreateManagedWidget(_("close"), commandWidgetClass, form, args, j);
4315 XtAddCallback(b_close, XtNcallback, callback, (XtPointer) 0);
4318 XtSetArg(args[j], XtNfromVert, edit); j++;
4319 XtSetArg(args[j], XtNfromHoriz, b_close); j++;
4320 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4321 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4322 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4323 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4325 XtCreateManagedWidget(_("edit"), commandWidgetClass, form, args, j);
4326 XtAddCallback(b_edit, XtNcallback, callback, (XtPointer) 0);
4329 XtRealizeWidget(shell);
4331 if (commentX == -1) {
4334 Dimension pw_height;
4335 Dimension ew_height;
4338 XtSetArg(args[j], XtNheight, &ew_height); j++;
4339 XtGetValues(edit, args, j);
4342 XtSetArg(args[j], XtNheight, &pw_height); j++;
4343 XtGetValues(shell, args, j);
4344 commentH = pw_height + (lines - 1) * ew_height;
4345 commentW = bw_width - 16;
4347 XSync(xDisplay, False);
4349 /* This code seems to tickle an X bug if it is executed too soon
4350 after xboard starts up. The coordinates get transformed as if
4351 the main window was positioned at (0, 0).
4353 XtTranslateCoords(shellWidget,
4354 (bw_width - commentW) / 2, 0 - commentH / 2,
4355 &commentX, &commentY);
4357 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
4358 RootWindowOfScreen(XtScreen(shellWidget)),
4359 (bw_width - commentW) / 2, 0 - commentH / 2,
4364 if (commentY < 0) commentY = 0; /*avoid positioning top offscreen*/
4367 XtSetArg(args[j], XtNheight, commentH); j++;
4368 XtSetArg(args[j], XtNwidth, commentW); j++;
4369 XtSetArg(args[j], XtNx, commentX); j++;
4370 XtSetArg(args[j], XtNy, commentY); j++;
4371 XtSetValues(shell, args, j);
4372 XtSetKeyboardFocus(shell, edit);
4377 /* Used for analysis window and ICS input window */
4378 Widget MiscCreate(name, text, mutable, callback, lines)
4380 int /*Boolean*/ mutable;
4381 XtCallbackProc callback;
4385 Widget shell, layout, form, edit;
4387 Dimension bw_width, pw_height, ew_height, w, h;
4393 XtSetArg(args[j], XtNresizable, True); j++;
4396 XtCreatePopupShell(name, topLevelShellWidgetClass,
4397 shellWidget, args, j);
4400 XtCreatePopupShell(name, transientShellWidgetClass,
4401 shellWidget, args, j);
4404 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
4405 layoutArgs, XtNumber(layoutArgs));
4407 XtCreateManagedWidget("form", formWidgetClass, layout,
4408 formArgs, XtNumber(formArgs));
4412 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
4413 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
4415 XtSetArg(args[j], XtNstring, text); j++;
4416 XtSetArg(args[j], XtNtop, XtChainTop); j++;
4417 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4418 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4419 XtSetArg(args[j], XtNright, XtChainRight); j++;
4420 XtSetArg(args[j], XtNresizable, True); j++;
4422 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
4424 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
4425 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
4427 XtSetArg(args[j], XtNautoFill, True); j++;
4428 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
4430 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
4432 XtRealizeWidget(shell);
4435 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4436 XtGetValues(boardWidget, args, j);
4439 XtSetArg(args[j], XtNheight, &ew_height); j++;
4440 XtGetValues(edit, args, j);
4443 XtSetArg(args[j], XtNheight, &pw_height); j++;
4444 XtGetValues(shell, args, j);
4445 h = pw_height + (lines - 1) * ew_height;
4448 XSync(xDisplay, False);
4450 /* This code seems to tickle an X bug if it is executed too soon
4451 after xboard starts up. The coordinates get transformed as if
4452 the main window was positioned at (0, 0).
4454 XtTranslateCoords(shellWidget, (bw_width - w) / 2, 0 - h / 2, &x, &y);
4456 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
4457 RootWindowOfScreen(XtScreen(shellWidget)),
4458 (bw_width - w) / 2, 0 - h / 2, &xx, &yy, &junk);
4462 if (y < 0) y = 0; /*avoid positioning top offscreen*/
4465 XtSetArg(args[j], XtNheight, h); j++;
4466 XtSetArg(args[j], XtNwidth, w); j++;
4467 XtSetArg(args[j], XtNx, x); j++;
4468 XtSetArg(args[j], XtNy, y); j++;
4469 XtSetValues(shell, args, j);
4475 static int savedIndex; /* gross that this is global */
4477 void EditCommentPopUp(index, title, text)
4486 if (text == NULL) text = "";
4488 if (editShell == NULL) {
4490 CommentCreate(title, text, True, EditCommentCallback, 4);
4491 XtRealizeWidget(editShell);
4492 CatchDeleteWindow(editShell, "EditCommentPopDown");
4494 edit = XtNameToWidget(editShell, "*form.text");
4496 XtSetArg(args[j], XtNstring, text); j++;
4497 XtSetValues(edit, args, j);
4499 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4500 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4501 XtSetValues(editShell, args, j);
4504 XtPopup(editShell, XtGrabNone);
4508 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
4509 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
4513 void EditCommentCallback(w, client_data, call_data)
4515 XtPointer client_data, call_data;
4523 XtSetArg(args[j], XtNlabel, &name); j++;
4524 XtGetValues(w, args, j);
4526 if (strcmp(name, _("ok")) == 0) {
4527 edit = XtNameToWidget(editShell, "*form.text");
4529 XtSetArg(args[j], XtNstring, &val); j++;
4530 XtGetValues(edit, args, j);
4531 ReplaceComment(savedIndex, val);
4532 EditCommentPopDown();
4533 } else if (strcmp(name, _("cancel")) == 0) {
4534 EditCommentPopDown();
4535 } else if (strcmp(name, _("clear")) == 0) {
4536 edit = XtNameToWidget(editShell, "*form.text");
4537 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
4538 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
4542 void EditCommentPopDown()
4547 if (!editUp) return;
4549 XtSetArg(args[j], XtNx, &commentX); j++;
4550 XtSetArg(args[j], XtNy, &commentY); j++;
4551 XtSetArg(args[j], XtNheight, &commentH); j++;
4552 XtSetArg(args[j], XtNwidth, &commentW); j++;
4553 XtGetValues(editShell, args, j);
4554 XtPopdown(editShell);
4557 XtSetArg(args[j], XtNleftBitmap, None); j++;
4558 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
4562 void ICSInputBoxPopUp()
4567 char *title = _("ICS Input");
4570 if (ICSInputShell == NULL) {
4571 ICSInputShell = MiscCreate(title, "", True, NULL, 1);
4572 tr = XtParseTranslationTable(ICSInputTranslations);
4573 edit = XtNameToWidget(ICSInputShell, "*form.text");
4574 XtOverrideTranslations(edit, tr);
4575 XtRealizeWidget(ICSInputShell);
4576 CatchDeleteWindow(ICSInputShell, "ICSInputBoxPopDown");
4579 edit = XtNameToWidget(ICSInputShell, "*form.text");
4581 XtSetArg(args[j], XtNstring, ""); j++;
4582 XtSetValues(edit, args, j);
4584 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4585 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4586 XtSetValues(ICSInputShell, args, j);
4589 XtPopup(ICSInputShell, XtGrabNone);
4590 XtSetKeyboardFocus(ICSInputShell, edit);
4592 ICSInputBoxUp = True;
4594 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
4595 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
4599 void ICSInputSendText()
4606 edit = XtNameToWidget(ICSInputShell, "*form.text");
4608 XtSetArg(args[j], XtNstring, &val); j++;
4609 XtGetValues(edit, args, j);
4610 SendMultiLineToICS(val);
4611 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
4612 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
4615 void ICSInputBoxPopDown()
4620 if (!ICSInputBoxUp) return;
4622 XtPopdown(ICSInputShell);
4623 ICSInputBoxUp = False;
4625 XtSetArg(args[j], XtNleftBitmap, None); j++;
4626 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
4630 void CommentPopUp(title, text)
4637 if (commentShell == NULL) {
4639 CommentCreate(title, text, False, CommentCallback, 4);
4640 XtRealizeWidget(commentShell);
4641 CatchDeleteWindow(commentShell, "CommentPopDown");
4643 edit = XtNameToWidget(commentShell, "*form.text");
4645 XtSetArg(args[j], XtNstring, text); j++;
4646 XtSetValues(edit, args, j);
4648 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4649 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4650 XtSetValues(commentShell, args, j);
4653 XtPopup(commentShell, XtGrabNone);
4654 XSync(xDisplay, False);
4659 void AnalysisPopUp(title, text)
4666 if (analysisShell == NULL) {
4667 analysisShell = MiscCreate(title, text, False, NULL, 4);
4668 XtRealizeWidget(analysisShell);
4669 CatchDeleteWindow(analysisShell, "AnalysisPopDown");
4672 edit = XtNameToWidget(analysisShell, "*form.text");
4674 XtSetArg(args[j], XtNstring, text); j++;
4675 XtSetValues(edit, args, j);
4677 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4678 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4679 XtSetValues(analysisShell, args, j);
4683 XtPopup(analysisShell, XtGrabNone);
4685 XSync(xDisplay, False);
4690 void CommentCallback(w, client_data, call_data)
4692 XtPointer client_data, call_data;
4699 XtSetArg(args[j], XtNlabel, &name); j++;
4700 XtGetValues(w, args, j);
4702 if (strcmp(name, _("close")) == 0) {
4704 } else if (strcmp(name, _("edit")) == 0) {
4711 void CommentPopDown()
4716 if (!commentUp) return;
4718 XtSetArg(args[j], XtNx, &commentX); j++;
4719 XtSetArg(args[j], XtNy, &commentY); j++;
4720 XtSetArg(args[j], XtNwidth, &commentW); j++;
4721 XtSetArg(args[j], XtNheight, &commentH); j++;
4722 XtGetValues(commentShell, args, j);
4723 XtPopdown(commentShell);
4724 XSync(xDisplay, False);
4728 void AnalysisPopDown()
4730 if (!analysisUp) return;
4731 XtPopdown(analysisShell);
4732 XSync(xDisplay, False);
4734 if (appData.icsEngineAnalyze) ExitAnalyzeMode(); /* [DM] icsEngineAnalyze */
4738 void FileNamePopUp(label, def, proc, openMode)
4745 Widget popup, layout, dialog, edit;
4751 fileProc = proc; /* I can't see a way not */
4752 fileOpenMode = openMode; /* to use globals here */
4755 XtSetArg(args[i], XtNresizable, True); i++;
4756 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
4757 XtSetArg(args[i], XtNtitle, XtNewString(_("File name prompt"))); i++;
4758 fileNameShell = popup =
4759 XtCreatePopupShell("File name prompt", transientShellWidgetClass,
4760 shellWidget, args, i);
4763 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
4764 layoutArgs, XtNumber(layoutArgs));
4767 XtSetArg(args[i], XtNlabel, label); i++;
4768 XtSetArg(args[i], XtNvalue, def); i++;
4769 XtSetArg(args[i], XtNborderWidth, 0); i++;
4770 dialog = XtCreateManagedWidget("fileName", dialogWidgetClass,
4773 XawDialogAddButton(dialog, _("ok"), FileNameCallback, (XtPointer) dialog);
4774 XawDialogAddButton(dialog, _("cancel"), FileNameCallback,
4775 (XtPointer) dialog);
4777 XtRealizeWidget(popup);
4778 CatchDeleteWindow(popup, "FileNamePopDown");
4780 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
4781 &x, &y, &win_x, &win_y, &mask);
4783 XtSetArg(args[0], XtNx, x - 10);
4784 XtSetArg(args[1], XtNy, y - 30);
4785 XtSetValues(popup, args, 2);
4787 XtPopup(popup, XtGrabExclusive);
4790 edit = XtNameToWidget(dialog, "*value");
4791 XtSetKeyboardFocus(popup, edit);
4794 void FileNamePopDown()
4796 if (!filenameUp) return;
4797 XtPopdown(fileNameShell);
4798 XtDestroyWidget(fileNameShell);
4803 void FileNameCallback(w, client_data, call_data)
4805 XtPointer client_data, call_data;
4810 XtSetArg(args[0], XtNlabel, &name);
4811 XtGetValues(w, args, 1);
4813 if (strcmp(name, _("cancel")) == 0) {
4818 FileNameAction(w, NULL, NULL, NULL);
4821 void FileNameAction(w, event, prms, nprms)
4833 name = XawDialogGetValueString(w = XtParent(w));
4835 if ((name != NULL) && (*name != NULLCHAR)) {
4837 XtPopdown(w = XtParent(XtParent(w)));
4841 p = strrchr(buf, ' ');
4848 fullname = ExpandPathName(buf);
4850 ErrorPopUp(_("Error"), _("Can't open file"), FALSE);
4853 f = fopen(fullname, fileOpenMode);
4855 DisplayError(_("Failed to open file"), errno);
4857 (void) (*fileProc)(f, index, buf);
4864 XtPopdown(w = XtParent(XtParent(w)));
4870 void PromotionPopUp()
4873 Widget dialog, layout;
4875 Dimension bw_width, pw_width;
4879 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4880 XtGetValues(boardWidget, args, j);
4883 XtSetArg(args[j], XtNresizable, True); j++;
4884 XtSetArg(args[j], XtNtitle, XtNewString(_("Promotion"))); j++;
4886 XtCreatePopupShell("Promotion", transientShellWidgetClass,
4887 shellWidget, args, j);
4889 XtCreateManagedWidget(layoutName, formWidgetClass, promotionShell,
4890 layoutArgs, XtNumber(layoutArgs));
4893 XtSetArg(args[j], XtNlabel, _("Promote to what?")); j++;
4894 XtSetArg(args[j], XtNborderWidth, 0); j++;
4895 dialog = XtCreateManagedWidget("promotion", dialogWidgetClass,
4898 if(gameInfo.variant != VariantShogi) {
4899 XawDialogAddButton(dialog, _("Queen"), PromotionCallback,
4900 (XtPointer) dialog);
4901 XawDialogAddButton(dialog, _("Rook"), PromotionCallback,
4902 (XtPointer) dialog);
4903 XawDialogAddButton(dialog, _("Bishop"), PromotionCallback,
4904 (XtPointer) dialog);
4905 XawDialogAddButton(dialog, _("Knight"), PromotionCallback,
4906 (XtPointer) dialog);
4907 if (!appData.testLegality || gameInfo.variant == VariantSuicide ||
4908 gameInfo.variant == VariantGiveaway) {
4909 XawDialogAddButton(dialog, _("King"), PromotionCallback,
4910 (XtPointer) dialog);
4912 if(gameInfo.variant == VariantCapablanca ||
4913 gameInfo.variant == VariantGothic ||
4914 gameInfo.variant == VariantCapaRandom) {
4915 XawDialogAddButton(dialog, _("Archbishop"), PromotionCallback,
4916 (XtPointer) dialog);
4917 XawDialogAddButton(dialog, _("Chancellor"), PromotionCallback,
4918 (XtPointer) dialog);
4920 } else // [HGM] shogi
4922 XawDialogAddButton(dialog, _("Promote"), PromotionCallback,
4923 (XtPointer) dialog);
4924 XawDialogAddButton(dialog, _("Defer"), PromotionCallback,
4925 (XtPointer) dialog);
4927 XawDialogAddButton(dialog, _("cancel"), PromotionCallback,
4928 (XtPointer) dialog);
4930 XtRealizeWidget(promotionShell);
4931 CatchDeleteWindow(promotionShell, "PromotionPopDown");
4934 XtSetArg(args[j], XtNwidth, &pw_width); j++;
4935 XtGetValues(promotionShell, args, j);
4937 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
4938 lineGap + squareSize/3 +
4939 ((toY == BOARD_HEIGHT-1) ^ (flipView) ?
4940 0 : 6*(squareSize + lineGap)), &x, &y);
4943 XtSetArg(args[j], XtNx, x); j++;
4944 XtSetArg(args[j], XtNy, y); j++;
4945 XtSetValues(promotionShell, args, j);
4947 XtPopup(promotionShell, XtGrabNone);
4952 void PromotionPopDown()
4954 if (!promotionUp) return;
4955 XtPopdown(promotionShell);
4956 XtDestroyWidget(promotionShell);
4957 promotionUp = False;
4960 void PromotionCallback(w, client_data, call_data)
4962 XtPointer client_data, call_data;
4968 XtSetArg(args[0], XtNlabel, &name);
4969 XtGetValues(w, args, 1);
4973 if (fromX == -1) return;
4975 if (strcmp(name, _("cancel")) == 0) {
4979 } else if (strcmp(name, _("Knight")) == 0) {
4981 } else if (strcmp(name, _("Promote")) == 0) {
4983 } else if (strcmp(name, _("Defer")) == 0) {
4986 promoChar = ToLower(name[0]);
4989 UserMoveEvent(fromX, fromY, toX, toY, promoChar);
4991 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
4992 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
4997 void ErrorCallback(w, client_data, call_data)
4999 XtPointer client_data, call_data;
5002 XtPopdown(w = XtParent(XtParent(XtParent(w))));
5004 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5010 if (!errorUp) return;
5014 gtk_widget_destroy(GTK_WIDGET(GUI_Error));
5016 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5021 void ErrorPopUp(title, label, modal)
5022 char *title, *label;
5025 GUI_Error = gtk_message_dialog_new(GTK_WINDOW(GUI_Window),
5026 GTK_DIALOG_DESTROY_WITH_PARENT,
5031 gtk_window_set_title(GTK_WINDOW(GUI_Error),(gchar *) title);
5034 gtk_dialog_run(GTK_DIALOG(GUI_Error));
5035 gtk_widget_destroy(GTK_WIDGET(GUI_Error));
5039 g_signal_connect_swapped (GUI_Error, "response",
5040 G_CALLBACK (ErrorPopDownProc),
5043 gtk_widget_show(GTK_WIDGET(GUI_Error));
5049 /* Disable all user input other than deleting the window */
5050 static int frozen = 0;
5054 /* Grab by a widget that doesn't accept input */
5055 // XtAddGrab(messageWidget, TRUE, FALSE);
5059 /* Undo a FreezeUI */
5062 if (!frozen) return;
5063 // XtRemoveGrab(messageWidget);
5067 char *ModeToWidgetName(mode)
5071 case BeginningOfGame:
5072 if (appData.icsActive)
5073 return "menuMode.ICS Client";
5074 else if (appData.noChessProgram ||
5075 *appData.cmailGameName != NULLCHAR)
5076 return "menuMode.Edit Game";
5078 return "menuMode.Machine Black";
5079 case MachinePlaysBlack:
5080 return "menuMode.Machine Black";
5081 case MachinePlaysWhite:
5082 return "menuMode.Machine White";
5084 return "menuMode.Analysis Mode";
5086 return "menuMode.Analyze File";
5087 case TwoMachinesPlay:
5088 return "menuMode.Two Machines";
5090 return "menuMode.Edit Game";
5091 case PlayFromGameFile:
5092 return "menuFile.Load Game";
5094 return "menuMode.Edit Position";
5096 return "menuMode.Training";
5097 case IcsPlayingWhite:
5098 case IcsPlayingBlack:
5102 return "menuMode.ICS Client";
5109 void ModeHighlight()
5111 static int oldPausing = FALSE;
5112 static GameMode oldmode = (GameMode) -1;
5115 // todo this toggling of the pause button doesn't seem to work?
5116 // e.g. select pause from buttonbar doesn't activate menumode.pause
5118 // if (!boardWidget || !XtIsRealized(boardWidget)) return;
5120 if (pausing != oldPausing) {
5121 oldPausing = pausing;
5122 gtk_button_set_relief(GTK_BUTTON (gtk_builder_get_object (builder, "menuMode.Pause")),pausing?GTK_RELIEF_NORMAL:GTK_RELIEF_NONE);
5123 /* toggle background color in showbuttonbar */
5124 if (appData.showButtonBar) {
5126 gtk_button_pressed(GTK_BUTTON (gtk_builder_get_object (builder, "buttonbar.Pause")));
5128 gtk_button_released(GTK_BUTTON (gtk_builder_get_object (builder, "buttonbar.Pause")));
5133 wname = ModeToWidgetName(oldmode);
5135 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, wname)),True);
5139 /* Maybe all the enables should be handled here, not just this one */
5140 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuMode.Training")),
5141 gameMode == Training || gameMode == PlayFromGameFile);
5146 * Button/menu procedures
5149 int LoadGamePopUp(f, gameNumber, title)
5154 cmailMsgLoaded = FALSE;
5155 if (gameNumber == 0) {
5156 int error = GameListBuild(f);
5158 DisplayError(_("Cannot build game list"), error);
5159 } else if (!ListEmpty(&gameList) &&
5160 ((ListGame *) gameList.tailPred)->number > 1) {
5161 GameListPopUp(f, title);
5167 return LoadGame(f, gameNumber, title, FALSE);
5171 void LoadNextPositionProc(w, event, prms, nprms)
5180 void LoadPrevPositionProc(w, event, prms, nprms)
5189 void ReloadPositionProc(w, event, prms, nprms)
5198 void LoadPositionProc(w, event, prms, nprms)
5204 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
5207 FileNamePopUp(_("Load position file name?"), "", LoadPosition, "rb");
5210 void SaveGameProc(w, event, prms, nprms)
5216 FileNamePopUp(_("Save game file name?"),
5217 DefaultFileName(appData.oldSaveStyle ? "game" : "pgn"),
5221 void SavePositionProc(w, event, prms, nprms)
5227 FileNamePopUp(_("Save position file name?"),
5228 DefaultFileName(appData.oldSaveStyle ? "pos" : "fen"),
5232 void ReloadCmailMsgProc(w, event, prms, nprms)
5238 ReloadCmailMsgEvent(FALSE);
5241 void MailMoveProc(w, event, prms, nprms)
5250 /* this variable is shared between CopyPositionProc and SendPositionSelection */
5251 static char *selected_fen_position=NULL;
5254 SendPositionSelection(Widget w, Atom *selection, Atom *target,
5255 Atom *type_return, XtPointer *value_return,
5256 unsigned long *length_return, int *format_return)
5258 char *selection_tmp;
5260 if (!selected_fen_position) return False; /* should never happen */
5261 if (*target == XA_STRING){
5262 /* note: since no XtSelectionDoneProc was registered, Xt will
5263 * automatically call XtFree on the value returned. So have to
5264 * make a copy of it allocated with XtMalloc */
5265 selection_tmp= XtMalloc(strlen(selected_fen_position)+16);
5266 strcpy(selection_tmp, selected_fen_position);
5268 *value_return=selection_tmp;
5269 *length_return=strlen(selection_tmp);
5270 *type_return=XA_STRING;
5271 *format_return = 8; /* bits per byte */
5278 /* note: when called from menu all parameters are NULL, so no clue what the
5279 * Widget which was clicked on was, or what the click event was
5281 void CopyPositionProc(w, event, prms, nprms)
5289 if (selected_fen_position) free(selected_fen_position);
5290 selected_fen_position = (char *)PositionToFEN(currentMove, NULL);
5291 if (!selected_fen_position) return;
5292 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
5294 SendPositionSelection,
5295 NULL/* lose_ownership_proc */ ,
5296 NULL/* transfer_done_proc */);
5298 free(selected_fen_position);
5299 selected_fen_position=NULL;
5303 /* function called when the data to Paste is ready */
5305 PastePositionCB(Widget w, XtPointer client_data, Atom *selection,
5306 Atom *type, XtPointer value, unsigned long *len, int *format)
5309 if (value==NULL || *len==0) return; /* nothing had been selected to copy */
5310 fenstr[*len]='\0'; /* normally this string is terminated, but be safe */
5311 EditPositionPasteFEN(fenstr);
5315 /* called when Paste Position button is pressed,
5316 * all parameters will be NULL */
5317 void PastePositionProc(w, event, prms, nprms)
5323 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
5324 /* (XtSelectionCallbackProc) */ PastePositionCB,
5325 NULL, /* client_data passed to PastePositionCB */
5327 /* better to use the time field from the event that triggered the
5328 * call to this function, but that isn't trivial to get
5336 SendGameSelection(Widget w, Atom *selection, Atom *target,
5337 Atom *type_return, XtPointer *value_return,
5338 unsigned long *length_return, int *format_return)
5340 char *selection_tmp;
5342 if (*target == XA_STRING){
5343 FILE* f = fopen(gameCopyFilename, "r");
5346 if (f == NULL) return False;
5350 selection_tmp = XtMalloc(len + 1);
5351 count = fread(selection_tmp, 1, len, f);
5353 XtFree(selection_tmp);
5356 selection_tmp[len] = NULLCHAR;
5357 *value_return = selection_tmp;
5358 *length_return = len;
5359 *type_return = XA_STRING;
5360 *format_return = 8; /* bits per byte */
5367 /* note: when called from menu all parameters are NULL, so no clue what the
5368 * Widget which was clicked on was, or what the click event was
5370 void CopyGameProc(w, event, prms, nprms)
5378 ret = SaveGameToFile(gameCopyFilename, FALSE);
5381 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
5384 NULL/* lose_ownership_proc */ ,
5385 NULL/* transfer_done_proc */);
5388 /* function called when the data to Paste is ready */
5390 PasteGameCB(Widget w, XtPointer client_data, Atom *selection,
5391 Atom *type, XtPointer value, unsigned long *len, int *format)
5394 if (value == NULL || *len == 0) {
5395 return; /* nothing had been selected to copy */
5397 f = fopen(gamePasteFilename, "w");
5399 DisplayError(_("Can't open temp file"), errno);
5402 fwrite(value, 1, *len, f);
5405 LoadGameFromFile(gamePasteFilename, 0, gamePasteFilename, TRUE);
5408 /* called when Paste Game button is pressed,
5409 * all parameters will be NULL */
5410 void PasteGameProc(w, event, prms, nprms)
5416 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
5417 /* (XtSelectionCallbackProc) */ PasteGameCB,
5418 NULL, /* client_data passed to PasteGameCB */
5420 /* better to use the time field from the event that triggered the
5421 * call to this function, but that isn't trivial to get
5431 SaveGameProc(NULL, NULL, NULL, NULL);
5434 void AnalyzeModeProc(w, event, prms, nprms)
5442 if (!first.analysisSupport) {
5443 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
5444 DisplayError(buf, 0);
5447 /* [DM] icsEngineAnalyze [HGM] This is horrible code; reverse the gameMode and isEngineAnalyze tests! */
5448 if (appData.icsActive) {
5449 if (gameMode != IcsObserving) {
5450 sprintf(buf,_("You are not observing a game"));
5451 DisplayError(buf, 0);
5453 if (appData.icsEngineAnalyze) {
5454 if (appData.debugMode)
5455 fprintf(debugFP, _("Found unexpected active ICS engine analyze \n"));
5461 /* if enable, use want disable icsEngineAnalyze */
5462 if (appData.icsEngineAnalyze) {
5467 appData.icsEngineAnalyze = TRUE;
5468 if (appData.debugMode)
5469 fprintf(debugFP, _("ICS engine analyze starting... \n"));
5471 if (!appData.showThinking)
5472 ShowThinkingProc(w,event,prms,nprms);
5477 void AnalyzeFileProc(w, event, prms, nprms)
5483 if (!first.analysisSupport) {
5485 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
5486 DisplayError(buf, 0);
5491 if (!appData.showThinking)
5492 ShowThinkingProc(w,event,prms,nprms);
5495 FileNamePopUp(_("File to analyze"), "", LoadGamePopUp, "rb");
5496 AnalysisPeriodicEvent(1);
5500 void EditGameProc(w, event, prms, nprms)
5509 void EditPositionProc(w, event, prms, nprms)
5515 EditPositionEvent();
5518 void TrainingProc(w, event, prms, nprms)
5527 void EditCommentProc(w, event, prms, nprms)
5534 EditCommentPopDown();
5540 void IcsInputBoxProc(w, event, prms, nprms)
5546 if (ICSInputBoxUp) {
5547 ICSInputBoxPopDown();
5554 void EnterKeyProc(w, event, prms, nprms)
5560 if (ICSInputBoxUp == True)
5564 void AlwaysQueenProc(w, event, prms, nprms)
5572 appData.alwaysPromoteToQueen = !appData.alwaysPromoteToQueen;
5574 if (appData.alwaysPromoteToQueen) {
5575 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5577 XtSetArg(args[0], XtNleftBitmap, None);
5579 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
5583 void AnimateDraggingProc(w, event, prms, nprms)
5591 appData.animateDragging = !appData.animateDragging;
5593 if (appData.animateDragging) {
5594 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5597 XtSetArg(args[0], XtNleftBitmap, None);
5599 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Dragging"),
5603 void AnimateMovingProc(w, event, prms, nprms)
5611 appData.animate = !appData.animate;
5613 if (appData.animate) {
5614 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5617 XtSetArg(args[0], XtNleftBitmap, None);
5619 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
5623 void AutocommProc(w, event, prms, nprms)
5631 appData.autoComment = !appData.autoComment;
5633 if (appData.autoComment) {
5634 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5636 XtSetArg(args[0], XtNleftBitmap, None);
5638 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
5643 void AutoflagProc(w, event, prms, nprms)
5651 appData.autoCallFlag = !appData.autoCallFlag;
5653 if (appData.autoCallFlag) {
5654 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5656 XtSetArg(args[0], XtNleftBitmap, None);
5658 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
5662 void AutoflipProc(w, event, prms, nprms)
5670 appData.autoFlipView = !appData.autoFlipView;
5672 if (appData.autoFlipView) {
5673 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5675 XtSetArg(args[0], XtNleftBitmap, None);
5677 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flip View"),
5681 void AutobsProc(w, event, prms, nprms)
5689 appData.autoObserve = !appData.autoObserve;
5691 if (appData.autoObserve) {
5692 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5694 XtSetArg(args[0], XtNleftBitmap, None);
5696 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
5700 void AutoraiseProc(w, event, prms, nprms)
5708 appData.autoRaiseBoard = !appData.autoRaiseBoard;
5710 if (appData.autoRaiseBoard) {
5711 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5713 XtSetArg(args[0], XtNleftBitmap, None);
5715 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Raise Board"),
5719 void AutosaveProc(w, event, prms, nprms)
5727 appData.autoSaveGames = !appData.autoSaveGames;
5729 if (appData.autoSaveGames) {
5730 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5732 XtSetArg(args[0], XtNleftBitmap, None);
5734 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
5738 void BlindfoldProc(w, event, prms, nprms)
5746 appData.blindfold = !appData.blindfold;
5748 if (appData.blindfold) {
5749 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5751 XtSetArg(args[0], XtNleftBitmap, None);
5753 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Blindfold"),
5756 DrawPosition(True, NULL);
5759 void TestLegalityProc(w, event, prms, nprms)
5767 appData.testLegality = !appData.testLegality;
5769 if (appData.testLegality) {
5770 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5772 XtSetArg(args[0], XtNleftBitmap, None);
5774 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Test Legality"),
5779 void FlashMovesProc(w, event, prms, nprms)
5787 if (appData.flashCount == 0) {
5788 appData.flashCount = 3;
5790 appData.flashCount = -appData.flashCount;
5793 if (appData.flashCount > 0) {
5794 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5796 XtSetArg(args[0], XtNleftBitmap, None);
5798 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flash Moves"),
5802 void GetMoveListProc(w, event, prms, nprms)
5810 appData.getMoveList = !appData.getMoveList;
5812 if (appData.getMoveList) {
5813 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5816 XtSetArg(args[0], XtNleftBitmap, None);
5818 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
5823 void HighlightDraggingProc(w, event, prms, nprms)
5831 appData.highlightDragging = !appData.highlightDragging;
5833 if (appData.highlightDragging) {
5834 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5836 XtSetArg(args[0], XtNleftBitmap, None);
5838 XtSetValues(XtNameToWidget(menuBarWidget,
5839 "menuOptions.Highlight Dragging"), args, 1);
5843 void HighlightLastMoveProc(w, event, prms, nprms)
5851 appData.highlightLastMove = !appData.highlightLastMove;
5853 if (appData.highlightLastMove) {
5854 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5856 XtSetArg(args[0], XtNleftBitmap, None);
5858 XtSetValues(XtNameToWidget(menuBarWidget,
5859 "menuOptions.Highlight Last Move"), args, 1);
5862 void IcsAlarmProc(w, event, prms, nprms)
5870 appData.icsAlarm = !appData.icsAlarm;
5872 if (appData.icsAlarm) {
5873 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5875 XtSetArg(args[0], XtNleftBitmap, None);
5877 XtSetValues(XtNameToWidget(menuBarWidget,
5878 "menuOptions.ICS Alarm"), args, 1);
5881 void MoveSoundProc(w, event, prms, nprms)
5889 appData.ringBellAfterMoves = !appData.ringBellAfterMoves;
5891 if (appData.ringBellAfterMoves) {
5892 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5894 XtSetArg(args[0], XtNleftBitmap, None);
5896 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
5901 void OldSaveStyleProc(w, event, prms, nprms)
5909 appData.oldSaveStyle = !appData.oldSaveStyle;
5911 if (appData.oldSaveStyle) {
5912 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5914 XtSetArg(args[0], XtNleftBitmap, None);
5916 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Old Save Style"),
5920 void PeriodicUpdatesProc(w, event, prms, nprms)
5928 PeriodicUpdatesEvent(!appData.periodicUpdates);
5930 if (appData.periodicUpdates) {
5931 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5933 XtSetArg(args[0], XtNleftBitmap, None);
5935 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Periodic Updates"),
5939 void PonderNextMoveProc(w, event, prms, nprms)
5947 PonderNextMoveEvent(!appData.ponderNextMove);
5949 if (appData.ponderNextMove) {
5950 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5952 XtSetArg(args[0], XtNleftBitmap, None);
5954 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Ponder Next Move"),
5958 void PopupExitMessageProc(w, event, prms, nprms)
5966 appData.popupExitMessage = !appData.popupExitMessage;
5968 if (appData.popupExitMessage) {
5969 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5971 XtSetArg(args[0], XtNleftBitmap, None);
5973 XtSetValues(XtNameToWidget(menuBarWidget,
5974 "menuOptions.Popup Exit Message"), args, 1);
5977 void PopupMoveErrorsProc(w, event, prms, nprms)
5985 appData.popupMoveErrors = !appData.popupMoveErrors;
5987 if (appData.popupMoveErrors) {
5988 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5990 XtSetArg(args[0], XtNleftBitmap, None);
5992 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Popup Move Errors"),
5996 void PremoveProc(w, event, prms, nprms)
6004 appData.premove = !appData.premove;
6006 if (appData.premove) {
6007 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6009 XtSetArg(args[0], XtNleftBitmap, None);
6011 XtSetValues(XtNameToWidget(menuBarWidget,
6012 "menuOptions.Premove"), args, 1);
6015 void QuietPlayProc(w, event, prms, nprms)
6023 appData.quietPlay = !appData.quietPlay;
6025 if (appData.quietPlay) {
6026 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6028 XtSetArg(args[0], XtNleftBitmap, None);
6030 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Quiet Play"),
6034 void ShowThinkingProc(w, event, prms, nprms)
6042 appData.showThinking = !appData.showThinking; // [HGM] thinking: tken out of ShowThinkingEvent
6043 ShowThinkingEvent();
6045 // [HGM] thinking: currently no suc menu item; replaced by Hide Thinking (From Human)
6046 if (appData.showThinking) {
6047 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6049 XtSetArg(args[0], XtNleftBitmap, None);
6051 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Thinking"),
6056 void HideThinkingProc(w, event, prms, nprms)
6064 appData.hideThinkingFromHuman = !appData.hideThinkingFromHuman; // [HGM] thinking: tken out of ShowThinkingEvent
6065 ShowThinkingEvent();
6067 if (appData.hideThinkingFromHuman) {
6068 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6070 XtSetArg(args[0], XtNleftBitmap, None);
6072 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
6076 void DebugProc(w, event, prms, nprms)
6082 appData.debugMode = !appData.debugMode;
6085 void AboutGameProc(w, event, prms, nprms)
6094 void NothingProc(w, event, prms, nprms)
6103 void Iconify(w, event, prms, nprms)
6112 XtSetArg(args[0], XtNiconic, True);
6113 XtSetValues(shellWidget, args, 1);
6116 void DisplayMessage(message, extMessage)
6117 gchar *message, *extMessage;
6124 snprintf(buf, sizeof(buf), "%s %s", message, extMessage);
6127 message = extMessage;
6130 gtk_label_set_text( GTK_LABEL(gtk_builder_get_object (builder, "Messages")),message);
6135 void DisplayTitle(text)
6138 gchar title[MSG_SIZ];
6140 if (text == NULL) text = "";
6142 if (appData.titleInWindow)
6147 if (*text != NULLCHAR)
6149 strcpy(title, text);
6151 else if (appData.icsActive)
6153 snprintf(title, sizeof(title), "%s: %s", programName, appData.icsHost);
6155 else if (appData.cmailGameName[0] != NULLCHAR)
6157 snprintf(title,sizeof(title), "%s: %s", programName, "CMail");
6159 // [HGM] license: This stuff should really be done in back-end, but WinBoard already had a pop-up for it
6161 else if (gameInfo.variant == VariantGothic)
6163 strcpy(title, GOTHIC);
6167 else if (gameInfo.variant == VariantFalcon)
6169 strcpy(title, FALCON);
6172 else if (appData.noChessProgram)
6174 strcpy(title, programName);
6178 snprintf(title,sizeof(title), "%s: %s", programName, first.tidy);
6180 gtk_window_set_title(GTK_WINDOW(GUI_Window),title);
6186 void DisplayError(message, error)
6193 if (appData.debugMode || appData.matchMode) {
6194 fprintf(stderr, "%s: %s\n", programName, message);
6197 if (appData.debugMode || appData.matchMode) {
6198 fprintf(stderr, "%s: %s: %s\n",
6199 programName, message, strerror(error));
6201 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
6204 ErrorPopUp(_("Error"), message, FALSE);
6208 void DisplayMoveError(message)
6213 DrawPosition(FALSE, NULL);
6214 if (appData.debugMode || appData.matchMode) {
6215 fprintf(stderr, "%s: %s\n", programName, message);
6217 if (appData.popupMoveErrors) {
6218 ErrorPopUp(_("Error"), message, FALSE);
6220 DisplayMessage(message, "");
6225 void DisplayFatalError(message, error, status)
6231 errorExitStatus = status;
6233 fprintf(stderr, "%s: %s\n", programName, message);
6235 fprintf(stderr, "%s: %s: %s\n",
6236 programName, message, strerror(error));
6237 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
6240 if (appData.popupExitMessage && boardWidget && XtIsRealized(boardWidget)) {
6241 ErrorPopUp(status ? _("Fatal Error") : _("Exiting"), message, TRUE);
6247 void DisplayInformation(message)
6251 ErrorPopUp(_("Information"), message, TRUE);
6254 void DisplayNote(message)
6258 ErrorPopUp(_("Note"), message, FALSE);
6262 NullXErrorCheck(dpy, error_event)
6264 XErrorEvent *error_event;
6269 void DisplayIcsInteractionTitle(message)
6272 if (oldICSInteractionTitle == NULL) {
6273 /* Magic to find the old window title, adapted from vim */
6274 char *wina = getenv("WINDOWID");
6276 Window win = (Window) atoi(wina);
6277 Window root, parent, *children;
6278 unsigned int nchildren;
6279 int (*oldHandler)() = XSetErrorHandler(NullXErrorCheck);
6281 if (XFetchName(xDisplay, win, &oldICSInteractionTitle)) break;
6282 if (!XQueryTree(xDisplay, win, &root, &parent,
6283 &children, &nchildren)) break;
6284 if (children) XFree((void *)children);
6285 if (parent == root || parent == 0) break;
6288 XSetErrorHandler(oldHandler);
6290 if (oldICSInteractionTitle == NULL) {
6291 oldICSInteractionTitle = "xterm";
6294 printf("\033]0;%s\007", message);
6298 char pendingReplyPrefix[MSG_SIZ];
6299 ProcRef pendingReplyPR;
6301 void AskQuestionProc(w, event, prms, nprms)
6308 fprintf(stderr, _("AskQuestionProc needed 4 parameters, got %d\n"),
6312 AskQuestionEvent(prms[0], prms[1], prms[2], prms[3]);
6315 void AskQuestionPopDown()
6317 if (!askQuestionUp) return;
6318 XtPopdown(askQuestionShell);
6319 XtDestroyWidget(askQuestionShell);
6320 askQuestionUp = False;
6323 void AskQuestionReplyAction(w, event, prms, nprms)
6333 reply = XawDialogGetValueString(w = XtParent(w));
6334 strcpy(buf, pendingReplyPrefix);
6335 if (*buf) strcat(buf, " ");
6338 OutputToProcess(pendingReplyPR, buf, strlen(buf), &err);
6339 AskQuestionPopDown();
6341 if (err) DisplayFatalError(_("Error writing to chess program"), err, 0);
6344 void AskQuestionCallback(w, client_data, call_data)
6346 XtPointer client_data, call_data;
6351 XtSetArg(args[0], XtNlabel, &name);
6352 XtGetValues(w, args, 1);
6354 if (strcmp(name, _("cancel")) == 0) {
6355 AskQuestionPopDown();
6357 AskQuestionReplyAction(w, NULL, NULL, NULL);
6361 void AskQuestion(title, question, replyPrefix, pr)
6362 char *title, *question, *replyPrefix;
6366 Widget popup, layout, dialog, edit;
6372 strcpy(pendingReplyPrefix, replyPrefix);
6373 pendingReplyPR = pr;
6376 XtSetArg(args[i], XtNresizable, True); i++;
6377 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
6378 askQuestionShell = popup =
6379 XtCreatePopupShell(title, transientShellWidgetClass,
6380 shellWidget, args, i);
6383 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
6384 layoutArgs, XtNumber(layoutArgs));
6387 XtSetArg(args[i], XtNlabel, question); i++;
6388 XtSetArg(args[i], XtNvalue, ""); i++;
6389 XtSetArg(args[i], XtNborderWidth, 0); i++;
6390 dialog = XtCreateManagedWidget("question", dialogWidgetClass,
6393 XawDialogAddButton(dialog, _("enter"), AskQuestionCallback,
6394 (XtPointer) dialog);
6395 XawDialogAddButton(dialog, _("cancel"), AskQuestionCallback,
6396 (XtPointer) dialog);
6398 XtRealizeWidget(popup);
6399 CatchDeleteWindow(popup, "AskQuestionPopDown");
6401 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
6402 &x, &y, &win_x, &win_y, &mask);
6404 XtSetArg(args[0], XtNx, x - 10);
6405 XtSetArg(args[1], XtNy, y - 30);
6406 XtSetValues(popup, args, 2);
6408 XtPopup(popup, XtGrabExclusive);
6409 askQuestionUp = True;
6411 edit = XtNameToWidget(dialog, "*value");
6412 XtSetKeyboardFocus(popup, edit);
6420 if (*name == NULLCHAR) {
6422 } else if (strcmp(name, "$") == 0) {
6423 putc(BELLCHAR, stderr);
6426 snprintf(buf, sizeof(buf), "%s '%s' &", appData.soundProgram, name);
6434 PlaySound(appData.soundMove);
6440 PlaySound(appData.soundIcsWin);
6446 PlaySound(appData.soundIcsLoss);
6452 PlaySound(appData.soundIcsDraw);
6456 PlayIcsUnfinishedSound()
6458 PlaySound(appData.soundIcsUnfinished);
6464 PlaySound(appData.soundIcsAlarm);
6470 system("stty echo");
6476 system("stty -echo");
6480 Colorize(cc, continuation)
6485 int count, outCount, error;
6487 if (textColors[(int)cc].bg > 0) {
6488 if (textColors[(int)cc].fg > 0) {
6489 sprintf(buf, "\033[0;%d;%d;%dm", textColors[(int)cc].attr,
6490 textColors[(int)cc].fg, textColors[(int)cc].bg);
6492 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
6493 textColors[(int)cc].bg);
6496 if (textColors[(int)cc].fg > 0) {
6497 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
6498 textColors[(int)cc].fg);
6500 sprintf(buf, "\033[0;%dm", textColors[(int)cc].attr);
6503 count = strlen(buf);
6504 outCount = OutputToProcess(NoProc, buf, count, &error);
6505 if (outCount < count) {
6506 DisplayFatalError(_("Error writing to display"), error, 1);
6509 if (continuation) return;
6512 PlaySound(appData.soundShout);
6515 PlaySound(appData.soundSShout);
6518 PlaySound(appData.soundChannel1);
6521 PlaySound(appData.soundChannel);
6524 PlaySound(appData.soundKibitz);
6527 PlaySound(appData.soundTell);
6529 case ColorChallenge:
6530 PlaySound(appData.soundChallenge);
6533 PlaySound(appData.soundRequest);
6536 PlaySound(appData.soundSeek);
6547 return getpwuid(getuid())->pw_name;
6550 static char *ExpandPathName(path)
6553 static char static_buf[2000];
6554 char *d, *s, buf[2000];
6560 while (*s && isspace(*s))
6569 if (*(s+1) == '/') {
6570 strcpy(d, getpwuid(getuid())->pw_dir);
6575 *strchr(buf, '/') = 0;
6576 pwd = getpwnam(buf);
6579 fprintf(stderr, _("ERROR: Unknown user %s (in path %s)\n"),
6583 strcpy(d, pwd->pw_dir);
6584 strcat(d, strchr(s+1, '/'));
6595 static char host_name[MSG_SIZ];
6597 #if HAVE_GETHOSTNAME
6598 gethostname(host_name, MSG_SIZ);
6600 #else /* not HAVE_GETHOSTNAME */
6601 # if HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H
6602 sysinfo(SI_HOSTNAME, host_name, MSG_SIZ);
6604 # else /* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
6606 # endif/* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
6607 #endif /* not HAVE_GETHOSTNAME */
6610 gint delayedEventTimerTag = 0;
6611 DelayedEventCallback delayedEventCallback = 0;
6614 FireDelayedEvent(data)
6617 delayedEventTimerTag = 0;
6618 delayedEventCallback();
6622 ScheduleDelayedEvent(cb, millisec)
6623 DelayedEventCallback cb; long millisec;
6625 delayedEventCallback = cb;
6626 delayedEventTimerTag = gtk_timeout_add(millisec,(GtkFunction) FireDelayedEvent, NULL);
6629 DelayedEventCallback
6632 if (delayedEventTimerTag)
6634 return delayedEventCallback;
6643 CancelDelayedEvent()
6645 if (delayedEventTimerTag)
6647 gtk_timeout_remove(delayedEventTimerTag);
6648 delayedEventTimerTag = 0;
6654 gint loadGameTimerTag = 0;
6656 int LoadGameTimerRunning()
6658 return loadGameTimerTag != 0;
6661 int StopLoadGameTimer()
6663 if (loadGameTimerTag != 0) {
6664 gtk_timeout_remove(loadGameTimerTag);
6665 loadGameTimerTag = 0;
6673 LoadGameTimerCallback(data)
6676 loadGameTimerTag = 0;
6681 StartLoadGameTimer(millisec)
6685 gtk_timeout_add( millisec, (GtkFunction) LoadGameTimerCallback, NULL);
6688 gint analysisClockTag = 0;
6691 AnalysisClockCallback(data)
6694 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile
6695 || appData.icsEngineAnalyze)
6697 AnalysisPeriodicEvent(0);
6698 StartAnalysisClock();
6703 StartAnalysisClock()
6706 gtk_timeout_add( 2000,(GtkFunction) AnalysisClockCallback, NULL);
6709 gint clockTimerTag = 0;
6711 int ClockTimerRunning()
6713 return clockTimerTag != 0;
6716 int StopClockTimer()
6718 if (clockTimerTag != 0)
6720 gtk_timeout_remove(clockTimerTag);
6731 ClockTimerCallback(data)
6740 StartClockTimer(millisec)
6743 clockTimerTag = gtk_timeout_add(millisec,(GtkFunction) ClockTimerCallback,NULL);
6748 DisplayTimerLabel(w, color, timer, highlight)
6757 if (appData.clockMode) {
6758 sprintf(buf, "%s: %s", color, TimeString(timer));
6760 sprintf(buf, "%s ", color);
6762 gtk_label_set_text(GTK_LABEL(w),buf);
6764 /* check for low time warning */
6765 // Pixel foregroundOrWarningColor = timerForegroundPixel;
6768 // appData.lowTimeWarning &&
6769 // (timer / 1000) < appData.icsAlarmTime)
6770 // foregroundOrWarningColor = lowTimeWarningColor;
6772 // if (appData.clockMode) {
6773 // sprintf(buf, "%s: %s", color, TimeString(timer));
6774 // XtSetArg(args[0], XtNlabel, buf);
6776 // sprintf(buf, "%s ", color);
6777 // XtSetArg(args[0], XtNlabel, buf);
6782 // XtSetArg(args[1], XtNbackground, foregroundOrWarningColor);
6783 // XtSetArg(args[2], XtNforeground, timerBackgroundPixel);
6785 // XtSetArg(args[1], XtNbackground, timerBackgroundPixel);
6786 // XtSetArg(args[2], XtNforeground, foregroundOrWarningColor);
6789 // XtSetValues(w, args, 3);
6794 DisplayWhiteClock(timeRemaining, highlight)
6798 if(appData.noGUI) return;
6800 DisplayTimerLabel(GUI_Whiteclock, _("White"), timeRemaining, highlight);
6801 if (highlight && WindowIcon == BlackIcon)
6803 WindowIcon = WhiteIcon;
6804 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
6809 DisplayBlackClock(timeRemaining, highlight)
6813 if(appData.noGUI) return;
6815 DisplayTimerLabel(GUI_Blackclock, _("Black"), timeRemaining, highlight);
6816 if (highlight && WindowIcon == WhiteIcon)
6818 WindowIcon = BlackIcon;
6819 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
6837 int StartChildProcess(cmdLine, dir, pr)
6844 int to_prog[2], from_prog[2];
6848 if (appData.debugMode) {
6849 fprintf(stderr, "StartChildProcess (dir=\"%s\") %s\n",dir, cmdLine);
6852 /* We do NOT feed the cmdLine to the shell; we just
6853 parse it into blank-separated arguments in the
6854 most simple-minded way possible.
6857 strcpy(buf, cmdLine);
6862 if (p == NULL) break;
6867 SetUpChildIO(to_prog, from_prog);
6869 if ((pid = fork()) == 0) {
6871 // [HGM] PSWBTM: made order resistant against case where fd of created pipe was 0 or 1
6872 close(to_prog[1]); // first close the unused pipe ends
6873 close(from_prog[0]);
6874 dup2(to_prog[0], 0); // to_prog was created first, nd is the only one to use 0 or 1
6875 dup2(from_prog[1], 1);
6876 if(to_prog[0] >= 2) close(to_prog[0]); // if 0 or 1, the dup2 already cosed the original
6877 close(from_prog[1]); // and closing again loses one of the pipes!
6878 if(fileno(stderr) >= 2) // better safe than sorry...
6879 dup2(1, fileno(stderr)); /* force stderr to the pipe */
6881 if (dir[0] != NULLCHAR && chdir(dir) != 0) {
6886 nice(appData.niceEngines); // [HGM] nice: adjust priority of engine proc
6888 execvp(argv[0], argv);
6890 /* If we get here, exec failed */
6895 /* Parent process */
6897 close(from_prog[1]);
6899 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
6902 cp->fdFrom = from_prog[0];
6903 cp->fdTo = to_prog[1];
6908 // [HGM] kill: implement the 'hard killing' of AS's Winboard_x
6909 static RETSIGTYPE AlarmCallBack(int n)
6915 DestroyChildProcess(pr, signalType)
6919 ChildProc *cp = (ChildProc *) pr;
6921 if (cp->kind != CPReal) return;
6923 if (signalType == 10) { // [HGM] kill: if it does not terminate in 3 sec, kill
6924 signal(SIGALRM, AlarmCallBack);
6926 if(wait((int *) 0) == -1) { // process does not terminate on its own accord
6927 kill(cp->pid, SIGKILL); // kill it forcefully
6928 wait((int *) 0); // and wait again
6932 kill(cp->pid, signalType == 9 ? SIGKILL : SIGTERM); // [HGM] kill: use hard kill if so requested
6934 /* Process is exiting either because of the kill or because of
6935 a quit command sent by the backend; either way, wait for it to die.
6944 InterruptChildProcess(pr)
6947 ChildProc *cp = (ChildProc *) pr;
6949 if (cp->kind != CPReal) return;
6950 (void) kill(cp->pid, SIGINT); /* stop it thinking */
6953 int OpenTelnet(host, port, pr)
6958 char cmdLine[MSG_SIZ];
6960 if (port[0] == NULLCHAR) {
6961 snprintf(cmdLine, sizeof(cmdLine), "%s %s", appData.telnetProgram, host);
6963 snprintf(cmdLine, sizeof(cmdLine), "%s %s %s", appData.telnetProgram, host, port);
6965 return StartChildProcess(cmdLine, "", pr);
6968 int OpenTCP(host, port, pr)
6974 DisplayFatalError(_("Socket support is not configured in"), 0, 2);
6975 #else /* !OMIT_SOCKETS */
6977 struct sockaddr_in sa;
6979 unsigned short uport;
6982 if ((s = socket(AF_INET, SOCK_STREAM, 6)) < 0) {
6986 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
6987 sa.sin_family = AF_INET;
6988 sa.sin_addr.s_addr = INADDR_ANY;
6989 uport = (unsigned short) 0;
6990 sa.sin_port = htons(uport);
6991 if (bind(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)) < 0) {
6995 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
6996 if (!(hp = gethostbyname(host))) {
6998 if (sscanf(host, "%d.%d.%d.%d", &b0, &b1, &b2, &b3) == 4) {
6999 hp = (struct hostent *) calloc(1, sizeof(struct hostent));
7000 hp->h_addrtype = AF_INET;
7002 hp->h_addr_list = (char **) calloc(2, sizeof(char *));
7003 hp->h_addr_list[0] = (char *) malloc(4);
7004 hp->h_addr_list[0][0] = b0;
7005 hp->h_addr_list[0][1] = b1;
7006 hp->h_addr_list[0][2] = b2;
7007 hp->h_addr_list[0][3] = b3;
7012 sa.sin_family = hp->h_addrtype;
7013 uport = (unsigned short) atoi(port);
7014 sa.sin_port = htons(uport);
7015 memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);
7017 if (connect(s, (struct sockaddr *) &sa,
7018 sizeof(struct sockaddr_in)) < 0) {
7022 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7029 #endif /* !OMIT_SOCKETS */
7034 int OpenCommPort(name, pr)
7041 fd = open(name, 2, 0);
7042 if (fd < 0) return errno;
7044 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7054 int OpenLoopback(pr)
7060 SetUpChildIO(to, from);
7062 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7065 cp->fdFrom = to[0]; /* note not from[0]; we are doing a loopback */
7072 int OpenRcmd(host, user, cmd, pr)
7073 char *host, *user, *cmd;
7076 DisplayFatalError(_("internal rcmd not implemented for Unix"), 0, 1);
7080 #define INPUT_SOURCE_BUF_SIZE 8192
7089 char buf[INPUT_SOURCE_BUF_SIZE];
7094 DoInputCallback(closure, source, xid)
7099 InputSource *is = (InputSource *) closure;
7104 if (is->lineByLine) {
7105 count = read(is->fd, is->unused,
7106 INPUT_SOURCE_BUF_SIZE - (is->unused - is->buf));
7108 (is->func)(is, is->closure, is->buf, count, count ? errno : 0);
7111 is->unused += count;
7113 while (p < is->unused) {
7114 q = memchr(p, '\n', is->unused - p);
7115 if (q == NULL) break;
7117 (is->func)(is, is->closure, p, q - p, 0);
7121 while (p < is->unused) {
7126 count = read(is->fd, is->buf, INPUT_SOURCE_BUF_SIZE);
7131 (is->func)(is, is->closure, is->buf, count, error);
7135 InputSourceRef AddInputSource(pr, lineByLine, func, closure)
7142 ChildProc *cp = (ChildProc *) pr;
7144 is = (InputSource *) calloc(1, sizeof(InputSource));
7145 is->lineByLine = lineByLine;
7149 is->fd = fileno(stdin);
7151 is->kind = cp->kind;
7152 is->fd = cp->fdFrom;
7155 is->unused = is->buf;
7158 is->xid = XtAppAddInput(appContext, is->fd,
7159 (XtPointer) (XtInputReadMask),
7160 (XtInputCallbackProc) DoInputCallback,
7162 is->closure = closure;
7163 return (InputSourceRef) is;
7167 RemoveInputSource(isr)
7170 InputSource *is = (InputSource *) isr;
7172 if (is->xid == 0) return;
7173 XtRemoveInput(is->xid);
7177 int OutputToProcess(pr, message, count, outError)
7183 ChildProc *cp = (ChildProc *) pr;
7187 outCount = fwrite(message, 1, count, stdout);
7189 outCount = write(cp->fdTo, message, count);
7199 /* Output message to process, with "ms" milliseconds of delay
7200 between each character. This is needed when sending the logon
7201 script to ICC, which for some reason doesn't like the
7202 instantaneous send. */
7203 int OutputToProcessDelayed(pr, message, count, outError, msdelay)
7210 ChildProc *cp = (ChildProc *) pr;
7215 r = write(cp->fdTo, message++, 1);
7228 /**** Animation code by Hugh Fisher, DCS, ANU.
7230 Known problem: if a window overlapping the board is
7231 moved away while a piece is being animated underneath,
7232 the newly exposed area won't be updated properly.
7233 I can live with this.
7235 Known problem: if you look carefully at the animation
7236 of pieces in mono mode, they are being drawn as solid
7237 shapes without interior detail while moving. Fixing
7238 this would be a major complication for minimal return.
7241 /* Masks for XPM pieces. Black and white pieces can have
7242 different shapes, but in the interest of retaining my
7243 sanity pieces must have the same outline on both light
7244 and dark squares, and all pieces must use the same
7245 background square colors/images. */
7247 static int xpmDone = 0;
7250 CreateAnimMasks (pieceDepth)
7257 unsigned long plane;
7260 /* just return for gtk at the moment */
7263 /* Need a bitmap just to get a GC with right depth */
7264 buf = XCreatePixmap(xDisplay, xBoardWindow,
7266 values.foreground = 1;
7267 values.background = 0;
7268 /* Don't use XtGetGC, not read only */
7269 maskGC = XCreateGC(xDisplay, buf,
7270 GCForeground | GCBackground, &values);
7271 XFreePixmap(xDisplay, buf);
7273 buf = XCreatePixmap(xDisplay, xBoardWindow,
7274 squareSize, squareSize, pieceDepth);
7275 values.foreground = XBlackPixel(xDisplay, xScreen);
7276 values.background = XWhitePixel(xDisplay, xScreen);
7277 bufGC = XCreateGC(xDisplay, buf,
7278 GCForeground | GCBackground, &values);
7280 for (piece = WhitePawn; piece <= BlackKing; piece++) {
7281 /* Begin with empty mask */
7282 if(!xpmDone) // [HGM] pieces: keep using existing
7283 xpmMask[piece] = XCreatePixmap(xDisplay, xBoardWindow,
7284 squareSize, squareSize, 1);
7285 XSetFunction(xDisplay, maskGC, GXclear);
7286 XFillRectangle(xDisplay, xpmMask[piece], maskGC,
7287 0, 0, squareSize, squareSize);
7289 /* Take a copy of the piece */
7294 XSetFunction(xDisplay, bufGC, GXcopy);
7295 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn],
7297 0, 0, squareSize, squareSize, 0, 0);
7299 /* XOR the background (light) over the piece */
7300 XSetFunction(xDisplay, bufGC, GXxor);
7302 XCopyArea(xDisplay, xpmLightSquare, buf, bufGC,
7303 0, 0, squareSize, squareSize, 0, 0);
7305 XSetForeground(xDisplay, bufGC, lightSquareColor);
7306 XFillRectangle(xDisplay, buf, bufGC, 0, 0, squareSize, squareSize);
7309 /* We now have an inverted piece image with the background
7310 erased. Construct mask by just selecting all the non-zero
7311 pixels - no need to reconstruct the original image. */
7312 XSetFunction(xDisplay, maskGC, GXor);
7314 /* Might be quicker to download an XImage and create bitmap
7315 data from it rather than this N copies per piece, but it
7316 only takes a fraction of a second and there is a much
7317 longer delay for loading the pieces. */
7318 for (n = 0; n < pieceDepth; n ++) {
7319 XCopyPlane(xDisplay, buf, xpmMask[piece], maskGC,
7320 0, 0, squareSize, squareSize,
7326 XFreePixmap(xDisplay, buf);
7327 XFreeGC(xDisplay, bufGC);
7328 XFreeGC(xDisplay, maskGC);
7332 InitAnimState (anim, info)
7334 XWindowAttributes * info;
7339 /* Each buffer is square size, same depth as window */
7340 // anim->saveBuf = XCreatePixmap(xDisplay, xBoardWindow,
7341 // squareSize, squareSize, info->depth);
7342 // anim->newBuf = XCreatePixmap(xDisplay, xBoardWindow,
7343 // squareSize, squareSize, info->depth);
7345 // /* Create a plain GC for blitting */
7346 // mask = GCForeground | GCBackground | GCFunction |
7347 // GCPlaneMask | GCGraphicsExposures;
7348 // values.foreground = XBlackPixel(xDisplay, xScreen);
7349 // values.background = XWhitePixel(xDisplay, xScreen);
7350 // values.function = GXcopy;
7351 // values.plane_mask = AllPlanes;
7352 // values.graphics_exposures = False;
7353 // anim->blitGC = XCreateGC(xDisplay, xBoardWindow, mask, &values);
7355 // /* Piece will be copied from an existing context at
7356 // the start of each new animation/drag. */
7357 // anim->pieceGC = XCreateGC(xDisplay, xBoardWindow, 0, &values);
7359 // /* Outline will be a read-only copy of an existing */
7360 // anim->outlineGC = None;
7366 static VariantClass old = (VariantClass) -1; // [HGM] pieces: redo every time variant changes
7367 XWindowAttributes info;
7369 /* for gtk at the moment just ... */
7372 if (xpmDone && gameInfo.variant == old) return;
7373 if(xpmDone) old = gameInfo.variant; // first time pieces might not be created yet
7374 // XGetWindowAttributes(xDisplay, xBoardWindow, &info);
7376 // InitAnimState(&game, &info);
7377 // InitAnimState(&player, &info);
7379 /* For XPM pieces, we need bitmaps to use as masks. */
7381 // CreateAnimMasks(info.depth);
7387 static Boolean frameWaiting;
7389 static RETSIGTYPE FrameAlarm (sig)
7392 frameWaiting = False;
7393 /* In case System-V style signals. Needed?? */
7394 signal(SIGALRM, FrameAlarm);
7401 struct itimerval delay;
7403 XSync(xDisplay, False);
7406 frameWaiting = True;
7407 signal(SIGALRM, FrameAlarm);
7408 delay.it_interval.tv_sec =
7409 delay.it_value.tv_sec = time / 1000;
7410 delay.it_interval.tv_usec =
7411 delay.it_value.tv_usec = (time % 1000) * 1000;
7412 setitimer(ITIMER_REAL, &delay, NULL);
7414 /* Ugh -- busy-wait! --tpm */
7415 while (frameWaiting);
7417 while (frameWaiting) pause();
7419 delay.it_interval.tv_sec = delay.it_value.tv_sec = 0;
7420 delay.it_interval.tv_usec = delay.it_value.tv_usec = 0;
7421 setitimer(ITIMER_REAL, &delay, NULL);
7431 // XSync(xDisplay, False);
7433 usleep(time * 1000);
7438 /* Convert board position to corner of screen rect and color */
7441 ScreenSquare(column, row, pt, color)
7442 int column; int row; XPoint * pt; int * color;
7445 pt->x = lineGap + ((BOARD_WIDTH-1)-column) * (squareSize + lineGap);
7446 pt->y = lineGap + row * (squareSize + lineGap);
7448 pt->x = lineGap + column * (squareSize + lineGap);
7449 pt->y = lineGap + ((BOARD_HEIGHT-1)-row) * (squareSize + lineGap);
7451 *color = SquareColor(row, column);
7454 /* Convert window coords to square */
7457 BoardSquare(x, y, column, row)
7458 int x; int y; int * column; int * row;
7460 *column = EventToSquare(x, BOARD_WIDTH);
7461 if (flipView && *column >= 0)
7462 *column = BOARD_WIDTH - 1 - *column;
7463 *row = EventToSquare(y, BOARD_HEIGHT);
7464 if (!flipView && *row >= 0)
7465 *row = BOARD_HEIGHT - 1 - *row;
7470 #undef Max /* just in case */
7472 #define Max(a, b) ((a) > (b) ? (a) : (b))
7473 #define Min(a, b) ((a) < (b) ? (a) : (b))
7476 SetRect(rect, x, y, width, height)
7477 XRectangle * rect; int x; int y; int width; int height;
7481 rect->width = width;
7482 rect->height = height;
7485 /* Test if two frames overlap. If they do, return
7486 intersection rect within old and location of
7487 that rect within new. */
7490 Intersect(old, new, size, area, pt)
7491 XPoint * old; XPoint * new;
7492 int size; XRectangle * area; XPoint * pt;
7494 if (old->x > new->x + size || new->x > old->x + size ||
7495 old->y > new->y + size || new->y > old->y + size) {
7498 SetRect(area, Max(new->x - old->x, 0), Max(new->y - old->y, 0),
7499 size - abs(old->x - new->x), size - abs(old->y - new->y));
7500 pt->x = Max(old->x - new->x, 0);
7501 pt->y = Max(old->y - new->y, 0);
7506 /* For two overlapping frames, return the rect(s)
7507 in the old that do not intersect with the new. */
7510 CalcUpdateRects(old, new, size, update, nUpdates)
7511 XPoint * old; XPoint * new; int size;
7512 XRectangle update[]; int * nUpdates;
7516 /* If old = new (shouldn't happen) then nothing to draw */
7517 if (old->x == new->x && old->y == new->y) {
7521 /* Work out what bits overlap. Since we know the rects
7522 are the same size we don't need a full intersect calc. */
7524 /* Top or bottom edge? */
7525 if (new->y > old->y) {
7526 SetRect(&(update[count]), old->x, old->y, size, new->y - old->y);
7528 } else if (old->y > new->y) {
7529 SetRect(&(update[count]), old->x, old->y + size - (old->y - new->y),
7530 size, old->y - new->y);
7533 /* Left or right edge - don't overlap any update calculated above. */
7534 if (new->x > old->x) {
7535 SetRect(&(update[count]), old->x, Max(new->y, old->y),
7536 new->x - old->x, size - abs(new->y - old->y));
7538 } else if (old->x > new->x) {
7539 SetRect(&(update[count]), new->x + size, Max(new->y, old->y),
7540 old->x - new->x, size - abs(new->y - old->y));
7547 /* Generate a series of frame coords from start->mid->finish.
7548 The movement rate doubles until the half way point is
7549 reached, then halves back down to the final destination,
7550 which gives a nice slow in/out effect. The algorithmn
7551 may seem to generate too many intermediates for short
7552 moves, but remember that the purpose is to attract the
7553 viewers attention to the piece about to be moved and
7554 then to where it ends up. Too few frames would be less
7558 Tween(start, mid, finish, factor, frames, nFrames)
7559 XPoint * start; XPoint * mid;
7560 XPoint * finish; int factor;
7561 XPoint frames[]; int * nFrames;
7563 int fraction, n, count;
7567 /* Slow in, stepping 1/16th, then 1/8th, ... */
7569 for (n = 0; n < factor; n++)
7571 for (n = 0; n < factor; n++) {
7572 frames[count].x = start->x + (mid->x - start->x) / fraction;
7573 frames[count].y = start->y + (mid->y - start->y) / fraction;
7575 fraction = fraction / 2;
7579 frames[count] = *mid;
7582 /* Slow out, stepping 1/2, then 1/4, ... */
7584 for (n = 0; n < factor; n++) {
7585 frames[count].x = finish->x - (finish->x - mid->x) / fraction;
7586 frames[count].y = finish->y - (finish->y - mid->y) / fraction;
7588 fraction = fraction * 2;
7593 /* Draw a piece on the screen without disturbing what's there */
7596 SelectGCMask(piece, clip, outline, mask)
7597 ChessSquare piece; GC * clip; GC * outline; Pixmap * mask;
7601 /* Bitmap for piece being moved. */
7602 if (appData.monoMode) {
7603 *mask = *pieceToSolid(piece);
7604 } else if (useImages) {
7606 *mask = xpmMask[piece];
7608 *mask = ximMaskPm[piece];
7611 *mask = *pieceToSolid(piece);
7614 /* GC for piece being moved. Square color doesn't matter, but
7615 since it gets modified we make a copy of the original. */
7617 if (appData.monoMode)
7622 if (appData.monoMode)
7627 // XCopyGC(xDisplay, source, 0xFFFFFFFF, *clip);
7629 /* Outline only used in mono mode and is not modified */
7631 *outline = bwPieceGC;
7633 *outline = wbPieceGC;
7637 OverlayPiece(piece, clip, outline, dest)
7638 ChessSquare piece; GC clip; GC outline; Drawable dest;
7643 /* Draw solid rectangle which will be clipped to shape of piece */
7644 // XFillRectangle(xDisplay, dest, clip,
7645 // 0, 0, squareSize, squareSize)
7647 if (appData.monoMode)
7648 /* Also draw outline in contrasting color for black
7649 on black / white on white cases */
7650 // XCopyPlane(xDisplay, *pieceToOutline(piece), dest, outline,
7651 // 0, 0, squareSize, squareSize, 0, 0, 1)
7654 /* Copy the piece */
7659 // XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
7661 // 0, 0, squareSize, squareSize,
7666 /* Animate the movement of a single piece */
7669 BeginAnimation(anim, piece, startColor, start)
7677 /* The old buffer is initialised with the start square (empty) */
7678 BlankSquare(0, 0, startColor, EmptySquare, anim->saveBuf);
7679 anim->prevFrame = *start;
7681 /* The piece will be drawn using its own bitmap as a matte */
7682 // SelectGCMask(piece, &anim->pieceGC, &anim->outlineGC, &mask);
7683 // XSetClipMask(xDisplay, anim->pieceGC, mask);
7687 AnimationFrame(anim, frame, piece)
7692 XRectangle updates[4];
7697 /* Save what we are about to draw into the new buffer */
7698 // XCopyArea(xDisplay, xBoardWindow, anim->newBuf, anim->blitGC,
7699 // frame->x, frame->y, squareSize, squareSize,
7702 /* Erase bits of the previous frame */
7703 if (Intersect(&anim->prevFrame, frame, squareSize, &overlap, &pt)) {
7704 /* Where the new frame overlapped the previous,
7705 the contents in newBuf are wrong. */
7706 // XCopyArea(xDisplay, anim->saveBuf, anim->newBuf, anim->blitGC,
7707 // overlap.x, overlap.y,
7708 // overlap.width, overlap.height,
7710 /* Repaint the areas in the old that don't overlap new */
7711 CalcUpdateRects(&anim->prevFrame, frame, squareSize, updates, &count);
7712 for (i = 0; i < count; i++)
7713 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
7714 // updates[i].x - anim->prevFrame.x,
7715 // updates[i].y - anim->prevFrame.y,
7716 // updates[i].width, updates[i].height,
7717 // updates[i].x, updates[i].y)
7720 /* Easy when no overlap */
7721 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
7722 // 0, 0, squareSize, squareSize,
7723 // anim->prevFrame.x, anim->prevFrame.y);
7726 /* Save this frame for next time round */
7727 // XCopyArea(xDisplay, anim->newBuf, anim->saveBuf, anim->blitGC,
7728 // 0, 0, squareSize, squareSize,
7730 anim->prevFrame = *frame;
7732 /* Draw piece over original screen contents, not current,
7733 and copy entire rect. Wipes out overlapping piece images. */
7734 OverlayPiece(piece, anim->pieceGC, anim->outlineGC, anim->newBuf);
7735 // XCopyArea(xDisplay, anim->newBuf, xBoardWindow, anim->blitGC,
7736 // 0, 0, squareSize, squareSize,
7737 // frame->x, frame->y);
7741 EndAnimation (anim, finish)
7745 XRectangle updates[4];
7750 /* The main code will redraw the final square, so we
7751 only need to erase the bits that don't overlap. */
7752 if (Intersect(&anim->prevFrame, finish, squareSize, &overlap, &pt)) {
7753 CalcUpdateRects(&anim->prevFrame, finish, squareSize, updates, &count);
7754 for (i = 0; i < count; i++)
7755 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
7756 // updates[i].x - anim->prevFrame.x,
7757 // updates[i].y - anim->prevFrame.y,
7758 // updates[i].width, updates[i].height,
7759 // updates[i].x, updates[i].y)
7762 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
7763 // 0, 0, squareSize, squareSize,
7764 // anim->prevFrame.x, anim->prevFrame.y);
7769 FrameSequence(anim, piece, startColor, start, finish, frames, nFrames)
7771 ChessSquare piece; int startColor;
7772 XPoint * start; XPoint * finish;
7773 XPoint frames[]; int nFrames;
7777 BeginAnimation(anim, piece, startColor, start);
7778 for (n = 0; n < nFrames; n++) {
7779 AnimationFrame(anim, &(frames[n]), piece);
7780 FrameDelay(appData.animSpeed);
7782 EndAnimation(anim, finish);
7785 /* Main control logic for deciding what to animate and how */
7788 AnimateMove(board, fromX, fromY, toX, toY)
7797 XPoint start, finish, mid;
7798 XPoint frames[kFactor * 2 + 1];
7799 int nFrames, startColor, endColor;
7801 /* Are we animating? */
7802 if (!appData.animate || appData.blindfold)
7805 if(board[toY][toX] == WhiteRook && board[fromY][fromX] == WhiteKing ||
7806 board[toY][toX] == BlackRook && board[fromY][fromX] == BlackKing)
7807 return; // [HGM] FRC: no animtion of FRC castlings, as to-square is not true to-square
7809 if (fromY < 0 || fromX < 0 || toX < 0 || toY < 0) return;
7810 piece = board[fromY][fromX];
7811 if (piece >= EmptySquare) return;
7816 hop = (piece == WhiteKnight || piece == BlackKnight);
7819 if (appData.debugMode) {
7820 fprintf(debugFP, hop ? _("AnimateMove: piece %d hops from %d,%d to %d,%d \n") :
7821 _("AnimateMove: piece %d slides from %d,%d to %d,%d \n"),
7822 piece, fromX, fromY, toX, toY); }
7824 ScreenSquare(fromX, fromY, &start, &startColor);
7825 ScreenSquare(toX, toY, &finish, &endColor);
7828 /* Knight: make diagonal movement then straight */
7829 if (abs(toY - fromY) < abs(toX - fromX)) {
7830 mid.x = start.x + (finish.x - start.x) / 2;
7834 mid.y = start.y + (finish.y - start.y) / 2;
7837 mid.x = start.x + (finish.x - start.x) / 2;
7838 mid.y = start.y + (finish.y - start.y) / 2;
7841 /* Don't use as many frames for very short moves */
7842 if (abs(toY - fromY) + abs(toX - fromX) <= 2)
7843 Tween(&start, &mid, &finish, kFactor - 1, frames, &nFrames);
7845 Tween(&start, &mid, &finish, kFactor, frames, &nFrames);
7846 FrameSequence(&game, piece, startColor, &start, &finish, frames, nFrames);
7848 /* Be sure end square is redrawn */
7849 damage[toY][toX] = True;
7853 DragPieceBegin(x, y)
7856 int boardX, boardY, color;
7859 /* Are we animating? */
7860 if (!appData.animateDragging || appData.blindfold)
7863 /* Figure out which square we start in and the
7864 mouse position relative to top left corner. */
7865 BoardSquare(x, y, &boardX, &boardY);
7866 player.startBoardX = boardX;
7867 player.startBoardY = boardY;
7868 ScreenSquare(boardX, boardY, &corner, &color);
7869 player.startSquare = corner;
7870 player.startColor = color;
7872 /* Start from exactly where the piece is. This can be confusing
7873 if you start dragging far from the center of the square; most
7874 or all of the piece can be over a different square from the one
7875 the mouse pointer is in. */
7876 player.mouseDelta.x = x - corner.x;
7877 player.mouseDelta.y = y - corner.y;
7879 /* As soon as we start dragging, the piece will jump slightly to
7880 be centered over the mouse pointer. */
7881 player.mouseDelta.x = squareSize/2;
7882 player.mouseDelta.y = squareSize/2;
7884 /* Initialise animation */
7885 player.dragPiece = PieceForSquare(boardX, boardY);
7887 if (player.dragPiece >= 0 && player.dragPiece < EmptySquare) {
7888 player.dragActive = True;
7889 BeginAnimation(&player, player.dragPiece, color, &corner);
7890 /* Mark this square as needing to be redrawn. Note that
7891 we don't remove the piece though, since logically (ie
7892 as seen by opponent) the move hasn't been made yet. */
7893 if(boardX == BOARD_RGHT+1 && PieceForSquare(boardX-1, boardY) > 1 ||
7894 boardX == BOARD_LEFT-2 && PieceForSquare(boardX+1, boardY) > 1)
7895 // XCopyArea(xDisplay, xBoardWindow, player.saveBuf, player.blitGC,
7896 // corner.x, corner.y, squareSize, squareSize,
7897 // 0, 0); // [HGM] zh: unstack in stead of grab
7898 damage[boardY][boardX] = True;
7900 player.dragActive = False;
7910 /* Are we animating? */
7911 if (!appData.animateDragging || appData.blindfold)
7915 if (! player.dragActive)
7917 /* Move piece, maintaining same relative position
7918 of mouse within square */
7919 corner.x = x - player.mouseDelta.x;
7920 corner.y = y - player.mouseDelta.y;
7921 AnimationFrame(&player, &corner, player.dragPiece);
7923 if (appData.highlightDragging) {
7925 BoardSquare(x, y, &boardX, &boardY);
7926 SetHighlights(fromX, fromY, boardX, boardY);
7935 int boardX, boardY, color;
7938 /* Are we animating? */
7939 if (!appData.animateDragging || appData.blindfold)
7943 if (! player.dragActive)
7945 /* Last frame in sequence is square piece is
7946 placed on, which may not match mouse exactly. */
7947 BoardSquare(x, y, &boardX, &boardY);
7948 ScreenSquare(boardX, boardY, &corner, &color);
7949 EndAnimation(&player, &corner);
7951 /* Be sure end square is redrawn */
7952 damage[boardY][boardX] = True;
7954 /* This prevents weird things happening with fast successive
7955 clicks which on my Sun at least can cause motion events
7956 without corresponding press/release. */
7957 player.dragActive = False;
7960 /* Handle expose event while piece being dragged */
7965 if (!player.dragActive || appData.blindfold)
7968 /* What we're doing: logically, the move hasn't been made yet,
7969 so the piece is still in it's original square. But visually
7970 it's being dragged around the board. So we erase the square
7971 that the piece is on and draw it at the last known drag point. */
7972 BlankSquare(player.startSquare.x, player.startSquare.y,
7973 player.startColor, EmptySquare, xBoardWindow);
7974 AnimationFrame(&player, &player.prevFrame, player.dragPiece);
7975 damage[player.startBoardY][player.startBoardX] = TRUE;
7979 SetProgramStats( FrontEndProgramStats * stats )
7982 // [HGM] done, but perhaps backend should call this directly?
7983 EngineOutputUpdate( stats );