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 { "adjudicateDrawMoves", "adjudicateDrawMoves", XtRInt,
1261 sizeof(int), XtOffset(AppDataPtr, adjudicateDrawMoves),
1262 XtRImmediate, (XtPointer) 0},
1263 { "pgnEventHeader", "pgnEventHeader", XtRString,
1264 sizeof(String), XtOffset(AppDataPtr, pgnEventHeader),
1265 XtRImmediate, (XtPointer) "Computer Chess Game" },
1266 { "defaultFrcPosition", "defaultFrcPositon", XtRInt,
1267 sizeof(int), XtOffset(AppDataPtr, defaultFrcPosition),
1268 XtRImmediate, (XtPointer) -1},
1269 { "gameListTags", "gameListTags", XtRString,
1270 sizeof(String), XtOffset(AppDataPtr, gameListTags),
1271 XtRImmediate, (XtPointer) GLT_DEFAULT_TAGS },
1273 // [HGM] 4.3.xx options
1274 { "boardWidth", "boardWidth", XtRInt,
1275 sizeof(int), XtOffset(AppDataPtr, NrFiles),
1276 XtRImmediate, (XtPointer) -1},
1277 { "boardHeight", "boardHeight", XtRInt,
1278 sizeof(int), XtOffset(AppDataPtr, NrRanks),
1279 XtRImmediate, (XtPointer) -1},
1280 { "matchPause", "matchPause", XtRInt,
1281 sizeof(int), XtOffset(AppDataPtr, matchPause),
1282 XtRImmediate, (XtPointer) 10000},
1283 { "holdingsSize", "holdingsSize", XtRInt,
1284 sizeof(int), XtOffset(AppDataPtr, holdingsSize),
1285 XtRImmediate, (XtPointer) -1},
1286 { "flipBlack", "flipBlack", XtRBoolean,
1287 sizeof(Boolean), XtOffset(AppDataPtr, upsideDown),
1288 XtRImmediate, (XtPointer) False},
1289 { "allWhite", "allWhite", XtRBoolean,
1290 sizeof(Boolean), XtOffset(AppDataPtr, allWhite),
1291 XtRImmediate, (XtPointer) False},
1292 { "pieceToCharTable", "pieceToCharTable", XtRString,
1293 sizeof(String), XtOffset(AppDataPtr, pieceToCharTable),
1294 XtRImmediate, (XtPointer) 0},
1295 { "alphaRank", "alphaRank", XtRBoolean,
1296 sizeof(Boolean), XtOffset(AppDataPtr, alphaRank),
1297 XtRImmediate, (XtPointer) False},
1298 { "testClaims", "testClaims", XtRBoolean,
1299 sizeof(Boolean), XtOffset(AppDataPtr, testClaims),
1300 XtRImmediate, (XtPointer) True},
1301 { "checkMates", "checkMates", XtRBoolean,
1302 sizeof(Boolean), XtOffset(AppDataPtr, checkMates),
1303 XtRImmediate, (XtPointer) True},
1304 { "materialDraws", "materialDraws", XtRBoolean,
1305 sizeof(Boolean), XtOffset(AppDataPtr, materialDraws),
1306 XtRImmediate, (XtPointer) True},
1307 { "trivialDraws", "trivialDraws", XtRBoolean,
1308 sizeof(Boolean), XtOffset(AppDataPtr, trivialDraws),
1309 XtRImmediate, (XtPointer) False},
1310 { "ruleMoves", "ruleMoves", XtRInt,
1311 sizeof(int), XtOffset(AppDataPtr, ruleMoves),
1312 XtRImmediate, (XtPointer) 51},
1313 { "repeatsToDraw", "repeatsToDraw", XtRInt,
1314 sizeof(int), XtOffset(AppDataPtr, drawRepeats),
1315 XtRImmediate, (XtPointer) 6},
1316 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1317 sizeof(int), XtOffset(AppDataPtr, engineComments),
1318 XtRImmediate, (XtPointer) 1},
1319 { "userName", "userName", XtRString,
1320 sizeof(int), XtOffset(AppDataPtr, userName),
1321 XtRImmediate, (XtPointer) 0},
1322 { "autoKibitz", "autoKibitz", XtRBoolean,
1323 sizeof(Boolean), XtOffset(AppDataPtr, autoKibitz),
1324 XtRImmediate, (XtPointer) False},
1325 { "firstTimeOdds", "firstTimeOdds", XtRInt,
1326 sizeof(int), XtOffset(AppDataPtr, firstTimeOdds),
1327 XtRImmediate, (XtPointer) 1},
1328 { "secondTimeOdds", "secondTimeOdds", XtRInt,
1329 sizeof(int), XtOffset(AppDataPtr, secondTimeOdds),
1330 XtRImmediate, (XtPointer) 1},
1331 { "timeOddsMode", "timeOddsMode", XtRInt,
1332 sizeof(int), XtOffset(AppDataPtr, timeOddsMode),
1333 XtRImmediate, (XtPointer) 0},
1334 { "firstAccumulateTC", "firstAccumulateTC", XtRInt,
1335 sizeof(int), XtOffset(AppDataPtr, firstAccumulateTC),
1336 XtRImmediate, (XtPointer) 1},
1337 { "secondAccumulateTC", "secondAccumulateTC", XtRInt,
1338 sizeof(int), XtOffset(AppDataPtr, secondAccumulateTC),
1339 XtRImmediate, (XtPointer) 1},
1340 { "firstNPS", "firstNPS", XtRInt,
1341 sizeof(int), XtOffset(AppDataPtr, firstNPS),
1342 XtRImmediate, (XtPointer) -1},
1343 { "secondNPS", "secondNPS", XtRInt,
1344 sizeof(int), XtOffset(AppDataPtr, secondNPS),
1345 XtRImmediate, (XtPointer) -1},
1346 { "serverMoves", "serverMoves", XtRString,
1347 sizeof(String), XtOffset(AppDataPtr, serverMovesName),
1348 XtRImmediate, (XtPointer) 0},
1349 { "serverPause", "serverPause", XtRInt,
1350 sizeof(int), XtOffset(AppDataPtr, serverPause),
1351 XtRImmediate, (XtPointer) 0},
1352 { "suppressLoadMoves", "suppressLoadMoves", XtRBoolean,
1353 sizeof(Boolean), XtOffset(AppDataPtr, suppressLoadMoves),
1354 XtRImmediate, (XtPointer) False},
1355 { "userName", "userName", XtRString,
1356 sizeof(String), XtOffset(AppDataPtr, userName),
1357 XtRImmediate, (XtPointer) 0},
1358 { "egtFormats", "egtFormats", XtRString,
1359 sizeof(String), XtOffset(AppDataPtr, egtFormats),
1360 XtRImmediate, (XtPointer) 0},
1361 { "rewindIndex", "rewindIndex", XtRInt,
1362 sizeof(int), XtOffset(AppDataPtr, rewindIndex),
1363 XtRImmediate, (XtPointer) 0},
1364 { "sameColorGames", "sameColorGames", XtRInt,
1365 sizeof(int), XtOffset(AppDataPtr, sameColorGames),
1366 XtRImmediate, (XtPointer) 0},
1367 { "smpCores", "smpCores", XtRInt,
1368 sizeof(int), XtOffset(AppDataPtr, smpCores),
1369 XtRImmediate, (XtPointer) 1},
1370 { "niceEngines", "niceEngines", XtRInt,
1371 sizeof(int), XtOffset(AppDataPtr, niceEngines),
1372 XtRImmediate, (XtPointer) 0},
1373 { "nameOfDebugFile", "nameOfDebugFile", XtRString,
1374 sizeof(String), XtOffset(AppDataPtr, nameOfDebugFile),
1375 XtRImmediate, (XtPointer) "xboard.debug"},
1376 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1377 sizeof(int), XtOffset(AppDataPtr, engineComments),
1378 XtRImmediate, (XtPointer) 1},
1379 { "noGUI", "noGUI", XtRBoolean,
1380 sizeof(Boolean), XtOffset(AppDataPtr, noGUI),
1381 XtRImmediate, (XtPointer) 0},
1382 { "firstOptions", "firstOptions", XtRString,
1383 sizeof(String), XtOffset(AppDataPtr, firstOptions),
1384 XtRImmediate, (XtPointer) "" },
1385 { "secondOptions", "secondOptions", XtRString,
1386 sizeof(String), XtOffset(AppDataPtr, secondOptions),
1387 XtRImmediate, (XtPointer) "" },
1388 { "firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XtRString,
1389 sizeof(String), XtOffset(AppDataPtr, fenOverride1),
1390 XtRImmediate, (XtPointer) 0 },
1391 { "secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XtRString,
1392 sizeof(String), XtOffset(AppDataPtr, fenOverride2),
1393 XtRImmediate, (XtPointer) 0 },
1395 // [HGM] Winboard_x UCI options
1396 { "firstIsUCI", "firstIsUCI", XtRBoolean,
1397 sizeof(Boolean), XtOffset(AppDataPtr, firstIsUCI),
1398 XtRImmediate, (XtPointer) False},
1399 { "secondIsUCI", "secondIsUCI", XtRBoolean,
1400 sizeof(Boolean), XtOffset(AppDataPtr, secondIsUCI),
1401 XtRImmediate, (XtPointer) False},
1402 { "firstHasOwnBookUCI", "firstHasOwnBookUCI", XtRBoolean,
1403 sizeof(Boolean), XtOffset(AppDataPtr, firstHasOwnBookUCI),
1404 XtRImmediate, (XtPointer) True},
1405 { "secondHasOwnBookUCI", "secondHasOwnBookUCI", XtRBoolean,
1406 sizeof(Boolean), XtOffset(AppDataPtr, secondHasOwnBookUCI),
1407 XtRImmediate, (XtPointer) True},
1408 { "usePolyglotBook", "usePolyglotBook", XtRBoolean,
1409 sizeof(Boolean), XtOffset(AppDataPtr, usePolyglotBook),
1410 XtRImmediate, (XtPointer) False},
1411 { "defaultHashSize", "defaultHashSize", XtRInt,
1412 sizeof(int), XtOffset(AppDataPtr, defaultHashSize),
1413 XtRImmediate, (XtPointer) 64},
1414 { "defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XtRInt,
1415 sizeof(int), XtOffset(AppDataPtr, defaultCacheSizeEGTB),
1416 XtRImmediate, (XtPointer) 4},
1417 { "polyglotDir", "polyglotDir", XtRString,
1418 sizeof(String), XtOffset(AppDataPtr, polyglotDir),
1419 XtRImmediate, (XtPointer) "." },
1420 { "polyglotBook", "polyglotBook", XtRString,
1421 sizeof(String), XtOffset(AppDataPtr, polyglotBook),
1422 XtRImmediate, (XtPointer) "" },
1423 { "defaultPathEGTB", "defaultPathEGTB", XtRString,
1424 sizeof(String), XtOffset(AppDataPtr, defaultPathEGTB),
1425 XtRImmediate, (XtPointer) "/usr/local/share/egtb"},
1426 { "delayBeforeQuit", "delayBeforeQuit", XtRInt,
1427 sizeof(int), XtOffset(AppDataPtr, delayBeforeQuit),
1428 XtRImmediate, (XtPointer) 0},
1429 { "delayAfterQuit", "delayAfterQuit", XtRInt,
1430 sizeof(int), XtOffset(AppDataPtr, delayAfterQuit),
1431 XtRImmediate, (XtPointer) 0},
1432 { "keepAlive", "keepAlive", XtRInt,
1433 sizeof(int), XtOffset(AppDataPtr, keepAlive),
1434 XtRImmediate, (XtPointer) 0},
1437 XrmOptionDescRec shellOptions[] = {
1438 { "-whitePieceColor", "whitePieceColor", XrmoptionSepArg, NULL },
1439 { "-blackPieceColor", "blackPieceColor", XrmoptionSepArg, NULL },
1440 { "-lightSquareColor", "lightSquareColor", XrmoptionSepArg, NULL },
1441 { "-darkSquareColor", "darkSquareColor", XrmoptionSepArg, NULL },
1442 { "-highlightSquareColor", "highlightSquareColor", XrmoptionSepArg, NULL },
1443 { "-premoveHighlightColor", "premoveHighlightColor", XrmoptionSepArg,NULL},
1444 { "-movesPerSession", "movesPerSession", XrmoptionSepArg, NULL },
1445 { "-mps", "movesPerSession", XrmoptionSepArg, NULL },
1446 { "-timeIncrement", "timeIncrement", XrmoptionSepArg, NULL },
1447 { "-inc", "timeIncrement", XrmoptionSepArg, NULL },
1448 { "-initString", "initString", XrmoptionSepArg, NULL },
1449 { "-firstInitString", "initString", XrmoptionSepArg, NULL },
1450 { "-secondInitString", "secondInitString", XrmoptionSepArg, NULL },
1451 { "-firstComputerString", "firstComputerString", XrmoptionSepArg, NULL },
1452 { "-secondComputerString", "secondComputerString", XrmoptionSepArg, NULL },
1453 { "-firstChessProgram", "firstChessProgram", XrmoptionSepArg, NULL },
1454 { "-fcp", "firstChessProgram", XrmoptionSepArg, NULL },
1455 { "-secondChessProgram", "secondChessProgram", XrmoptionSepArg, NULL },
1456 { "-scp", "secondChessProgram", XrmoptionSepArg, NULL },
1457 { "-firstPlaysBlack", "firstPlaysBlack", XrmoptionSepArg, NULL },
1458 { "-fb", "firstPlaysBlack", XrmoptionNoArg, "True" },
1459 { "-xfb", "firstPlaysBlack", XrmoptionNoArg, "False" },
1460 { "-noChessProgram", "noChessProgram", XrmoptionSepArg, NULL },
1461 { "-ncp", "noChessProgram", XrmoptionNoArg, "True" },
1462 { "-xncp", "noChessProgram", XrmoptionNoArg, "False" },
1463 { "-firstHost", "firstHost", XrmoptionSepArg, NULL },
1464 { "-fh", "firstHost", XrmoptionSepArg, NULL },
1465 { "-secondHost", "secondHost", XrmoptionSepArg, NULL },
1466 { "-sh", "secondHost", XrmoptionSepArg, NULL },
1467 { "-firstDirectory", "firstDirectory", XrmoptionSepArg, NULL },
1468 { "-fd", "firstDirectory", XrmoptionSepArg, NULL },
1469 { "-secondDirectory", "secondDirectory", XrmoptionSepArg, NULL },
1470 { "-sd", "secondDirectory", XrmoptionSepArg, NULL },
1471 { "-bitmapDirectory", "bitmapDirectory", XrmoptionSepArg, NULL },
1472 { "-bm", "bitmapDirectory", XrmoptionSepArg, NULL },
1473 { "-remoteShell", "remoteShell", XrmoptionSepArg, NULL },
1474 { "-rsh", "remoteShell", XrmoptionSepArg, NULL },
1475 { "-remoteUser", "remoteUser", XrmoptionSepArg, NULL },
1476 { "-ruser", "remoteUser", XrmoptionSepArg, NULL },
1477 { "-timeDelay", "timeDelay", XrmoptionSepArg, NULL },
1478 { "-td", "timeDelay", XrmoptionSepArg, NULL },
1479 { "-timeControl", "timeControl", XrmoptionSepArg, NULL },
1480 { "-tc", "timeControl", XrmoptionSepArg, NULL },
1481 { "-internetChessServerMode", "internetChessServerMode",
1482 XrmoptionSepArg, NULL },
1483 { "-ics", "internetChessServerMode", XrmoptionNoArg, "True" },
1484 { "-xics", "internetChessServerMode", XrmoptionNoArg, "False" },
1485 { "-internetChessServerHost", "internetChessServerHost",
1486 XrmoptionSepArg, NULL },
1487 { "-icshost", "internetChessServerHost", XrmoptionSepArg, NULL },
1488 { "-internetChessServerPort", "internetChessServerPort",
1489 XrmoptionSepArg, NULL },
1490 { "-icsport", "internetChessServerPort", XrmoptionSepArg, NULL },
1491 { "-internetChessServerCommPort", "internetChessServerCommPort",
1492 XrmoptionSepArg, NULL },
1493 { "-icscomm", "internetChessServerCommPort", XrmoptionSepArg, NULL },
1494 { "-internetChessServerLogonScript", "internetChessServerLogonScript",
1495 XrmoptionSepArg, NULL },
1496 { "-icslogon", "internetChessServerLogonScript", XrmoptionSepArg, NULL },
1497 { "-internetChessServerHelper", "internetChessServerHelper",
1498 XrmoptionSepArg, NULL },
1499 { "-icshelper", "internetChessServerHelper", XrmoptionSepArg, NULL },
1500 { "-internetChessServerInputBox", "internetChessServerInputBox",
1501 XrmoptionSepArg, NULL },
1502 { "-icsinput", "internetChessServerInputBox", XrmoptionNoArg, "True" },
1503 { "-xicsinput", "internetChessServerInputBox", XrmoptionNoArg, "False" },
1504 { "-icsAlarm", "icsAlarm", XrmoptionSepArg, NULL },
1505 { "-alarm", "icsAlarm", XrmoptionNoArg, "True" },
1506 { "-xalarm", "icsAlarm", XrmoptionNoArg, "False" },
1507 { "-icsAlarmTime", "icsAlarmTime", XrmoptionSepArg, NULL },
1508 { "-useTelnet", "useTelnet", XrmoptionSepArg, NULL },
1509 { "-telnet", "useTelnet", XrmoptionNoArg, "True" },
1510 { "-xtelnet", "useTelnet", XrmoptionNoArg, "False" },
1511 { "-telnetProgram", "telnetProgram", XrmoptionSepArg, NULL },
1512 { "-gateway", "gateway", XrmoptionSepArg, NULL },
1513 { "-loadGameFile", "loadGameFile", XrmoptionSepArg, NULL },
1514 { "-lgf", "loadGameFile", XrmoptionSepArg, NULL },
1515 { "-loadGameIndex", "loadGameIndex", XrmoptionSepArg, NULL },
1516 { "-lgi", "loadGameIndex", XrmoptionSepArg, NULL },
1517 { "-saveGameFile", "saveGameFile", XrmoptionSepArg, NULL },
1518 { "-sgf", "saveGameFile", XrmoptionSepArg, NULL },
1519 { "-autoSaveGames", "autoSaveGames", XrmoptionSepArg, NULL },
1520 { "-autosave", "autoSaveGames", XrmoptionNoArg, "True" },
1521 { "-xautosave", "autoSaveGames", XrmoptionNoArg, "False" },
1522 { "-autoRaiseBoard", "autoRaiseBoard", XrmoptionSepArg, NULL },
1523 { "-autoraise", "autoRaiseBoard", XrmoptionNoArg, "True" },
1524 { "-xautoraise", "autoRaiseBoard", XrmoptionNoArg, "False" },
1525 { "-blindfold", "blindfold", XrmoptionSepArg, NULL },
1526 { "-blind", "blindfold", XrmoptionNoArg, "True" },
1527 { "-xblind", "blindfold", XrmoptionNoArg, "False" },
1528 { "-loadPositionFile", "loadPositionFile", XrmoptionSepArg, NULL },
1529 { "-lpf", "loadPositionFile", XrmoptionSepArg, NULL },
1530 { "-loadPositionIndex", "loadPositionIndex", XrmoptionSepArg, NULL },
1531 { "-lpi", "loadPositionIndex", XrmoptionSepArg, NULL },
1532 { "-savePositionFile", "savePositionFile", XrmoptionSepArg, NULL },
1533 { "-spf", "savePositionFile", XrmoptionSepArg, NULL },
1534 { "-matchMode", "matchMode", XrmoptionSepArg, NULL },
1535 { "-mm", "matchMode", XrmoptionNoArg, "True" },
1536 { "-xmm", "matchMode", XrmoptionNoArg, "False" },
1537 { "-matchGames", "matchGames", XrmoptionSepArg, NULL },
1538 { "-mg", "matchGames", XrmoptionSepArg, NULL },
1539 { "-monoMode", "monoMode", XrmoptionSepArg, NULL },
1540 { "-mono", "monoMode", XrmoptionNoArg, "True" },
1541 { "-xmono", "monoMode", XrmoptionNoArg, "False" },
1542 { "-debugMode", "debugMode", XrmoptionSepArg, NULL },
1543 { "-debug", "debugMode", XrmoptionNoArg, "True" },
1544 { "-xdebug", "debugMode", XrmoptionNoArg, "False" },
1545 { "-clockMode", "clockMode", XrmoptionSepArg, NULL },
1546 { "-clock", "clockMode", XrmoptionNoArg, "True" },
1547 { "-xclock", "clockMode", XrmoptionNoArg, "False" },
1548 { "-boardSize", "boardSize", XrmoptionSepArg, NULL },
1549 { "-size", "boardSize", XrmoptionSepArg, NULL },
1550 { "-searchTime", "searchTime", XrmoptionSepArg, NULL },
1551 { "-st", "searchTime", XrmoptionSepArg, NULL },
1552 { "-searchDepth", "searchDepth", XrmoptionSepArg, NULL },
1553 { "-depth", "searchDepth", XrmoptionSepArg, NULL },
1554 { "-showCoords", "showCoords", XrmoptionSepArg, NULL },
1555 { "-coords", "showCoords", XrmoptionNoArg, "True" },
1556 { "-xcoords", "showCoords", XrmoptionNoArg, "False" },
1558 { "-showJail", "showJail", XrmoptionSepArg, NULL },
1559 { "-jail", "showJail", XrmoptionNoArg, "1" },
1560 { "-sidejail", "showJail", XrmoptionNoArg, "2" },
1561 { "-xjail", "showJail", XrmoptionNoArg, "0" },
1563 { "-showThinking", "showThinking", XrmoptionSepArg, NULL },
1564 { "-thinking", "showThinking", XrmoptionNoArg, "True" },
1565 { "-xthinking", "showThinking", XrmoptionNoArg, "False" },
1566 { "-ponderNextMove", "ponderNextMove", XrmoptionSepArg, NULL },
1567 { "-ponder", "ponderNextMove", XrmoptionNoArg, "True" },
1568 { "-xponder", "ponderNextMove", XrmoptionNoArg, "False" },
1569 { "-periodicUpdates", "periodicUpdates", XrmoptionSepArg, NULL },
1570 { "-periodic", "periodicUpdates", XrmoptionNoArg, "True" },
1571 { "-xperiodic", "periodicUpdates", XrmoptionNoArg, "False" },
1572 { "-clockFont", "clockFont", XrmoptionSepArg, NULL },
1573 { "-coordFont", "coordFont", XrmoptionSepArg, NULL },
1574 { "-font", "font", XrmoptionSepArg, NULL },
1575 { "-ringBellAfterMoves", "ringBellAfterMoves", XrmoptionSepArg, NULL },
1576 { "-bell", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1577 { "-xbell", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1578 { "-movesound", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1579 { "-xmovesound", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1580 { "-autoCallFlag", "autoCallFlag", XrmoptionSepArg, NULL },
1581 { "-autoflag", "autoCallFlag", XrmoptionNoArg, "True" },
1582 { "-xautoflag", "autoCallFlag", XrmoptionNoArg, "False" },
1583 { "-autoFlipView", "autoFlipView", XrmoptionSepArg, NULL },
1584 { "-autoflip", "autoFlipView", XrmoptionNoArg, "True" },
1585 { "-xautoflip", "autoFlipView", XrmoptionNoArg, "False" },
1586 { "-autoObserve", "autoObserve", XrmoptionSepArg, NULL },
1587 { "-autobs", "autoObserve", XrmoptionNoArg, "True" },
1588 { "-xautobs", "autoObserve", XrmoptionNoArg, "False" },
1589 { "-autoComment", "autoComment", XrmoptionSepArg, NULL },
1590 { "-autocomm", "autoComment", XrmoptionNoArg, "True" },
1591 { "-xautocomm", "autoComment", XrmoptionNoArg, "False" },
1592 { "-getMoveList", "getMoveList", XrmoptionSepArg, NULL },
1593 { "-moves", "getMoveList", XrmoptionNoArg, "True" },
1594 { "-xmoves", "getMoveList", XrmoptionNoArg, "False" },
1596 { "-highlightDragging", "highlightDragging", XrmoptionSepArg, NULL },
1597 { "-highdrag", "highlightDragging", XrmoptionNoArg, "True" },
1598 { "-xhighdrag", "highlightDragging", XrmoptionNoArg, "False" },
1600 { "-highlightLastMove", "highlightLastMove", XrmoptionSepArg, NULL },
1601 { "-highlight", "highlightLastMove", XrmoptionNoArg, "True" },
1602 { "-xhighlight", "highlightLastMove", XrmoptionNoArg, "False" },
1603 { "-premove", "premove", XrmoptionSepArg, NULL },
1604 { "-pre", "premove", XrmoptionNoArg, "True" },
1605 { "-xpre", "premove", XrmoptionNoArg, "False" },
1606 { "-testLegality", "testLegality", XrmoptionSepArg, NULL },
1607 { "-legal", "testLegality", XrmoptionNoArg, "True" },
1608 { "-xlegal", "testLegality", XrmoptionNoArg, "False" },
1609 { "-flipView", "flipView", XrmoptionSepArg, NULL },
1610 { "-flip", "flipView", XrmoptionNoArg, "True" },
1611 { "-xflip", "flipView", XrmoptionNoArg, "False" },
1612 { "-cmail", "cmailGameName", XrmoptionSepArg, NULL },
1613 { "-alwaysPromoteToQueen", "alwaysPromoteToQueen",
1614 XrmoptionSepArg, NULL },
1615 { "-queen", "alwaysPromoteToQueen", XrmoptionNoArg, "True" },
1616 { "-xqueen", "alwaysPromoteToQueen", XrmoptionNoArg, "False" },
1617 { "-oldSaveStyle", "oldSaveStyle", XrmoptionSepArg, NULL },
1618 { "-oldsave", "oldSaveStyle", XrmoptionNoArg, "True" },
1619 { "-xoldsave", "oldSaveStyle", XrmoptionNoArg, "False" },
1620 { "-quietPlay", "quietPlay", XrmoptionSepArg, NULL },
1621 { "-quiet", "quietPlay", XrmoptionNoArg, "True" },
1622 { "-xquiet", "quietPlay", XrmoptionNoArg, "False" },
1623 { "-titleInWindow", "titleInWindow", XrmoptionSepArg, NULL },
1624 { "-title", "titleInWindow", XrmoptionNoArg, "True" },
1625 { "-xtitle", "titleInWindow", XrmoptionNoArg, "False" },
1627 { "-zippyTalk", "zippyTalk", XrmoptionSepArg, NULL },
1628 { "-zt", "zippyTalk", XrmoptionNoArg, "True" },
1629 { "-xzt", "zippyTalk", XrmoptionNoArg, "False" },
1630 { "-zippyPlay", "zippyPlay", XrmoptionSepArg, NULL },
1631 { "-zp", "zippyPlay", XrmoptionNoArg, "True" },
1632 { "-xzp", "zippyPlay", XrmoptionNoArg, "False" },
1633 { "-zippyLines", "zippyLines", XrmoptionSepArg, NULL },
1634 { "-zippyPinhead", "zippyPinhead", XrmoptionSepArg, NULL },
1635 { "-zippyPassword", "zippyPassword", XrmoptionSepArg, NULL },
1636 { "-zippyPassword2", "zippyPassword2", XrmoptionSepArg, NULL },
1637 { "-zippyWrongPassword", "zippyWrongPassword", XrmoptionSepArg, NULL },
1638 { "-zippyAcceptOnly", "zippyAcceptOnly", XrmoptionSepArg, NULL },
1639 { "-zippyUseI", "zippyUseI", XrmoptionSepArg, NULL },
1640 { "-zui", "zippyUseI", XrmoptionNoArg, "True" },
1641 { "-xzui", "zippyUseI", XrmoptionNoArg, "False" },
1642 { "-zippyBughouse", "zippyBughouse", XrmoptionSepArg, NULL },
1643 { "-zippyNoplayCrafty", "zippyNoplayCrafty", XrmoptionSepArg, NULL },
1644 { "-znc", "zippyNoplayCrafty", XrmoptionNoArg, "True" },
1645 { "-xznc", "zippyNoplayCrafty", XrmoptionNoArg, "False" },
1646 { "-zippyGameEnd", "zippyGameEnd", XrmoptionSepArg, NULL },
1647 { "-zippyGameStart", "zippyGameStart", XrmoptionSepArg, NULL },
1648 { "-zippyAdjourn", "zippyAdjourn", XrmoptionSepArg, NULL },
1649 { "-zadj", "zippyAdjourn", XrmoptionNoArg, "True" },
1650 { "-xzadj", "zippyAdjourn", XrmoptionNoArg, "False" },
1651 { "-zippyAbort", "zippyAbort", XrmoptionSepArg, NULL },
1652 { "-zab", "zippyAbort", XrmoptionNoArg, "True" },
1653 { "-xzab", "zippyAbort", XrmoptionNoArg, "False" },
1654 { "-zippyVariants", "zippyVariants", XrmoptionSepArg, NULL },
1655 { "-zippyMaxGames", "zippyMaxGames", XrmoptionSepArg, NULL },
1656 { "-zippyReplayTimeout", "zippyReplayTimeout", XrmoptionSepArg, NULL },
1657 { "-zippyShortGame", "zippyShortGame", XrmoptionSepArg, NULL },
1659 { "-flashCount", "flashCount", XrmoptionSepArg, NULL },
1660 { "-flash", "flashCount", XrmoptionNoArg, "3" },
1661 { "-xflash", "flashCount", XrmoptionNoArg, "0" },
1662 { "-flashRate", "flashRate", XrmoptionSepArg, NULL },
1663 { "-pixmapDirectory", "pixmapDirectory", XrmoptionSepArg, NULL },
1664 { "-msLoginDelay", "msLoginDelay", XrmoptionSepArg, NULL },
1665 { "-pixmap", "pixmapDirectory", XrmoptionSepArg, NULL },
1666 { "-colorizeMessages", "colorizeMessages", XrmoptionSepArg, NULL },
1667 { "-colorize", "colorizeMessages", XrmoptionNoArg, "True" },
1668 { "-xcolorize", "colorizeMessages", XrmoptionNoArg, "False" },
1669 { "-colorShout", "colorShout", XrmoptionSepArg, NULL },
1670 { "-colorSShout", "colorSShout", XrmoptionSepArg, NULL },
1671 { "-colorCShout", "colorSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1672 { "-colorChannel1", "colorChannel1", XrmoptionSepArg, NULL },
1673 { "-colorChannel", "colorChannel", XrmoptionSepArg, NULL },
1674 { "-colorKibitz", "colorKibitz", XrmoptionSepArg, NULL },
1675 { "-colorTell", "colorTell", XrmoptionSepArg, NULL },
1676 { "-colorChallenge", "colorChallenge", XrmoptionSepArg, NULL },
1677 { "-colorRequest", "colorRequest", XrmoptionSepArg, NULL },
1678 { "-colorSeek", "colorSeek", XrmoptionSepArg, NULL },
1679 { "-colorNormal", "colorNormal", XrmoptionSepArg, NULL },
1680 { "-soundProgram", "soundProgram", XrmoptionSepArg, NULL },
1681 { "-soundShout", "soundShout", XrmoptionSepArg, NULL },
1682 { "-soundSShout", "soundSShout", XrmoptionSepArg, NULL },
1683 { "-soundCShout", "soundSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1684 { "-soundChannel1", "soundChannel1", XrmoptionSepArg, NULL },
1685 { "-soundChannel", "soundChannel", XrmoptionSepArg, NULL },
1686 { "-soundKibitz", "soundKibitz", XrmoptionSepArg, NULL },
1687 { "-soundTell", "soundTell", XrmoptionSepArg, NULL },
1688 { "-soundChallenge", "soundChallenge", XrmoptionSepArg, NULL },
1689 { "-soundRequest", "soundRequest", XrmoptionSepArg, NULL },
1690 { "-soundSeek", "soundSeek", XrmoptionSepArg, NULL },
1691 { "-soundMove", "soundMove", XrmoptionSepArg, NULL },
1692 { "-soundIcsWin", "soundIcsWin", XrmoptionSepArg, NULL },
1693 { "-soundIcsLoss", "soundIcsLoss", XrmoptionSepArg, NULL },
1694 { "-soundIcsDraw", "soundIcsDraw", XrmoptionSepArg, NULL },
1695 { "-soundIcsUnfinished", "soundIcsUnfinished", XrmoptionSepArg, NULL },
1696 { "-soundIcsAlarm", "soundIcsAlarm", XrmoptionSepArg, NULL },
1697 { "-reuseFirst", "reuseFirst", XrmoptionSepArg, NULL },
1698 { "-reuseChessPrograms", "reuseFirst", XrmoptionSepArg, NULL }, /*compat*/
1699 { "-reuse", "reuseFirst", XrmoptionNoArg, "True" },
1700 { "-xreuse", "reuseFirst", XrmoptionNoArg, "False" },
1701 { "-reuseSecond", "reuseSecond", XrmoptionSepArg, NULL },
1702 { "-reuse2", "reuseSecond", XrmoptionNoArg, "True" },
1703 { "-xreuse2", "reuseSecond", XrmoptionNoArg, "False" },
1704 { "-animateMoving", "animateMoving", XrmoptionSepArg, NULL },
1705 { "-animate", "animateMoving", XrmoptionNoArg, "True" },
1706 { "-xanimate", "animateMoving", XrmoptionNoArg, "False" },
1707 { "-animateDragging", "animateDragging", XrmoptionSepArg, NULL },
1708 { "-drag", "animateDragging", XrmoptionNoArg, "True" },
1709 { "-xdrag", "animateDragging", XrmoptionNoArg, "False" },
1710 { "-animateSpeed", "animateSpeed", XrmoptionSepArg, NULL },
1711 { "-popupExitMessage", "popupExitMessage", XrmoptionSepArg, NULL },
1712 { "-exit", "popupExitMessage", XrmoptionNoArg, "True" },
1713 { "-xexit", "popupExitMessage", XrmoptionNoArg, "False" },
1714 { "-popupMoveErrors", "popupMoveErrors", XrmoptionSepArg, NULL },
1715 { "-popup", "popupMoveErrors", XrmoptionNoArg, "True" },
1716 { "-xpopup", "popupMoveErrors", XrmoptionNoArg, "False" },
1717 { "-fontSizeTolerance", "fontSizeTolerance", XrmoptionSepArg, NULL },
1718 { "-initialMode", "initialMode", XrmoptionSepArg, NULL },
1719 { "-mode", "initialMode", XrmoptionSepArg, NULL },
1720 { "-variant", "variant", XrmoptionSepArg, NULL },
1721 { "-firstProtocolVersion", "firstProtocolVersion", XrmoptionSepArg, NULL },
1722 { "-secondProtocolVersion","secondProtocolVersion",XrmoptionSepArg, NULL },
1723 { "-showButtonBar", "showButtonBar", XrmoptionSepArg, NULL },
1724 { "-buttons", "showButtonBar", XrmoptionNoArg, "True" },
1725 { "-xbuttons", "showButtonBar", XrmoptionNoArg, "False" },
1726 { "-lowTimeWarningColor", "lowTimeWarningColor", XrmoptionSepArg, NULL },
1727 { "-lowTimeWarning", "lowTimeWarning", XrmoptionSepArg, NULL },
1728 /* [AS,HR] New features */
1729 { "-firstScoreAbs", "firstScoreAbs", XrmoptionSepArg, NULL },
1730 { "-secondScoreAbs", "secondScoreAbs", XrmoptionSepArg, NULL },
1731 { "-pgnExtendedInfo", "pgnExtendedInfo", XrmoptionSepArg, NULL },
1732 { "-hideThinkingFromHuman", "hideThinkingFromHuman", XrmoptionSepArg, NULL },
1733 { "-adjudicateLossThreshold", "adjudicateLossThreshold", XrmoptionSepArg, NULL },
1734 { "-adjudicateDrawMoves", "adjudicateDrawMoves", XrmoptionSepArg, NULL },
1735 { "-pgnEventHeader", "pgnEventHeader", XrmoptionSepArg, NULL },
1736 { "-firstIsUCI", "firstIsUCI", XrmoptionSepArg, NULL },
1737 { "-secondIsUCI", "secondIsUCI", XrmoptionSepArg, NULL },
1738 { "-fUCI", "firstIsUCI", XrmoptionNoArg, "True" },
1739 { "-sUCI", "secondIsUCI", XrmoptionNoArg, "True" },
1740 { "-firstHasOwnBookUCI", "firstHasOwnBookUCI", XrmoptionSepArg, NULL },
1741 { "-secondHasOwnBookUCI", "secondHasOwnBookUCI", XrmoptionSepArg, NULL },
1742 { "-fNoOwnBookUCI", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1743 { "-sNoOwnBookUCI", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1744 { "-firstXBook", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1745 { "-secondXBook", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1746 { "-polyglotDir", "polyglotDir", XrmoptionSepArg, NULL },
1747 { "-usePolyglotBook", "usePolyglotBook", XrmoptionSepArg, NULL },
1748 { "-polyglotBook", "polyglotBook", XrmoptionSepArg, NULL },
1749 { "-defaultHashSize", "defaultHashSize", XrmoptionSepArg, NULL },
1750 { "-defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XrmoptionSepArg, NULL },
1751 { "-defaultPathEGTB", "defaultPathEGTB", XrmoptionSepArg, NULL },
1752 { "-defaultFrcPosition", "defaultFrcPosition", XrmoptionSepArg, NULL },
1753 { "-gameListTags", "gameListTags", XrmoptionSepArg, NULL },
1754 // [HGM] I am sure AS added many more options, but we have to fish them out, from the list in winboard.c
1756 /* [HGM,HR] User-selectable board size */
1757 { "-boardWidth", "boardWidth", XrmoptionSepArg, NULL },
1758 { "-boardHeight", "boardHeight", XrmoptionSepArg, NULL },
1759 { "-matchPause", "matchPause", XrmoptionSepArg, NULL },
1761 /* [HGM] new arguments of 4.3.xx. All except first three are back-end options, which should work immediately */
1762 { "-holdingsSize", "holdingsSize", XrmoptionSepArg, NULL }, // requires extensive front-end changes to work
1763 { "-flipBlack", "flipBlack", XrmoptionSepArg, NULL }, // requires front-end changes to work
1764 { "-allWhite", "allWhite", XrmoptionSepArg, NULL }, // requires front-end changes to work
1765 { "-pieceToCharTable", "pieceToCharTable", XrmoptionSepArg, NULL },
1766 { "-alphaRank", "alphaRank", XrmoptionSepArg, NULL },
1767 { "-testClaims", "testClaims", XrmoptionSepArg, NULL },
1768 { "-checkMates", "checkMates", XrmoptionSepArg, NULL },
1769 { "-materialDraws", "materialDraws", XrmoptionSepArg, NULL },
1770 { "-trivialDraws", "trivialDraws", XrmoptionSepArg, NULL },
1771 { "-ruleMoves", "ruleMoves", XrmoptionSepArg, NULL },
1772 { "-repeatsToDraw", "repeatsToDraw", XrmoptionSepArg, NULL },
1773 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1774 { "-userName", "userName", XrmoptionSepArg, NULL },
1775 { "-autoKibitz", "autoKibitz", XrmoptionNoArg, "True" },
1776 { "-firstTimeOdds", "firstTimeOdds", XrmoptionSepArg, NULL },
1777 { "-secondTimeOdds", "secondTimeOdds", XrmoptionSepArg, NULL },
1778 { "-timeOddsMode", "timeOddsMode", XrmoptionSepArg, NULL },
1779 { "-firstAccumulateTC", "firstAccumulateTC", XrmoptionSepArg, NULL },
1780 { "-secondAccumulateTC", "secondAccumulateTC", XrmoptionSepArg, NULL },
1781 { "-firstNPS", "firstNPS", XrmoptionSepArg, NULL },
1782 { "-secondNPS", "secondNPS", XrmoptionSepArg, NULL },
1783 { "-serverMoves", "serverMoves", XrmoptionSepArg, NULL },
1784 { "-serverPause", "serverPause", XrmoptionSepArg, NULL },
1785 { "-suppressLoadMoves", "suppressLoadMoves", XrmoptionSepArg, NULL },
1786 { "-egtFormats", "egtFormats", XrmoptionSepArg, NULL },
1787 { "-userName", "userName", XrmoptionSepArg, NULL },
1788 { "-smpCores", "smpCores", XrmoptionSepArg, NULL },
1789 { "-sameColorGames", "sameColorGames", XrmoptionSepArg, NULL },
1790 { "-rewindIndex", "rewindIndex", XrmoptionSepArg, NULL },
1791 { "-niceEngines", "niceEngines", XrmoptionSepArg, NULL },
1792 { "-delayBeforeQuit", "delayBeforeQuit", XrmoptionSepArg, NULL },
1793 { "-delayAfterQuit", "delayAfterQuit", XrmoptionSepArg, NULL },
1794 { "-nameOfDebugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1795 { "-debugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1796 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1797 { "-noGUI", "noGUI", XrmoptionNoArg, "True" },
1798 { "-firstOptions", "firstOptions", XrmoptionSepArg, NULL },
1799 { "-secondOptions", "secondOptions", XrmoptionSepArg, NULL },
1800 { "-firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1801 { "-secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1802 { "-keepAlive", "keepAlive", XrmoptionSepArg, NULL },
1806 XtActionsRec boardActions[] = {
1807 { "HandleUserMove", HandleUserMove },
1808 { "AnimateUserMove", AnimateUserMove },
1809 { "FileNameAction", FileNameAction },
1810 { "AskQuestionProc", AskQuestionProc },
1811 { "AskQuestionReplyAction", AskQuestionReplyAction },
1812 { "PieceMenuPopup", PieceMenuPopup },
1813 { "WhiteClock", WhiteClock },
1814 { "BlackClock", BlackClock },
1815 { "Iconify", Iconify },
1816 { "LoadSelectedProc", LoadSelectedProc },
1817 { "LoadPositionProc", LoadPositionProc },
1818 { "LoadNextPositionProc", LoadNextPositionProc },
1819 { "LoadPrevPositionProc", LoadPrevPositionProc },
1820 { "ReloadPositionProc", ReloadPositionProc },
1821 { "CopyPositionProc", CopyPositionProc },
1822 { "PastePositionProc", PastePositionProc },
1823 { "CopyGameProc", CopyGameProc },
1824 { "PasteGameProc", PasteGameProc },
1825 { "SaveGameProc", SaveGameProc },
1826 { "SavePositionProc", SavePositionProc },
1827 { "MailMoveProc", MailMoveProc },
1828 { "ReloadCmailMsgProc", ReloadCmailMsgProc },
1829 // { "MachineWhiteProc", MachineWhiteProc },
1830 // { "MachineBlackProc", MachineBlackProc },
1831 { "AnalysisModeProc", AnalyzeModeProc },
1832 { "AnalyzeFileProc", AnalyzeFileProc },
1833 // { "TwoMachinesProc", TwoMachinesProc },
1834 // { "IcsClientProc", IcsClientProc },
1835 { "EditGameProc", EditGameProc },
1836 { "EditPositionProc", EditPositionProc },
1837 { "TrainingProc", EditPositionProc },
1838 { "EngineOutputProc", EngineOutputProc}, // [HGM] Winboard_x engine-output window
1839 { "ShowGameListProc", ShowGameListProc },
1840 { "ShowMoveListProc", HistoryShowProc},
1841 { "EditTagsProc", EditCommentProc },
1842 { "EditCommentProc", EditCommentProc },
1843 { "IcsAlarmProc", IcsAlarmProc },
1844 { "IcsInputBoxProc", IcsInputBoxProc },
1845 // { "AcceptProc", AcceptProc },
1846 // { "DeclineProc", DeclineProc },
1847 // { "RematchProc", RematchProc },
1848 // { "CallFlagProc", CallFlagProc },
1849 // { "DrawProc", DrawProc },
1850 // { "AdjournProc", AdjournProc },
1851 // { "AbortProc", AbortProc },
1852 // { "ResignProc", ResignProc },
1853 // { "AdjuWhiteProc", AdjuWhiteProc },
1854 // { "AdjuBlackProc", AdjuBlackProc },
1855 // { "AdjuDrawProc", AdjuDrawProc },
1856 { "EnterKeyProc", EnterKeyProc },
1857 // { "StopObservingProc", StopObservingProc },
1858 // { "StopExaminingProc", StopExaminingProc },
1859 // { "BackwardProc", BackwardProc },
1860 // { "ForwardProc", ForwardProc },
1861 // { "ToStartProc", ToStartProc },
1862 // { "ToEndProc", ToEndProc },
1863 // { "RevertProc", RevertProc },
1864 // { "TruncateGameProc", TruncateGameProc },
1865 // { "MoveNowProc", MoveNowProc },
1866 // { "RetractMoveProc", RetractMoveProc },
1867 { "AlwaysQueenProc", AlwaysQueenProc },
1868 { "AnimateDraggingProc", AnimateDraggingProc },
1869 { "AnimateMovingProc", AnimateMovingProc },
1870 { "AutoflagProc", AutoflagProc },
1871 { "AutoflipProc", AutoflipProc },
1872 { "AutobsProc", AutobsProc },
1873 { "AutoraiseProc", AutoraiseProc },
1874 { "AutosaveProc", AutosaveProc },
1875 { "BlindfoldProc", BlindfoldProc },
1876 { "FlashMovesProc", FlashMovesProc },
1877 // { "FlipViewProc", FlipViewProc },
1878 { "GetMoveListProc", GetMoveListProc },
1880 { "HighlightDraggingProc", HighlightDraggingProc },
1882 { "HighlightLastMoveProc", HighlightLastMoveProc },
1883 { "IcsAlarmProc", IcsAlarmProc },
1884 { "MoveSoundProc", MoveSoundProc },
1885 { "OldSaveStyleProc", OldSaveStyleProc },
1886 { "PeriodicUpdatesProc", PeriodicUpdatesProc },
1887 { "PonderNextMoveProc", PonderNextMoveProc },
1888 { "PopupExitMessageProc", PopupExitMessageProc },
1889 { "PopupMoveErrorsProc", PopupMoveErrorsProc },
1890 { "PremoveProc", PremoveProc },
1891 { "QuietPlayProc", QuietPlayProc },
1892 { "ShowThinkingProc", ShowThinkingProc },
1893 { "HideThinkingProc", HideThinkingProc },
1894 { "TestLegalityProc", TestLegalityProc },
1895 // { "InfoProc", InfoProc },
1896 // { "ManProc", ManProc },
1897 // { "HintProc", HintProc },
1898 // { "BookProc", BookProc },
1899 { "AboutGameProc", AboutGameProc },
1900 { "DebugProc", DebugProc },
1901 { "NothingProc", NothingProc },
1902 { "CommentPopDown", (XtActionProc) CommentPopDown },
1903 { "EditCommentPopDown", (XtActionProc) EditCommentPopDown },
1904 { "TagsPopDown", (XtActionProc) TagsPopDown },
1905 { "ErrorPopDown", (XtActionProc) ErrorPopDown },
1906 { "ICSInputBoxPopDown", (XtActionProc) ICSInputBoxPopDown },
1907 { "AnalysisPopDown", (XtActionProc) AnalysisPopDown },
1908 { "FileNamePopDown", (XtActionProc) FileNamePopDown },
1909 { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown },
1910 { "GameListPopDown", (XtActionProc) GameListPopDown },
1911 { "PromotionPopDown", (XtActionProc) PromotionPopDown },
1912 { "HistoryPopDown", (XtActionProc) HistoryPopDown },
1913 { "EngineOutputPopDown", (XtActionProc) EngineOutputPopDown },
1914 { "ShufflePopDown", (XtActionProc) ShufflePopDown },
1915 { "EnginePopDown", (XtActionProc) EnginePopDown },
1916 { "UciPopDown", (XtActionProc) UciPopDown },
1917 { "TimeControlPopDown", (XtActionProc) TimeControlPopDown },
1918 { "NewVariantPopDown", (XtActionProc) NewVariantPopDown },
1919 { "SettingsPopDown", (XtActionProc) SettingsPopDown },
1923 char ICSInputTranslations[] =
1924 "<Key>Return: EnterKeyProc() \n";
1926 String xboardResources[] = {
1927 "*fileName*value.translations: #override\\n <Key>Return: FileNameAction()",
1928 "*question*value.translations: #override\\n <Key>Return: AskQuestionReplyAction()",
1929 "*errorpopup*translations: #override\\n <Key>Return: ErrorPopDown()",
1933 static char *cnames[9] = { "black", "red", "green", "yellow", "blue",
1934 "magenta", "cyan", "white" };
1938 TextColors textColors[(int)NColorClasses];
1940 /* String is: "fg, bg, attr". Which is 0, 1, 2 */
1942 parse_color(str, which)
1946 char *p, buf[100], *d;
1949 if (strlen(str) > 99) /* watch bounds on buf */
1954 for (i=0; i<which; ++i) {
1961 /* Could be looking at something like:
1963 .. in which case we want to stop on a comma also */
1964 while (*p && *p != ',' && !isalpha(*p) && !isdigit(*p))
1968 return -1; /* Use default for empty field */
1971 if (which == 2 || isdigit(*p))
1974 while (*p && isalpha(*p))
1979 for (i=0; i<8; ++i) {
1980 if (!StrCaseCmp(buf, cnames[i]))
1981 return which? (i+40) : (i+30);
1983 if (!StrCaseCmp(buf, "default")) return -1;
1985 fprintf(stderr, _("%s: unrecognized color %s\n"), programName, buf);
1990 parse_cpair(cc, str)
1994 if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {
1995 fprintf(stderr, _("%s: can't parse foreground color in `%s'\n"),
2000 /* bg and attr are optional */
2001 textColors[(int)cc].bg = parse_color(str, 1);
2002 if ((textColors[(int)cc].attr = parse_color(str, 2)) < 0) {
2003 textColors[(int)cc].attr = 0;
2009 /* Arrange to catch delete-window events */
2010 Atom wm_delete_window;
2012 CatchDeleteWindow(Widget w, String procname)
2015 XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
2016 snprintf(buf, sizeof(buf), "<Message>WM_PROTOCOLS: %s() \n", procname);
2017 XtAugmentTranslations(w, XtParseTranslationTable(buf));
2023 /* this should raise the board to the top */
2024 gtk_window_present(GTK_WINDOW(GUI_Window));
2029 // eventually, all layout determining code should go into a subroutine, but until then IDSIZE remains undefined
2031 #define BoardSize int
2032 void InitDrawingSizes(BoardSize boardSize, int flags)
2033 { // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
2034 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2036 XtGeometryResult gres;
2039 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2040 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2042 timerWidth = (boardWidth - sep) / 2;
2044 if (appData.titleInWindow)
2049 w = boardWidth - 2*bor;
2053 w = boardWidth - w - sep - 2*bor - 2; // WIDTH_FUDGE
2057 if(!formWidget) return;
2060 * Inhibit shell resizing.
2063 // [HGM] pieces: tailor piece bitmaps to needs of specific variant
2066 for(i=0; i<4; i++) {
2068 for(p=0; p<=(int)WhiteKing; p++)
2069 xpmPieceBitmap[i][p] = xpmPieceBitmap2[i][p]; // defaults
2070 if(gameInfo.variant == VariantShogi) {
2071 xpmPieceBitmap[i][(int)WhiteCannon] = xpmPieceBitmap2[i][(int)WhiteKing+1];
2072 xpmPieceBitmap[i][(int)WhiteNightrider] = xpmPieceBitmap2[i][(int)WhiteKing+2];
2073 xpmPieceBitmap[i][(int)WhiteSilver] = xpmPieceBitmap2[i][(int)WhiteKing+3];
2074 xpmPieceBitmap[i][(int)WhiteGrasshopper] = xpmPieceBitmap2[i][(int)WhiteKing+4];
2075 xpmPieceBitmap[i][(int)WhiteQueen] = xpmPieceBitmap2[i][(int)WhiteLance];
2078 if(gameInfo.variant == VariantGothic) {
2079 xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteSilver];
2083 // [HGM] why are thee ximMasks used at all? the ximPieceBitmaps seem to be never used!
2084 for(p=0; p<=(int)WhiteKing; p++)
2085 ximMaskPm[p] = ximMaskPm2[p]; // defaults
2086 if(gameInfo.variant == VariantShogi) {
2087 ximMaskPm[(int)WhiteCannon] = ximMaskPm2[(int)WhiteKing+1];
2088 ximMaskPm[(int)WhiteNightrider] = ximMaskPm2[(int)WhiteKing+2];
2089 ximMaskPm[(int)WhiteSilver] = ximMaskPm2[(int)WhiteKing+3];
2090 ximMaskPm[(int)WhiteGrasshopper] = ximMaskPm2[(int)WhiteKing+4];
2091 ximMaskPm[(int)WhiteQueen] = ximMaskPm2[(int)WhiteLance];
2094 if(gameInfo.variant == VariantGothic) {
2095 ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[(int)WhiteSilver];
2101 for(i=0; i<2; i++) {
2103 for(p=0; p<=(int)WhiteKing; p++)
2104 pieceBitmap[i][p] = pieceBitmap2[i][p]; // defaults
2105 if(gameInfo.variant == VariantShogi) {
2106 pieceBitmap[i][(int)WhiteCannon] = pieceBitmap2[i][(int)WhiteKing+1];
2107 pieceBitmap[i][(int)WhiteNightrider] = pieceBitmap2[i][(int)WhiteKing+2];
2108 pieceBitmap[i][(int)WhiteSilver] = pieceBitmap2[i][(int)WhiteKing+3];
2109 pieceBitmap[i][(int)WhiteGrasshopper] = pieceBitmap2[i][(int)WhiteKing+4];
2110 pieceBitmap[i][(int)WhiteQueen] = pieceBitmap2[i][(int)WhiteLance];
2113 if(gameInfo.variant == VariantGothic) {
2114 pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteSilver];
2125 void EscapeExpand(char *p, char *q)
2126 { // [HGM] initstring: routine to shape up string arguments
2127 while(*p++ = *q++) if(p[-1] == '\\')
2129 case 'n': p[-1] = '\n'; break;
2130 case 'r': p[-1] = '\r'; break;
2131 case 't': p[-1] = '\t'; break;
2132 case '\\': p[-1] = '\\'; break;
2133 case 0: *p = 0; return;
2134 default: p[-1] = q[-1]; break;
2143 int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
2144 XSetWindowAttributes window_attributes;
2146 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2147 XrmValue vFrom, vTo;
2148 XtGeometryResult gres;
2151 int forceMono = False;
2155 // [HGM] before anything else, expand any indirection files amongst options
2156 char *argvCopy[1000]; // 1000 seems enough
2157 char newArgs[10000]; // holds actual characters
2160 srandom(time(0)); // [HGM] book: make random truly random
2163 for(i=0; i<argc; i++) {
2164 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2165 //fprintf(stderr, "arg %s\n", argv[i]);
2166 if(argv[i][0] != '@') argvCopy[j++] = argv[i]; else {
2168 FILE *f = fopen(argv[i]+1, "rb");
2169 if(f == NULL) { fprintf(stderr, _("ignore %s\n"), argv[i]); continue; } // do not expand non-existing
2170 argvCopy[j++] = newArgs + k; // get ready for first argument from file
2171 while((c = fgetc(f)) != EOF) { // each line of file inserts 1 argument in the list
2173 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2174 newArgs[k++] = 0; // terminate current arg
2175 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2176 argvCopy[j++] = newArgs + k; // get ready for next
2178 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2191 if(appData.debugMode,1) { // OK, appData is not initialized here yet...
2192 for(i=0; i<argc; i++) fprintf(stderr, "argv[%2d] = '%s'\n", i, argv[i]);
2197 setbuf(stdout, NULL);
2198 setbuf(stderr, NULL);
2201 programName = strrchr(argv[0], '/');
2202 if (programName == NULL)
2203 programName = argv[0];
2208 XtSetLanguageProc(NULL, NULL, NULL);
2209 bindtextdomain(PACKAGE, LOCALEDIR);
2210 textdomain(PACKAGE);
2214 XtAppInitialize(&appContext, "XBoard", shellOptions,
2215 XtNumber(shellOptions),
2216 &argc, argv, xboardResources, NULL, 0);
2220 gtk_init (&argc, &argv);
2222 /* parse glade file to build widgets */
2224 builder = gtk_builder_new ();
2225 gtk_builder_add_from_file (builder, "gtk-interface.xml", NULL);
2227 /* test if everything worked ok */
2229 GUI_Window = GTK_WIDGET (gtk_builder_get_object (builder, "MainWindow"));
2230 if(!GUI_Window) printf("Error: gtk_builder didn't work!\n");
2231 GUI_Board = GTK_WIDGET (gtk_builder_get_object (builder, "Board"));
2232 if(!GUI_Board) printf("Error: gtk_builder didn't work!\n");
2233 GUI_Whiteclock = GTK_WIDGET (gtk_builder_get_object (builder, "WhiteClock"));
2234 if(!GUI_Whiteclock) printf("Error: gtk_builder didn't work!\n");
2235 GUI_Blackclock = GTK_WIDGET (gtk_builder_get_object (builder, "BlackClock"));
2236 if(!GUI_Blackclock) printf("Error: gtk_builder didn't work!\n");
2238 gtk_builder_connect_signals (builder, NULL);
2240 // don't unref the builder, since we use it to get references to widgets
2241 // g_object_unref (G_OBJECT (builder));
2243 /* end parse glade file */
2247 fprintf(stderr, _("%s: unrecognized argument %s\n"),
2248 programName, argv[1]);
2249 fprintf(stderr, "Recognized options:\n");
2250 for(i = 0; i < XtNumber(shellOptions); i++)
2252 j = fprintf(stderr, " %s%s", shellOptions[i].option,
2253 (shellOptions[i].argKind == XrmoptionSepArg
2255 if (i++ < XtNumber(shellOptions))
2257 fprintf(stderr, "%*c%s%s\n", 40 - j, ' ',
2258 shellOptions[i].option,
2259 (shellOptions[i].argKind == XrmoptionSepArg
2264 fprintf(stderr, "\n");
2270 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL)
2276 if (chdir(chessDir) != 0)
2278 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
2285 if (p == NULL) p = "/tmp";
2286 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
2287 gameCopyFilename = (char*) malloc(i);
2288 gamePasteFilename = (char*) malloc(i);
2289 snprintf(gameCopyFilename,i, "%s/.xboard%05uc.pgn", p, getpid());
2290 snprintf(gamePasteFilename,i, "%s/.xboard%05up.pgn", p, getpid());
2292 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
2293 clientResources, XtNumber(clientResources),
2296 { // [HGM] initstring: kludge to fix bad bug. expand '\n' characters in init string and computer string.
2297 static char buf[MSG_SIZ];
2298 EscapeExpand(buf, appData.initString);
2299 appData.initString = strdup(buf);
2300 EscapeExpand(buf, appData.secondInitString);
2301 appData.secondInitString = strdup(buf);
2302 EscapeExpand(buf, appData.firstComputerString);
2303 appData.firstComputerString = strdup(buf);
2304 EscapeExpand(buf, appData.secondComputerString);
2305 appData.secondComputerString = strdup(buf);
2308 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
2311 if (chdir(chessDir) != 0) {
2312 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
2318 if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) {
2319 /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */
2320 if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL) {
2321 printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile);
2324 setbuf(debugFP, NULL);
2327 /* [HGM,HR] make sure board size is acceptable */
2328 if(appData.NrFiles > BOARD_SIZE ||
2329 appData.NrRanks > BOARD_SIZE )
2330 DisplayFatalError(_("Recompile with BOARD_SIZE > 12, to support this size"), 0, 2);
2333 /* This feature does not work; animation needs a rewrite */
2334 appData.highlightDragging = FALSE;
2338 xDisplay = XtDisplay(shellWidget);
2339 xScreen = DefaultScreen(xDisplay);
2340 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
2342 gameInfo.variant = StringToVariant(appData.variant);
2343 InitPosition(FALSE);
2347 * Determine boardSize
2349 gameInfo.boardWidth = gameInfo.boardHeight = 8; // [HGM] boardsize: make sure we start as 8x8
2352 // [HGM] as long as we have not created the possibility to change size while running, start with requested size
2353 gameInfo.boardWidth = appData.NrFiles > 0 ? appData.NrFiles : 8;
2354 gameInfo.boardHeight = appData.NrRanks > 0 ? appData.NrRanks : 8;
2355 gameInfo.holdingsWidth = appData.holdingsSize > 0 ? 2 : 0;
2360 InitDrawingSizes(-1, 0); // [HGM] initsize: make this into a subroutine
2362 if (isdigit(appData.boardSize[0])) {
2363 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
2364 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
2365 &fontPxlSize, &smallLayout, &tinyLayout);
2367 fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
2368 programName, appData.boardSize);
2372 /* Find some defaults; use the nearest known size */
2373 SizeDefaults *szd, *nearest;
2374 int distance = 99999;
2375 nearest = szd = sizeDefaults;
2376 while (szd->name != NULL) {
2377 if (abs(szd->squareSize - squareSize) < distance) {
2379 distance = abs(szd->squareSize - squareSize);
2380 if (distance == 0) break;
2384 if (i < 2) lineGap = nearest->lineGap;
2385 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
2386 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
2387 if (i < 5) fontPxlSize = nearest->fontPxlSize;
2388 if (i < 6) smallLayout = nearest->smallLayout;
2389 if (i < 7) tinyLayout = nearest->tinyLayout;
2392 SizeDefaults *szd = sizeDefaults;
2393 if (*appData.boardSize == NULLCHAR) {
2394 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize ||
2395 DisplayHeight(xDisplay, xScreen) < szd->minScreenSize) {
2398 if (szd->name == NULL) szd--;
2400 while (szd->name != NULL &&
2401 StrCaseCmp(szd->name, appData.boardSize) != 0) szd++;
2402 if (szd->name == NULL) {
2403 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
2404 programName, appData.boardSize);
2408 squareSize = szd->squareSize;
2409 lineGap = szd->lineGap;
2410 clockFontPxlSize = szd->clockFontPxlSize;
2411 coordFontPxlSize = szd->coordFontPxlSize;
2412 fontPxlSize = szd->fontPxlSize;
2413 smallLayout = szd->smallLayout;
2414 tinyLayout = szd->tinyLayout;
2417 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2418 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2419 if (appData.showJail == 1) {
2420 /* Jail on top and bottom */
2421 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2422 XtSetArg(boardArgs[2], XtNheight,
2423 boardHeight + 2*(lineGap + squareSize));
2424 } else if (appData.showJail == 2) {
2426 XtSetArg(boardArgs[1], XtNwidth,
2427 boardWidth + 2*(lineGap + squareSize));
2428 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2431 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2432 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2436 * Determine what fonts to use.
2438 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
2439 clockFontID = XLoadFont(xDisplay, appData.clockFont);
2440 clockFontStruct = XQueryFont(xDisplay, clockFontID);
2441 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
2442 coordFontID = XLoadFont(xDisplay, appData.coordFont);
2443 coordFontStruct = XQueryFont(xDisplay, coordFontID);
2444 appData.font = FindFont(appData.font, fontPxlSize);
2445 countFontID = XLoadFont(xDisplay, appData.coordFont); // [HGM] holdings
2446 countFontStruct = XQueryFont(xDisplay, countFontID);
2447 // appData.font = FindFont(appData.font, fontPxlSize);
2449 xdb = XtDatabase(xDisplay);
2450 XrmPutStringResource(&xdb, "*font", appData.font);
2453 * Detect if there are not enough colors available and adapt.
2455 if (DefaultDepth(xDisplay, xScreen) <= 2) {
2456 appData.monoMode = True;
2459 if (!appData.monoMode) {
2460 vFrom.addr = (caddr_t) appData.lightSquareColor;
2461 vFrom.size = strlen(appData.lightSquareColor);
2462 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2463 if (vTo.addr == NULL) {
2464 appData.monoMode = True;
2467 lightSquareColor = *(Pixel *) vTo.addr;
2470 if (!appData.monoMode) {
2471 vFrom.addr = (caddr_t) appData.darkSquareColor;
2472 vFrom.size = strlen(appData.darkSquareColor);
2473 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2474 if (vTo.addr == NULL) {
2475 appData.monoMode = True;
2478 darkSquareColor = *(Pixel *) vTo.addr;
2481 if (!appData.monoMode) {
2482 vFrom.addr = (caddr_t) appData.whitePieceColor;
2483 vFrom.size = strlen(appData.whitePieceColor);
2484 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2485 if (vTo.addr == NULL) {
2486 appData.monoMode = True;
2489 whitePieceColor = *(Pixel *) vTo.addr;
2492 if (!appData.monoMode) {
2493 vFrom.addr = (caddr_t) appData.blackPieceColor;
2494 vFrom.size = strlen(appData.blackPieceColor);
2495 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2496 if (vTo.addr == NULL) {
2497 appData.monoMode = True;
2500 blackPieceColor = *(Pixel *) vTo.addr;
2504 if (!appData.monoMode) {
2505 vFrom.addr = (caddr_t) appData.highlightSquareColor;
2506 vFrom.size = strlen(appData.highlightSquareColor);
2507 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2508 if (vTo.addr == NULL) {
2509 appData.monoMode = True;
2512 highlightSquareColor = *(Pixel *) vTo.addr;
2516 if (!appData.monoMode) {
2517 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
2518 vFrom.size = strlen(appData.premoveHighlightColor);
2519 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2520 if (vTo.addr == NULL) {
2521 appData.monoMode = True;
2524 premoveHighlightColor = *(Pixel *) vTo.addr;
2529 fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2532 if (appData.bitmapDirectory == NULL ||
2533 appData.bitmapDirectory[0] == NULLCHAR)
2534 appData.bitmapDirectory = DEF_BITMAP_DIR;
2537 if (appData.lowTimeWarning && !appData.monoMode) {
2538 vFrom.addr = (caddr_t) appData.lowTimeWarningColor;
2539 vFrom.size = strlen(appData.lowTimeWarningColor);
2540 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2541 if (vTo.addr == NULL)
2542 appData.monoMode = True;
2544 lowTimeWarningColor = *(Pixel *) vTo.addr;
2547 if (appData.monoMode && appData.debugMode) {
2548 fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2549 (unsigned long) XWhitePixel(xDisplay, xScreen),
2550 (unsigned long) XBlackPixel(xDisplay, xScreen));
2553 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
2554 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
2555 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
2556 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
2557 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
2558 parse_cpair(ColorTell, appData.colorTell) < 0 ||
2559 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
2560 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
2561 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
2562 parse_cpair(ColorNormal, appData.colorNormal) < 0)
2564 if (appData.colorize) {
2566 _("%s: can't parse color names; disabling colorization\n"),
2569 appData.colorize = FALSE;
2571 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2572 textColors[ColorNone].attr = 0;
2574 // XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2580 layoutName = "tinyLayout";
2581 } else if (smallLayout) {
2582 layoutName = "smallLayout";
2584 layoutName = "normalLayout";
2587 if (appData.titleInWindow) {
2588 /* todo check what this appdata does */
2591 if (appData.showButtonBar) {
2592 /* TODO hide button bar if requested */
2596 * gtk set properties of widgets
2599 /* set board size */
2600 gtk_widget_set_size_request(GTK_WIDGET(GUI_Board),
2601 boardWidth,boardHeight);
2603 /* end gtk set properties of widgets */
2605 if (appData.titleInWindow)
2610 if (appData.showButtonBar)
2617 if (appData.showButtonBar)
2626 // [HGM] it seems the layout code ends here, but perhaps the color stuff is size independent and would
2627 // not need to go into InitDrawingSizes().
2630 /* set some checkboxes in the menu according to appData */
2632 if (appData.alwaysPromoteToQueen)
2633 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Always Queen")),TRUE);
2635 if (appData.animateDragging)
2636 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Animate Dragging")),TRUE);
2638 if (appData.animate)
2639 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Animate Moving")),TRUE);
2641 if (appData.autoComment)
2642 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Comment")),TRUE);
2644 if (appData.autoCallFlag)
2645 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Flag")),TRUE);
2647 if (appData.autoFlipView)
2648 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Flip View")),TRUE);
2650 if (appData.autoObserve)
2651 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Observe")),TRUE);
2653 if (appData.autoRaiseBoard)
2654 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Raise Board")),TRUE);
2656 if (appData.autoSaveGames)
2657 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Save")),TRUE);
2659 if (appData.saveGameFile[0] != NULLCHAR)
2661 /* Can't turn this off from menu */
2662 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Save")),TRUE);
2663 gtk_action_set_sensitive(GTK_ACTION (gtk_builder_get_object (builder, "menuOptions.Auto Save")),FALSE);
2666 if (appData.blindfold)
2667 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Blindfold")),TRUE);
2669 if (appData.flashCount > 0)
2670 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Flash Moves")),TRUE);
2672 if (appData.getMoveList)
2673 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Get Move List")),TRUE);
2676 if (appData.highlightDragging)
2677 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Highlight Dragging")),TRUE);
2680 if (appData.highlightLastMove)
2681 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Highlight Last Move")),TRUE);
2683 if (appData.icsAlarm)
2684 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.ICS Alarm")),TRUE);
2686 if (appData.ringBellAfterMoves)
2687 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Move Sound")),TRUE);
2689 if (appData.oldSaveStyle)
2690 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Old Save Style")),TRUE);
2692 if (appData.periodicUpdates)
2693 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Periodic Updates")),TRUE);
2695 if (appData.ponderNextMove)
2696 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Ponder Next Move")),TRUE);
2698 if (appData.popupExitMessage)
2699 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Popup Exit Message")),TRUE);
2701 if (appData.popupMoveErrors)
2702 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Popup Move Errors")),TRUE);
2704 if (appData.premove)
2705 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Premove")),TRUE);
2707 if (appData.quietPlay)
2708 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Quit Play")),TRUE);
2710 if (appData.showCoords)
2711 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Show Coords")),TRUE);
2713 if (appData.showThinking)
2714 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Show Thinking")),TRUE);
2716 if (appData.testLegality)
2717 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Test Legality")),TRUE);
2719 /* end setting check boxes */
2722 /* load square colors */
2723 SVGLightSquare = load_pixbuf("svg/LightSquare.svg",squareSize);
2724 SVGDarkSquare = load_pixbuf("svg/DarkSquare.svg",squareSize);
2725 SVGNeutralSquare = load_pixbuf("svg/NeutralSquare.svg",squareSize);
2727 /* use two icons to indicate if it is white's or black's turn */
2728 WhiteIcon = load_pixbuf("svg/icon_white.svg",0);
2729 BlackIcon = load_pixbuf("svg/icon_black.svg",0);
2730 WindowIcon = WhiteIcon;
2731 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
2733 /* do resizing to a fixed aspect ratio */
2738 GUI_SetAspectRatio(0.7);
2740 /* realize window */
2741 gtk_widget_show (GUI_Window);
2747 if (appData.animate || appData.animateDragging)
2752 if (errorExitStatus == -1) {
2753 if (appData.icsActive) {
2754 /* We now wait until we see "login:" from the ICS before
2755 sending the logon script (problems with timestamp otherwise) */
2756 /*ICSInitScript();*/
2757 if (appData.icsInputBox) ICSInputBoxPopUp();
2760 signal(SIGINT, IntSigHandler);
2761 signal(SIGTERM, IntSigHandler);
2762 if (*appData.cmailGameName != NULLCHAR) {
2763 signal(SIGUSR1, CmailSigHandler);
2766 gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes()
2770 * Create a cursor for the board widget.
2771 * (This needs to be called after the window has been created to have access to board-window)
2774 BoardCursor = gdk_cursor_new(GDK_HAND2);
2775 gdk_window_set_cursor(GUI_Board->window, BoardCursor);
2776 gdk_cursor_destroy(BoardCursor);
2781 if (appData.debugMode) fclose(debugFP); // [DM] debug
2788 if (appData.icsActive && oldICSInteractionTitle != NULL) {
2789 DisplayIcsInteractionTitle(oldICSInteractionTitle);
2791 unlink(gameCopyFilename);
2792 unlink(gamePasteFilename);
2803 CmailSigHandler(sig)
2809 signal(SIGUSR1, SIG_IGN); /* suspend handler */
2811 /* Activate call-back function CmailSigHandlerCallBack() */
2812 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
2814 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
2818 CmailSigHandlerCallBack(isr, closure, message, count, error)
2826 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
2828 /**** end signal code ****/
2838 f = fopen(appData.icsLogon, "r");
2844 strcat(buf, appData.icsLogon);
2845 f = fopen(buf, "r");
2849 ProcessICSInitScript(f);
2856 EditCommentPopDown();
2862 SetMenuEnables(enab)
2867 if (!builder) return;
2868 while (enab->name != NULL) {
2869 o = gtk_builder_get_object(builder, enab->name);
2870 if(GTK_IS_WIDGET(o))
2871 gtk_widget_set_sensitive(GTK_WIDGET (o),enab->value);
2874 if(GTK_IS_ACTION(o))
2875 gtk_action_set_sensitive(GTK_ACTION (o),enab->value);
2877 DisplayError(enab->name, 0);
2885 SetMenuEnables(icsEnables);
2888 if (appData.zippyPlay && !appData.noChessProgram) /* [DM] icsEngineAnalyze */
2889 {}; // XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
2896 SetMenuEnables(ncpEnables);
2902 SetMenuEnables(gnuEnables);
2908 SetMenuEnables(cmailEnables);
2914 SetMenuEnables(trainingOnEnables);
2915 if (appData.showButtonBar) {
2916 // XtSetSensitive(buttonBarWidget, False);
2922 SetTrainingModeOff()
2924 SetMenuEnables(trainingOffEnables);
2925 if (appData.showButtonBar) {
2926 // XtSetSensitive(buttonBarWidget, True);
2931 SetUserThinkingEnables()
2933 if (appData.noChessProgram) return;
2934 SetMenuEnables(userThinkingEnables);
2938 SetMachineThinkingEnables()
2940 if (appData.noChessProgram) return;
2941 SetMenuEnables(machineThinkingEnables);
2943 case MachinePlaysBlack:
2944 case MachinePlaysWhite:
2945 case TwoMachinesPlay:
2946 // XtSetSensitive(XtNameToWidget(menuBarWidget,
2947 // ModeToWidgetName(gameMode)), True);
2954 #define Abs(n) ((n)<0 ? -(n) : (n))
2957 * Find a font that matches "pattern" that is as close as
2958 * possible to the targetPxlSize. Prefer fonts that are k
2959 * pixels smaller to fonts that are k pixels larger. The
2960 * pattern must be in the X Consortium standard format,
2961 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
2962 * The return value should be freed with XtFree when no
2965 char *FindFont(pattern, targetPxlSize)
2969 char **fonts, *p, *best, *scalable, *scalableTail;
2970 int i, j, nfonts, minerr, err, pxlSize;
2973 char **missing_list;
2975 char *def_string, *base_fnt_lst, strInt[3];
2977 XFontStruct **fnt_list;
2979 base_fnt_lst = calloc(1, strlen(pattern) + 3);
2980 sprintf(strInt, "%d", targetPxlSize);
2981 p = strstr(pattern, "--");
2982 strncpy(base_fnt_lst, pattern, p - pattern + 2);
2983 strcat(base_fnt_lst, strInt);
2984 strcat(base_fnt_lst, strchr(p + 2, '-'));
2986 if ((fntSet = XCreateFontSet(xDisplay,
2990 &def_string)) == NULL) {
2992 fprintf(stderr, _("Unable to create font set.\n"));
2996 nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
2998 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
3000 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
3001 programName, pattern);
3009 for (i=0; i<nfonts; i++) {
3012 if (*p != '-') continue;
3014 if (*p == NULLCHAR) break;
3015 if (*p++ == '-') j++;
3017 if (j < 7) continue;
3020 scalable = fonts[i];
3023 err = pxlSize - targetPxlSize;
3024 if (Abs(err) < Abs(minerr) ||
3025 (minerr > 0 && err < 0 && -err == minerr)) {
3031 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
3032 /* If the error is too big and there is a scalable font,
3033 use the scalable font. */
3034 int headlen = scalableTail - scalable;
3035 p = (char *) XtMalloc(strlen(scalable) + 10);
3036 while (isdigit(*scalableTail)) scalableTail++;
3037 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
3039 p = (char *) XtMalloc(strlen(best) + 1);
3042 if (appData.debugMode) {
3043 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
3044 pattern, targetPxlSize, p);
3047 if (missing_count > 0)
3048 XFreeStringList(missing_list);
3049 XFreeFontSet(xDisplay, fntSet);
3051 XFreeFontNames(fonts);
3058 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
3059 | GCBackground | GCFunction | GCPlaneMask;
3060 XGCValues gc_values;
3063 gc_values.plane_mask = AllPlanes;
3064 gc_values.line_width = lineGap;
3065 gc_values.line_style = LineSolid;
3066 gc_values.function = GXcopy;
3068 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3069 gc_values.background = XWhitePixel(xDisplay, xScreen);
3070 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
3071 XSetFont(xDisplay, coordGC, coordFontID);
3073 if (appData.monoMode) {
3074 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3075 gc_values.background = XBlackPixel(xDisplay, xScreen);
3076 lightSquareGC = wbPieceGC
3077 = XtGetGC(shellWidget, value_mask, &gc_values);
3079 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3080 gc_values.background = XWhitePixel(xDisplay, xScreen);
3081 darkSquareGC = bwPieceGC
3082 = XtGetGC(shellWidget, value_mask, &gc_values);
3084 if (DefaultDepth(xDisplay, xScreen) == 1) {
3085 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3086 gc_values.function = GXcopyInverted;
3087 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3088 gc_values.function = GXcopy;
3089 if (XBlackPixel(xDisplay, xScreen) == 1) {
3090 bwPieceGC = darkSquareGC;
3091 wbPieceGC = copyInvertedGC;
3093 bwPieceGC = copyInvertedGC;
3094 wbPieceGC = lightSquareGC;
3098 gc_values.foreground = lightSquareColor;
3099 gc_values.background = darkSquareColor;
3100 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3102 gc_values.foreground = darkSquareColor;
3103 gc_values.background = lightSquareColor;
3104 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3106 gc_values.foreground = jailSquareColor;
3107 gc_values.background = jailSquareColor;
3108 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3110 gc_values.foreground = whitePieceColor;
3111 gc_values.background = darkSquareColor;
3112 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3114 gc_values.foreground = whitePieceColor;
3115 gc_values.background = lightSquareColor;
3116 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3118 gc_values.foreground = whitePieceColor;
3119 gc_values.background = jailSquareColor;
3120 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3122 gc_values.foreground = blackPieceColor;
3123 gc_values.background = darkSquareColor;
3124 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3126 gc_values.foreground = blackPieceColor;
3127 gc_values.background = lightSquareColor;
3128 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3130 gc_values.foreground = blackPieceColor;
3131 gc_values.background = jailSquareColor;
3132 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3139 WhitePawn, WhiteKnight, WhiteBishop, WhiteRook, WhiteQueen, WhiteKing,
3140 BlackPawn, BlackKnight, BlackBishop, BlackRook, BlackQueen, BlackKing,
3144 /* get some defaults going */
3145 for(i=WhitePawn; i<DemotePiece+1; i++)
3146 SVGpieces[i] = load_pixbuf("svg/NeutralSquare.svg",squareSize);
3149 SVGpieces[WhitePawn] = load_pixbuf("svg/WhitePawn.svg",squareSize);
3150 SVGpieces[WhiteKnight] = load_pixbuf("svg/WhiteKnight.svg",squareSize);
3151 SVGpieces[WhiteBishop] = load_pixbuf("svg/WhiteBishop.svg",squareSize);
3152 SVGpieces[WhiteRook] = load_pixbuf("svg/WhiteRook.svg",squareSize);
3153 SVGpieces[WhiteQueen] = load_pixbuf("svg/WhiteQueen.svg",squareSize);
3154 SVGpieces[WhiteKing] = load_pixbuf("svg/WhiteKing.svg",squareSize);
3156 SVGpieces[BlackPawn] = load_pixbuf("svg/BlackPawn.svg",squareSize);
3157 SVGpieces[BlackKnight] = load_pixbuf("svg/BlackKnight.svg",squareSize);
3158 SVGpieces[BlackBishop] = load_pixbuf("svg/BlackBishop.svg",squareSize);
3159 SVGpieces[BlackRook] = load_pixbuf("svg/BlackRook.svg",squareSize);
3160 SVGpieces[BlackQueen] = load_pixbuf("svg/BlackQueen.svg",squareSize);
3161 SVGpieces[BlackKing] = load_pixbuf("svg/BlackKing.svg",squareSize);
3167 static void MenuBarSelect(w, addr, index)
3172 XtActionProc proc = (XtActionProc) addr;
3174 (proc)(NULL, NULL, NULL, NULL);
3177 void CreateMenuBarPopup(parent, name, mb)
3187 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3190 XtSetArg(args[j], XtNleftMargin, 20); j++;
3191 XtSetArg(args[j], XtNrightMargin, 20); j++;
3193 while (mi->string != NULL) {
3194 if (strcmp(mi->string, "----") == 0) {
3195 entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
3198 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string)));
3199 entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass,
3201 XtAddCallback(entry, XtNcallback,
3202 (XtCallbackProc) MenuBarSelect,
3203 (caddr_t) mi->proc);
3209 Widget CreateMenuBar(mb)
3213 Widget anchor, menuBar;
3215 char menuName[MSG_SIZ];
3218 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3219 XtSetArg(args[j], XtNvSpace, 0); j++;
3220 XtSetArg(args[j], XtNborderWidth, 0); j++;
3221 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
3222 formWidget, args, j);
3224 while (mb->name != NULL) {
3225 strcpy(menuName, "menu");
3226 strcat(menuName, mb->name);
3228 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
3231 shortName[0] = _(mb->name)[0];
3232 shortName[1] = NULLCHAR;
3233 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
3236 XtSetArg(args[j], XtNlabel, XtNewString(_(mb->name))); j++;
3239 XtSetArg(args[j], XtNborderWidth, 0); j++;
3240 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
3242 CreateMenuBarPopup(menuBar, menuName, mb);
3248 Widget CreateButtonBar(mi)
3252 Widget button, buttonBar;
3256 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3258 XtSetArg(args[j], XtNhSpace, 0); j++;
3260 XtSetArg(args[j], XtNborderWidth, 0); j++;
3261 XtSetArg(args[j], XtNvSpace, 0); j++;
3262 buttonBar = XtCreateWidget("buttonBar", boxWidgetClass,
3263 formWidget, args, j);
3265 while (mi->string != NULL) {
3268 XtSetArg(args[j], XtNinternalWidth, 2); j++;
3269 XtSetArg(args[j], XtNborderWidth, 0); j++;
3271 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string))); j++;
3272 button = XtCreateManagedWidget(mi->string, commandWidgetClass,
3273 buttonBar, args, j);
3274 XtAddCallback(button, XtNcallback,
3275 (XtCallbackProc) MenuBarSelect,
3276 (caddr_t) mi->proc);
3283 CreatePieceMenu(name, color)
3290 ChessSquare selection;
3292 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3293 boardWidget, args, 0);
3295 for (i = 0; i < PIECE_MENU_SIZE; i++) {
3296 String item = pieceMenuStrings[color][i];
3298 if (strcmp(item, "----") == 0) {
3299 entry = XtCreateManagedWidget(item, smeLineObjectClass,
3302 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3303 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3305 selection = pieceMenuTranslation[color][i];
3306 XtAddCallback(entry, XtNcallback,
3307 (XtCallbackProc) PieceMenuSelect,
3308 (caddr_t) selection);
3309 if (selection == WhitePawn || selection == BlackPawn) {
3310 XtSetArg(args[0], XtNpopupOnEntry, entry);
3311 XtSetValues(menu, args, 1);
3324 ChessSquare selection;
3326 // whitePieceMenu = CreatePieceMenu("menuW", 0);
3327 // blackPieceMenu = CreatePieceMenu("menuB", 1);
3329 // XtRegisterGrabAction(PieceMenuPopup, True,
3330 // (unsigned)(ButtonPressMask|ButtonReleaseMask),
3331 // GrabModeAsync, GrabModeAsync);
3333 // XtSetArg(args[0], XtNlabel, _("Drop"));
3334 // dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
3335 // boardWidget, args, 1);
3336 // for (i = 0; i < DROP_MENU_SIZE; i++) {
3337 // String item = dropMenuStrings[i];
3339 // if (strcmp(item, "----") == 0) {
3340 // entry = XtCreateManagedWidget(item, smeLineObjectClass,
3341 // dropMenu, NULL, 0);
3343 // XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3344 // entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3345 // dropMenu, args, 1);
3346 // selection = dropMenuTranslation[i];
3347 // XtAddCallback(entry, XtNcallback,
3348 // (XtCallbackProc) DropMenuSelect,
3349 // (caddr_t) selection);
3354 void SetupDropMenu()
3362 for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
3363 entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
3364 p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
3365 dmEnables[i].piece);
3366 XtSetSensitive(entry, p != NULL || !appData.testLegality
3367 /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
3368 && !appData.icsActive));
3370 while (p && *p++ == dmEnables[i].piece) count++;
3371 snprintf(label, sizeof(label), "%s %d", dmEnables[i].widget, count);
3373 XtSetArg(args[j], XtNlabel, label); j++;
3374 XtSetValues(entry, args, j);
3378 void PieceMenuPopup(w, event, params, num_params)
3382 Cardinal *num_params;
3385 if (event->type != ButtonPress) return;
3386 if (errorUp) ErrorPopDown();
3390 whichMenu = params[0];
3392 case IcsPlayingWhite:
3393 case IcsPlayingBlack:
3395 case MachinePlaysWhite:
3396 case MachinePlaysBlack:
3397 if (appData.testLegality &&
3398 gameInfo.variant != VariantBughouse &&
3399 gameInfo.variant != VariantCrazyhouse) return;
3401 whichMenu = "menuD";
3407 if (((pmFromX = EventToSquare(event->xbutton.x, BOARD_WIDTH)) < 0) ||
3408 ((pmFromY = EventToSquare(event->xbutton.y, BOARD_HEIGHT)) < 0)) {
3409 pmFromX = pmFromY = -1;
3413 pmFromX = BOARD_WIDTH - 1 - pmFromX;
3415 pmFromY = BOARD_HEIGHT - 1 - pmFromY;
3417 XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
3420 static void PieceMenuSelect(w, piece, junk)
3425 if (pmFromX < 0 || pmFromY < 0) return;
3426 EditPositionMenuEvent(piece, pmFromX, pmFromY);
3429 static void DropMenuSelect(w, piece, junk)
3434 if (pmFromX < 0 || pmFromY < 0) return;
3435 DropMenuEvent(piece, pmFromX, pmFromY);
3438 void WhiteClock(w, event, prms, nprms)
3444 if (gameMode == EditPosition || gameMode == IcsExamining) {
3445 SetWhiteToPlayEvent();
3446 } else if (gameMode == IcsPlayingBlack || gameMode == MachinePlaysWhite) {
3451 void BlackClock(w, event, prms, nprms)
3457 if (gameMode == EditPosition || gameMode == IcsExamining) {
3458 SetBlackToPlayEvent();
3459 } else if (gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) {
3466 * If the user selects on a border boundary, return -1; if off the board,
3467 * return -2. Otherwise map the event coordinate to the square.
3469 int EventToSquare(x, limit)
3477 if ((x % (squareSize + lineGap)) >= squareSize)
3479 x /= (squareSize + lineGap);
3485 static void do_flash_delay(msec)
3491 static void drawHighlight(file, rank, line_type)
3492 int file, rank, line_type;
3497 if (lineGap == 0 || appData.blindfold) return;
3501 x = lineGap/2 + ((BOARD_WIDTH-1)-file) *
3502 (squareSize + lineGap);
3503 y = lineGap/2 + rank * (squareSize + lineGap);
3507 x = lineGap/2 + file * (squareSize + lineGap);
3508 y = lineGap/2 + ((BOARD_HEIGHT-1)-rank) *
3509 (squareSize + lineGap);
3513 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3515 /* draw the highlight */
3516 cairo_move_to (cr, x, y);
3517 cairo_rel_line_to (cr, 0,squareSize+lineGap);
3518 cairo_rel_line_to (cr, squareSize+lineGap,0);
3519 cairo_rel_line_to (cr, 0,-squareSize-lineGap);
3520 cairo_close_path (cr);
3522 cairo_set_line_width (cr, lineGap);
3525 /* TODO: use appdata colors */
3526 case LINE_TYPE_HIGHLIGHT:
3527 cairo_set_source_rgba (cr, 1, 1, 0, 1.0);
3530 cairo_set_source_rgba (cr, 1, 0, 0, 1.0);
3532 case LINE_TYPE_NORMAL:
3534 cairo_set_source_rgba (cr, 0, 1, 0, 1.0);
3545 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
3546 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
3549 SetHighlights(fromX, fromY, toX, toY)
3550 int fromX, fromY, toX, toY;
3552 if (hi1X != fromX || hi1Y != fromY)
3554 if (hi1X >= 0 && hi1Y >= 0)
3556 drawHighlight(hi1X, hi1Y, LINE_TYPE_NORMAL);
3558 if (fromX >= 0 && fromY >= 0)
3560 drawHighlight(fromX, fromY, LINE_TYPE_HIGHLIGHT);
3563 if (hi2X != toX || hi2Y != toY)
3565 if (hi2X >= 0 && hi2Y >= 0)
3567 drawHighlight(hi2X, hi2Y, LINE_TYPE_NORMAL);
3569 if (toX >= 0 && toY >= 0)
3571 drawHighlight(toX, toY, LINE_TYPE_HIGHLIGHT);
3585 SetHighlights(-1, -1, -1, -1);
3590 SetPremoveHighlights(fromX, fromY, toX, toY)
3591 int fromX, fromY, toX, toY;
3593 if (pm1X != fromX || pm1Y != fromY)
3595 if (pm1X >= 0 && pm1Y >= 0)
3597 drawHighlight(pm1X, pm1Y, LINE_TYPE_NORMAL);
3599 if (fromX >= 0 && fromY >= 0)
3601 drawHighlight(fromX, fromY, LINE_TYPE_PRE);
3604 if (pm2X != toX || pm2Y != toY)
3606 if (pm2X >= 0 && pm2Y >= 0)
3608 drawHighlight(pm2X, pm2Y, LINE_TYPE_NORMAL);
3610 if (toX >= 0 && toY >= 0)
3612 drawHighlight(toX, toY, LINE_TYPE_PRE);
3625 ClearPremoveHighlights()
3627 SetPremoveHighlights(-1, -1, -1, -1);
3630 static void BlankSquare(x, y, color, piece, dest)
3643 pb = SVGLightSquare;
3645 case 2: /* neutral */
3647 pb = SVGNeutralSquare;
3650 gdk_draw_pixbuf(GDK_WINDOW(GUI_Board->window),NULL,pb,0,0,x,y,-1,-1, GDK_RGB_DITHER_NORMAL, 0, 0);
3654 static void DrawPiece(piece, square_color, x, y, dest)
3656 int square_color, x, y;
3659 /* redraw background, since piece might be transparent in some areas */
3660 BlankSquare(x,y,square_color,piece,dest);
3663 gdk_draw_pixbuf(GDK_WINDOW(GUI_Board->window),NULL,
3664 GDK_PIXBUF(SVGpieces[piece]),0,0,x,y,-1,-1,
3665 GDK_RGB_DITHER_NORMAL, 0, 0);
3669 /* [HR] determine square color depending on chess variant. */
3670 static int SquareColor(row, column)
3675 if (gameInfo.variant == VariantXiangqi) {
3676 if (column >= 3 && column <= 5 && row >= 0 && row <= 2) {
3678 } else if (column >= 3 && column <= 5 && row >= 7 && row <= 9) {
3680 } else if (row <= 4) {
3686 square_color = ((column + row) % 2) == 1;
3689 /* [hgm] holdings: next line makes all holdings squares light */
3690 if(column < BOARD_LEFT || column >= BOARD_RGHT) square_color = 1;
3692 return square_color;
3695 void DrawSquare(row, column, piece, do_flash)
3696 int row, column, do_flash;
3699 int square_color, x, y;
3704 /* Calculate delay in milliseconds (2-delays per complete flash) */
3705 flash_delay = 500 / appData.flashRate;
3707 /* calculate x and y coordinates from row and column */
3710 x = lineGap + ((BOARD_WIDTH-1)-column) *
3711 (squareSize + lineGap);
3712 y = lineGap + row * (squareSize + lineGap);
3716 x = lineGap + column * (squareSize + lineGap);
3717 y = lineGap + ((BOARD_HEIGHT-1)-row) *
3718 (squareSize + lineGap);
3721 square_color = SquareColor(row, column);
3723 // [HGM] holdings: blank out area between board and holdings
3724 if ( column == BOARD_LEFT-1 || column == BOARD_RGHT
3725 || (column == BOARD_LEFT-2 && row < BOARD_HEIGHT-gameInfo.holdingsSize)
3726 || (column == BOARD_RGHT+1 && row >= gameInfo.holdingsSize) )
3728 BlankSquare(x, y, 2, EmptySquare, xBoardWindow);
3730 // [HGM] print piece counts next to holdings
3731 string[1] = NULLCHAR;
3734 cairo_text_extents_t extents;
3739 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3741 string[0] = '0' + piece;
3743 /* TODO this has to go into the font-selection */
3744 cairo_select_font_face (cr, "Sans",
3745 CAIRO_FONT_SLANT_NORMAL,
3746 CAIRO_FONT_WEIGHT_NORMAL);
3748 cairo_set_font_size (cr, 12.0);
3749 cairo_text_extents (cr, string, &extents);
3751 if (column == (flipView ? BOARD_LEFT-1 : BOARD_RGHT) )
3753 xpos= x + squareSize - extents.width - 2;
3754 ypos= y + extents.y_bearing + 1;
3756 if (column == (flipView ? BOARD_RGHT : BOARD_LEFT-1) && piece > 1)
3759 ypos = y + extents.y_bearing + 1;
3762 /* TODO mono mode? */
3763 cairo_move_to (cr, xpos, ypos);
3764 cairo_text_path (cr, string);
3765 cairo_set_source_rgb (cr, 1.0, 1.0, 1);
3766 cairo_fill_preserve (cr);
3767 cairo_set_source_rgb (cr, 0, 0, 0);
3768 cairo_set_line_width (cr, 0.1);
3777 /* square on the board */
3778 if (piece == EmptySquare || appData.blindfold)
3780 BlankSquare(x, y, square_color, piece, xBoardWindow);
3784 if (do_flash && appData.flashCount > 0)
3786 for (i=0; i<appData.flashCount; ++i)
3789 DrawPiece(piece, square_color, x, y, xBoardWindow);
3790 do_flash_delay(flash_delay);
3792 BlankSquare(x, y, square_color, piece, xBoardWindow);
3793 do_flash_delay(flash_delay);
3796 DrawPiece(piece, square_color, x, y, xBoardWindow);
3800 /* show coordinates if necessary */
3801 if(appData.showCoords)
3803 cairo_text_extents_t extents;
3807 /* TODO this has to go into the font-selection */
3808 cairo_select_font_face (cr, "Sans",
3809 CAIRO_FONT_SLANT_NORMAL,
3810 CAIRO_FONT_WEIGHT_NORMAL);
3811 cairo_set_font_size (cr, 12.0);
3813 string[1] = NULLCHAR;
3816 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3818 if (row == (flipView ? BOARD_HEIGHT-1 : 0) &&
3819 column >= BOARD_LEFT && column < BOARD_RGHT)
3821 string[0] = 'a' + column - BOARD_LEFT;
3822 cairo_text_extents (cr, string, &extents);
3824 xpos = x + squareSize - extents.width - 2;
3825 ypos = y + squareSize - extents.height - extents.y_bearing - 1;
3827 if (appData.monoMode)
3834 cairo_move_to (cr, xpos, ypos);
3835 cairo_text_path (cr, string);
3836 cairo_set_source_rgb (cr, 0.0, 0.0, 0);
3837 cairo_fill_preserve (cr);
3838 cairo_set_source_rgb (cr, 0, 1.0, 0);
3839 cairo_set_line_width (cr, 0.1);
3842 if ( column == (flipView ? BOARD_RGHT-1 : BOARD_LEFT))
3845 string[0] = ONE + row;
3846 cairo_text_extents (cr, string, &extents);
3849 ypos = y + extents.height + 1;
3851 if (appData.monoMode)
3858 cairo_move_to (cr, xpos, ypos);
3859 cairo_text_path (cr, string);
3860 cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
3861 cairo_fill_preserve (cr);
3862 cairo_set_source_rgb (cr, 0, 0, 1.0);
3863 cairo_set_line_width (cr, 0.1);
3875 /* Returns 1 if there are "too many" differences between b1 and b2
3876 (i.e. more than 1 move was made) */
3877 static int too_many_diffs(b1, b2)
3883 for (i=0; i<BOARD_HEIGHT; ++i) {
3884 for (j=0; j<BOARD_WIDTH; ++j) {
3885 if (b1[i][j] != b2[i][j]) {
3886 if (++c > 4) /* Castling causes 4 diffs */
3895 /* Matrix describing castling maneuvers */
3896 /* Row, ColRookFrom, ColKingFrom, ColRookTo, ColKingTo */
3897 static int castling_matrix[4][5] = {
3898 { 0, 0, 4, 3, 2 }, /* 0-0-0, white */
3899 { 0, 7, 4, 5, 6 }, /* 0-0, white */
3900 { 7, 0, 4, 3, 2 }, /* 0-0-0, black */
3901 { 7, 7, 4, 5, 6 } /* 0-0, black */
3904 /* Checks whether castling occurred. If it did, *rrow and *rcol
3905 are set to the destination (row,col) of the rook that moved.
3907 Returns 1 if castling occurred, 0 if not.
3909 Note: Only handles a max of 1 castling move, so be sure
3910 to call too_many_diffs() first.
3912 static int check_castle_draw(newb, oldb, rrow, rcol)
3919 /* For each type of castling... */
3920 for (i=0; i<4; ++i) {
3921 r = castling_matrix[i];
3923 /* Check the 4 squares involved in the castling move */
3925 for (j=1; j<=4; ++j) {
3926 if (newb[r[0]][r[j]] == oldb[r[0]][r[j]]) {
3933 /* All 4 changed, so it must be a castling move */
3942 static int damage[BOARD_SIZE][BOARD_SIZE];
3945 * event handler for redrawing the board
3947 void DrawPosition( repaint, board)
3948 /*Boolean*/int repaint;
3952 static int lastFlipView = 0;
3953 static int lastBoardValid = 0;
3954 static Board lastBoard;
3957 if (board == NULL) {
3958 if (!lastBoardValid) return;
3961 if (!lastBoardValid || lastFlipView != flipView) {
3962 // XtSetArg(args[0], XtNleftBitmap, (flipView ? xMarkPixmap : None));
3963 // XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flip View"),
3968 * It would be simpler to clear the window with XClearWindow()
3969 * but this causes a very distracting flicker.
3972 if (!repaint && lastBoardValid && lastFlipView == flipView)
3974 /* If too much changes (begin observing new game, etc.), don't
3976 do_flash = too_many_diffs(board, lastBoard) ? 0 : 1;
3978 /* Special check for castling so we don't flash both the king
3979 and the rook (just flash the king). */
3982 if (check_castle_draw(board, lastBoard, &rrow, &rcol))
3984 /* Draw rook with NO flashing. King will be drawn flashing later */
3985 DrawSquare(rrow, rcol, board[rrow][rcol], 0);
3986 lastBoard[rrow][rcol] = board[rrow][rcol];
3990 /* First pass -- Draw (newly) empty squares and repair damage.
3991 This prevents you from having a piece show up twice while it
3992 is flashing on its new square */
3993 for (i = 0; i < BOARD_HEIGHT; i++)
3994 for (j = 0; j < BOARD_WIDTH; j++)
3995 if ((board[i][j] != lastBoard[i][j] && board[i][j] == EmptySquare)
3998 DrawSquare(i, j, board[i][j], 0);
3999 damage[i][j] = False;
4002 /* Second pass -- Draw piece(s) in new position and flash them */
4003 for (i = 0; i < BOARD_HEIGHT; i++)
4004 for (j = 0; j < BOARD_WIDTH; j++)
4005 if (board[i][j] != lastBoard[i][j])
4007 DrawSquare(i, j, board[i][j], do_flash);
4019 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
4021 cairo_set_line_width (cr, lineGap);
4023 /* TODO: use appdata colors */
4024 cairo_set_source_rgba (cr, 0, 1, 0, 1.0);
4028 for (i = 0; i < BOARD_HEIGHT + 1; i++)
4031 x2 = lineGap + BOARD_WIDTH * (squareSize + lineGap);
4032 y1 = y2 = lineGap / 2 + (i * (squareSize + lineGap));
4034 cairo_move_to (cr, x1, y1);
4035 cairo_rel_line_to (cr, x2,0);
4039 for (j = 0; j < BOARD_WIDTH + 1; j++)
4042 y2 = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
4043 x1 = x2 = lineGap / 2 + (j * (squareSize + lineGap));
4045 cairo_move_to (cr, x1, y1);
4046 cairo_rel_line_to (cr, 0, y2);
4055 for (i = 0; i < BOARD_HEIGHT; i++)
4056 for (j = 0; j < BOARD_WIDTH; j++)
4058 DrawSquare(i, j, board[i][j], 0);
4059 damage[i][j] = False;
4063 CopyBoard(lastBoard, board);
4065 lastFlipView = flipView;
4067 /* Draw highlights */
4068 if (pm1X >= 0 && pm1Y >= 0)
4070 drawHighlight(pm1X, pm1Y, LINE_TYPE_PRE);
4072 if (pm2X >= 0 && pm2Y >= 0)
4074 drawHighlight(pm2X, pm2Y, LINE_TYPE_PRE);
4076 if (hi1X >= 0 && hi1Y >= 0)
4078 drawHighlight(hi1X, hi1Y, LINE_TYPE_HIGHLIGHT);
4080 if (hi2X >= 0 && hi2Y >= 0)
4082 drawHighlight(hi2X, hi2Y, LINE_TYPE_HIGHLIGHT);
4085 /* If piece being dragged around board, must redraw that too */
4092 * event handler for parsing user moves
4094 // [HGM] This routine will need quite some reworking. Although the backend still supports the old
4095 // way of doing things, by calling UserMoveEvent() to test the legality of the move and then perform
4096 // it at the end, and doing all kind of preliminary tests here (e.g. to weed out self-captures), it
4097 // should be made to use the new way, of calling UserMoveTest early to determine the legality of the
4098 // move, (which will weed out the illegal selfcaptures and moves into the holdings, and flag promotions),
4099 // and at the end FinishMove() to perform the move after optional promotion popups.
4100 // For now I patched it to allow self-capture with King, and suppress clicks between board and holdings.
4101 void HandleUserMove(w, event, prms, nprms)
4108 Boolean saveAnimate;
4109 static int second = 0;
4111 if (w != boardWidget || errorExitStatus != -1) return;
4113 if (event->type == ButtonPress) ErrorPopDown();
4116 if (event->type == ButtonPress) {
4117 // XtPopdown(promotionShell);
4118 // XtDestroyWidget(promotionShell);
4119 promotionUp = False;
4127 x = EventToSquare(event->xbutton.x, BOARD_WIDTH);
4128 y = EventToSquare(event->xbutton.y, BOARD_HEIGHT);
4129 if (!flipView && y >= 0) {
4130 y = BOARD_HEIGHT - 1 - y;
4132 if (flipView && x >= 0) {
4133 x = BOARD_WIDTH - 1 - x;
4136 /* [HGM] holdings: next 5 lines: ignore all clicks between board and holdings */
4137 if(event->type == ButtonPress
4138 && ( x == BOARD_LEFT-1 ||
4140 (x == BOARD_LEFT-2 && y < BOARD_HEIGHT-gameInfo.holdingsSize ) ||
4141 (x == BOARD_RGHT+1 && y >= gameInfo.holdingsSize)) )
4145 if (event->type == ButtonPress) {
4147 if (OKToStartUserMove(x, y)) {
4151 DragPieceBegin(event->xbutton.x, event->xbutton.y);
4152 if (appData.highlightDragging) {
4153 SetHighlights(x, y, -1, -1);
4161 if (event->type == ButtonPress && gameMode != EditPosition &&
4167 /* Check if clicking again on the same color piece */
4168 fromP = boards[currentMove][fromY][fromX];
4169 toP = boards[currentMove][y][x];
4170 frc = gameInfo.variant == VariantFischeRandom || gameInfo.variant == VariantCapaRandom;
4171 if ((WhitePawn <= fromP && fromP <= WhiteKing && // [HGM] this test should go, as UserMoveTest now does it.
4172 WhitePawn <= toP && toP <= WhiteKing &&
4173 !(fromP == WhiteKing && toP == WhiteRook && frc)) ||
4174 (BlackPawn <= fromP && fromP <= BlackKing &&
4175 BlackPawn <= toP && toP <= BlackKing &&
4176 !(fromP == BlackKing && toP == BlackRook && frc))) {
4177 /* Clicked again on same color piece -- changed his mind */
4178 second = (x == fromX && y == fromY);
4179 if (appData.highlightDragging) {
4180 SetHighlights(x, y, -1, -1);
4184 if (OKToStartUserMove(x, y)) {
4187 DragPieceBegin(event->xbutton.x, event->xbutton.y);
4193 if (event->type == ButtonRelease && x == fromX && y == fromY) {
4194 DragPieceEnd(event->xbutton.x, event->xbutton.y);
4195 if (appData.animateDragging) {
4196 /* Undo animation damage if any */
4197 DrawPosition(FALSE, NULL);
4200 /* Second up/down in same square; just abort move */
4205 ClearPremoveHighlights();
4207 /* First upclick in same square; start click-click mode */
4208 SetHighlights(x, y, -1, -1);
4213 /* Completed move */
4216 saveAnimate = appData.animate;
4217 if (event->type == ButtonPress) {
4218 /* Finish clickclick move */
4219 if (appData.animate || appData.highlightLastMove) {
4220 SetHighlights(fromX, fromY, toX, toY);
4225 /* Finish drag move */
4226 if (appData.highlightLastMove) {
4227 SetHighlights(fromX, fromY, toX, toY);
4231 DragPieceEnd(event->xbutton.x, event->xbutton.y);
4232 /* Don't animate move and drag both */
4233 appData.animate = FALSE;
4235 if (IsPromotion(fromX, fromY, toX, toY)) {
4236 if (appData.alwaysPromoteToQueen) {
4237 UserMoveEvent(fromX, fromY, toX, toY, 'q');
4238 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
4239 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
4242 SetHighlights(fromX, fromY, toX, toY);
4246 UserMoveEvent(fromX, fromY, toX, toY, NULLCHAR);
4247 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
4248 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
4251 appData.animate = saveAnimate;
4252 if (appData.animate || appData.animateDragging) {
4253 /* Undo animation damage if needed */
4254 DrawPosition(FALSE, NULL);
4258 void AnimateUserMove (Widget w, XEvent * event,
4259 String * params, Cardinal * nParams)
4261 DragPieceMove(event->xmotion.x, event->xmotion.y);
4264 Widget CommentCreate(name, text, mutable, callback, lines)
4266 int /*Boolean*/ mutable;
4267 XtCallbackProc callback;
4271 Widget shell, layout, form, edit, b_ok, b_cancel, b_clear, b_close, b_edit;
4276 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4277 XtGetValues(boardWidget, args, j);
4280 XtSetArg(args[j], XtNresizable, True); j++;
4283 XtCreatePopupShell(name, topLevelShellWidgetClass,
4284 shellWidget, args, j);
4287 XtCreatePopupShell(name, transientShellWidgetClass,
4288 shellWidget, args, j);
4291 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
4292 layoutArgs, XtNumber(layoutArgs));
4294 XtCreateManagedWidget("form", formWidgetClass, layout,
4295 formArgs, XtNumber(formArgs));
4299 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
4300 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
4302 XtSetArg(args[j], XtNstring, text); j++;
4303 XtSetArg(args[j], XtNtop, XtChainTop); j++;
4304 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4305 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4306 XtSetArg(args[j], XtNright, XtChainRight); j++;
4307 XtSetArg(args[j], XtNresizable, True); j++;
4308 XtSetArg(args[j], XtNwidth, bw_width); j++; /*force wider than buttons*/
4310 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
4312 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
4313 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
4315 XtSetArg(args[j], XtNautoFill, True); j++;
4316 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
4318 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
4322 XtSetArg(args[j], XtNfromVert, edit); j++;
4323 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4324 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4325 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4326 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4328 XtCreateManagedWidget(_("ok"), commandWidgetClass, form, args, j);
4329 XtAddCallback(b_ok, XtNcallback, callback, (XtPointer) 0);
4332 XtSetArg(args[j], XtNfromVert, edit); j++;
4333 XtSetArg(args[j], XtNfromHoriz, b_ok); j++;
4334 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4335 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4336 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4337 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4339 XtCreateManagedWidget(_("cancel"), commandWidgetClass, form, args, j);
4340 XtAddCallback(b_cancel, XtNcallback, callback, (XtPointer) 0);
4343 XtSetArg(args[j], XtNfromVert, edit); j++;
4344 XtSetArg(args[j], XtNfromHoriz, b_cancel); j++;
4345 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4346 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4347 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4348 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4350 XtCreateManagedWidget(_("clear"), commandWidgetClass, form, args, j);
4351 XtAddCallback(b_clear, XtNcallback, callback, (XtPointer) 0);
4354 XtSetArg(args[j], XtNfromVert, edit); j++;
4355 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4356 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4357 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4358 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4360 XtCreateManagedWidget(_("close"), commandWidgetClass, form, args, j);
4361 XtAddCallback(b_close, XtNcallback, callback, (XtPointer) 0);
4364 XtSetArg(args[j], XtNfromVert, edit); j++;
4365 XtSetArg(args[j], XtNfromHoriz, b_close); j++;
4366 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4367 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4368 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4369 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4371 XtCreateManagedWidget(_("edit"), commandWidgetClass, form, args, j);
4372 XtAddCallback(b_edit, XtNcallback, callback, (XtPointer) 0);
4375 XtRealizeWidget(shell);
4377 if (commentX == -1) {
4380 Dimension pw_height;
4381 Dimension ew_height;
4384 XtSetArg(args[j], XtNheight, &ew_height); j++;
4385 XtGetValues(edit, args, j);
4388 XtSetArg(args[j], XtNheight, &pw_height); j++;
4389 XtGetValues(shell, args, j);
4390 commentH = pw_height + (lines - 1) * ew_height;
4391 commentW = bw_width - 16;
4393 XSync(xDisplay, False);
4395 /* This code seems to tickle an X bug if it is executed too soon
4396 after xboard starts up. The coordinates get transformed as if
4397 the main window was positioned at (0, 0).
4399 XtTranslateCoords(shellWidget,
4400 (bw_width - commentW) / 2, 0 - commentH / 2,
4401 &commentX, &commentY);
4403 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
4404 RootWindowOfScreen(XtScreen(shellWidget)),
4405 (bw_width - commentW) / 2, 0 - commentH / 2,
4410 if (commentY < 0) commentY = 0; /*avoid positioning top offscreen*/
4413 XtSetArg(args[j], XtNheight, commentH); j++;
4414 XtSetArg(args[j], XtNwidth, commentW); j++;
4415 XtSetArg(args[j], XtNx, commentX); j++;
4416 XtSetArg(args[j], XtNy, commentY); j++;
4417 XtSetValues(shell, args, j);
4418 XtSetKeyboardFocus(shell, edit);
4423 /* Used for analysis window and ICS input window */
4424 Widget MiscCreate(name, text, mutable, callback, lines)
4426 int /*Boolean*/ mutable;
4427 XtCallbackProc callback;
4431 Widget shell, layout, form, edit;
4433 Dimension bw_width, pw_height, ew_height, w, h;
4439 XtSetArg(args[j], XtNresizable, True); j++;
4442 XtCreatePopupShell(name, topLevelShellWidgetClass,
4443 shellWidget, args, j);
4446 XtCreatePopupShell(name, transientShellWidgetClass,
4447 shellWidget, args, j);
4450 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
4451 layoutArgs, XtNumber(layoutArgs));
4453 XtCreateManagedWidget("form", formWidgetClass, layout,
4454 formArgs, XtNumber(formArgs));
4458 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
4459 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
4461 XtSetArg(args[j], XtNstring, text); j++;
4462 XtSetArg(args[j], XtNtop, XtChainTop); j++;
4463 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4464 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4465 XtSetArg(args[j], XtNright, XtChainRight); j++;
4466 XtSetArg(args[j], XtNresizable, True); j++;
4468 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
4470 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
4471 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
4473 XtSetArg(args[j], XtNautoFill, True); j++;
4474 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
4476 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
4478 XtRealizeWidget(shell);
4481 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4482 XtGetValues(boardWidget, args, j);
4485 XtSetArg(args[j], XtNheight, &ew_height); j++;
4486 XtGetValues(edit, args, j);
4489 XtSetArg(args[j], XtNheight, &pw_height); j++;
4490 XtGetValues(shell, args, j);
4491 h = pw_height + (lines - 1) * ew_height;
4494 XSync(xDisplay, False);
4496 /* This code seems to tickle an X bug if it is executed too soon
4497 after xboard starts up. The coordinates get transformed as if
4498 the main window was positioned at (0, 0).
4500 XtTranslateCoords(shellWidget, (bw_width - w) / 2, 0 - h / 2, &x, &y);
4502 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
4503 RootWindowOfScreen(XtScreen(shellWidget)),
4504 (bw_width - w) / 2, 0 - h / 2, &xx, &yy, &junk);
4508 if (y < 0) y = 0; /*avoid positioning top offscreen*/
4511 XtSetArg(args[j], XtNheight, h); j++;
4512 XtSetArg(args[j], XtNwidth, w); j++;
4513 XtSetArg(args[j], XtNx, x); j++;
4514 XtSetArg(args[j], XtNy, y); j++;
4515 XtSetValues(shell, args, j);
4521 static int savedIndex; /* gross that this is global */
4523 void EditCommentPopUp(index, title, text)
4532 if (text == NULL) text = "";
4534 if (editShell == NULL) {
4536 CommentCreate(title, text, True, EditCommentCallback, 4);
4537 XtRealizeWidget(editShell);
4538 CatchDeleteWindow(editShell, "EditCommentPopDown");
4540 edit = XtNameToWidget(editShell, "*form.text");
4542 XtSetArg(args[j], XtNstring, text); j++;
4543 XtSetValues(edit, args, j);
4545 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4546 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4547 XtSetValues(editShell, args, j);
4550 XtPopup(editShell, XtGrabNone);
4554 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
4555 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
4559 void EditCommentCallback(w, client_data, call_data)
4561 XtPointer client_data, call_data;
4569 XtSetArg(args[j], XtNlabel, &name); j++;
4570 XtGetValues(w, args, j);
4572 if (strcmp(name, _("ok")) == 0) {
4573 edit = XtNameToWidget(editShell, "*form.text");
4575 XtSetArg(args[j], XtNstring, &val); j++;
4576 XtGetValues(edit, args, j);
4577 ReplaceComment(savedIndex, val);
4578 EditCommentPopDown();
4579 } else if (strcmp(name, _("cancel")) == 0) {
4580 EditCommentPopDown();
4581 } else if (strcmp(name, _("clear")) == 0) {
4582 edit = XtNameToWidget(editShell, "*form.text");
4583 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
4584 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
4588 void EditCommentPopDown()
4593 if (!editUp) return;
4595 XtSetArg(args[j], XtNx, &commentX); j++;
4596 XtSetArg(args[j], XtNy, &commentY); j++;
4597 XtSetArg(args[j], XtNheight, &commentH); j++;
4598 XtSetArg(args[j], XtNwidth, &commentW); j++;
4599 XtGetValues(editShell, args, j);
4600 XtPopdown(editShell);
4603 XtSetArg(args[j], XtNleftBitmap, None); j++;
4604 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
4608 void ICSInputBoxPopUp()
4613 char *title = _("ICS Input");
4616 if (ICSInputShell == NULL) {
4617 ICSInputShell = MiscCreate(title, "", True, NULL, 1);
4618 tr = XtParseTranslationTable(ICSInputTranslations);
4619 edit = XtNameToWidget(ICSInputShell, "*form.text");
4620 XtOverrideTranslations(edit, tr);
4621 XtRealizeWidget(ICSInputShell);
4622 CatchDeleteWindow(ICSInputShell, "ICSInputBoxPopDown");
4625 edit = XtNameToWidget(ICSInputShell, "*form.text");
4627 XtSetArg(args[j], XtNstring, ""); j++;
4628 XtSetValues(edit, args, j);
4630 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4631 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4632 XtSetValues(ICSInputShell, args, j);
4635 XtPopup(ICSInputShell, XtGrabNone);
4636 XtSetKeyboardFocus(ICSInputShell, edit);
4638 ICSInputBoxUp = True;
4640 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
4641 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
4645 void ICSInputSendText()
4652 edit = XtNameToWidget(ICSInputShell, "*form.text");
4654 XtSetArg(args[j], XtNstring, &val); j++;
4655 XtGetValues(edit, args, j);
4656 SendMultiLineToICS(val);
4657 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
4658 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
4661 void ICSInputBoxPopDown()
4666 if (!ICSInputBoxUp) return;
4668 XtPopdown(ICSInputShell);
4669 ICSInputBoxUp = False;
4671 XtSetArg(args[j], XtNleftBitmap, None); j++;
4672 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
4676 void CommentPopUp(title, text)
4683 if (commentShell == NULL) {
4685 CommentCreate(title, text, False, CommentCallback, 4);
4686 XtRealizeWidget(commentShell);
4687 CatchDeleteWindow(commentShell, "CommentPopDown");
4689 edit = XtNameToWidget(commentShell, "*form.text");
4691 XtSetArg(args[j], XtNstring, text); j++;
4692 XtSetValues(edit, args, j);
4694 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4695 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4696 XtSetValues(commentShell, args, j);
4699 XtPopup(commentShell, XtGrabNone);
4700 XSync(xDisplay, False);
4705 void AnalysisPopUp(title, text)
4712 if (analysisShell == NULL) {
4713 analysisShell = MiscCreate(title, text, False, NULL, 4);
4714 XtRealizeWidget(analysisShell);
4715 CatchDeleteWindow(analysisShell, "AnalysisPopDown");
4718 edit = XtNameToWidget(analysisShell, "*form.text");
4720 XtSetArg(args[j], XtNstring, text); j++;
4721 XtSetValues(edit, args, j);
4723 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4724 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4725 XtSetValues(analysisShell, args, j);
4729 XtPopup(analysisShell, XtGrabNone);
4731 XSync(xDisplay, False);
4736 void CommentCallback(w, client_data, call_data)
4738 XtPointer client_data, call_data;
4745 XtSetArg(args[j], XtNlabel, &name); j++;
4746 XtGetValues(w, args, j);
4748 if (strcmp(name, _("close")) == 0) {
4750 } else if (strcmp(name, _("edit")) == 0) {
4757 void CommentPopDown()
4762 if (!commentUp) return;
4764 XtSetArg(args[j], XtNx, &commentX); j++;
4765 XtSetArg(args[j], XtNy, &commentY); j++;
4766 XtSetArg(args[j], XtNwidth, &commentW); j++;
4767 XtSetArg(args[j], XtNheight, &commentH); j++;
4768 XtGetValues(commentShell, args, j);
4769 XtPopdown(commentShell);
4770 XSync(xDisplay, False);
4774 void AnalysisPopDown()
4776 if (!analysisUp) return;
4777 XtPopdown(analysisShell);
4778 XSync(xDisplay, False);
4780 if (appData.icsEngineAnalyze) ExitAnalyzeMode(); /* [DM] icsEngineAnalyze */
4784 void FileNamePopUp(label, def, proc, openMode)
4791 Widget popup, layout, dialog, edit;
4797 fileProc = proc; /* I can't see a way not */
4798 fileOpenMode = openMode; /* to use globals here */
4801 XtSetArg(args[i], XtNresizable, True); i++;
4802 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
4803 XtSetArg(args[i], XtNtitle, XtNewString(_("File name prompt"))); i++;
4804 fileNameShell = popup =
4805 XtCreatePopupShell("File name prompt", transientShellWidgetClass,
4806 shellWidget, args, i);
4809 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
4810 layoutArgs, XtNumber(layoutArgs));
4813 XtSetArg(args[i], XtNlabel, label); i++;
4814 XtSetArg(args[i], XtNvalue, def); i++;
4815 XtSetArg(args[i], XtNborderWidth, 0); i++;
4816 dialog = XtCreateManagedWidget("fileName", dialogWidgetClass,
4819 XawDialogAddButton(dialog, _("ok"), FileNameCallback, (XtPointer) dialog);
4820 XawDialogAddButton(dialog, _("cancel"), FileNameCallback,
4821 (XtPointer) dialog);
4823 XtRealizeWidget(popup);
4824 CatchDeleteWindow(popup, "FileNamePopDown");
4826 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
4827 &x, &y, &win_x, &win_y, &mask);
4829 XtSetArg(args[0], XtNx, x - 10);
4830 XtSetArg(args[1], XtNy, y - 30);
4831 XtSetValues(popup, args, 2);
4833 XtPopup(popup, XtGrabExclusive);
4836 edit = XtNameToWidget(dialog, "*value");
4837 XtSetKeyboardFocus(popup, edit);
4840 void FileNamePopDown()
4842 if (!filenameUp) return;
4843 XtPopdown(fileNameShell);
4844 XtDestroyWidget(fileNameShell);
4849 void FileNameCallback(w, client_data, call_data)
4851 XtPointer client_data, call_data;
4856 XtSetArg(args[0], XtNlabel, &name);
4857 XtGetValues(w, args, 1);
4859 if (strcmp(name, _("cancel")) == 0) {
4864 FileNameAction(w, NULL, NULL, NULL);
4867 void FileNameAction(w, event, prms, nprms)
4879 name = XawDialogGetValueString(w = XtParent(w));
4881 if ((name != NULL) && (*name != NULLCHAR)) {
4883 XtPopdown(w = XtParent(XtParent(w)));
4887 p = strrchr(buf, ' ');
4894 fullname = ExpandPathName(buf);
4896 ErrorPopUp(_("Error"), _("Can't open file"), FALSE);
4899 f = fopen(fullname, fileOpenMode);
4901 DisplayError(_("Failed to open file"), errno);
4903 (void) (*fileProc)(f, index, buf);
4910 XtPopdown(w = XtParent(XtParent(w)));
4916 void PromotionPopUp()
4919 Widget dialog, layout;
4921 Dimension bw_width, pw_width;
4925 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4926 XtGetValues(boardWidget, args, j);
4929 XtSetArg(args[j], XtNresizable, True); j++;
4930 XtSetArg(args[j], XtNtitle, XtNewString(_("Promotion"))); j++;
4932 XtCreatePopupShell("Promotion", transientShellWidgetClass,
4933 shellWidget, args, j);
4935 XtCreateManagedWidget(layoutName, formWidgetClass, promotionShell,
4936 layoutArgs, XtNumber(layoutArgs));
4939 XtSetArg(args[j], XtNlabel, _("Promote to what?")); j++;
4940 XtSetArg(args[j], XtNborderWidth, 0); j++;
4941 dialog = XtCreateManagedWidget("promotion", dialogWidgetClass,
4944 if(gameInfo.variant != VariantShogi) {
4945 XawDialogAddButton(dialog, _("Queen"), PromotionCallback,
4946 (XtPointer) dialog);
4947 XawDialogAddButton(dialog, _("Rook"), PromotionCallback,
4948 (XtPointer) dialog);
4949 XawDialogAddButton(dialog, _("Bishop"), PromotionCallback,
4950 (XtPointer) dialog);
4951 XawDialogAddButton(dialog, _("Knight"), PromotionCallback,
4952 (XtPointer) dialog);
4953 if (!appData.testLegality || gameInfo.variant == VariantSuicide ||
4954 gameInfo.variant == VariantGiveaway) {
4955 XawDialogAddButton(dialog, _("King"), PromotionCallback,
4956 (XtPointer) dialog);
4958 if(gameInfo.variant == VariantCapablanca ||
4959 gameInfo.variant == VariantGothic ||
4960 gameInfo.variant == VariantCapaRandom) {
4961 XawDialogAddButton(dialog, _("Archbishop"), PromotionCallback,
4962 (XtPointer) dialog);
4963 XawDialogAddButton(dialog, _("Chancellor"), PromotionCallback,
4964 (XtPointer) dialog);
4966 } else // [HGM] shogi
4968 XawDialogAddButton(dialog, _("Promote"), PromotionCallback,
4969 (XtPointer) dialog);
4970 XawDialogAddButton(dialog, _("Defer"), PromotionCallback,
4971 (XtPointer) dialog);
4973 XawDialogAddButton(dialog, _("cancel"), PromotionCallback,
4974 (XtPointer) dialog);
4976 XtRealizeWidget(promotionShell);
4977 CatchDeleteWindow(promotionShell, "PromotionPopDown");
4980 XtSetArg(args[j], XtNwidth, &pw_width); j++;
4981 XtGetValues(promotionShell, args, j);
4983 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
4984 lineGap + squareSize/3 +
4985 ((toY == BOARD_HEIGHT-1) ^ (flipView) ?
4986 0 : 6*(squareSize + lineGap)), &x, &y);
4989 XtSetArg(args[j], XtNx, x); j++;
4990 XtSetArg(args[j], XtNy, y); j++;
4991 XtSetValues(promotionShell, args, j);
4993 XtPopup(promotionShell, XtGrabNone);
4998 void PromotionPopDown()
5000 if (!promotionUp) return;
5001 XtPopdown(promotionShell);
5002 XtDestroyWidget(promotionShell);
5003 promotionUp = False;
5006 void PromotionCallback(w, client_data, call_data)
5008 XtPointer client_data, call_data;
5014 XtSetArg(args[0], XtNlabel, &name);
5015 XtGetValues(w, args, 1);
5019 if (fromX == -1) return;
5021 if (strcmp(name, _("cancel")) == 0) {
5025 } else if (strcmp(name, _("Knight")) == 0) {
5027 } else if (strcmp(name, _("Promote")) == 0) {
5029 } else if (strcmp(name, _("Defer")) == 0) {
5032 promoChar = ToLower(name[0]);
5035 UserMoveEvent(fromX, fromY, toX, toY, promoChar);
5037 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
5038 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
5043 void ErrorCallback(w, client_data, call_data)
5045 XtPointer client_data, call_data;
5048 XtPopdown(w = XtParent(XtParent(XtParent(w))));
5050 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5056 if (!errorUp) return;
5060 gtk_widget_destroy(GTK_WIDGET(GUI_Error));
5062 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5067 void ErrorPopUp(title, label, modal)
5068 char *title, *label;
5071 GUI_Error = gtk_message_dialog_new(GTK_WINDOW(GUI_Window),
5072 GTK_DIALOG_DESTROY_WITH_PARENT,
5077 gtk_window_set_title(GTK_WINDOW(GUI_Error),(gchar *) title);
5080 gtk_dialog_run(GTK_DIALOG(GUI_Error));
5081 gtk_widget_destroy(GTK_WIDGET(GUI_Error));
5085 g_signal_connect_swapped (GUI_Error, "response",
5086 G_CALLBACK (ErrorPopDownProc),
5089 gtk_widget_show(GTK_WIDGET(GUI_Error));
5095 /* Disable all user input other than deleting the window */
5096 static int frozen = 0;
5100 /* Grab by a widget that doesn't accept input */
5101 // XtAddGrab(messageWidget, TRUE, FALSE);
5105 /* Undo a FreezeUI */
5108 if (!frozen) return;
5109 // XtRemoveGrab(messageWidget);
5113 char *ModeToWidgetName(mode)
5117 case BeginningOfGame:
5118 if (appData.icsActive)
5119 return "menuMode.ICS Client";
5120 else if (appData.noChessProgram ||
5121 *appData.cmailGameName != NULLCHAR)
5122 return "menuMode.Edit Game";
5124 return "menuMode.Machine Black";
5125 case MachinePlaysBlack:
5126 return "menuMode.Machine Black";
5127 case MachinePlaysWhite:
5128 return "menuMode.Machine White";
5130 return "menuMode.Analysis Mode";
5132 return "menuMode.Analyze File";
5133 case TwoMachinesPlay:
5134 return "menuMode.Two Machines";
5136 return "menuMode.Edit Game";
5137 case PlayFromGameFile:
5138 return "menuFile.Load Game";
5140 return "menuMode.Edit Position";
5142 return "menuMode.Training";
5143 case IcsPlayingWhite:
5144 case IcsPlayingBlack:
5148 return "menuMode.ICS Client";
5155 void ModeHighlight()
5157 static int oldPausing = FALSE;
5158 static GameMode oldmode = (GameMode) -1;
5161 // todo this toggling of the pause button doesn't seem to work?
5162 // e.g. select pause from buttonbar doesn't activate menumode.pause
5164 // if (!boardWidget || !XtIsRealized(boardWidget)) return;
5166 if (pausing != oldPausing) {
5167 oldPausing = pausing;
5168 gtk_button_set_relief(GTK_BUTTON (gtk_builder_get_object (builder, "menuMode.Pause")),pausing?GTK_RELIEF_NORMAL:GTK_RELIEF_NONE);
5169 /* toggle background color in showbuttonbar */
5170 if (appData.showButtonBar) {
5172 gtk_button_pressed(GTK_BUTTON (gtk_builder_get_object (builder, "buttonbar.Pause")));
5174 gtk_button_released(GTK_BUTTON (gtk_builder_get_object (builder, "buttonbar.Pause")));
5179 wname = ModeToWidgetName(oldmode);
5181 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, wname)),True);
5185 /* Maybe all the enables should be handled here, not just this one */
5186 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuMode.Training")),
5187 gameMode == Training || gameMode == PlayFromGameFile);
5192 * Button/menu procedures
5195 int LoadGamePopUp(f, gameNumber, title)
5200 cmailMsgLoaded = FALSE;
5201 if (gameNumber == 0) {
5202 int error = GameListBuild(f);
5204 DisplayError(_("Cannot build game list"), error);
5205 } else if (!ListEmpty(&gameList) &&
5206 ((ListGame *) gameList.tailPred)->number > 1) {
5207 GameListPopUp(f, title);
5213 return LoadGame(f, gameNumber, title, FALSE);
5217 void LoadNextPositionProc(w, event, prms, nprms)
5226 void LoadPrevPositionProc(w, event, prms, nprms)
5235 void ReloadPositionProc(w, event, prms, nprms)
5244 void LoadPositionProc(w, event, prms, nprms)
5250 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
5253 FileNamePopUp(_("Load position file name?"), "", LoadPosition, "rb");
5256 void SaveGameProc(w, event, prms, nprms)
5262 FileNamePopUp(_("Save game file name?"),
5263 DefaultFileName(appData.oldSaveStyle ? "game" : "pgn"),
5267 void SavePositionProc(w, event, prms, nprms)
5273 FileNamePopUp(_("Save position file name?"),
5274 DefaultFileName(appData.oldSaveStyle ? "pos" : "fen"),
5278 void ReloadCmailMsgProc(w, event, prms, nprms)
5284 ReloadCmailMsgEvent(FALSE);
5287 void MailMoveProc(w, event, prms, nprms)
5296 /* this variable is shared between CopyPositionProc and SendPositionSelection */
5297 static char *selected_fen_position=NULL;
5300 SendPositionSelection(Widget w, Atom *selection, Atom *target,
5301 Atom *type_return, XtPointer *value_return,
5302 unsigned long *length_return, int *format_return)
5304 char *selection_tmp;
5306 if (!selected_fen_position) return False; /* should never happen */
5307 if (*target == XA_STRING){
5308 /* note: since no XtSelectionDoneProc was registered, Xt will
5309 * automatically call XtFree on the value returned. So have to
5310 * make a copy of it allocated with XtMalloc */
5311 selection_tmp= XtMalloc(strlen(selected_fen_position)+16);
5312 strcpy(selection_tmp, selected_fen_position);
5314 *value_return=selection_tmp;
5315 *length_return=strlen(selection_tmp);
5316 *type_return=XA_STRING;
5317 *format_return = 8; /* bits per byte */
5324 /* note: when called from menu all parameters are NULL, so no clue what the
5325 * Widget which was clicked on was, or what the click event was
5327 void CopyPositionProc(w, event, prms, nprms)
5335 if (selected_fen_position) free(selected_fen_position);
5336 selected_fen_position = (char *)PositionToFEN(currentMove, NULL);
5337 if (!selected_fen_position) return;
5338 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
5340 SendPositionSelection,
5341 NULL/* lose_ownership_proc */ ,
5342 NULL/* transfer_done_proc */);
5344 free(selected_fen_position);
5345 selected_fen_position=NULL;
5349 /* function called when the data to Paste is ready */
5351 PastePositionCB(Widget w, XtPointer client_data, Atom *selection,
5352 Atom *type, XtPointer value, unsigned long *len, int *format)
5355 if (value==NULL || *len==0) return; /* nothing had been selected to copy */
5356 fenstr[*len]='\0'; /* normally this string is terminated, but be safe */
5357 EditPositionPasteFEN(fenstr);
5361 /* called when Paste Position button is pressed,
5362 * all parameters will be NULL */
5363 void PastePositionProc(w, event, prms, nprms)
5369 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
5370 /* (XtSelectionCallbackProc) */ PastePositionCB,
5371 NULL, /* client_data passed to PastePositionCB */
5373 /* better to use the time field from the event that triggered the
5374 * call to this function, but that isn't trivial to get
5382 SendGameSelection(Widget w, Atom *selection, Atom *target,
5383 Atom *type_return, XtPointer *value_return,
5384 unsigned long *length_return, int *format_return)
5386 char *selection_tmp;
5388 if (*target == XA_STRING){
5389 FILE* f = fopen(gameCopyFilename, "r");
5392 if (f == NULL) return False;
5396 selection_tmp = XtMalloc(len + 1);
5397 count = fread(selection_tmp, 1, len, f);
5399 XtFree(selection_tmp);
5402 selection_tmp[len] = NULLCHAR;
5403 *value_return = selection_tmp;
5404 *length_return = len;
5405 *type_return = XA_STRING;
5406 *format_return = 8; /* bits per byte */
5413 /* note: when called from menu all parameters are NULL, so no clue what the
5414 * Widget which was clicked on was, or what the click event was
5416 void CopyGameProc(w, event, prms, nprms)
5424 ret = SaveGameToFile(gameCopyFilename, FALSE);
5427 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
5430 NULL/* lose_ownership_proc */ ,
5431 NULL/* transfer_done_proc */);
5434 /* function called when the data to Paste is ready */
5436 PasteGameCB(Widget w, XtPointer client_data, Atom *selection,
5437 Atom *type, XtPointer value, unsigned long *len, int *format)
5440 if (value == NULL || *len == 0) {
5441 return; /* nothing had been selected to copy */
5443 f = fopen(gamePasteFilename, "w");
5445 DisplayError(_("Can't open temp file"), errno);
5448 fwrite(value, 1, *len, f);
5451 LoadGameFromFile(gamePasteFilename, 0, gamePasteFilename, TRUE);
5454 /* called when Paste Game button is pressed,
5455 * all parameters will be NULL */
5456 void PasteGameProc(w, event, prms, nprms)
5462 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
5463 /* (XtSelectionCallbackProc) */ PasteGameCB,
5464 NULL, /* client_data passed to PasteGameCB */
5466 /* better to use the time field from the event that triggered the
5467 * call to this function, but that isn't trivial to get
5477 SaveGameProc(NULL, NULL, NULL, NULL);
5480 void AnalyzeModeProc(w, event, prms, nprms)
5488 if (!first.analysisSupport) {
5489 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
5490 DisplayError(buf, 0);
5493 /* [DM] icsEngineAnalyze [HGM] This is horrible code; reverse the gameMode and isEngineAnalyze tests! */
5494 if (appData.icsActive) {
5495 if (gameMode != IcsObserving) {
5496 sprintf(buf,_("You are not observing a game"));
5497 DisplayError(buf, 0);
5499 if (appData.icsEngineAnalyze) {
5500 if (appData.debugMode)
5501 fprintf(debugFP, _("Found unexpected active ICS engine analyze \n"));
5507 /* if enable, use want disable icsEngineAnalyze */
5508 if (appData.icsEngineAnalyze) {
5513 appData.icsEngineAnalyze = TRUE;
5514 if (appData.debugMode)
5515 fprintf(debugFP, _("ICS engine analyze starting... \n"));
5517 if (!appData.showThinking)
5518 ShowThinkingProc(w,event,prms,nprms);
5523 void AnalyzeFileProc(w, event, prms, nprms)
5529 if (!first.analysisSupport) {
5531 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
5532 DisplayError(buf, 0);
5537 if (!appData.showThinking)
5538 ShowThinkingProc(w,event,prms,nprms);
5541 FileNamePopUp(_("File to analyze"), "", LoadGamePopUp, "rb");
5542 AnalysisPeriodicEvent(1);
5546 void EditGameProc(w, event, prms, nprms)
5555 void EditPositionProc(w, event, prms, nprms)
5561 EditPositionEvent();
5564 void TrainingProc(w, event, prms, nprms)
5573 void EditCommentProc(w, event, prms, nprms)
5580 EditCommentPopDown();
5586 void IcsInputBoxProc(w, event, prms, nprms)
5592 if (ICSInputBoxUp) {
5593 ICSInputBoxPopDown();
5600 void EnterKeyProc(w, event, prms, nprms)
5606 if (ICSInputBoxUp == True)
5610 void AlwaysQueenProc(w, event, prms, nprms)
5618 appData.alwaysPromoteToQueen = !appData.alwaysPromoteToQueen;
5620 if (appData.alwaysPromoteToQueen) {
5621 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5623 XtSetArg(args[0], XtNleftBitmap, None);
5625 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
5629 void AnimateDraggingProc(w, event, prms, nprms)
5637 appData.animateDragging = !appData.animateDragging;
5639 if (appData.animateDragging) {
5640 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5643 XtSetArg(args[0], XtNleftBitmap, None);
5645 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Dragging"),
5649 void AnimateMovingProc(w, event, prms, nprms)
5657 appData.animate = !appData.animate;
5659 if (appData.animate) {
5660 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5663 XtSetArg(args[0], XtNleftBitmap, None);
5665 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
5669 void AutocommProc(w, event, prms, nprms)
5677 appData.autoComment = !appData.autoComment;
5679 if (appData.autoComment) {
5680 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5682 XtSetArg(args[0], XtNleftBitmap, None);
5684 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
5689 void AutoflagProc(w, event, prms, nprms)
5697 appData.autoCallFlag = !appData.autoCallFlag;
5699 if (appData.autoCallFlag) {
5700 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5702 XtSetArg(args[0], XtNleftBitmap, None);
5704 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
5708 void AutoflipProc(w, event, prms, nprms)
5716 appData.autoFlipView = !appData.autoFlipView;
5718 if (appData.autoFlipView) {
5719 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5721 XtSetArg(args[0], XtNleftBitmap, None);
5723 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flip View"),
5727 void AutobsProc(w, event, prms, nprms)
5735 appData.autoObserve = !appData.autoObserve;
5737 if (appData.autoObserve) {
5738 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5740 XtSetArg(args[0], XtNleftBitmap, None);
5742 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
5746 void AutoraiseProc(w, event, prms, nprms)
5754 appData.autoRaiseBoard = !appData.autoRaiseBoard;
5756 if (appData.autoRaiseBoard) {
5757 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5759 XtSetArg(args[0], XtNleftBitmap, None);
5761 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Raise Board"),
5765 void AutosaveProc(w, event, prms, nprms)
5773 appData.autoSaveGames = !appData.autoSaveGames;
5775 if (appData.autoSaveGames) {
5776 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5778 XtSetArg(args[0], XtNleftBitmap, None);
5780 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
5784 void BlindfoldProc(w, event, prms, nprms)
5792 appData.blindfold = !appData.blindfold;
5794 if (appData.blindfold) {
5795 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5797 XtSetArg(args[0], XtNleftBitmap, None);
5799 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Blindfold"),
5802 DrawPosition(True, NULL);
5805 void TestLegalityProc(w, event, prms, nprms)
5813 appData.testLegality = !appData.testLegality;
5815 if (appData.testLegality) {
5816 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5818 XtSetArg(args[0], XtNleftBitmap, None);
5820 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Test Legality"),
5825 void FlashMovesProc(w, event, prms, nprms)
5833 if (appData.flashCount == 0) {
5834 appData.flashCount = 3;
5836 appData.flashCount = -appData.flashCount;
5839 if (appData.flashCount > 0) {
5840 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5842 XtSetArg(args[0], XtNleftBitmap, None);
5844 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flash Moves"),
5848 void GetMoveListProc(w, event, prms, nprms)
5856 appData.getMoveList = !appData.getMoveList;
5858 if (appData.getMoveList) {
5859 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5862 XtSetArg(args[0], XtNleftBitmap, None);
5864 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
5869 void HighlightDraggingProc(w, event, prms, nprms)
5877 appData.highlightDragging = !appData.highlightDragging;
5879 if (appData.highlightDragging) {
5880 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5882 XtSetArg(args[0], XtNleftBitmap, None);
5884 XtSetValues(XtNameToWidget(menuBarWidget,
5885 "menuOptions.Highlight Dragging"), args, 1);
5889 void HighlightLastMoveProc(w, event, prms, nprms)
5897 appData.highlightLastMove = !appData.highlightLastMove;
5899 if (appData.highlightLastMove) {
5900 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5902 XtSetArg(args[0], XtNleftBitmap, None);
5904 XtSetValues(XtNameToWidget(menuBarWidget,
5905 "menuOptions.Highlight Last Move"), args, 1);
5908 void IcsAlarmProc(w, event, prms, nprms)
5916 appData.icsAlarm = !appData.icsAlarm;
5918 if (appData.icsAlarm) {
5919 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5921 XtSetArg(args[0], XtNleftBitmap, None);
5923 XtSetValues(XtNameToWidget(menuBarWidget,
5924 "menuOptions.ICS Alarm"), args, 1);
5927 void MoveSoundProc(w, event, prms, nprms)
5935 appData.ringBellAfterMoves = !appData.ringBellAfterMoves;
5937 if (appData.ringBellAfterMoves) {
5938 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5940 XtSetArg(args[0], XtNleftBitmap, None);
5942 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
5947 void OldSaveStyleProc(w, event, prms, nprms)
5955 appData.oldSaveStyle = !appData.oldSaveStyle;
5957 if (appData.oldSaveStyle) {
5958 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5960 XtSetArg(args[0], XtNleftBitmap, None);
5962 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Old Save Style"),
5966 void PeriodicUpdatesProc(w, event, prms, nprms)
5974 PeriodicUpdatesEvent(!appData.periodicUpdates);
5976 if (appData.periodicUpdates) {
5977 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5979 XtSetArg(args[0], XtNleftBitmap, None);
5981 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Periodic Updates"),
5985 void PonderNextMoveProc(w, event, prms, nprms)
5993 PonderNextMoveEvent(!appData.ponderNextMove);
5995 if (appData.ponderNextMove) {
5996 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5998 XtSetArg(args[0], XtNleftBitmap, None);
6000 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Ponder Next Move"),
6004 void PopupExitMessageProc(w, event, prms, nprms)
6012 appData.popupExitMessage = !appData.popupExitMessage;
6014 if (appData.popupExitMessage) {
6015 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6017 XtSetArg(args[0], XtNleftBitmap, None);
6019 XtSetValues(XtNameToWidget(menuBarWidget,
6020 "menuOptions.Popup Exit Message"), args, 1);
6023 void PopupMoveErrorsProc(w, event, prms, nprms)
6031 appData.popupMoveErrors = !appData.popupMoveErrors;
6033 if (appData.popupMoveErrors) {
6034 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6036 XtSetArg(args[0], XtNleftBitmap, None);
6038 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Popup Move Errors"),
6042 void PremoveProc(w, event, prms, nprms)
6050 appData.premove = !appData.premove;
6052 if (appData.premove) {
6053 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6055 XtSetArg(args[0], XtNleftBitmap, None);
6057 XtSetValues(XtNameToWidget(menuBarWidget,
6058 "menuOptions.Premove"), args, 1);
6061 void QuietPlayProc(w, event, prms, nprms)
6069 appData.quietPlay = !appData.quietPlay;
6071 if (appData.quietPlay) {
6072 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6074 XtSetArg(args[0], XtNleftBitmap, None);
6076 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Quiet Play"),
6080 void ShowThinkingProc(w, event, prms, nprms)
6088 appData.showThinking = !appData.showThinking; // [HGM] thinking: tken out of ShowThinkingEvent
6089 ShowThinkingEvent();
6091 // [HGM] thinking: currently no suc menu item; replaced by Hide Thinking (From Human)
6092 if (appData.showThinking) {
6093 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6095 XtSetArg(args[0], XtNleftBitmap, None);
6097 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Thinking"),
6102 void HideThinkingProc(w, event, prms, nprms)
6110 appData.hideThinkingFromHuman = !appData.hideThinkingFromHuman; // [HGM] thinking: tken out of ShowThinkingEvent
6111 ShowThinkingEvent();
6113 if (appData.hideThinkingFromHuman) {
6114 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6116 XtSetArg(args[0], XtNleftBitmap, None);
6118 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
6122 void DebugProc(w, event, prms, nprms)
6128 appData.debugMode = !appData.debugMode;
6131 void AboutGameProc(w, event, prms, nprms)
6140 void NothingProc(w, event, prms, nprms)
6149 void Iconify(w, event, prms, nprms)
6158 XtSetArg(args[0], XtNiconic, True);
6159 XtSetValues(shellWidget, args, 1);
6162 void DisplayMessage(message, extMessage)
6163 gchar *message, *extMessage;
6170 snprintf(buf, sizeof(buf), "%s %s", message, extMessage);
6173 message = extMessage;
6176 gtk_label_set_text( GTK_LABEL(gtk_builder_get_object (builder, "Messages")),message);
6181 void DisplayTitle(text)
6184 gchar title[MSG_SIZ];
6186 if (text == NULL) text = "";
6188 if (appData.titleInWindow)
6193 if (*text != NULLCHAR)
6195 strcpy(title, text);
6197 else if (appData.icsActive)
6199 snprintf(title, sizeof(title), "%s: %s", programName, appData.icsHost);
6201 else if (appData.cmailGameName[0] != NULLCHAR)
6203 snprintf(title,sizeof(title), "%s: %s", programName, "CMail");
6205 // [HGM] license: This stuff should really be done in back-end, but WinBoard already had a pop-up for it
6207 else if (gameInfo.variant == VariantGothic)
6209 strcpy(title, GOTHIC);
6213 else if (gameInfo.variant == VariantFalcon)
6215 strcpy(title, FALCON);
6218 else if (appData.noChessProgram)
6220 strcpy(title, programName);
6224 snprintf(title,sizeof(title), "%s: %s", programName, first.tidy);
6226 gtk_window_set_title(GTK_WINDOW(GUI_Window),title);
6232 void DisplayError(message, error)
6239 if (appData.debugMode || appData.matchMode) {
6240 fprintf(stderr, "%s: %s\n", programName, message);
6243 if (appData.debugMode || appData.matchMode) {
6244 fprintf(stderr, "%s: %s: %s\n",
6245 programName, message, strerror(error));
6247 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
6250 ErrorPopUp(_("Error"), message, FALSE);
6254 void DisplayMoveError(message)
6259 DrawPosition(FALSE, NULL);
6260 if (appData.debugMode || appData.matchMode) {
6261 fprintf(stderr, "%s: %s\n", programName, message);
6263 if (appData.popupMoveErrors) {
6264 ErrorPopUp(_("Error"), message, FALSE);
6266 DisplayMessage(message, "");
6271 void DisplayFatalError(message, error, status)
6277 errorExitStatus = status;
6279 fprintf(stderr, "%s: %s\n", programName, message);
6281 fprintf(stderr, "%s: %s: %s\n",
6282 programName, message, strerror(error));
6283 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
6286 if (appData.popupExitMessage && boardWidget && XtIsRealized(boardWidget)) {
6287 ErrorPopUp(status ? _("Fatal Error") : _("Exiting"), message, TRUE);
6293 void DisplayInformation(message)
6297 ErrorPopUp(_("Information"), message, TRUE);
6300 void DisplayNote(message)
6304 ErrorPopUp(_("Note"), message, FALSE);
6308 NullXErrorCheck(dpy, error_event)
6310 XErrorEvent *error_event;
6315 void DisplayIcsInteractionTitle(message)
6318 if (oldICSInteractionTitle == NULL) {
6319 /* Magic to find the old window title, adapted from vim */
6320 char *wina = getenv("WINDOWID");
6322 Window win = (Window) atoi(wina);
6323 Window root, parent, *children;
6324 unsigned int nchildren;
6325 int (*oldHandler)() = XSetErrorHandler(NullXErrorCheck);
6327 if (XFetchName(xDisplay, win, &oldICSInteractionTitle)) break;
6328 if (!XQueryTree(xDisplay, win, &root, &parent,
6329 &children, &nchildren)) break;
6330 if (children) XFree((void *)children);
6331 if (parent == root || parent == 0) break;
6334 XSetErrorHandler(oldHandler);
6336 if (oldICSInteractionTitle == NULL) {
6337 oldICSInteractionTitle = "xterm";
6340 printf("\033]0;%s\007", message);
6344 char pendingReplyPrefix[MSG_SIZ];
6345 ProcRef pendingReplyPR;
6347 void AskQuestionProc(w, event, prms, nprms)
6354 fprintf(stderr, _("AskQuestionProc needed 4 parameters, got %d\n"),
6358 AskQuestionEvent(prms[0], prms[1], prms[2], prms[3]);
6361 void AskQuestionPopDown()
6363 if (!askQuestionUp) return;
6364 XtPopdown(askQuestionShell);
6365 XtDestroyWidget(askQuestionShell);
6366 askQuestionUp = False;
6369 void AskQuestionReplyAction(w, event, prms, nprms)
6379 reply = XawDialogGetValueString(w = XtParent(w));
6380 strcpy(buf, pendingReplyPrefix);
6381 if (*buf) strcat(buf, " ");
6384 OutputToProcess(pendingReplyPR, buf, strlen(buf), &err);
6385 AskQuestionPopDown();
6387 if (err) DisplayFatalError(_("Error writing to chess program"), err, 0);
6390 void AskQuestionCallback(w, client_data, call_data)
6392 XtPointer client_data, call_data;
6397 XtSetArg(args[0], XtNlabel, &name);
6398 XtGetValues(w, args, 1);
6400 if (strcmp(name, _("cancel")) == 0) {
6401 AskQuestionPopDown();
6403 AskQuestionReplyAction(w, NULL, NULL, NULL);
6407 void AskQuestion(title, question, replyPrefix, pr)
6408 char *title, *question, *replyPrefix;
6412 Widget popup, layout, dialog, edit;
6418 strcpy(pendingReplyPrefix, replyPrefix);
6419 pendingReplyPR = pr;
6422 XtSetArg(args[i], XtNresizable, True); i++;
6423 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
6424 askQuestionShell = popup =
6425 XtCreatePopupShell(title, transientShellWidgetClass,
6426 shellWidget, args, i);
6429 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
6430 layoutArgs, XtNumber(layoutArgs));
6433 XtSetArg(args[i], XtNlabel, question); i++;
6434 XtSetArg(args[i], XtNvalue, ""); i++;
6435 XtSetArg(args[i], XtNborderWidth, 0); i++;
6436 dialog = XtCreateManagedWidget("question", dialogWidgetClass,
6439 XawDialogAddButton(dialog, _("enter"), AskQuestionCallback,
6440 (XtPointer) dialog);
6441 XawDialogAddButton(dialog, _("cancel"), AskQuestionCallback,
6442 (XtPointer) dialog);
6444 XtRealizeWidget(popup);
6445 CatchDeleteWindow(popup, "AskQuestionPopDown");
6447 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
6448 &x, &y, &win_x, &win_y, &mask);
6450 XtSetArg(args[0], XtNx, x - 10);
6451 XtSetArg(args[1], XtNy, y - 30);
6452 XtSetValues(popup, args, 2);
6454 XtPopup(popup, XtGrabExclusive);
6455 askQuestionUp = True;
6457 edit = XtNameToWidget(dialog, "*value");
6458 XtSetKeyboardFocus(popup, edit);
6466 if (*name == NULLCHAR) {
6468 } else if (strcmp(name, "$") == 0) {
6469 putc(BELLCHAR, stderr);
6472 snprintf(buf, sizeof(buf), "%s '%s' &", appData.soundProgram, name);
6480 PlaySound(appData.soundMove);
6486 PlaySound(appData.soundIcsWin);
6492 PlaySound(appData.soundIcsLoss);
6498 PlaySound(appData.soundIcsDraw);
6502 PlayIcsUnfinishedSound()
6504 PlaySound(appData.soundIcsUnfinished);
6510 PlaySound(appData.soundIcsAlarm);
6516 system("stty echo");
6522 system("stty -echo");
6526 Colorize(cc, continuation)
6531 int count, outCount, error;
6533 if (textColors[(int)cc].bg > 0) {
6534 if (textColors[(int)cc].fg > 0) {
6535 sprintf(buf, "\033[0;%d;%d;%dm", textColors[(int)cc].attr,
6536 textColors[(int)cc].fg, textColors[(int)cc].bg);
6538 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
6539 textColors[(int)cc].bg);
6542 if (textColors[(int)cc].fg > 0) {
6543 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
6544 textColors[(int)cc].fg);
6546 sprintf(buf, "\033[0;%dm", textColors[(int)cc].attr);
6549 count = strlen(buf);
6550 outCount = OutputToProcess(NoProc, buf, count, &error);
6551 if (outCount < count) {
6552 DisplayFatalError(_("Error writing to display"), error, 1);
6555 if (continuation) return;
6558 PlaySound(appData.soundShout);
6561 PlaySound(appData.soundSShout);
6564 PlaySound(appData.soundChannel1);
6567 PlaySound(appData.soundChannel);
6570 PlaySound(appData.soundKibitz);
6573 PlaySound(appData.soundTell);
6575 case ColorChallenge:
6576 PlaySound(appData.soundChallenge);
6579 PlaySound(appData.soundRequest);
6582 PlaySound(appData.soundSeek);
6593 return getpwuid(getuid())->pw_name;
6596 static char *ExpandPathName(path)
6599 static char static_buf[2000];
6600 char *d, *s, buf[2000];
6606 while (*s && isspace(*s))
6615 if (*(s+1) == '/') {
6616 strcpy(d, getpwuid(getuid())->pw_dir);
6621 *strchr(buf, '/') = 0;
6622 pwd = getpwnam(buf);
6625 fprintf(stderr, _("ERROR: Unknown user %s (in path %s)\n"),
6629 strcpy(d, pwd->pw_dir);
6630 strcat(d, strchr(s+1, '/'));
6641 static char host_name[MSG_SIZ];
6643 #if HAVE_GETHOSTNAME
6644 gethostname(host_name, MSG_SIZ);
6646 #else /* not HAVE_GETHOSTNAME */
6647 # if HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H
6648 sysinfo(SI_HOSTNAME, host_name, MSG_SIZ);
6650 # else /* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
6652 # endif/* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
6653 #endif /* not HAVE_GETHOSTNAME */
6656 guint delayedEventTimerTag = 0;
6657 DelayedEventCallback delayedEventCallback = 0;
6660 FireDelayedEvent(data)
6664 g_source_remove(delayedEventTimerTag);
6665 delayedEventTimerTag = 0;
6668 delayedEventCallback();
6674 ScheduleDelayedEvent(cb, millisec)
6675 DelayedEventCallback cb; guint millisec;
6677 if(delayedEventTimerTag && delayedEventCallback == cb)
6678 // [HGM] alive: replace, rather than add or flush identical event
6679 g_source_remove(delayedEventTimerTag);
6680 delayedEventCallback = cb;
6681 delayedEventTimerTag = g_timeout_add(millisec,(GSourceFunc) FireDelayedEvent, NULL);
6685 DelayedEventCallback
6688 if (delayedEventTimerTag)
6690 return delayedEventCallback;
6699 CancelDelayedEvent()
6701 if (delayedEventTimerTag)
6703 g_source_remove(delayedEventTimerTag);
6704 delayedEventTimerTag = 0;
6710 guint loadGameTimerTag = 0;
6712 int LoadGameTimerRunning()
6714 return loadGameTimerTag != 0;
6717 int StopLoadGameTimer()
6719 if (loadGameTimerTag != 0) {
6720 g_source_remove(loadGameTimerTag);
6721 loadGameTimerTag = 0;
6729 LoadGameTimerCallback(data)
6733 g_source_remove(loadGameTimerTag);
6734 loadGameTimerTag = 0;
6741 StartLoadGameTimer(millisec)
6745 g_timeout_add( millisec, (GSourceFunc) LoadGameTimerCallback, NULL);
6749 guint analysisClockTag = 0;
6752 AnalysisClockCallback(data)
6755 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile
6756 || appData.icsEngineAnalyze)
6758 AnalysisPeriodicEvent(0);
6759 return 1; /* keep on going */
6761 return 0; /* stop timer */
6765 StartAnalysisClock()
6768 g_timeout_add( 2000,(GSourceFunc) AnalysisClockCallback, NULL);
6772 guint clockTimerTag = 0;
6774 int ClockTimerRunning()
6776 return clockTimerTag != 0;
6779 int StopClockTimer()
6781 if (clockTimerTag != 0)
6783 g_source_remove(clockTimerTag);
6794 ClockTimerCallback(data)
6798 g_source_remove(clockTimerTag);
6806 StartClockTimer(millisec)
6809 clockTimerTag = g_timeout_add(millisec,(GSourceFunc) ClockTimerCallback,NULL);
6814 DisplayTimerLabel(w, color, timer, highlight)
6823 if (appData.clockMode) {
6824 sprintf(buf, "%s: %s", color, TimeString(timer));
6826 sprintf(buf, "%s ", color);
6828 gtk_label_set_text(GTK_LABEL(w),buf);
6830 /* check for low time warning */
6831 // Pixel foregroundOrWarningColor = timerForegroundPixel;
6834 // appData.lowTimeWarning &&
6835 // (timer / 1000) < appData.icsAlarmTime)
6836 // foregroundOrWarningColor = lowTimeWarningColor;
6838 // if (appData.clockMode) {
6839 // sprintf(buf, "%s: %s", color, TimeString(timer));
6840 // XtSetArg(args[0], XtNlabel, buf);
6842 // sprintf(buf, "%s ", color);
6843 // XtSetArg(args[0], XtNlabel, buf);
6848 // XtSetArg(args[1], XtNbackground, foregroundOrWarningColor);
6849 // XtSetArg(args[2], XtNforeground, timerBackgroundPixel);
6851 // XtSetArg(args[1], XtNbackground, timerBackgroundPixel);
6852 // XtSetArg(args[2], XtNforeground, foregroundOrWarningColor);
6855 // XtSetValues(w, args, 3);
6860 DisplayWhiteClock(timeRemaining, highlight)
6864 if(appData.noGUI) return;
6866 DisplayTimerLabel(GUI_Whiteclock, _("White"), timeRemaining, highlight);
6867 if (highlight && WindowIcon == BlackIcon)
6869 WindowIcon = WhiteIcon;
6870 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
6875 DisplayBlackClock(timeRemaining, highlight)
6879 if(appData.noGUI) return;
6881 DisplayTimerLabel(GUI_Blackclock, _("Black"), timeRemaining, highlight);
6882 if (highlight && WindowIcon == WhiteIcon)
6884 WindowIcon = BlackIcon;
6885 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
6903 int StartChildProcess(cmdLine, dir, pr)
6910 int to_prog[2], from_prog[2];
6914 if (appData.debugMode) {
6915 fprintf(stderr, "StartChildProcess (dir=\"%s\") %s\n",dir, cmdLine);
6918 /* We do NOT feed the cmdLine to the shell; we just
6919 parse it into blank-separated arguments in the
6920 most simple-minded way possible.
6923 strcpy(buf, cmdLine);
6928 if (p == NULL) break;
6933 SetUpChildIO(to_prog, from_prog);
6935 if ((pid = fork()) == 0) {
6937 // [HGM] PSWBTM: made order resistant against case where fd of created pipe was 0 or 1
6938 close(to_prog[1]); // first close the unused pipe ends
6939 close(from_prog[0]);
6940 dup2(to_prog[0], 0); // to_prog was created first, nd is the only one to use 0 or 1
6941 dup2(from_prog[1], 1);
6942 if(to_prog[0] >= 2) close(to_prog[0]); // if 0 or 1, the dup2 already cosed the original
6943 close(from_prog[1]); // and closing again loses one of the pipes!
6944 if(fileno(stderr) >= 2) // better safe than sorry...
6945 dup2(1, fileno(stderr)); /* force stderr to the pipe */
6947 if (dir[0] != NULLCHAR && chdir(dir) != 0) {
6952 nice(appData.niceEngines); // [HGM] nice: adjust priority of engine proc
6954 execvp(argv[0], argv);
6956 /* If we get here, exec failed */
6961 /* Parent process */
6963 close(from_prog[1]);
6965 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
6968 cp->fdFrom = from_prog[0];
6969 cp->fdTo = to_prog[1];
6974 // [HGM] kill: implement the 'hard killing' of AS's Winboard_x
6975 static RETSIGTYPE AlarmCallBack(int n)
6981 DestroyChildProcess(pr, signalType)
6985 ChildProc *cp = (ChildProc *) pr;
6987 if (cp->kind != CPReal) return;
6989 if (signalType == 10) { // [HGM] kill: if it does not terminate in 3 sec, kill
6990 signal(SIGALRM, AlarmCallBack);
6992 if(wait((int *) 0) == -1) { // process does not terminate on its own accord
6993 kill(cp->pid, SIGKILL); // kill it forcefully
6994 wait((int *) 0); // and wait again
6998 kill(cp->pid, signalType == 9 ? SIGKILL : SIGTERM); // [HGM] kill: use hard kill if so requested
7000 /* Process is exiting either because of the kill or because of
7001 a quit command sent by the backend; either way, wait for it to die.
7010 InterruptChildProcess(pr)
7013 ChildProc *cp = (ChildProc *) pr;
7015 if (cp->kind != CPReal) return;
7016 (void) kill(cp->pid, SIGINT); /* stop it thinking */
7019 int OpenTelnet(host, port, pr)
7024 char cmdLine[MSG_SIZ];
7026 if (port[0] == NULLCHAR) {
7027 snprintf(cmdLine, sizeof(cmdLine), "%s %s", appData.telnetProgram, host);
7029 snprintf(cmdLine, sizeof(cmdLine), "%s %s %s", appData.telnetProgram, host, port);
7031 return StartChildProcess(cmdLine, "", pr);
7034 int OpenTCP(host, port, pr)
7040 DisplayFatalError(_("Socket support is not configured in"), 0, 2);
7041 #else /* !OMIT_SOCKETS */
7043 struct sockaddr_in sa;
7045 unsigned short uport;
7048 if ((s = socket(AF_INET, SOCK_STREAM, 6)) < 0) {
7052 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
7053 sa.sin_family = AF_INET;
7054 sa.sin_addr.s_addr = INADDR_ANY;
7055 uport = (unsigned short) 0;
7056 sa.sin_port = htons(uport);
7057 if (bind(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)) < 0) {
7061 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
7062 if (!(hp = gethostbyname(host))) {
7064 if (sscanf(host, "%d.%d.%d.%d", &b0, &b1, &b2, &b3) == 4) {
7065 hp = (struct hostent *) calloc(1, sizeof(struct hostent));
7066 hp->h_addrtype = AF_INET;
7068 hp->h_addr_list = (char **) calloc(2, sizeof(char *));
7069 hp->h_addr_list[0] = (char *) malloc(4);
7070 hp->h_addr_list[0][0] = b0;
7071 hp->h_addr_list[0][1] = b1;
7072 hp->h_addr_list[0][2] = b2;
7073 hp->h_addr_list[0][3] = b3;
7078 sa.sin_family = hp->h_addrtype;
7079 uport = (unsigned short) atoi(port);
7080 sa.sin_port = htons(uport);
7081 memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);
7083 if (connect(s, (struct sockaddr *) &sa,
7084 sizeof(struct sockaddr_in)) < 0) {
7088 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7095 #endif /* !OMIT_SOCKETS */
7100 int OpenCommPort(name, pr)
7107 fd = open(name, 2, 0);
7108 if (fd < 0) return errno;
7110 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7120 int OpenLoopback(pr)
7126 SetUpChildIO(to, from);
7128 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7131 cp->fdFrom = to[0]; /* note not from[0]; we are doing a loopback */
7138 int OpenRcmd(host, user, cmd, pr)
7139 char *host, *user, *cmd;
7142 DisplayFatalError(_("internal rcmd not implemented for Unix"), 0, 1);
7146 #define INPUT_SOURCE_BUF_SIZE 8192
7155 char buf[INPUT_SOURCE_BUF_SIZE];
7160 DoInputCallback(io,cond,data)
7165 /* read input from one of the input source (for example a chess program, ICS, etc).
7166 * and call a function that will handle the input
7169 int count; /* how many bytes did we read */
7173 /* All information (callback function, file descriptor, etc) is
7174 * saved in an InputSource structure
7176 InputSource *is = (InputSource *) data;
7180 count = read(is->fd, is->unused,
7181 INPUT_SOURCE_BUF_SIZE - (is->unused - is->buf));
7185 (is->func)(is, is->closure, is->buf, count, count ? errno : 0);
7188 is->unused += count;
7190 /* break input into lines and call the callback function on each
7193 while (p < is->unused)
7195 q = memchr(p, '\n', is->unused - p);
7196 if (q == NULL) break;
7198 (is->func)(is, is->closure, p, q - p, 0);
7201 /* remember not yet used part of the buffer */
7203 while (p < is->unused)
7211 /* read maximum length of input buffer and send the whole buffer
7212 * to the callback function
7214 count = read(is->fd, is->buf, INPUT_SOURCE_BUF_SIZE);
7219 (is->func)(is, is->closure, is->buf, count, error);
7225 InputSourceRef AddInputSource(pr, lineByLine, func, closure)
7232 GIOChannel *channel;
7233 ChildProc *cp = (ChildProc *) pr;
7235 is = (InputSource *) calloc(1, sizeof(InputSource));
7236 is->lineByLine = lineByLine;
7240 is->fd = fileno(stdin);
7242 is->kind = cp->kind;
7243 is->fd = cp->fdFrom;
7246 is->unused = is->buf;
7250 // is->xid = XtAppAddInput(appContext, is->fd,
7251 // (XtPointer) (XtInputReadMask),
7252 // (XtInputCallbackProc) DoInputCallback,
7256 /* TODO: will this work on windows?*/
7257 printf("DEBUG: fd=%d %d\n",is->fd,is);
7259 channel = g_io_channel_unix_new(is->fd);
7260 g_io_channel_set_close_on_unref (channel, TRUE);
7261 is->sid = g_io_add_watch(channel, G_IO_IN,(GIOFunc) DoInputCallback, is);
7262 is->closure = closure;
7263 return (InputSourceRef) is;
7267 RemoveInputSource(isr)
7270 InputSource *is = (InputSource *) isr;
7272 if (is->sid == 0) return;
7273 g_source_remove(is->sid);
7278 int OutputToProcess(pr, message, count, outError)
7284 ChildProc *cp = (ChildProc *) pr;
7288 outCount = fwrite(message, 1, count, stdout);
7290 outCount = write(cp->fdTo, message, count);
7300 /* Output message to process, with "ms" milliseconds of delay
7301 between each character. This is needed when sending the logon
7302 script to ICC, which for some reason doesn't like the
7303 instantaneous send. */
7304 int OutputToProcessDelayed(pr, message, count, outError, msdelay)
7311 ChildProc *cp = (ChildProc *) pr;
7316 r = write(cp->fdTo, message++, 1);
7329 /**** Animation code by Hugh Fisher, DCS, ANU.
7331 Known problem: if a window overlapping the board is
7332 moved away while a piece is being animated underneath,
7333 the newly exposed area won't be updated properly.
7334 I can live with this.
7336 Known problem: if you look carefully at the animation
7337 of pieces in mono mode, they are being drawn as solid
7338 shapes without interior detail while moving. Fixing
7339 this would be a major complication for minimal return.
7342 /* Masks for XPM pieces. Black and white pieces can have
7343 different shapes, but in the interest of retaining my
7344 sanity pieces must have the same outline on both light
7345 and dark squares, and all pieces must use the same
7346 background square colors/images. */
7348 static int xpmDone = 0;
7351 CreateAnimMasks (pieceDepth)
7358 unsigned long plane;
7361 /* just return for gtk at the moment */
7364 /* Need a bitmap just to get a GC with right depth */
7365 buf = XCreatePixmap(xDisplay, xBoardWindow,
7367 values.foreground = 1;
7368 values.background = 0;
7369 /* Don't use XtGetGC, not read only */
7370 maskGC = XCreateGC(xDisplay, buf,
7371 GCForeground | GCBackground, &values);
7372 XFreePixmap(xDisplay, buf);
7374 buf = XCreatePixmap(xDisplay, xBoardWindow,
7375 squareSize, squareSize, pieceDepth);
7376 values.foreground = XBlackPixel(xDisplay, xScreen);
7377 values.background = XWhitePixel(xDisplay, xScreen);
7378 bufGC = XCreateGC(xDisplay, buf,
7379 GCForeground | GCBackground, &values);
7381 for (piece = WhitePawn; piece <= BlackKing; piece++) {
7382 /* Begin with empty mask */
7383 if(!xpmDone) // [HGM] pieces: keep using existing
7384 xpmMask[piece] = XCreatePixmap(xDisplay, xBoardWindow,
7385 squareSize, squareSize, 1);
7386 XSetFunction(xDisplay, maskGC, GXclear);
7387 XFillRectangle(xDisplay, xpmMask[piece], maskGC,
7388 0, 0, squareSize, squareSize);
7390 /* Take a copy of the piece */
7395 XSetFunction(xDisplay, bufGC, GXcopy);
7396 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn],
7398 0, 0, squareSize, squareSize, 0, 0);
7400 /* XOR the background (light) over the piece */
7401 XSetFunction(xDisplay, bufGC, GXxor);
7403 XCopyArea(xDisplay, xpmLightSquare, buf, bufGC,
7404 0, 0, squareSize, squareSize, 0, 0);
7406 XSetForeground(xDisplay, bufGC, lightSquareColor);
7407 XFillRectangle(xDisplay, buf, bufGC, 0, 0, squareSize, squareSize);
7410 /* We now have an inverted piece image with the background
7411 erased. Construct mask by just selecting all the non-zero
7412 pixels - no need to reconstruct the original image. */
7413 XSetFunction(xDisplay, maskGC, GXor);
7415 /* Might be quicker to download an XImage and create bitmap
7416 data from it rather than this N copies per piece, but it
7417 only takes a fraction of a second and there is a much
7418 longer delay for loading the pieces. */
7419 for (n = 0; n < pieceDepth; n ++) {
7420 XCopyPlane(xDisplay, buf, xpmMask[piece], maskGC,
7421 0, 0, squareSize, squareSize,
7427 XFreePixmap(xDisplay, buf);
7428 XFreeGC(xDisplay, bufGC);
7429 XFreeGC(xDisplay, maskGC);
7433 InitAnimState (anim, info)
7435 XWindowAttributes * info;
7440 /* Each buffer is square size, same depth as window */
7441 // anim->saveBuf = XCreatePixmap(xDisplay, xBoardWindow,
7442 // squareSize, squareSize, info->depth);
7443 // anim->newBuf = XCreatePixmap(xDisplay, xBoardWindow,
7444 // squareSize, squareSize, info->depth);
7446 // /* Create a plain GC for blitting */
7447 // mask = GCForeground | GCBackground | GCFunction |
7448 // GCPlaneMask | GCGraphicsExposures;
7449 // values.foreground = XBlackPixel(xDisplay, xScreen);
7450 // values.background = XWhitePixel(xDisplay, xScreen);
7451 // values.function = GXcopy;
7452 // values.plane_mask = AllPlanes;
7453 // values.graphics_exposures = False;
7454 // anim->blitGC = XCreateGC(xDisplay, xBoardWindow, mask, &values);
7456 // /* Piece will be copied from an existing context at
7457 // the start of each new animation/drag. */
7458 // anim->pieceGC = XCreateGC(xDisplay, xBoardWindow, 0, &values);
7460 // /* Outline will be a read-only copy of an existing */
7461 // anim->outlineGC = None;
7467 static VariantClass old = (VariantClass) -1; // [HGM] pieces: redo every time variant changes
7468 XWindowAttributes info;
7470 /* for gtk at the moment just ... */
7473 if (xpmDone && gameInfo.variant == old) return;
7474 if(xpmDone) old = gameInfo.variant; // first time pieces might not be created yet
7475 // XGetWindowAttributes(xDisplay, xBoardWindow, &info);
7477 // InitAnimState(&game, &info);
7478 // InitAnimState(&player, &info);
7480 /* For XPM pieces, we need bitmaps to use as masks. */
7482 // CreateAnimMasks(info.depth);
7488 static Boolean frameWaiting;
7490 static RETSIGTYPE FrameAlarm (sig)
7493 frameWaiting = False;
7494 /* In case System-V style signals. Needed?? */
7495 signal(SIGALRM, FrameAlarm);
7502 struct itimerval delay;
7504 XSync(xDisplay, False);
7507 frameWaiting = True;
7508 signal(SIGALRM, FrameAlarm);
7509 delay.it_interval.tv_sec =
7510 delay.it_value.tv_sec = time / 1000;
7511 delay.it_interval.tv_usec =
7512 delay.it_value.tv_usec = (time % 1000) * 1000;
7513 setitimer(ITIMER_REAL, &delay, NULL);
7515 /* Ugh -- busy-wait! --tpm */
7516 while (frameWaiting);
7518 while (frameWaiting) pause();
7520 delay.it_interval.tv_sec = delay.it_value.tv_sec = 0;
7521 delay.it_interval.tv_usec = delay.it_value.tv_usec = 0;
7522 setitimer(ITIMER_REAL, &delay, NULL);
7532 // XSync(xDisplay, False);
7534 usleep(time * 1000);
7539 /* Convert board position to corner of screen rect and color */
7542 ScreenSquare(column, row, pt, color)
7543 int column; int row; XPoint * pt; int * color;
7546 pt->x = lineGap + ((BOARD_WIDTH-1)-column) * (squareSize + lineGap);
7547 pt->y = lineGap + row * (squareSize + lineGap);
7549 pt->x = lineGap + column * (squareSize + lineGap);
7550 pt->y = lineGap + ((BOARD_HEIGHT-1)-row) * (squareSize + lineGap);
7552 *color = SquareColor(row, column);
7555 /* Convert window coords to square */
7558 BoardSquare(x, y, column, row)
7559 int x; int y; int * column; int * row;
7561 *column = EventToSquare(x, BOARD_WIDTH);
7562 if (flipView && *column >= 0)
7563 *column = BOARD_WIDTH - 1 - *column;
7564 *row = EventToSquare(y, BOARD_HEIGHT);
7565 if (!flipView && *row >= 0)
7566 *row = BOARD_HEIGHT - 1 - *row;
7571 #undef Max /* just in case */
7573 #define Max(a, b) ((a) > (b) ? (a) : (b))
7574 #define Min(a, b) ((a) < (b) ? (a) : (b))
7577 SetRect(rect, x, y, width, height)
7578 XRectangle * rect; int x; int y; int width; int height;
7582 rect->width = width;
7583 rect->height = height;
7586 /* Test if two frames overlap. If they do, return
7587 intersection rect within old and location of
7588 that rect within new. */
7591 Intersect(old, new, size, area, pt)
7592 XPoint * old; XPoint * new;
7593 int size; XRectangle * area; XPoint * pt;
7595 if (old->x > new->x + size || new->x > old->x + size ||
7596 old->y > new->y + size || new->y > old->y + size) {
7599 SetRect(area, Max(new->x - old->x, 0), Max(new->y - old->y, 0),
7600 size - abs(old->x - new->x), size - abs(old->y - new->y));
7601 pt->x = Max(old->x - new->x, 0);
7602 pt->y = Max(old->y - new->y, 0);
7607 /* For two overlapping frames, return the rect(s)
7608 in the old that do not intersect with the new. */
7611 CalcUpdateRects(old, new, size, update, nUpdates)
7612 XPoint * old; XPoint * new; int size;
7613 XRectangle update[]; int * nUpdates;
7617 /* If old = new (shouldn't happen) then nothing to draw */
7618 if (old->x == new->x && old->y == new->y) {
7622 /* Work out what bits overlap. Since we know the rects
7623 are the same size we don't need a full intersect calc. */
7625 /* Top or bottom edge? */
7626 if (new->y > old->y) {
7627 SetRect(&(update[count]), old->x, old->y, size, new->y - old->y);
7629 } else if (old->y > new->y) {
7630 SetRect(&(update[count]), old->x, old->y + size - (old->y - new->y),
7631 size, old->y - new->y);
7634 /* Left or right edge - don't overlap any update calculated above. */
7635 if (new->x > old->x) {
7636 SetRect(&(update[count]), old->x, Max(new->y, old->y),
7637 new->x - old->x, size - abs(new->y - old->y));
7639 } else if (old->x > new->x) {
7640 SetRect(&(update[count]), new->x + size, Max(new->y, old->y),
7641 old->x - new->x, size - abs(new->y - old->y));
7648 /* Generate a series of frame coords from start->mid->finish.
7649 The movement rate doubles until the half way point is
7650 reached, then halves back down to the final destination,
7651 which gives a nice slow in/out effect. The algorithmn
7652 may seem to generate too many intermediates for short
7653 moves, but remember that the purpose is to attract the
7654 viewers attention to the piece about to be moved and
7655 then to where it ends up. Too few frames would be less
7659 Tween(start, mid, finish, factor, frames, nFrames)
7660 XPoint * start; XPoint * mid;
7661 XPoint * finish; int factor;
7662 XPoint frames[]; int * nFrames;
7664 int fraction, n, count;
7668 /* Slow in, stepping 1/16th, then 1/8th, ... */
7670 for (n = 0; n < factor; n++)
7672 for (n = 0; n < factor; n++) {
7673 frames[count].x = start->x + (mid->x - start->x) / fraction;
7674 frames[count].y = start->y + (mid->y - start->y) / fraction;
7676 fraction = fraction / 2;
7680 frames[count] = *mid;
7683 /* Slow out, stepping 1/2, then 1/4, ... */
7685 for (n = 0; n < factor; n++) {
7686 frames[count].x = finish->x - (finish->x - mid->x) / fraction;
7687 frames[count].y = finish->y - (finish->y - mid->y) / fraction;
7689 fraction = fraction * 2;
7694 /* Draw a piece on the screen without disturbing what's there */
7697 SelectGCMask(piece, clip, outline, mask)
7698 ChessSquare piece; GC * clip; GC * outline; Pixmap * mask;
7702 /* Bitmap for piece being moved. */
7703 if (appData.monoMode) {
7704 *mask = *pieceToSolid(piece);
7705 } else if (useImages) {
7707 *mask = xpmMask[piece];
7709 *mask = ximMaskPm[piece];
7712 *mask = *pieceToSolid(piece);
7715 /* GC for piece being moved. Square color doesn't matter, but
7716 since it gets modified we make a copy of the original. */
7718 if (appData.monoMode)
7723 if (appData.monoMode)
7728 // XCopyGC(xDisplay, source, 0xFFFFFFFF, *clip);
7730 /* Outline only used in mono mode and is not modified */
7732 *outline = bwPieceGC;
7734 *outline = wbPieceGC;
7738 OverlayPiece(piece, clip, outline, dest)
7739 ChessSquare piece; GC clip; GC outline; Drawable dest;
7744 /* Draw solid rectangle which will be clipped to shape of piece */
7745 // XFillRectangle(xDisplay, dest, clip,
7746 // 0, 0, squareSize, squareSize)
7748 if (appData.monoMode)
7749 /* Also draw outline in contrasting color for black
7750 on black / white on white cases */
7751 // XCopyPlane(xDisplay, *pieceToOutline(piece), dest, outline,
7752 // 0, 0, squareSize, squareSize, 0, 0, 1)
7755 /* Copy the piece */
7760 // XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
7762 // 0, 0, squareSize, squareSize,
7767 /* Animate the movement of a single piece */
7770 BeginAnimation(anim, piece, startColor, start)
7778 /* The old buffer is initialised with the start square (empty) */
7779 BlankSquare(0, 0, startColor, EmptySquare, anim->saveBuf);
7780 anim->prevFrame = *start;
7782 /* The piece will be drawn using its own bitmap as a matte */
7783 // SelectGCMask(piece, &anim->pieceGC, &anim->outlineGC, &mask);
7784 // XSetClipMask(xDisplay, anim->pieceGC, mask);
7788 AnimationFrame(anim, frame, piece)
7793 XRectangle updates[4];
7798 /* Save what we are about to draw into the new buffer */
7799 // XCopyArea(xDisplay, xBoardWindow, anim->newBuf, anim->blitGC,
7800 // frame->x, frame->y, squareSize, squareSize,
7803 /* Erase bits of the previous frame */
7804 if (Intersect(&anim->prevFrame, frame, squareSize, &overlap, &pt)) {
7805 /* Where the new frame overlapped the previous,
7806 the contents in newBuf are wrong. */
7807 // XCopyArea(xDisplay, anim->saveBuf, anim->newBuf, anim->blitGC,
7808 // overlap.x, overlap.y,
7809 // overlap.width, overlap.height,
7811 /* Repaint the areas in the old that don't overlap new */
7812 CalcUpdateRects(&anim->prevFrame, frame, squareSize, updates, &count);
7813 for (i = 0; i < count; i++)
7814 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
7815 // updates[i].x - anim->prevFrame.x,
7816 // updates[i].y - anim->prevFrame.y,
7817 // updates[i].width, updates[i].height,
7818 // updates[i].x, updates[i].y)
7821 /* Easy when no overlap */
7822 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
7823 // 0, 0, squareSize, squareSize,
7824 // anim->prevFrame.x, anim->prevFrame.y);
7827 /* Save this frame for next time round */
7828 // XCopyArea(xDisplay, anim->newBuf, anim->saveBuf, anim->blitGC,
7829 // 0, 0, squareSize, squareSize,
7831 anim->prevFrame = *frame;
7833 /* Draw piece over original screen contents, not current,
7834 and copy entire rect. Wipes out overlapping piece images. */
7835 OverlayPiece(piece, anim->pieceGC, anim->outlineGC, anim->newBuf);
7836 // XCopyArea(xDisplay, anim->newBuf, xBoardWindow, anim->blitGC,
7837 // 0, 0, squareSize, squareSize,
7838 // frame->x, frame->y);
7842 EndAnimation (anim, finish)
7846 XRectangle updates[4];
7851 /* The main code will redraw the final square, so we
7852 only need to erase the bits that don't overlap. */
7853 if (Intersect(&anim->prevFrame, finish, squareSize, &overlap, &pt)) {
7854 CalcUpdateRects(&anim->prevFrame, finish, squareSize, updates, &count);
7855 for (i = 0; i < count; i++)
7856 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
7857 // updates[i].x - anim->prevFrame.x,
7858 // updates[i].y - anim->prevFrame.y,
7859 // updates[i].width, updates[i].height,
7860 // updates[i].x, updates[i].y)
7863 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
7864 // 0, 0, squareSize, squareSize,
7865 // anim->prevFrame.x, anim->prevFrame.y);
7870 FrameSequence(anim, piece, startColor, start, finish, frames, nFrames)
7872 ChessSquare piece; int startColor;
7873 XPoint * start; XPoint * finish;
7874 XPoint frames[]; int nFrames;
7878 BeginAnimation(anim, piece, startColor, start);
7879 for (n = 0; n < nFrames; n++) {
7880 AnimationFrame(anim, &(frames[n]), piece);
7881 FrameDelay(appData.animSpeed);
7883 EndAnimation(anim, finish);
7886 /* Main control logic for deciding what to animate and how */
7889 AnimateMove(board, fromX, fromY, toX, toY)
7898 XPoint start, finish, mid;
7899 XPoint frames[kFactor * 2 + 1];
7900 int nFrames, startColor, endColor;
7902 /* Are we animating? */
7903 if (!appData.animate || appData.blindfold)
7906 if(board[toY][toX] == WhiteRook && board[fromY][fromX] == WhiteKing ||
7907 board[toY][toX] == BlackRook && board[fromY][fromX] == BlackKing)
7908 return; // [HGM] FRC: no animtion of FRC castlings, as to-square is not true to-square
7910 if (fromY < 0 || fromX < 0 || toX < 0 || toY < 0) return;
7911 piece = board[fromY][fromX];
7912 if (piece >= EmptySquare) return;
7917 hop = (piece == WhiteKnight || piece == BlackKnight);
7920 if (appData.debugMode) {
7921 fprintf(debugFP, hop ? _("AnimateMove: piece %d hops from %d,%d to %d,%d \n") :
7922 _("AnimateMove: piece %d slides from %d,%d to %d,%d \n"),
7923 piece, fromX, fromY, toX, toY); }
7925 ScreenSquare(fromX, fromY, &start, &startColor);
7926 ScreenSquare(toX, toY, &finish, &endColor);
7929 /* Knight: make diagonal movement then straight */
7930 if (abs(toY - fromY) < abs(toX - fromX)) {
7931 mid.x = start.x + (finish.x - start.x) / 2;
7935 mid.y = start.y + (finish.y - start.y) / 2;
7938 mid.x = start.x + (finish.x - start.x) / 2;
7939 mid.y = start.y + (finish.y - start.y) / 2;
7942 /* Don't use as many frames for very short moves */
7943 if (abs(toY - fromY) + abs(toX - fromX) <= 2)
7944 Tween(&start, &mid, &finish, kFactor - 1, frames, &nFrames);
7946 Tween(&start, &mid, &finish, kFactor, frames, &nFrames);
7947 FrameSequence(&game, piece, startColor, &start, &finish, frames, nFrames);
7949 /* Be sure end square is redrawn */
7950 damage[toY][toX] = True;
7954 DragPieceBegin(x, y)
7957 int boardX, boardY, color;
7960 /* Are we animating? */
7961 if (!appData.animateDragging || appData.blindfold)
7964 /* Figure out which square we start in and the
7965 mouse position relative to top left corner. */
7966 BoardSquare(x, y, &boardX, &boardY);
7967 player.startBoardX = boardX;
7968 player.startBoardY = boardY;
7969 ScreenSquare(boardX, boardY, &corner, &color);
7970 player.startSquare = corner;
7971 player.startColor = color;
7973 /* Start from exactly where the piece is. This can be confusing
7974 if you start dragging far from the center of the square; most
7975 or all of the piece can be over a different square from the one
7976 the mouse pointer is in. */
7977 player.mouseDelta.x = x - corner.x;
7978 player.mouseDelta.y = y - corner.y;
7980 /* As soon as we start dragging, the piece will jump slightly to
7981 be centered over the mouse pointer. */
7982 player.mouseDelta.x = squareSize/2;
7983 player.mouseDelta.y = squareSize/2;
7985 /* Initialise animation */
7986 player.dragPiece = PieceForSquare(boardX, boardY);
7988 if (player.dragPiece >= 0 && player.dragPiece < EmptySquare) {
7989 player.dragActive = True;
7990 BeginAnimation(&player, player.dragPiece, color, &corner);
7991 /* Mark this square as needing to be redrawn. Note that
7992 we don't remove the piece though, since logically (ie
7993 as seen by opponent) the move hasn't been made yet. */
7994 if(boardX == BOARD_RGHT+1 && PieceForSquare(boardX-1, boardY) > 1 ||
7995 boardX == BOARD_LEFT-2 && PieceForSquare(boardX+1, boardY) > 1)
7996 // XCopyArea(xDisplay, xBoardWindow, player.saveBuf, player.blitGC,
7997 // corner.x, corner.y, squareSize, squareSize,
7998 // 0, 0); // [HGM] zh: unstack in stead of grab
7999 damage[boardY][boardX] = True;
8001 player.dragActive = False;
8011 /* Are we animating? */
8012 if (!appData.animateDragging || appData.blindfold)
8016 if (! player.dragActive)
8018 /* Move piece, maintaining same relative position
8019 of mouse within square */
8020 corner.x = x - player.mouseDelta.x;
8021 corner.y = y - player.mouseDelta.y;
8022 AnimationFrame(&player, &corner, player.dragPiece);
8024 if (appData.highlightDragging) {
8026 BoardSquare(x, y, &boardX, &boardY);
8027 SetHighlights(fromX, fromY, boardX, boardY);
8036 int boardX, boardY, color;
8039 /* Are we animating? */
8040 if (!appData.animateDragging || appData.blindfold)
8044 if (! player.dragActive)
8046 /* Last frame in sequence is square piece is
8047 placed on, which may not match mouse exactly. */
8048 BoardSquare(x, y, &boardX, &boardY);
8049 ScreenSquare(boardX, boardY, &corner, &color);
8050 EndAnimation(&player, &corner);
8052 /* Be sure end square is redrawn */
8053 damage[boardY][boardX] = True;
8055 /* This prevents weird things happening with fast successive
8056 clicks which on my Sun at least can cause motion events
8057 without corresponding press/release. */
8058 player.dragActive = False;
8061 /* Handle expose event while piece being dragged */
8066 if (!player.dragActive || appData.blindfold)
8069 /* What we're doing: logically, the move hasn't been made yet,
8070 so the piece is still in it's original square. But visually
8071 it's being dragged around the board. So we erase the square
8072 that the piece is on and draw it at the last known drag point. */
8073 BlankSquare(player.startSquare.x, player.startSquare.y,
8074 player.startColor, EmptySquare, xBoardWindow);
8075 AnimationFrame(&player, &player.prevFrame, player.dragPiece);
8076 damage[player.startBoardY][player.startBoardX] = TRUE;
8080 SetProgramStats( FrontEndProgramStats * stats )
8083 // [HGM] done, but perhaps backend should call this directly?
8084 EngineOutputUpdate( stats );