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) 0},
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},
1434 XrmOptionDescRec shellOptions[] = {
1435 { "-whitePieceColor", "whitePieceColor", XrmoptionSepArg, NULL },
1436 { "-blackPieceColor", "blackPieceColor", XrmoptionSepArg, NULL },
1437 { "-lightSquareColor", "lightSquareColor", XrmoptionSepArg, NULL },
1438 { "-darkSquareColor", "darkSquareColor", XrmoptionSepArg, NULL },
1439 { "-highlightSquareColor", "highlightSquareColor", XrmoptionSepArg, NULL },
1440 { "-premoveHighlightColor", "premoveHighlightColor", XrmoptionSepArg,NULL},
1441 { "-movesPerSession", "movesPerSession", XrmoptionSepArg, NULL },
1442 { "-mps", "movesPerSession", XrmoptionSepArg, NULL },
1443 { "-timeIncrement", "timeIncrement", XrmoptionSepArg, NULL },
1444 { "-inc", "timeIncrement", XrmoptionSepArg, NULL },
1445 { "-initString", "initString", XrmoptionSepArg, NULL },
1446 { "-firstInitString", "initString", XrmoptionSepArg, NULL },
1447 { "-secondInitString", "secondInitString", XrmoptionSepArg, NULL },
1448 { "-firstComputerString", "firstComputerString", XrmoptionSepArg, NULL },
1449 { "-secondComputerString", "secondComputerString", XrmoptionSepArg, NULL },
1450 { "-firstChessProgram", "firstChessProgram", XrmoptionSepArg, NULL },
1451 { "-fcp", "firstChessProgram", XrmoptionSepArg, NULL },
1452 { "-secondChessProgram", "secondChessProgram", XrmoptionSepArg, NULL },
1453 { "-scp", "secondChessProgram", XrmoptionSepArg, NULL },
1454 { "-firstPlaysBlack", "firstPlaysBlack", XrmoptionSepArg, NULL },
1455 { "-fb", "firstPlaysBlack", XrmoptionNoArg, "True" },
1456 { "-xfb", "firstPlaysBlack", XrmoptionNoArg, "False" },
1457 { "-noChessProgram", "noChessProgram", XrmoptionSepArg, NULL },
1458 { "-ncp", "noChessProgram", XrmoptionNoArg, "True" },
1459 { "-xncp", "noChessProgram", XrmoptionNoArg, "False" },
1460 { "-firstHost", "firstHost", XrmoptionSepArg, NULL },
1461 { "-fh", "firstHost", XrmoptionSepArg, NULL },
1462 { "-secondHost", "secondHost", XrmoptionSepArg, NULL },
1463 { "-sh", "secondHost", XrmoptionSepArg, NULL },
1464 { "-firstDirectory", "firstDirectory", XrmoptionSepArg, NULL },
1465 { "-fd", "firstDirectory", XrmoptionSepArg, NULL },
1466 { "-secondDirectory", "secondDirectory", XrmoptionSepArg, NULL },
1467 { "-sd", "secondDirectory", XrmoptionSepArg, NULL },
1468 { "-bitmapDirectory", "bitmapDirectory", XrmoptionSepArg, NULL },
1469 { "-bm", "bitmapDirectory", XrmoptionSepArg, NULL },
1470 { "-remoteShell", "remoteShell", XrmoptionSepArg, NULL },
1471 { "-rsh", "remoteShell", XrmoptionSepArg, NULL },
1472 { "-remoteUser", "remoteUser", XrmoptionSepArg, NULL },
1473 { "-ruser", "remoteUser", XrmoptionSepArg, NULL },
1474 { "-timeDelay", "timeDelay", XrmoptionSepArg, NULL },
1475 { "-td", "timeDelay", XrmoptionSepArg, NULL },
1476 { "-timeControl", "timeControl", XrmoptionSepArg, NULL },
1477 { "-tc", "timeControl", XrmoptionSepArg, NULL },
1478 { "-internetChessServerMode", "internetChessServerMode",
1479 XrmoptionSepArg, NULL },
1480 { "-ics", "internetChessServerMode", XrmoptionNoArg, "True" },
1481 { "-xics", "internetChessServerMode", XrmoptionNoArg, "False" },
1482 { "-internetChessServerHost", "internetChessServerHost",
1483 XrmoptionSepArg, NULL },
1484 { "-icshost", "internetChessServerHost", XrmoptionSepArg, NULL },
1485 { "-internetChessServerPort", "internetChessServerPort",
1486 XrmoptionSepArg, NULL },
1487 { "-icsport", "internetChessServerPort", XrmoptionSepArg, NULL },
1488 { "-internetChessServerCommPort", "internetChessServerCommPort",
1489 XrmoptionSepArg, NULL },
1490 { "-icscomm", "internetChessServerCommPort", XrmoptionSepArg, NULL },
1491 { "-internetChessServerLogonScript", "internetChessServerLogonScript",
1492 XrmoptionSepArg, NULL },
1493 { "-icslogon", "internetChessServerLogonScript", XrmoptionSepArg, NULL },
1494 { "-internetChessServerHelper", "internetChessServerHelper",
1495 XrmoptionSepArg, NULL },
1496 { "-icshelper", "internetChessServerHelper", XrmoptionSepArg, NULL },
1497 { "-internetChessServerInputBox", "internetChessServerInputBox",
1498 XrmoptionSepArg, NULL },
1499 { "-icsinput", "internetChessServerInputBox", XrmoptionNoArg, "True" },
1500 { "-xicsinput", "internetChessServerInputBox", XrmoptionNoArg, "False" },
1501 { "-icsAlarm", "icsAlarm", XrmoptionSepArg, NULL },
1502 { "-alarm", "icsAlarm", XrmoptionNoArg, "True" },
1503 { "-xalarm", "icsAlarm", XrmoptionNoArg, "False" },
1504 { "-icsAlarmTime", "icsAlarmTime", XrmoptionSepArg, NULL },
1505 { "-useTelnet", "useTelnet", XrmoptionSepArg, NULL },
1506 { "-telnet", "useTelnet", XrmoptionNoArg, "True" },
1507 { "-xtelnet", "useTelnet", XrmoptionNoArg, "False" },
1508 { "-telnetProgram", "telnetProgram", XrmoptionSepArg, NULL },
1509 { "-gateway", "gateway", XrmoptionSepArg, NULL },
1510 { "-loadGameFile", "loadGameFile", XrmoptionSepArg, NULL },
1511 { "-lgf", "loadGameFile", XrmoptionSepArg, NULL },
1512 { "-loadGameIndex", "loadGameIndex", XrmoptionSepArg, NULL },
1513 { "-lgi", "loadGameIndex", XrmoptionSepArg, NULL },
1514 { "-saveGameFile", "saveGameFile", XrmoptionSepArg, NULL },
1515 { "-sgf", "saveGameFile", XrmoptionSepArg, NULL },
1516 { "-autoSaveGames", "autoSaveGames", XrmoptionSepArg, NULL },
1517 { "-autosave", "autoSaveGames", XrmoptionNoArg, "True" },
1518 { "-xautosave", "autoSaveGames", XrmoptionNoArg, "False" },
1519 { "-autoRaiseBoard", "autoRaiseBoard", XrmoptionSepArg, NULL },
1520 { "-autoraise", "autoRaiseBoard", XrmoptionNoArg, "True" },
1521 { "-xautoraise", "autoRaiseBoard", XrmoptionNoArg, "False" },
1522 { "-blindfold", "blindfold", XrmoptionSepArg, NULL },
1523 { "-blind", "blindfold", XrmoptionNoArg, "True" },
1524 { "-xblind", "blindfold", XrmoptionNoArg, "False" },
1525 { "-loadPositionFile", "loadPositionFile", XrmoptionSepArg, NULL },
1526 { "-lpf", "loadPositionFile", XrmoptionSepArg, NULL },
1527 { "-loadPositionIndex", "loadPositionIndex", XrmoptionSepArg, NULL },
1528 { "-lpi", "loadPositionIndex", XrmoptionSepArg, NULL },
1529 { "-savePositionFile", "savePositionFile", XrmoptionSepArg, NULL },
1530 { "-spf", "savePositionFile", XrmoptionSepArg, NULL },
1531 { "-matchMode", "matchMode", XrmoptionSepArg, NULL },
1532 { "-mm", "matchMode", XrmoptionNoArg, "True" },
1533 { "-xmm", "matchMode", XrmoptionNoArg, "False" },
1534 { "-matchGames", "matchGames", XrmoptionSepArg, NULL },
1535 { "-mg", "matchGames", XrmoptionSepArg, NULL },
1536 { "-monoMode", "monoMode", XrmoptionSepArg, NULL },
1537 { "-mono", "monoMode", XrmoptionNoArg, "True" },
1538 { "-xmono", "monoMode", XrmoptionNoArg, "False" },
1539 { "-debugMode", "debugMode", XrmoptionSepArg, NULL },
1540 { "-debug", "debugMode", XrmoptionNoArg, "True" },
1541 { "-xdebug", "debugMode", XrmoptionNoArg, "False" },
1542 { "-clockMode", "clockMode", XrmoptionSepArg, NULL },
1543 { "-clock", "clockMode", XrmoptionNoArg, "True" },
1544 { "-xclock", "clockMode", XrmoptionNoArg, "False" },
1545 { "-boardSize", "boardSize", XrmoptionSepArg, NULL },
1546 { "-size", "boardSize", XrmoptionSepArg, NULL },
1547 { "-searchTime", "searchTime", XrmoptionSepArg, NULL },
1548 { "-st", "searchTime", XrmoptionSepArg, NULL },
1549 { "-searchDepth", "searchDepth", XrmoptionSepArg, NULL },
1550 { "-depth", "searchDepth", XrmoptionSepArg, NULL },
1551 { "-showCoords", "showCoords", XrmoptionSepArg, NULL },
1552 { "-coords", "showCoords", XrmoptionNoArg, "True" },
1553 { "-xcoords", "showCoords", XrmoptionNoArg, "False" },
1555 { "-showJail", "showJail", XrmoptionSepArg, NULL },
1556 { "-jail", "showJail", XrmoptionNoArg, "1" },
1557 { "-sidejail", "showJail", XrmoptionNoArg, "2" },
1558 { "-xjail", "showJail", XrmoptionNoArg, "0" },
1560 { "-showThinking", "showThinking", XrmoptionSepArg, NULL },
1561 { "-thinking", "showThinking", XrmoptionNoArg, "True" },
1562 { "-xthinking", "showThinking", XrmoptionNoArg, "False" },
1563 { "-ponderNextMove", "ponderNextMove", XrmoptionSepArg, NULL },
1564 { "-ponder", "ponderNextMove", XrmoptionNoArg, "True" },
1565 { "-xponder", "ponderNextMove", XrmoptionNoArg, "False" },
1566 { "-periodicUpdates", "periodicUpdates", XrmoptionSepArg, NULL },
1567 { "-periodic", "periodicUpdates", XrmoptionNoArg, "True" },
1568 { "-xperiodic", "periodicUpdates", XrmoptionNoArg, "False" },
1569 { "-clockFont", "clockFont", XrmoptionSepArg, NULL },
1570 { "-coordFont", "coordFont", XrmoptionSepArg, NULL },
1571 { "-font", "font", XrmoptionSepArg, NULL },
1572 { "-ringBellAfterMoves", "ringBellAfterMoves", XrmoptionSepArg, NULL },
1573 { "-bell", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1574 { "-xbell", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1575 { "-movesound", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1576 { "-xmovesound", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1577 { "-autoCallFlag", "autoCallFlag", XrmoptionSepArg, NULL },
1578 { "-autoflag", "autoCallFlag", XrmoptionNoArg, "True" },
1579 { "-xautoflag", "autoCallFlag", XrmoptionNoArg, "False" },
1580 { "-autoFlipView", "autoFlipView", XrmoptionSepArg, NULL },
1581 { "-autoflip", "autoFlipView", XrmoptionNoArg, "True" },
1582 { "-xautoflip", "autoFlipView", XrmoptionNoArg, "False" },
1583 { "-autoObserve", "autoObserve", XrmoptionSepArg, NULL },
1584 { "-autobs", "autoObserve", XrmoptionNoArg, "True" },
1585 { "-xautobs", "autoObserve", XrmoptionNoArg, "False" },
1586 { "-autoComment", "autoComment", XrmoptionSepArg, NULL },
1587 { "-autocomm", "autoComment", XrmoptionNoArg, "True" },
1588 { "-xautocomm", "autoComment", XrmoptionNoArg, "False" },
1589 { "-getMoveList", "getMoveList", XrmoptionSepArg, NULL },
1590 { "-moves", "getMoveList", XrmoptionNoArg, "True" },
1591 { "-xmoves", "getMoveList", XrmoptionNoArg, "False" },
1593 { "-highlightDragging", "highlightDragging", XrmoptionSepArg, NULL },
1594 { "-highdrag", "highlightDragging", XrmoptionNoArg, "True" },
1595 { "-xhighdrag", "highlightDragging", XrmoptionNoArg, "False" },
1597 { "-highlightLastMove", "highlightLastMove", XrmoptionSepArg, NULL },
1598 { "-highlight", "highlightLastMove", XrmoptionNoArg, "True" },
1599 { "-xhighlight", "highlightLastMove", XrmoptionNoArg, "False" },
1600 { "-premove", "premove", XrmoptionSepArg, NULL },
1601 { "-pre", "premove", XrmoptionNoArg, "True" },
1602 { "-xpre", "premove", XrmoptionNoArg, "False" },
1603 { "-testLegality", "testLegality", XrmoptionSepArg, NULL },
1604 { "-legal", "testLegality", XrmoptionNoArg, "True" },
1605 { "-xlegal", "testLegality", XrmoptionNoArg, "False" },
1606 { "-flipView", "flipView", XrmoptionSepArg, NULL },
1607 { "-flip", "flipView", XrmoptionNoArg, "True" },
1608 { "-xflip", "flipView", XrmoptionNoArg, "False" },
1609 { "-cmail", "cmailGameName", XrmoptionSepArg, NULL },
1610 { "-alwaysPromoteToQueen", "alwaysPromoteToQueen",
1611 XrmoptionSepArg, NULL },
1612 { "-queen", "alwaysPromoteToQueen", XrmoptionNoArg, "True" },
1613 { "-xqueen", "alwaysPromoteToQueen", XrmoptionNoArg, "False" },
1614 { "-oldSaveStyle", "oldSaveStyle", XrmoptionSepArg, NULL },
1615 { "-oldsave", "oldSaveStyle", XrmoptionNoArg, "True" },
1616 { "-xoldsave", "oldSaveStyle", XrmoptionNoArg, "False" },
1617 { "-quietPlay", "quietPlay", XrmoptionSepArg, NULL },
1618 { "-quiet", "quietPlay", XrmoptionNoArg, "True" },
1619 { "-xquiet", "quietPlay", XrmoptionNoArg, "False" },
1620 { "-titleInWindow", "titleInWindow", XrmoptionSepArg, NULL },
1621 { "-title", "titleInWindow", XrmoptionNoArg, "True" },
1622 { "-xtitle", "titleInWindow", XrmoptionNoArg, "False" },
1624 { "-zippyTalk", "zippyTalk", XrmoptionSepArg, NULL },
1625 { "-zt", "zippyTalk", XrmoptionNoArg, "True" },
1626 { "-xzt", "zippyTalk", XrmoptionNoArg, "False" },
1627 { "-zippyPlay", "zippyPlay", XrmoptionSepArg, NULL },
1628 { "-zp", "zippyPlay", XrmoptionNoArg, "True" },
1629 { "-xzp", "zippyPlay", XrmoptionNoArg, "False" },
1630 { "-zippyLines", "zippyLines", XrmoptionSepArg, NULL },
1631 { "-zippyPinhead", "zippyPinhead", XrmoptionSepArg, NULL },
1632 { "-zippyPassword", "zippyPassword", XrmoptionSepArg, NULL },
1633 { "-zippyPassword2", "zippyPassword2", XrmoptionSepArg, NULL },
1634 { "-zippyWrongPassword", "zippyWrongPassword", XrmoptionSepArg, NULL },
1635 { "-zippyAcceptOnly", "zippyAcceptOnly", XrmoptionSepArg, NULL },
1636 { "-zippyUseI", "zippyUseI", XrmoptionSepArg, NULL },
1637 { "-zui", "zippyUseI", XrmoptionNoArg, "True" },
1638 { "-xzui", "zippyUseI", XrmoptionNoArg, "False" },
1639 { "-zippyBughouse", "zippyBughouse", XrmoptionSepArg, NULL },
1640 { "-zippyNoplayCrafty", "zippyNoplayCrafty", XrmoptionSepArg, NULL },
1641 { "-znc", "zippyNoplayCrafty", XrmoptionNoArg, "True" },
1642 { "-xznc", "zippyNoplayCrafty", XrmoptionNoArg, "False" },
1643 { "-zippyGameEnd", "zippyGameEnd", XrmoptionSepArg, NULL },
1644 { "-zippyGameStart", "zippyGameStart", XrmoptionSepArg, NULL },
1645 { "-zippyAdjourn", "zippyAdjourn", XrmoptionSepArg, NULL },
1646 { "-zadj", "zippyAdjourn", XrmoptionNoArg, "True" },
1647 { "-xzadj", "zippyAdjourn", XrmoptionNoArg, "False" },
1648 { "-zippyAbort", "zippyAbort", XrmoptionSepArg, NULL },
1649 { "-zab", "zippyAbort", XrmoptionNoArg, "True" },
1650 { "-xzab", "zippyAbort", XrmoptionNoArg, "False" },
1651 { "-zippyVariants", "zippyVariants", XrmoptionSepArg, NULL },
1652 { "-zippyMaxGames", "zippyMaxGames", XrmoptionSepArg, NULL },
1653 { "-zippyReplayTimeout", "zippyReplayTimeout", XrmoptionSepArg, NULL },
1654 { "-zippyShortGame", "zippyShortGame", XrmoptionSepArg, NULL },
1656 { "-flashCount", "flashCount", XrmoptionSepArg, NULL },
1657 { "-flash", "flashCount", XrmoptionNoArg, "3" },
1658 { "-xflash", "flashCount", XrmoptionNoArg, "0" },
1659 { "-flashRate", "flashRate", XrmoptionSepArg, NULL },
1660 { "-pixmapDirectory", "pixmapDirectory", XrmoptionSepArg, NULL },
1661 { "-msLoginDelay", "msLoginDelay", XrmoptionSepArg, NULL },
1662 { "-pixmap", "pixmapDirectory", XrmoptionSepArg, NULL },
1663 { "-colorizeMessages", "colorizeMessages", XrmoptionSepArg, NULL },
1664 { "-colorize", "colorizeMessages", XrmoptionNoArg, "True" },
1665 { "-xcolorize", "colorizeMessages", XrmoptionNoArg, "False" },
1666 { "-colorShout", "colorShout", XrmoptionSepArg, NULL },
1667 { "-colorSShout", "colorSShout", XrmoptionSepArg, NULL },
1668 { "-colorCShout", "colorSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1669 { "-colorChannel1", "colorChannel1", XrmoptionSepArg, NULL },
1670 { "-colorChannel", "colorChannel", XrmoptionSepArg, NULL },
1671 { "-colorKibitz", "colorKibitz", XrmoptionSepArg, NULL },
1672 { "-colorTell", "colorTell", XrmoptionSepArg, NULL },
1673 { "-colorChallenge", "colorChallenge", XrmoptionSepArg, NULL },
1674 { "-colorRequest", "colorRequest", XrmoptionSepArg, NULL },
1675 { "-colorSeek", "colorSeek", XrmoptionSepArg, NULL },
1676 { "-colorNormal", "colorNormal", XrmoptionSepArg, NULL },
1677 { "-soundProgram", "soundProgram", XrmoptionSepArg, NULL },
1678 { "-soundShout", "soundShout", XrmoptionSepArg, NULL },
1679 { "-soundSShout", "soundSShout", XrmoptionSepArg, NULL },
1680 { "-soundCShout", "soundSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1681 { "-soundChannel1", "soundChannel1", XrmoptionSepArg, NULL },
1682 { "-soundChannel", "soundChannel", XrmoptionSepArg, NULL },
1683 { "-soundKibitz", "soundKibitz", XrmoptionSepArg, NULL },
1684 { "-soundTell", "soundTell", XrmoptionSepArg, NULL },
1685 { "-soundChallenge", "soundChallenge", XrmoptionSepArg, NULL },
1686 { "-soundRequest", "soundRequest", XrmoptionSepArg, NULL },
1687 { "-soundSeek", "soundSeek", XrmoptionSepArg, NULL },
1688 { "-soundMove", "soundMove", XrmoptionSepArg, NULL },
1689 { "-soundIcsWin", "soundIcsWin", XrmoptionSepArg, NULL },
1690 { "-soundIcsLoss", "soundIcsLoss", XrmoptionSepArg, NULL },
1691 { "-soundIcsDraw", "soundIcsDraw", XrmoptionSepArg, NULL },
1692 { "-soundIcsUnfinished", "soundIcsUnfinished", XrmoptionSepArg, NULL },
1693 { "-soundIcsAlarm", "soundIcsAlarm", XrmoptionSepArg, NULL },
1694 { "-reuseFirst", "reuseFirst", XrmoptionSepArg, NULL },
1695 { "-reuseChessPrograms", "reuseFirst", XrmoptionSepArg, NULL }, /*compat*/
1696 { "-reuse", "reuseFirst", XrmoptionNoArg, "True" },
1697 { "-xreuse", "reuseFirst", XrmoptionNoArg, "False" },
1698 { "-reuseSecond", "reuseSecond", XrmoptionSepArg, NULL },
1699 { "-reuse2", "reuseSecond", XrmoptionNoArg, "True" },
1700 { "-xreuse2", "reuseSecond", XrmoptionNoArg, "False" },
1701 { "-animateMoving", "animateMoving", XrmoptionSepArg, NULL },
1702 { "-animate", "animateMoving", XrmoptionNoArg, "True" },
1703 { "-xanimate", "animateMoving", XrmoptionNoArg, "False" },
1704 { "-animateDragging", "animateDragging", XrmoptionSepArg, NULL },
1705 { "-drag", "animateDragging", XrmoptionNoArg, "True" },
1706 { "-xdrag", "animateDragging", XrmoptionNoArg, "False" },
1707 { "-animateSpeed", "animateSpeed", XrmoptionSepArg, NULL },
1708 { "-popupExitMessage", "popupExitMessage", XrmoptionSepArg, NULL },
1709 { "-exit", "popupExitMessage", XrmoptionNoArg, "True" },
1710 { "-xexit", "popupExitMessage", XrmoptionNoArg, "False" },
1711 { "-popupMoveErrors", "popupMoveErrors", XrmoptionSepArg, NULL },
1712 { "-popup", "popupMoveErrors", XrmoptionNoArg, "True" },
1713 { "-xpopup", "popupMoveErrors", XrmoptionNoArg, "False" },
1714 { "-fontSizeTolerance", "fontSizeTolerance", XrmoptionSepArg, NULL },
1715 { "-initialMode", "initialMode", XrmoptionSepArg, NULL },
1716 { "-mode", "initialMode", XrmoptionSepArg, NULL },
1717 { "-variant", "variant", XrmoptionSepArg, NULL },
1718 { "-firstProtocolVersion", "firstProtocolVersion", XrmoptionSepArg, NULL },
1719 { "-secondProtocolVersion","secondProtocolVersion",XrmoptionSepArg, NULL },
1720 { "-showButtonBar", "showButtonBar", XrmoptionSepArg, NULL },
1721 { "-buttons", "showButtonBar", XrmoptionNoArg, "True" },
1722 { "-xbuttons", "showButtonBar", XrmoptionNoArg, "False" },
1723 { "-lowTimeWarningColor", "lowTimeWarningColor", XrmoptionSepArg, NULL },
1724 { "-lowTimeWarning", "lowTimeWarning", XrmoptionSepArg, NULL },
1725 /* [AS,HR] New features */
1726 { "-firstScoreAbs", "firstScoreAbs", XrmoptionSepArg, NULL },
1727 { "-secondScoreAbs", "secondScoreAbs", XrmoptionSepArg, NULL },
1728 { "-pgnExtendedInfo", "pgnExtendedInfo", XrmoptionSepArg, NULL },
1729 { "-hideThinkingFromHuman", "hideThinkingFromHuman", XrmoptionSepArg, NULL },
1730 { "-adjudicateLossThreshold", "adjudicateLossThreshold", XrmoptionSepArg, NULL },
1731 { "-adjudicateDrawMoves", "adjudicateDrawMoves", XrmoptionSepArg, NULL },
1732 { "-pgnEventHeader", "pgnEventHeader", XrmoptionSepArg, NULL },
1733 { "-firstIsUCI", "firstIsUCI", XrmoptionSepArg, NULL },
1734 { "-secondIsUCI", "secondIsUCI", XrmoptionSepArg, NULL },
1735 { "-fUCI", "firstIsUCI", XrmoptionNoArg, "True" },
1736 { "-sUCI", "secondIsUCI", XrmoptionNoArg, "True" },
1737 { "-firstHasOwnBookUCI", "firstHasOwnBookUCI", XrmoptionSepArg, NULL },
1738 { "-secondHasOwnBookUCI", "secondHasOwnBookUCI", XrmoptionSepArg, NULL },
1739 { "-fNoOwnBookUCI", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1740 { "-sNoOwnBookUCI", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1741 { "-firstXBook", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1742 { "-secondXBook", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1743 { "-polyglotDir", "polyglotDir", XrmoptionSepArg, NULL },
1744 { "-usePolyglotBook", "usePolyglotBook", XrmoptionSepArg, NULL },
1745 { "-polyglotBook", "polyglotBook", XrmoptionSepArg, NULL },
1746 { "-defaultHashSize", "defaultHashSize", XrmoptionSepArg, NULL },
1747 { "-defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XrmoptionSepArg, NULL },
1748 { "-defaultPathEGTB", "defaultPathEGTB", XrmoptionSepArg, NULL },
1749 { "-defaultFrcPosition", "defaultFrcPosition", XrmoptionSepArg, NULL },
1750 { "-gameListTags", "gameListTags", XrmoptionSepArg, NULL },
1751 // [HGM] I am sure AS added many more options, but we have to fish them out, from the list in winboard.c
1753 /* [HGM,HR] User-selectable board size */
1754 { "-boardWidth", "boardWidth", XrmoptionSepArg, NULL },
1755 { "-boardHeight", "boardHeight", XrmoptionSepArg, NULL },
1756 { "-matchPause", "matchPause", XrmoptionSepArg, NULL },
1758 /* [HGM] new arguments of 4.3.xx. All except first three are back-end options, which should work immediately */
1759 { "-holdingsSize", "holdingsSize", XrmoptionSepArg, NULL }, // requires extensive front-end changes to work
1760 { "-flipBlack", "flipBlack", XrmoptionSepArg, NULL }, // requires front-end changes to work
1761 { "-allWhite", "allWhite", XrmoptionSepArg, NULL }, // requires front-end changes to work
1762 { "-pieceToCharTable", "pieceToCharTable", XrmoptionSepArg, NULL },
1763 { "-alphaRank", "alphaRank", XrmoptionSepArg, NULL },
1764 { "-testClaims", "testClaims", XrmoptionSepArg, NULL },
1765 { "-checkMates", "checkMates", XrmoptionSepArg, NULL },
1766 { "-materialDraws", "materialDraws", XrmoptionSepArg, NULL },
1767 { "-trivialDraws", "trivialDraws", XrmoptionSepArg, NULL },
1768 { "-ruleMoves", "ruleMoves", XrmoptionSepArg, NULL },
1769 { "-repeatsToDraw", "repeatsToDraw", XrmoptionSepArg, NULL },
1770 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1771 { "-userName", "userName", XrmoptionSepArg, NULL },
1772 { "-autoKibitz", "autoKibitz", XrmoptionNoArg, "True" },
1773 { "-firstTimeOdds", "firstTimeOdds", XrmoptionSepArg, NULL },
1774 { "-secondTimeOdds", "secondTimeOdds", XrmoptionSepArg, NULL },
1775 { "-timeOddsMode", "timeOddsMode", XrmoptionSepArg, NULL },
1776 { "-firstAccumulateTC", "firstAccumulateTC", XrmoptionSepArg, NULL },
1777 { "-secondAccumulateTC", "secondAccumulateTC", XrmoptionSepArg, NULL },
1778 { "-firstNPS", "firstNPS", XrmoptionSepArg, NULL },
1779 { "-secondNPS", "secondNPS", XrmoptionSepArg, NULL },
1780 { "-serverMoves", "serverMoves", XrmoptionSepArg, NULL },
1781 { "-serverPause", "serverPause", XrmoptionSepArg, NULL },
1782 { "-suppressLoadMoves", "suppressLoadMoves", XrmoptionSepArg, NULL },
1783 { "-egtFormats", "egtFormats", XrmoptionSepArg, NULL },
1784 { "-userName", "userName", XrmoptionSepArg, NULL },
1785 { "-smpCores", "smpCores", XrmoptionSepArg, NULL },
1786 { "-sameColorGames", "sameColorGames", XrmoptionSepArg, NULL },
1787 { "-rewindIndex", "rewindIndex", XrmoptionSepArg, NULL },
1788 { "-niceEngines", "niceEngines", XrmoptionSepArg, NULL },
1789 { "-delayBeforeQuit", "delayBeforeQuit", XrmoptionSepArg, NULL },
1790 { "-delayAfterQuit", "delayAfterQuit", XrmoptionSepArg, NULL },
1791 { "-nameOfDebugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1792 { "-debugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1793 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1794 { "-noGUI", "noGUI", XrmoptionNoArg, "True" },
1795 { "-firstOptions", "firstOptions", XrmoptionSepArg, NULL },
1796 { "-secondOptions", "secondOptions", XrmoptionSepArg, NULL },
1797 { "-firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1798 { "-secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1802 XtActionsRec boardActions[] = {
1803 { "HandleUserMove", HandleUserMove },
1804 { "AnimateUserMove", AnimateUserMove },
1805 { "FileNameAction", FileNameAction },
1806 { "AskQuestionProc", AskQuestionProc },
1807 { "AskQuestionReplyAction", AskQuestionReplyAction },
1808 { "PieceMenuPopup", PieceMenuPopup },
1809 { "WhiteClock", WhiteClock },
1810 { "BlackClock", BlackClock },
1811 { "Iconify", Iconify },
1812 { "LoadSelectedProc", LoadSelectedProc },
1813 { "LoadPositionProc", LoadPositionProc },
1814 { "LoadNextPositionProc", LoadNextPositionProc },
1815 { "LoadPrevPositionProc", LoadPrevPositionProc },
1816 { "ReloadPositionProc", ReloadPositionProc },
1817 { "CopyPositionProc", CopyPositionProc },
1818 { "PastePositionProc", PastePositionProc },
1819 { "CopyGameProc", CopyGameProc },
1820 { "PasteGameProc", PasteGameProc },
1821 { "SaveGameProc", SaveGameProc },
1822 { "SavePositionProc", SavePositionProc },
1823 { "MailMoveProc", MailMoveProc },
1824 { "ReloadCmailMsgProc", ReloadCmailMsgProc },
1825 // { "MachineWhiteProc", MachineWhiteProc },
1826 // { "MachineBlackProc", MachineBlackProc },
1827 { "AnalysisModeProc", AnalyzeModeProc },
1828 { "AnalyzeFileProc", AnalyzeFileProc },
1829 // { "TwoMachinesProc", TwoMachinesProc },
1830 // { "IcsClientProc", IcsClientProc },
1831 { "EditGameProc", EditGameProc },
1832 { "EditPositionProc", EditPositionProc },
1833 { "TrainingProc", EditPositionProc },
1834 { "EngineOutputProc", EngineOutputProc}, // [HGM] Winboard_x engine-output window
1835 { "ShowGameListProc", ShowGameListProc },
1836 { "ShowMoveListProc", HistoryShowProc},
1837 { "EditTagsProc", EditCommentProc },
1838 { "EditCommentProc", EditCommentProc },
1839 { "IcsAlarmProc", IcsAlarmProc },
1840 { "IcsInputBoxProc", IcsInputBoxProc },
1841 // { "AcceptProc", AcceptProc },
1842 // { "DeclineProc", DeclineProc },
1843 // { "RematchProc", RematchProc },
1844 // { "CallFlagProc", CallFlagProc },
1845 // { "DrawProc", DrawProc },
1846 // { "AdjournProc", AdjournProc },
1847 // { "AbortProc", AbortProc },
1848 // { "ResignProc", ResignProc },
1849 // { "AdjuWhiteProc", AdjuWhiteProc },
1850 // { "AdjuBlackProc", AdjuBlackProc },
1851 // { "AdjuDrawProc", AdjuDrawProc },
1852 { "EnterKeyProc", EnterKeyProc },
1853 // { "StopObservingProc", StopObservingProc },
1854 // { "StopExaminingProc", StopExaminingProc },
1855 // { "BackwardProc", BackwardProc },
1856 // { "ForwardProc", ForwardProc },
1857 // { "ToStartProc", ToStartProc },
1858 // { "ToEndProc", ToEndProc },
1859 // { "RevertProc", RevertProc },
1860 // { "TruncateGameProc", TruncateGameProc },
1861 // { "MoveNowProc", MoveNowProc },
1862 // { "RetractMoveProc", RetractMoveProc },
1863 { "AlwaysQueenProc", AlwaysQueenProc },
1864 { "AnimateDraggingProc", AnimateDraggingProc },
1865 { "AnimateMovingProc", AnimateMovingProc },
1866 { "AutoflagProc", AutoflagProc },
1867 { "AutoflipProc", AutoflipProc },
1868 { "AutobsProc", AutobsProc },
1869 { "AutoraiseProc", AutoraiseProc },
1870 { "AutosaveProc", AutosaveProc },
1871 { "BlindfoldProc", BlindfoldProc },
1872 { "FlashMovesProc", FlashMovesProc },
1873 // { "FlipViewProc", FlipViewProc },
1874 { "GetMoveListProc", GetMoveListProc },
1876 { "HighlightDraggingProc", HighlightDraggingProc },
1878 { "HighlightLastMoveProc", HighlightLastMoveProc },
1879 { "IcsAlarmProc", IcsAlarmProc },
1880 { "MoveSoundProc", MoveSoundProc },
1881 { "OldSaveStyleProc", OldSaveStyleProc },
1882 { "PeriodicUpdatesProc", PeriodicUpdatesProc },
1883 { "PonderNextMoveProc", PonderNextMoveProc },
1884 { "PopupExitMessageProc", PopupExitMessageProc },
1885 { "PopupMoveErrorsProc", PopupMoveErrorsProc },
1886 { "PremoveProc", PremoveProc },
1887 { "QuietPlayProc", QuietPlayProc },
1888 { "ShowThinkingProc", ShowThinkingProc },
1889 { "HideThinkingProc", HideThinkingProc },
1890 { "TestLegalityProc", TestLegalityProc },
1891 // { "InfoProc", InfoProc },
1892 // { "ManProc", ManProc },
1893 // { "HintProc", HintProc },
1894 // { "BookProc", BookProc },
1895 { "AboutGameProc", AboutGameProc },
1896 { "DebugProc", DebugProc },
1897 { "NothingProc", NothingProc },
1898 { "CommentPopDown", (XtActionProc) CommentPopDown },
1899 { "EditCommentPopDown", (XtActionProc) EditCommentPopDown },
1900 { "TagsPopDown", (XtActionProc) TagsPopDown },
1901 { "ErrorPopDown", (XtActionProc) ErrorPopDown },
1902 { "ICSInputBoxPopDown", (XtActionProc) ICSInputBoxPopDown },
1903 { "AnalysisPopDown", (XtActionProc) AnalysisPopDown },
1904 { "FileNamePopDown", (XtActionProc) FileNamePopDown },
1905 { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown },
1906 { "GameListPopDown", (XtActionProc) GameListPopDown },
1907 { "PromotionPopDown", (XtActionProc) PromotionPopDown },
1908 { "HistoryPopDown", (XtActionProc) HistoryPopDown },
1909 { "EngineOutputPopDown", (XtActionProc) EngineOutputPopDown },
1910 { "ShufflePopDown", (XtActionProc) ShufflePopDown },
1911 { "EnginePopDown", (XtActionProc) EnginePopDown },
1912 { "UciPopDown", (XtActionProc) UciPopDown },
1913 { "TimeControlPopDown", (XtActionProc) TimeControlPopDown },
1914 { "NewVariantPopDown", (XtActionProc) NewVariantPopDown },
1915 { "SettingsPopDown", (XtActionProc) SettingsPopDown },
1919 char ICSInputTranslations[] =
1920 "<Key>Return: EnterKeyProc() \n";
1922 String xboardResources[] = {
1923 "*fileName*value.translations: #override\\n <Key>Return: FileNameAction()",
1924 "*question*value.translations: #override\\n <Key>Return: AskQuestionReplyAction()",
1925 "*errorpopup*translations: #override\\n <Key>Return: ErrorPopDown()",
1929 static char *cnames[9] = { "black", "red", "green", "yellow", "blue",
1930 "magenta", "cyan", "white" };
1934 TextColors textColors[(int)NColorClasses];
1936 /* String is: "fg, bg, attr". Which is 0, 1, 2 */
1938 parse_color(str, which)
1942 char *p, buf[100], *d;
1945 if (strlen(str) > 99) /* watch bounds on buf */
1950 for (i=0; i<which; ++i) {
1957 /* Could be looking at something like:
1959 .. in which case we want to stop on a comma also */
1960 while (*p && *p != ',' && !isalpha(*p) && !isdigit(*p))
1964 return -1; /* Use default for empty field */
1967 if (which == 2 || isdigit(*p))
1970 while (*p && isalpha(*p))
1975 for (i=0; i<8; ++i) {
1976 if (!StrCaseCmp(buf, cnames[i]))
1977 return which? (i+40) : (i+30);
1979 if (!StrCaseCmp(buf, "default")) return -1;
1981 fprintf(stderr, _("%s: unrecognized color %s\n"), programName, buf);
1986 parse_cpair(cc, str)
1990 if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {
1991 fprintf(stderr, _("%s: can't parse foreground color in `%s'\n"),
1996 /* bg and attr are optional */
1997 textColors[(int)cc].bg = parse_color(str, 1);
1998 if ((textColors[(int)cc].attr = parse_color(str, 2)) < 0) {
1999 textColors[(int)cc].attr = 0;
2005 /* Arrange to catch delete-window events */
2006 Atom wm_delete_window;
2008 CatchDeleteWindow(Widget w, String procname)
2011 XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
2012 snprintf(buf, sizeof(buf), "<Message>WM_PROTOCOLS: %s() \n", procname);
2013 XtAugmentTranslations(w, XtParseTranslationTable(buf));
2019 /* this should raise the board to the top */
2020 gtk_window_present(GTK_WINDOW(GUI_Window));
2025 // eventually, all layout determining code should go into a subroutine, but until then IDSIZE remains undefined
2027 #define BoardSize int
2028 void InitDrawingSizes(BoardSize boardSize, int flags)
2029 { // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
2030 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2032 XtGeometryResult gres;
2035 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2036 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2038 timerWidth = (boardWidth - sep) / 2;
2040 if (appData.titleInWindow)
2045 w = boardWidth - 2*bor;
2049 w = boardWidth - w - sep - 2*bor - 2; // WIDTH_FUDGE
2053 if(!formWidget) return;
2056 * Inhibit shell resizing.
2059 // [HGM] pieces: tailor piece bitmaps to needs of specific variant
2062 for(i=0; i<4; i++) {
2064 for(p=0; p<=(int)WhiteKing; p++)
2065 xpmPieceBitmap[i][p] = xpmPieceBitmap2[i][p]; // defaults
2066 if(gameInfo.variant == VariantShogi) {
2067 xpmPieceBitmap[i][(int)WhiteCannon] = xpmPieceBitmap2[i][(int)WhiteKing+1];
2068 xpmPieceBitmap[i][(int)WhiteNightrider] = xpmPieceBitmap2[i][(int)WhiteKing+2];
2069 xpmPieceBitmap[i][(int)WhiteSilver] = xpmPieceBitmap2[i][(int)WhiteKing+3];
2070 xpmPieceBitmap[i][(int)WhiteGrasshopper] = xpmPieceBitmap2[i][(int)WhiteKing+4];
2071 xpmPieceBitmap[i][(int)WhiteQueen] = xpmPieceBitmap2[i][(int)WhiteLance];
2074 if(gameInfo.variant == VariantGothic) {
2075 xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteSilver];
2079 // [HGM] why are thee ximMasks used at all? the ximPieceBitmaps seem to be never used!
2080 for(p=0; p<=(int)WhiteKing; p++)
2081 ximMaskPm[p] = ximMaskPm2[p]; // defaults
2082 if(gameInfo.variant == VariantShogi) {
2083 ximMaskPm[(int)WhiteCannon] = ximMaskPm2[(int)WhiteKing+1];
2084 ximMaskPm[(int)WhiteNightrider] = ximMaskPm2[(int)WhiteKing+2];
2085 ximMaskPm[(int)WhiteSilver] = ximMaskPm2[(int)WhiteKing+3];
2086 ximMaskPm[(int)WhiteGrasshopper] = ximMaskPm2[(int)WhiteKing+4];
2087 ximMaskPm[(int)WhiteQueen] = ximMaskPm2[(int)WhiteLance];
2090 if(gameInfo.variant == VariantGothic) {
2091 ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[i][(int)WhiteSilver];
2097 for(i=0; i<2; i++) {
2099 for(p=0; p<=(int)WhiteKing; p++)
2100 pieceBitmap[i][p] = pieceBitmap2[i][p]; // defaults
2101 if(gameInfo.variant == VariantShogi) {
2102 pieceBitmap[i][(int)WhiteCannon] = pieceBitmap2[i][(int)WhiteKing+1];
2103 pieceBitmap[i][(int)WhiteNightrider] = pieceBitmap2[i][(int)WhiteKing+2];
2104 pieceBitmap[i][(int)WhiteSilver] = pieceBitmap2[i][(int)WhiteKing+3];
2105 pieceBitmap[i][(int)WhiteGrasshopper] = pieceBitmap2[i][(int)WhiteKing+4];
2106 pieceBitmap[i][(int)WhiteQueen] = pieceBitmap2[i][(int)WhiteLance];
2109 if(gameInfo.variant == VariantGothic) {
2110 pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteSilver];
2121 void EscapeExpand(char *p, char *q)
2122 { // [HGM] initstring: routine to shape up string arguments
2123 while(*p++ = *q++) if(p[-1] == '\\')
2125 case 'n': p[-1] = '\n'; break;
2126 case 'r': p[-1] = '\r'; break;
2127 case 't': p[-1] = '\t'; break;
2128 case '\\': p[-1] = '\\'; break;
2129 case 0: *p = 0; return;
2130 default: p[-1] = q[-1]; break;
2139 int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
2140 XSetWindowAttributes window_attributes;
2142 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2143 XrmValue vFrom, vTo;
2144 XtGeometryResult gres;
2147 int forceMono = False;
2151 // [HGM] before anything else, expand any indirection files amongst options
2152 char *argvCopy[1000]; // 1000 seems enough
2153 char newArgs[10000]; // holds actual characters
2156 srandom(time(0)); // [HGM] book: make random truly random
2159 for(i=0; i<argc; i++) {
2160 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2161 //fprintf(stderr, "arg %s\n", argv[i]);
2162 if(argv[i][0] != '@') argvCopy[j++] = argv[i]; else {
2164 FILE *f = fopen(argv[i]+1, "rb");
2165 if(f == NULL) { fprintf(stderr, _("ignore %s\n"), argv[i]); continue; } // do not expand non-existing
2166 argvCopy[j++] = newArgs + k; // get ready for first argument from file
2167 while((c = fgetc(f)) != EOF) { // each line of file inserts 1 argument in the list
2169 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2170 newArgs[k++] = 0; // terminate current arg
2171 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2172 argvCopy[j++] = newArgs + k; // get ready for next
2174 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2187 if(appData.debugMode,1) { // OK, appData is not initialized here yet...
2188 for(i=0; i<argc; i++) fprintf(stderr, "argv[%2d] = '%s'\n", i, argv[i]);
2193 setbuf(stdout, NULL);
2194 setbuf(stderr, NULL);
2197 programName = strrchr(argv[0], '/');
2198 if (programName == NULL)
2199 programName = argv[0];
2204 XtSetLanguageProc(NULL, NULL, NULL);
2205 bindtextdomain(PACKAGE, LOCALEDIR);
2206 textdomain(PACKAGE);
2210 XtAppInitialize(&appContext, "XBoard", shellOptions,
2211 XtNumber(shellOptions),
2212 &argc, argv, xboardResources, NULL, 0);
2216 gtk_init (&argc, &argv);
2218 /* parse glade file to build widgets */
2220 builder = gtk_builder_new ();
2221 gtk_builder_add_from_file (builder, "gtk-interface.xml", NULL);
2223 /* test if everything worked ok */
2225 GUI_Window = GTK_WIDGET (gtk_builder_get_object (builder, "MainWindow"));
2226 if(!GUI_Window) printf("Error: gtk_builder didn't work!\n");
2227 GUI_Board = GTK_WIDGET (gtk_builder_get_object (builder, "Board"));
2228 if(!GUI_Board) printf("Error: gtk_builder didn't work!\n");
2229 GUI_Whiteclock = GTK_WIDGET (gtk_builder_get_object (builder, "WhiteClock"));
2230 if(!GUI_Whiteclock) printf("Error: gtk_builder didn't work!\n");
2231 GUI_Blackclock = GTK_WIDGET (gtk_builder_get_object (builder, "BlackClock"));
2232 if(!GUI_Blackclock) printf("Error: gtk_builder didn't work!\n");
2234 gtk_builder_connect_signals (builder, NULL);
2236 // don't unref the builder, since we use it to get references to widgets
2237 // g_object_unref (G_OBJECT (builder));
2239 /* end parse glade file */
2243 fprintf(stderr, _("%s: unrecognized argument %s\n"),
2244 programName, argv[1]);
2245 fprintf(stderr, "Recognized options:\n");
2246 for(i = 0; i < XtNumber(shellOptions); i++)
2248 j = fprintf(stderr, " %s%s", shellOptions[i].option,
2249 (shellOptions[i].argKind == XrmoptionSepArg
2251 if (i++ < XtNumber(shellOptions))
2253 fprintf(stderr, "%*c%s%s\n", 40 - j, ' ',
2254 shellOptions[i].option,
2255 (shellOptions[i].argKind == XrmoptionSepArg
2260 fprintf(stderr, "\n");
2266 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL)
2272 if (chdir(chessDir) != 0)
2274 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
2281 if (p == NULL) p = "/tmp";
2282 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
2283 gameCopyFilename = (char*) malloc(i);
2284 gamePasteFilename = (char*) malloc(i);
2285 snprintf(gameCopyFilename,i, "%s/.xboard%05uc.pgn", p, getpid());
2286 snprintf(gamePasteFilename,i, "%s/.xboard%05up.pgn", p, getpid());
2288 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
2289 clientResources, XtNumber(clientResources),
2292 { // [HGM] initstring: kludge to fix bad bug. expand '\n' characters in init string and computer string.
2293 static char buf[MSG_SIZ];
2294 EscapeExpand(buf, appData.initString);
2295 appData.initString = strdup(buf);
2296 EscapeExpand(buf, appData.secondInitString);
2297 appData.secondInitString = strdup(buf);
2298 EscapeExpand(buf, appData.firstComputerString);
2299 appData.firstComputerString = strdup(buf);
2300 EscapeExpand(buf, appData.secondComputerString);
2301 appData.secondComputerString = strdup(buf);
2304 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
2307 if (chdir(chessDir) != 0) {
2308 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
2314 if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) {
2315 /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */
2316 if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL) {
2317 printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile);
2320 setbuf(debugFP, NULL);
2323 /* [HGM,HR] make sure board size is acceptable */
2324 if(appData.NrFiles > BOARD_SIZE ||
2325 appData.NrRanks > BOARD_SIZE )
2326 DisplayFatalError(_("Recompile with BOARD_SIZE > 12, to support this size"), 0, 2);
2329 /* This feature does not work; animation needs a rewrite */
2330 appData.highlightDragging = FALSE;
2334 xDisplay = XtDisplay(shellWidget);
2335 xScreen = DefaultScreen(xDisplay);
2336 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
2338 gameInfo.variant = StringToVariant(appData.variant);
2339 InitPosition(FALSE);
2343 * Determine boardSize
2345 gameInfo.boardWidth = gameInfo.boardHeight = 8; // [HGM] boardsize: make sure we start as 8x8
2348 // [HGM] as long as we have not created the possibility to change size while running, start with requested size
2349 gameInfo.boardWidth = appData.NrFiles > 0 ? appData.NrFiles : 8;
2350 gameInfo.boardHeight = appData.NrRanks > 0 ? appData.NrRanks : 8;
2351 gameInfo.holdingsWidth = appData.holdingsSize > 0 ? 2 : 0;
2356 InitDrawingSizes(-1, 0); // [HGM] initsize: make this into a subroutine
2358 if (isdigit(appData.boardSize[0])) {
2359 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
2360 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
2361 &fontPxlSize, &smallLayout, &tinyLayout);
2363 fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
2364 programName, appData.boardSize);
2368 /* Find some defaults; use the nearest known size */
2369 SizeDefaults *szd, *nearest;
2370 int distance = 99999;
2371 nearest = szd = sizeDefaults;
2372 while (szd->name != NULL) {
2373 if (abs(szd->squareSize - squareSize) < distance) {
2375 distance = abs(szd->squareSize - squareSize);
2376 if (distance == 0) break;
2380 if (i < 2) lineGap = nearest->lineGap;
2381 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
2382 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
2383 if (i < 5) fontPxlSize = nearest->fontPxlSize;
2384 if (i < 6) smallLayout = nearest->smallLayout;
2385 if (i < 7) tinyLayout = nearest->tinyLayout;
2388 SizeDefaults *szd = sizeDefaults;
2389 if (*appData.boardSize == NULLCHAR) {
2390 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize ||
2391 DisplayHeight(xDisplay, xScreen) < szd->minScreenSize) {
2394 if (szd->name == NULL) szd--;
2396 while (szd->name != NULL &&
2397 StrCaseCmp(szd->name, appData.boardSize) != 0) szd++;
2398 if (szd->name == NULL) {
2399 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
2400 programName, appData.boardSize);
2404 squareSize = szd->squareSize;
2405 lineGap = szd->lineGap;
2406 clockFontPxlSize = szd->clockFontPxlSize;
2407 coordFontPxlSize = szd->coordFontPxlSize;
2408 fontPxlSize = szd->fontPxlSize;
2409 smallLayout = szd->smallLayout;
2410 tinyLayout = szd->tinyLayout;
2413 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2414 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2415 if (appData.showJail == 1) {
2416 /* Jail on top and bottom */
2417 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2418 XtSetArg(boardArgs[2], XtNheight,
2419 boardHeight + 2*(lineGap + squareSize));
2420 } else if (appData.showJail == 2) {
2422 XtSetArg(boardArgs[1], XtNwidth,
2423 boardWidth + 2*(lineGap + squareSize));
2424 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2427 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2428 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2432 * Determine what fonts to use.
2434 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
2435 clockFontID = XLoadFont(xDisplay, appData.clockFont);
2436 clockFontStruct = XQueryFont(xDisplay, clockFontID);
2437 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
2438 coordFontID = XLoadFont(xDisplay, appData.coordFont);
2439 coordFontStruct = XQueryFont(xDisplay, coordFontID);
2440 appData.font = FindFont(appData.font, fontPxlSize);
2441 countFontID = XLoadFont(xDisplay, appData.coordFont); // [HGM] holdings
2442 countFontStruct = XQueryFont(xDisplay, countFontID);
2443 // appData.font = FindFont(appData.font, fontPxlSize);
2445 xdb = XtDatabase(xDisplay);
2446 XrmPutStringResource(&xdb, "*font", appData.font);
2449 * Detect if there are not enough colors available and adapt.
2451 if (DefaultDepth(xDisplay, xScreen) <= 2) {
2452 appData.monoMode = True;
2455 if (!appData.monoMode) {
2456 vFrom.addr = (caddr_t) appData.lightSquareColor;
2457 vFrom.size = strlen(appData.lightSquareColor);
2458 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2459 if (vTo.addr == NULL) {
2460 appData.monoMode = True;
2463 lightSquareColor = *(Pixel *) vTo.addr;
2466 if (!appData.monoMode) {
2467 vFrom.addr = (caddr_t) appData.darkSquareColor;
2468 vFrom.size = strlen(appData.darkSquareColor);
2469 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2470 if (vTo.addr == NULL) {
2471 appData.monoMode = True;
2474 darkSquareColor = *(Pixel *) vTo.addr;
2477 if (!appData.monoMode) {
2478 vFrom.addr = (caddr_t) appData.whitePieceColor;
2479 vFrom.size = strlen(appData.whitePieceColor);
2480 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2481 if (vTo.addr == NULL) {
2482 appData.monoMode = True;
2485 whitePieceColor = *(Pixel *) vTo.addr;
2488 if (!appData.monoMode) {
2489 vFrom.addr = (caddr_t) appData.blackPieceColor;
2490 vFrom.size = strlen(appData.blackPieceColor);
2491 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2492 if (vTo.addr == NULL) {
2493 appData.monoMode = True;
2496 blackPieceColor = *(Pixel *) vTo.addr;
2500 if (!appData.monoMode) {
2501 vFrom.addr = (caddr_t) appData.highlightSquareColor;
2502 vFrom.size = strlen(appData.highlightSquareColor);
2503 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2504 if (vTo.addr == NULL) {
2505 appData.monoMode = True;
2508 highlightSquareColor = *(Pixel *) vTo.addr;
2512 if (!appData.monoMode) {
2513 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
2514 vFrom.size = strlen(appData.premoveHighlightColor);
2515 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2516 if (vTo.addr == NULL) {
2517 appData.monoMode = True;
2520 premoveHighlightColor = *(Pixel *) vTo.addr;
2525 fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2528 if (appData.bitmapDirectory == NULL ||
2529 appData.bitmapDirectory[0] == NULLCHAR)
2530 appData.bitmapDirectory = DEF_BITMAP_DIR;
2533 if (appData.lowTimeWarning && !appData.monoMode) {
2534 vFrom.addr = (caddr_t) appData.lowTimeWarningColor;
2535 vFrom.size = strlen(appData.lowTimeWarningColor);
2536 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2537 if (vTo.addr == NULL)
2538 appData.monoMode = True;
2540 lowTimeWarningColor = *(Pixel *) vTo.addr;
2543 if (appData.monoMode && appData.debugMode) {
2544 fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2545 (unsigned long) XWhitePixel(xDisplay, xScreen),
2546 (unsigned long) XBlackPixel(xDisplay, xScreen));
2549 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
2550 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
2551 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
2552 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
2553 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
2554 parse_cpair(ColorTell, appData.colorTell) < 0 ||
2555 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
2556 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
2557 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
2558 parse_cpair(ColorNormal, appData.colorNormal) < 0)
2560 if (appData.colorize) {
2562 _("%s: can't parse color names; disabling colorization\n"),
2565 appData.colorize = FALSE;
2567 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2568 textColors[ColorNone].attr = 0;
2570 // XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2576 layoutName = "tinyLayout";
2577 } else if (smallLayout) {
2578 layoutName = "smallLayout";
2580 layoutName = "normalLayout";
2583 if (appData.titleInWindow) {
2584 /* todo check what this appdata does */
2587 if (appData.showButtonBar) {
2588 /* TODO hide button bar if requested */
2592 * gtk set properties of widgets
2595 /* set board size */
2596 gtk_widget_set_size_request(GTK_WIDGET(GUI_Board),
2597 boardWidth,boardHeight);
2599 /* end gtk set properties of widgets */
2601 if (appData.titleInWindow)
2606 if (appData.showButtonBar)
2613 if (appData.showButtonBar)
2622 // [HGM] it seems the layout code ends here, but perhaps the color stuff is size independent and would
2623 // not need to go into InitDrawingSizes().
2626 /* set some checkboxes in the menu according to appData */
2628 if (appData.alwaysPromoteToQueen)
2629 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Always Queen")),TRUE);
2631 if (appData.animateDragging)
2632 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Animate Dragging")),TRUE);
2634 if (appData.animate)
2635 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Animate Moving")),TRUE);
2637 if (appData.autoComment)
2638 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Comment")),TRUE);
2640 if (appData.autoCallFlag)
2641 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Flag")),TRUE);
2643 if (appData.autoFlipView)
2644 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Flip View")),TRUE);
2646 if (appData.autoObserve)
2647 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Observe")),TRUE);
2649 if (appData.autoRaiseBoard)
2650 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Raise Board")),TRUE);
2652 if (appData.autoSaveGames)
2653 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Save")),TRUE);
2655 if (appData.saveGameFile[0] != NULLCHAR)
2657 /* Can't turn this off from menu */
2658 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Save")),TRUE);
2659 gtk_action_set_sensitive(GTK_ACTION (gtk_builder_get_object (builder, "menuOptions.Auto Save")),FALSE);
2662 if (appData.blindfold)
2663 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Blindfold")),TRUE);
2665 if (appData.flashCount > 0)
2666 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Flash Moves")),TRUE);
2668 if (appData.getMoveList)
2669 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Get Move List")),TRUE);
2672 if (appData.highlightDragging)
2673 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Highlight Dragging")),TRUE);
2676 if (appData.highlightLastMove)
2677 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Highlight Last Move")),TRUE);
2679 if (appData.icsAlarm)
2680 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.ICS Alarm")),TRUE);
2682 if (appData.ringBellAfterMoves)
2683 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Move Sound")),TRUE);
2685 if (appData.oldSaveStyle)
2686 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Old Save Style")),TRUE);
2688 if (appData.periodicUpdates)
2689 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Periodic Updates")),TRUE);
2691 if (appData.ponderNextMove)
2692 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Ponder Next Move")),TRUE);
2694 if (appData.popupExitMessage)
2695 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Popup Exit Message")),TRUE);
2697 if (appData.popupMoveErrors)
2698 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Popup Move Errors")),TRUE);
2700 if (appData.premove)
2701 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Premove")),TRUE);
2703 if (appData.quietPlay)
2704 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Quit Play")),TRUE);
2706 if (appData.showCoords)
2707 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Show Coords")),TRUE);
2709 if (appData.showThinking)
2710 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Show Thinking")),TRUE);
2712 if (appData.testLegality)
2713 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Test Legality")),TRUE);
2715 /* end setting check boxes */
2718 /* load square colors */
2719 SVGLightSquare = load_pixbuf("svg/LightSquare.svg",squareSize);
2720 SVGDarkSquare = load_pixbuf("svg/DarkSquare.svg",squareSize);
2721 SVGNeutralSquare = load_pixbuf("svg/NeutralSquare.svg",squareSize);
2723 /* use two icons to indicate if it is white's or black's turn */
2724 WhiteIcon = load_pixbuf("svg/icon_white.svg",0);
2725 BlackIcon = load_pixbuf("svg/icon_black.svg",0);
2726 WindowIcon = WhiteIcon;
2727 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
2729 /* do resizing to a fixed aspect ratio */
2734 GUI_SetAspectRatio(0.7);
2736 /* realize window */
2737 gtk_widget_show (GUI_Window);
2743 if (appData.animate || appData.animateDragging)
2748 if (errorExitStatus == -1) {
2749 if (appData.icsActive) {
2750 /* We now wait until we see "login:" from the ICS before
2751 sending the logon script (problems with timestamp otherwise) */
2752 /*ICSInitScript();*/
2753 if (appData.icsInputBox) ICSInputBoxPopUp();
2756 signal(SIGINT, IntSigHandler);
2757 signal(SIGTERM, IntSigHandler);
2758 if (*appData.cmailGameName != NULLCHAR) {
2759 signal(SIGUSR1, CmailSigHandler);
2762 gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes()
2766 * Create a cursor for the board widget.
2767 * (This needs to be called after the window has been created to have access to board-window)
2770 BoardCursor = gdk_cursor_new(GDK_HAND2);
2771 gdk_window_set_cursor(GUI_Board->window, BoardCursor);
2772 gdk_cursor_destroy(BoardCursor);
2777 if (appData.debugMode) fclose(debugFP); // [DM] debug
2784 if (appData.icsActive && oldICSInteractionTitle != NULL) {
2785 DisplayIcsInteractionTitle(oldICSInteractionTitle);
2787 unlink(gameCopyFilename);
2788 unlink(gamePasteFilename);
2799 CmailSigHandler(sig)
2805 signal(SIGUSR1, SIG_IGN); /* suspend handler */
2807 /* Activate call-back function CmailSigHandlerCallBack() */
2808 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
2810 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
2814 CmailSigHandlerCallBack(isr, closure, message, count, error)
2822 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
2824 /**** end signal code ****/
2834 f = fopen(appData.icsLogon, "r");
2840 strcat(buf, appData.icsLogon);
2841 f = fopen(buf, "r");
2845 ProcessICSInitScript(f);
2852 EditCommentPopDown();
2858 SetMenuEnables(enab)
2863 if (!builder) return;
2864 while (enab->name != NULL) {
2865 o = gtk_builder_get_object(builder, enab->name);
2866 if(GTK_IS_WIDGET(o))
2867 gtk_widget_set_sensitive(GTK_WIDGET (o),enab->value);
2870 if(GTK_IS_ACTION(o))
2871 gtk_action_set_sensitive(GTK_ACTION (o),enab->value);
2873 DisplayError(enab->name, 0);
2881 SetMenuEnables(icsEnables);
2884 if (appData.zippyPlay && !appData.noChessProgram) /* [DM] icsEngineAnalyze */
2885 {}; // XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
2892 SetMenuEnables(ncpEnables);
2898 SetMenuEnables(gnuEnables);
2904 SetMenuEnables(cmailEnables);
2910 SetMenuEnables(trainingOnEnables);
2911 if (appData.showButtonBar) {
2912 // XtSetSensitive(buttonBarWidget, False);
2918 SetTrainingModeOff()
2920 SetMenuEnables(trainingOffEnables);
2921 if (appData.showButtonBar) {
2922 // XtSetSensitive(buttonBarWidget, True);
2927 SetUserThinkingEnables()
2929 if (appData.noChessProgram) return;
2930 SetMenuEnables(userThinkingEnables);
2934 SetMachineThinkingEnables()
2936 if (appData.noChessProgram) return;
2937 SetMenuEnables(machineThinkingEnables);
2939 case MachinePlaysBlack:
2940 case MachinePlaysWhite:
2941 case TwoMachinesPlay:
2942 // XtSetSensitive(XtNameToWidget(menuBarWidget,
2943 // ModeToWidgetName(gameMode)), True);
2950 #define Abs(n) ((n)<0 ? -(n) : (n))
2953 * Find a font that matches "pattern" that is as close as
2954 * possible to the targetPxlSize. Prefer fonts that are k
2955 * pixels smaller to fonts that are k pixels larger. The
2956 * pattern must be in the X Consortium standard format,
2957 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
2958 * The return value should be freed with XtFree when no
2961 char *FindFont(pattern, targetPxlSize)
2965 char **fonts, *p, *best, *scalable, *scalableTail;
2966 int i, j, nfonts, minerr, err, pxlSize;
2969 char **missing_list;
2971 char *def_string, *base_fnt_lst, strInt[3];
2973 XFontStruct **fnt_list;
2975 base_fnt_lst = calloc(1, strlen(pattern) + 3);
2976 sprintf(strInt, "%d", targetPxlSize);
2977 p = strstr(pattern, "--");
2978 strncpy(base_fnt_lst, pattern, p - pattern + 2);
2979 strcat(base_fnt_lst, strInt);
2980 strcat(base_fnt_lst, strchr(p + 2, '-'));
2982 if ((fntSet = XCreateFontSet(xDisplay,
2986 &def_string)) == NULL) {
2988 fprintf(stderr, _("Unable to create font set.\n"));
2992 nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
2994 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
2996 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
2997 programName, pattern);
3005 for (i=0; i<nfonts; i++) {
3008 if (*p != '-') continue;
3010 if (*p == NULLCHAR) break;
3011 if (*p++ == '-') j++;
3013 if (j < 7) continue;
3016 scalable = fonts[i];
3019 err = pxlSize - targetPxlSize;
3020 if (Abs(err) < Abs(minerr) ||
3021 (minerr > 0 && err < 0 && -err == minerr)) {
3027 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
3028 /* If the error is too big and there is a scalable font,
3029 use the scalable font. */
3030 int headlen = scalableTail - scalable;
3031 p = (char *) XtMalloc(strlen(scalable) + 10);
3032 while (isdigit(*scalableTail)) scalableTail++;
3033 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
3035 p = (char *) XtMalloc(strlen(best) + 1);
3038 if (appData.debugMode) {
3039 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
3040 pattern, targetPxlSize, p);
3043 if (missing_count > 0)
3044 XFreeStringList(missing_list);
3045 XFreeFontSet(xDisplay, fntSet);
3047 XFreeFontNames(fonts);
3054 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
3055 | GCBackground | GCFunction | GCPlaneMask;
3056 XGCValues gc_values;
3059 gc_values.plane_mask = AllPlanes;
3060 gc_values.line_width = lineGap;
3061 gc_values.line_style = LineSolid;
3062 gc_values.function = GXcopy;
3064 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3065 gc_values.background = XWhitePixel(xDisplay, xScreen);
3066 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
3067 XSetFont(xDisplay, coordGC, coordFontID);
3069 if (appData.monoMode) {
3070 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3071 gc_values.background = XBlackPixel(xDisplay, xScreen);
3072 lightSquareGC = wbPieceGC
3073 = XtGetGC(shellWidget, value_mask, &gc_values);
3075 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3076 gc_values.background = XWhitePixel(xDisplay, xScreen);
3077 darkSquareGC = bwPieceGC
3078 = XtGetGC(shellWidget, value_mask, &gc_values);
3080 if (DefaultDepth(xDisplay, xScreen) == 1) {
3081 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3082 gc_values.function = GXcopyInverted;
3083 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3084 gc_values.function = GXcopy;
3085 if (XBlackPixel(xDisplay, xScreen) == 1) {
3086 bwPieceGC = darkSquareGC;
3087 wbPieceGC = copyInvertedGC;
3089 bwPieceGC = copyInvertedGC;
3090 wbPieceGC = lightSquareGC;
3094 gc_values.foreground = lightSquareColor;
3095 gc_values.background = darkSquareColor;
3096 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3098 gc_values.foreground = darkSquareColor;
3099 gc_values.background = lightSquareColor;
3100 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3102 gc_values.foreground = jailSquareColor;
3103 gc_values.background = jailSquareColor;
3104 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3106 gc_values.foreground = whitePieceColor;
3107 gc_values.background = darkSquareColor;
3108 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3110 gc_values.foreground = whitePieceColor;
3111 gc_values.background = lightSquareColor;
3112 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3114 gc_values.foreground = whitePieceColor;
3115 gc_values.background = jailSquareColor;
3116 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3118 gc_values.foreground = blackPieceColor;
3119 gc_values.background = darkSquareColor;
3120 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3122 gc_values.foreground = blackPieceColor;
3123 gc_values.background = lightSquareColor;
3124 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3126 gc_values.foreground = blackPieceColor;
3127 gc_values.background = jailSquareColor;
3128 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3135 WhitePawn, WhiteKnight, WhiteBishop, WhiteRook, WhiteQueen, WhiteKing,
3136 BlackPawn, BlackKnight, BlackBishop, BlackRook, BlackQueen, BlackKing,
3140 /* get some defaults going */
3141 for(i=WhitePawn; i<DemotePiece+1; i++)
3142 SVGpieces[i] = load_pixbuf("svg/NeutralSquare.svg",squareSize);
3145 SVGpieces[WhitePawn] = load_pixbuf("svg/WhitePawn.svg",squareSize);
3146 SVGpieces[WhiteKnight] = load_pixbuf("svg/WhiteKnight.svg",squareSize);
3147 SVGpieces[WhiteBishop] = load_pixbuf("svg/WhiteBishop.svg",squareSize);
3148 SVGpieces[WhiteRook] = load_pixbuf("svg/WhiteRook.svg",squareSize);
3149 SVGpieces[WhiteQueen] = load_pixbuf("svg/WhiteQueen.svg",squareSize);
3150 SVGpieces[WhiteKing] = load_pixbuf("svg/WhiteKing.svg",squareSize);
3152 SVGpieces[BlackPawn] = load_pixbuf("svg/BlackPawn.svg",squareSize);
3153 SVGpieces[BlackKnight] = load_pixbuf("svg/BlackKnight.svg",squareSize);
3154 SVGpieces[BlackBishop] = load_pixbuf("svg/BlackBishop.svg",squareSize);
3155 SVGpieces[BlackRook] = load_pixbuf("svg/BlackRook.svg",squareSize);
3156 SVGpieces[BlackQueen] = load_pixbuf("svg/BlackQueen.svg",squareSize);
3157 SVGpieces[BlackKing] = load_pixbuf("svg/BlackKing.svg",squareSize);
3163 static void MenuBarSelect(w, addr, index)
3168 XtActionProc proc = (XtActionProc) addr;
3170 (proc)(NULL, NULL, NULL, NULL);
3173 void CreateMenuBarPopup(parent, name, mb)
3183 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3186 XtSetArg(args[j], XtNleftMargin, 20); j++;
3187 XtSetArg(args[j], XtNrightMargin, 20); j++;
3189 while (mi->string != NULL) {
3190 if (strcmp(mi->string, "----") == 0) {
3191 entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
3194 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string)));
3195 entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass,
3197 XtAddCallback(entry, XtNcallback,
3198 (XtCallbackProc) MenuBarSelect,
3199 (caddr_t) mi->proc);
3205 Widget CreateMenuBar(mb)
3209 Widget anchor, menuBar;
3211 char menuName[MSG_SIZ];
3214 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3215 XtSetArg(args[j], XtNvSpace, 0); j++;
3216 XtSetArg(args[j], XtNborderWidth, 0); j++;
3217 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
3218 formWidget, args, j);
3220 while (mb->name != NULL) {
3221 strcpy(menuName, "menu");
3222 strcat(menuName, mb->name);
3224 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
3227 shortName[0] = _(mb->name)[0];
3228 shortName[1] = NULLCHAR;
3229 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
3232 XtSetArg(args[j], XtNlabel, XtNewString(_(mb->name))); j++;
3235 XtSetArg(args[j], XtNborderWidth, 0); j++;
3236 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
3238 CreateMenuBarPopup(menuBar, menuName, mb);
3244 Widget CreateButtonBar(mi)
3248 Widget button, buttonBar;
3252 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3254 XtSetArg(args[j], XtNhSpace, 0); j++;
3256 XtSetArg(args[j], XtNborderWidth, 0); j++;
3257 XtSetArg(args[j], XtNvSpace, 0); j++;
3258 buttonBar = XtCreateWidget("buttonBar", boxWidgetClass,
3259 formWidget, args, j);
3261 while (mi->string != NULL) {
3264 XtSetArg(args[j], XtNinternalWidth, 2); j++;
3265 XtSetArg(args[j], XtNborderWidth, 0); j++;
3267 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string))); j++;
3268 button = XtCreateManagedWidget(mi->string, commandWidgetClass,
3269 buttonBar, args, j);
3270 XtAddCallback(button, XtNcallback,
3271 (XtCallbackProc) MenuBarSelect,
3272 (caddr_t) mi->proc);
3279 CreatePieceMenu(name, color)
3286 ChessSquare selection;
3288 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3289 boardWidget, args, 0);
3291 for (i = 0; i < PIECE_MENU_SIZE; i++) {
3292 String item = pieceMenuStrings[color][i];
3294 if (strcmp(item, "----") == 0) {
3295 entry = XtCreateManagedWidget(item, smeLineObjectClass,
3298 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3299 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3301 selection = pieceMenuTranslation[color][i];
3302 XtAddCallback(entry, XtNcallback,
3303 (XtCallbackProc) PieceMenuSelect,
3304 (caddr_t) selection);
3305 if (selection == WhitePawn || selection == BlackPawn) {
3306 XtSetArg(args[0], XtNpopupOnEntry, entry);
3307 XtSetValues(menu, args, 1);
3320 ChessSquare selection;
3322 // whitePieceMenu = CreatePieceMenu("menuW", 0);
3323 // blackPieceMenu = CreatePieceMenu("menuB", 1);
3325 // XtRegisterGrabAction(PieceMenuPopup, True,
3326 // (unsigned)(ButtonPressMask|ButtonReleaseMask),
3327 // GrabModeAsync, GrabModeAsync);
3329 // XtSetArg(args[0], XtNlabel, _("Drop"));
3330 // dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
3331 // boardWidget, args, 1);
3332 // for (i = 0; i < DROP_MENU_SIZE; i++) {
3333 // String item = dropMenuStrings[i];
3335 // if (strcmp(item, "----") == 0) {
3336 // entry = XtCreateManagedWidget(item, smeLineObjectClass,
3337 // dropMenu, NULL, 0);
3339 // XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3340 // entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3341 // dropMenu, args, 1);
3342 // selection = dropMenuTranslation[i];
3343 // XtAddCallback(entry, XtNcallback,
3344 // (XtCallbackProc) DropMenuSelect,
3345 // (caddr_t) selection);
3350 void SetupDropMenu()
3358 for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
3359 entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
3360 p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
3361 dmEnables[i].piece);
3362 XtSetSensitive(entry, p != NULL || !appData.testLegality
3363 /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
3364 && !appData.icsActive));
3366 while (p && *p++ == dmEnables[i].piece) count++;
3367 snprintf(label, sizeof(label), "%s %d", dmEnables[i].widget, count);
3369 XtSetArg(args[j], XtNlabel, label); j++;
3370 XtSetValues(entry, args, j);
3374 void PieceMenuPopup(w, event, params, num_params)
3378 Cardinal *num_params;
3381 if (event->type != ButtonPress) return;
3382 if (errorUp) ErrorPopDown();
3386 whichMenu = params[0];
3388 case IcsPlayingWhite:
3389 case IcsPlayingBlack:
3391 case MachinePlaysWhite:
3392 case MachinePlaysBlack:
3393 if (appData.testLegality &&
3394 gameInfo.variant != VariantBughouse &&
3395 gameInfo.variant != VariantCrazyhouse) return;
3397 whichMenu = "menuD";
3403 if (((pmFromX = EventToSquare(event->xbutton.x, BOARD_WIDTH)) < 0) ||
3404 ((pmFromY = EventToSquare(event->xbutton.y, BOARD_HEIGHT)) < 0)) {
3405 pmFromX = pmFromY = -1;
3409 pmFromX = BOARD_WIDTH - 1 - pmFromX;
3411 pmFromY = BOARD_HEIGHT - 1 - pmFromY;
3413 XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
3416 static void PieceMenuSelect(w, piece, junk)
3421 if (pmFromX < 0 || pmFromY < 0) return;
3422 EditPositionMenuEvent(piece, pmFromX, pmFromY);
3425 static void DropMenuSelect(w, piece, junk)
3430 if (pmFromX < 0 || pmFromY < 0) return;
3431 DropMenuEvent(piece, pmFromX, pmFromY);
3434 void WhiteClock(w, event, prms, nprms)
3440 if (gameMode == EditPosition || gameMode == IcsExamining) {
3441 SetWhiteToPlayEvent();
3442 } else if (gameMode == IcsPlayingBlack || gameMode == MachinePlaysWhite) {
3447 void BlackClock(w, event, prms, nprms)
3453 if (gameMode == EditPosition || gameMode == IcsExamining) {
3454 SetBlackToPlayEvent();
3455 } else if (gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) {
3462 * If the user selects on a border boundary, return -1; if off the board,
3463 * return -2. Otherwise map the event coordinate to the square.
3465 int EventToSquare(x, limit)
3473 if ((x % (squareSize + lineGap)) >= squareSize)
3475 x /= (squareSize + lineGap);
3481 static void do_flash_delay(msec)
3487 static void drawHighlight(file, rank, line_type)
3488 int file, rank, line_type;
3493 if (lineGap == 0 || appData.blindfold) return;
3497 x = lineGap/2 + ((BOARD_WIDTH-1)-file) *
3498 (squareSize + lineGap);
3499 y = lineGap/2 + rank * (squareSize + lineGap);
3503 x = lineGap/2 + file * (squareSize + lineGap);
3504 y = lineGap/2 + ((BOARD_HEIGHT-1)-rank) *
3505 (squareSize + lineGap);
3509 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3511 /* draw the highlight */
3512 cairo_move_to (cr, x, y);
3513 cairo_rel_line_to (cr, 0,squareSize+lineGap);
3514 cairo_rel_line_to (cr, squareSize+lineGap,0);
3515 cairo_rel_line_to (cr, 0,-squareSize-lineGap);
3516 cairo_close_path (cr);
3518 cairo_set_line_width (cr, lineGap);
3521 /* TODO: use appdata colors */
3522 case LINE_TYPE_HIGHLIGHT:
3523 cairo_set_source_rgba (cr, 1, 1, 0, 1.0);
3526 cairo_set_source_rgba (cr, 1, 0, 0, 1.0);
3528 case LINE_TYPE_NORMAL:
3530 cairo_set_source_rgba (cr, 0, 1, 0, 1.0);
3541 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
3542 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
3545 SetHighlights(fromX, fromY, toX, toY)
3546 int fromX, fromY, toX, toY;
3548 if (hi1X != fromX || hi1Y != fromY)
3550 if (hi1X >= 0 && hi1Y >= 0)
3552 drawHighlight(hi1X, hi1Y, LINE_TYPE_NORMAL);
3554 if (fromX >= 0 && fromY >= 0)
3556 drawHighlight(fromX, fromY, LINE_TYPE_HIGHLIGHT);
3559 if (hi2X != toX || hi2Y != toY)
3561 if (hi2X >= 0 && hi2Y >= 0)
3563 drawHighlight(hi2X, hi2Y, LINE_TYPE_NORMAL);
3565 if (toX >= 0 && toY >= 0)
3567 drawHighlight(toX, toY, LINE_TYPE_HIGHLIGHT);
3581 SetHighlights(-1, -1, -1, -1);
3586 SetPremoveHighlights(fromX, fromY, toX, toY)
3587 int fromX, fromY, toX, toY;
3589 if (pm1X != fromX || pm1Y != fromY)
3591 if (pm1X >= 0 && pm1Y >= 0)
3593 drawHighlight(pm1X, pm1Y, LINE_TYPE_NORMAL);
3595 if (fromX >= 0 && fromY >= 0)
3597 drawHighlight(fromX, fromY, LINE_TYPE_PRE);
3600 if (pm2X != toX || pm2Y != toY)
3602 if (pm2X >= 0 && pm2Y >= 0)
3604 drawHighlight(pm2X, pm2Y, LINE_TYPE_NORMAL);
3606 if (toX >= 0 && toY >= 0)
3608 drawHighlight(toX, toY, LINE_TYPE_PRE);
3621 ClearPremoveHighlights()
3623 SetPremoveHighlights(-1, -1, -1, -1);
3626 static void BlankSquare(x, y, color, piece, dest)
3639 pb = SVGLightSquare;
3641 case 2: /* neutral */
3643 pb = SVGNeutralSquare;
3646 gdk_draw_pixbuf(GDK_WINDOW(GUI_Board->window),NULL,pb,0,0,x,y,-1,-1, GDK_RGB_DITHER_NORMAL, 0, 0);
3650 static void DrawPiece(piece, square_color, x, y, dest)
3652 int square_color, x, y;
3655 /* redraw background, since piece might be transparent in some areas */
3656 BlankSquare(x,y,square_color,piece,dest);
3659 gdk_draw_pixbuf(GDK_WINDOW(GUI_Board->window),NULL,
3660 GDK_PIXBUF(SVGpieces[piece]),0,0,x,y,-1,-1,
3661 GDK_RGB_DITHER_NORMAL, 0, 0);
3665 /* [HR] determine square color depending on chess variant. */
3666 static int SquareColor(row, column)
3671 if (gameInfo.variant == VariantXiangqi) {
3672 if (column >= 3 && column <= 5 && row >= 0 && row <= 2) {
3674 } else if (column >= 3 && column <= 5 && row >= 7 && row <= 9) {
3676 } else if (row <= 4) {
3682 square_color = ((column + row) % 2) == 1;
3685 /* [hgm] holdings: next line makes all holdings squares light */
3686 if(column < BOARD_LEFT || column >= BOARD_RGHT) square_color = 1;
3688 return square_color;
3691 void DrawSquare(row, column, piece, do_flash)
3692 int row, column, do_flash;
3695 int square_color, x, y;
3700 /* Calculate delay in milliseconds (2-delays per complete flash) */
3701 flash_delay = 500 / appData.flashRate;
3703 /* calculate x and y coordinates from row and column */
3706 x = lineGap + ((BOARD_WIDTH-1)-column) *
3707 (squareSize + lineGap);
3708 y = lineGap + row * (squareSize + lineGap);
3712 x = lineGap + column * (squareSize + lineGap);
3713 y = lineGap + ((BOARD_HEIGHT-1)-row) *
3714 (squareSize + lineGap);
3717 square_color = SquareColor(row, column);
3719 // [HGM] holdings: blank out area between board and holdings
3720 if ( column == BOARD_LEFT-1 || column == BOARD_RGHT
3721 || (column == BOARD_LEFT-2 && row < BOARD_HEIGHT-gameInfo.holdingsSize)
3722 || (column == BOARD_RGHT+1 && row >= gameInfo.holdingsSize) )
3724 BlankSquare(x, y, 2, EmptySquare, xBoardWindow);
3726 // [HGM] print piece counts next to holdings
3727 string[1] = NULLCHAR;
3730 cairo_text_extents_t extents;
3735 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3737 string[0] = '0' + piece;
3739 /* TODO this has to go into the font-selection */
3740 cairo_select_font_face (cr, "Sans",
3741 CAIRO_FONT_SLANT_NORMAL,
3742 CAIRO_FONT_WEIGHT_NORMAL);
3744 cairo_set_font_size (cr, 12.0);
3745 cairo_text_extents (cr, string, &extents);
3747 if (column == (flipView ? BOARD_LEFT-1 : BOARD_RGHT) )
3749 xpos= x + squareSize - extents.width - 2;
3750 ypos= y + extents.y_bearing + 1;
3752 if (column == (flipView ? BOARD_RGHT : BOARD_LEFT-1) && piece > 1)
3755 ypos = y + extents.y_bearing + 1;
3758 /* TODO mono mode? */
3759 cairo_move_to (cr, xpos, ypos);
3760 cairo_text_path (cr, string);
3761 cairo_set_source_rgb (cr, 1.0, 1.0, 1);
3762 cairo_fill_preserve (cr);
3763 cairo_set_source_rgb (cr, 0, 0, 0);
3764 cairo_set_line_width (cr, 0.1);
3773 /* square on the board */
3774 if (piece == EmptySquare || appData.blindfold)
3776 BlankSquare(x, y, square_color, piece, xBoardWindow);
3780 if (do_flash && appData.flashCount > 0)
3782 for (i=0; i<appData.flashCount; ++i)
3785 DrawPiece(piece, square_color, x, y, xBoardWindow);
3786 do_flash_delay(flash_delay);
3788 BlankSquare(x, y, square_color, piece, xBoardWindow);
3789 do_flash_delay(flash_delay);
3792 DrawPiece(piece, square_color, x, y, xBoardWindow);
3796 /* show coordinates if necessary */
3797 if(appData.showCoords)
3799 cairo_text_extents_t extents;
3803 /* TODO this has to go into the font-selection */
3804 cairo_select_font_face (cr, "Sans",
3805 CAIRO_FONT_SLANT_NORMAL,
3806 CAIRO_FONT_WEIGHT_NORMAL);
3807 cairo_set_font_size (cr, 12.0);
3809 string[1] = NULLCHAR;
3812 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3814 if (row == (flipView ? BOARD_HEIGHT-1 : 0) &&
3815 column >= BOARD_LEFT && column < BOARD_RGHT)
3817 string[0] = 'a' + column - BOARD_LEFT;
3818 cairo_text_extents (cr, string, &extents);
3820 xpos = x + squareSize - extents.width - 2;
3821 ypos = y + squareSize - extents.height - extents.y_bearing - 1;
3823 if (appData.monoMode)
3830 cairo_move_to (cr, xpos, ypos);
3831 cairo_text_path (cr, string);
3832 cairo_set_source_rgb (cr, 0.0, 0.0, 0);
3833 cairo_fill_preserve (cr);
3834 cairo_set_source_rgb (cr, 0, 1.0, 0);
3835 cairo_set_line_width (cr, 0.1);
3838 if ( column == (flipView ? BOARD_RGHT-1 : BOARD_LEFT))
3841 string[0] = ONE + row;
3842 cairo_text_extents (cr, string, &extents);
3845 ypos = y + extents.height + 1;
3847 if (appData.monoMode)
3854 cairo_move_to (cr, xpos, ypos);
3855 cairo_text_path (cr, string);
3856 cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
3857 cairo_fill_preserve (cr);
3858 cairo_set_source_rgb (cr, 0, 0, 1.0);
3859 cairo_set_line_width (cr, 0.1);
3871 /* Returns 1 if there are "too many" differences between b1 and b2
3872 (i.e. more than 1 move was made) */
3873 static int too_many_diffs(b1, b2)
3879 for (i=0; i<BOARD_HEIGHT; ++i) {
3880 for (j=0; j<BOARD_WIDTH; ++j) {
3881 if (b1[i][j] != b2[i][j]) {
3882 if (++c > 4) /* Castling causes 4 diffs */
3891 /* Matrix describing castling maneuvers */
3892 /* Row, ColRookFrom, ColKingFrom, ColRookTo, ColKingTo */
3893 static int castling_matrix[4][5] = {
3894 { 0, 0, 4, 3, 2 }, /* 0-0-0, white */
3895 { 0, 7, 4, 5, 6 }, /* 0-0, white */
3896 { 7, 0, 4, 3, 2 }, /* 0-0-0, black */
3897 { 7, 7, 4, 5, 6 } /* 0-0, black */
3900 /* Checks whether castling occurred. If it did, *rrow and *rcol
3901 are set to the destination (row,col) of the rook that moved.
3903 Returns 1 if castling occurred, 0 if not.
3905 Note: Only handles a max of 1 castling move, so be sure
3906 to call too_many_diffs() first.
3908 static int check_castle_draw(newb, oldb, rrow, rcol)
3915 /* For each type of castling... */
3916 for (i=0; i<4; ++i) {
3917 r = castling_matrix[i];
3919 /* Check the 4 squares involved in the castling move */
3921 for (j=1; j<=4; ++j) {
3922 if (newb[r[0]][r[j]] == oldb[r[0]][r[j]]) {
3929 /* All 4 changed, so it must be a castling move */
3938 static int damage[BOARD_SIZE][BOARD_SIZE];
3941 * event handler for redrawing the board
3943 void DrawPosition( repaint, board)
3944 /*Boolean*/int repaint;
3948 static int lastFlipView = 0;
3949 static int lastBoardValid = 0;
3950 static Board lastBoard;
3953 if (board == NULL) {
3954 if (!lastBoardValid) return;
3957 if (!lastBoardValid || lastFlipView != flipView) {
3958 // XtSetArg(args[0], XtNleftBitmap, (flipView ? xMarkPixmap : None));
3959 // XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flip View"),
3964 * It would be simpler to clear the window with XClearWindow()
3965 * but this causes a very distracting flicker.
3968 if (!repaint && lastBoardValid && lastFlipView == flipView)
3970 /* If too much changes (begin observing new game, etc.), don't
3972 do_flash = too_many_diffs(board, lastBoard) ? 0 : 1;
3974 /* Special check for castling so we don't flash both the king
3975 and the rook (just flash the king). */
3978 if (check_castle_draw(board, lastBoard, &rrow, &rcol))
3980 /* Draw rook with NO flashing. King will be drawn flashing later */
3981 DrawSquare(rrow, rcol, board[rrow][rcol], 0);
3982 lastBoard[rrow][rcol] = board[rrow][rcol];
3986 /* First pass -- Draw (newly) empty squares and repair damage.
3987 This prevents you from having a piece show up twice while it
3988 is flashing on its new square */
3989 for (i = 0; i < BOARD_HEIGHT; i++)
3990 for (j = 0; j < BOARD_WIDTH; j++)
3991 if ((board[i][j] != lastBoard[i][j] && board[i][j] == EmptySquare)
3994 DrawSquare(i, j, board[i][j], 0);
3995 damage[i][j] = False;
3998 /* Second pass -- Draw piece(s) in new position and flash them */
3999 for (i = 0; i < BOARD_HEIGHT; i++)
4000 for (j = 0; j < BOARD_WIDTH; j++)
4001 if (board[i][j] != lastBoard[i][j])
4003 DrawSquare(i, j, board[i][j], do_flash);
4015 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
4017 cairo_set_line_width (cr, lineGap);
4019 /* TODO: use appdata colors */
4020 cairo_set_source_rgba (cr, 0, 1, 0, 1.0);
4024 for (i = 0; i < BOARD_HEIGHT + 1; i++)
4027 x2 = lineGap + BOARD_WIDTH * (squareSize + lineGap);
4028 y1 = y2 = lineGap / 2 + (i * (squareSize + lineGap));
4030 cairo_move_to (cr, x1, y1);
4031 cairo_rel_line_to (cr, x2,0);
4035 for (j = 0; j < BOARD_WIDTH + 1; j++)
4038 y2 = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
4039 x1 = x2 = lineGap / 2 + (j * (squareSize + lineGap));
4041 cairo_move_to (cr, x1, y1);
4042 cairo_rel_line_to (cr, 0, y2);
4051 for (i = 0; i < BOARD_HEIGHT; i++)
4052 for (j = 0; j < BOARD_WIDTH; j++)
4054 DrawSquare(i, j, board[i][j], 0);
4055 damage[i][j] = False;
4059 CopyBoard(lastBoard, board);
4061 lastFlipView = flipView;
4063 /* Draw highlights */
4064 if (pm1X >= 0 && pm1Y >= 0)
4066 drawHighlight(pm1X, pm1Y, LINE_TYPE_PRE);
4068 if (pm2X >= 0 && pm2Y >= 0)
4070 drawHighlight(pm2X, pm2Y, LINE_TYPE_PRE);
4072 if (hi1X >= 0 && hi1Y >= 0)
4074 drawHighlight(hi1X, hi1Y, LINE_TYPE_HIGHLIGHT);
4076 if (hi2X >= 0 && hi2Y >= 0)
4078 drawHighlight(hi2X, hi2Y, LINE_TYPE_HIGHLIGHT);
4081 /* If piece being dragged around board, must redraw that too */
4088 * event handler for parsing user moves
4090 // [HGM] This routine will need quite some reworking. Although the backend still supports the old
4091 // way of doing things, by calling UserMoveEvent() to test the legality of the move and then perform
4092 // it at the end, and doing all kind of preliminary tests here (e.g. to weed out self-captures), it
4093 // should be made to use the new way, of calling UserMoveTest early to determine the legality of the
4094 // move, (which will weed out the illegal selfcaptures and moves into the holdings, and flag promotions),
4095 // and at the end FinishMove() to perform the move after optional promotion popups.
4096 // For now I patched it to allow self-capture with King, and suppress clicks between board and holdings.
4097 void HandleUserMove(w, event, prms, nprms)
4104 Boolean saveAnimate;
4105 static int second = 0;
4107 if (w != boardWidget || errorExitStatus != -1) return;
4109 if (event->type == ButtonPress) ErrorPopDown();
4112 if (event->type == ButtonPress) {
4113 // XtPopdown(promotionShell);
4114 // XtDestroyWidget(promotionShell);
4115 promotionUp = False;
4123 x = EventToSquare(event->xbutton.x, BOARD_WIDTH);
4124 y = EventToSquare(event->xbutton.y, BOARD_HEIGHT);
4125 if (!flipView && y >= 0) {
4126 y = BOARD_HEIGHT - 1 - y;
4128 if (flipView && x >= 0) {
4129 x = BOARD_WIDTH - 1 - x;
4132 /* [HGM] holdings: next 5 lines: ignore all clicks between board and holdings */
4133 if(event->type == ButtonPress
4134 && ( x == BOARD_LEFT-1 ||
4136 (x == BOARD_LEFT-2 && y < BOARD_HEIGHT-gameInfo.holdingsSize ) ||
4137 (x == BOARD_RGHT+1 && y >= gameInfo.holdingsSize)) )
4141 if (event->type == ButtonPress) {
4143 if (OKToStartUserMove(x, y)) {
4147 DragPieceBegin(event->xbutton.x, event->xbutton.y);
4148 if (appData.highlightDragging) {
4149 SetHighlights(x, y, -1, -1);
4157 if (event->type == ButtonPress && gameMode != EditPosition &&
4163 /* Check if clicking again on the same color piece */
4164 fromP = boards[currentMove][fromY][fromX];
4165 toP = boards[currentMove][y][x];
4166 frc = gameInfo.variant == VariantFischeRandom || gameInfo.variant == VariantCapaRandom;
4167 if ((WhitePawn <= fromP && fromP <= WhiteKing && // [HGM] this test should go, as UserMoveTest now does it.
4168 WhitePawn <= toP && toP <= WhiteKing &&
4169 !(fromP == WhiteKing && toP == WhiteRook && frc)) ||
4170 (BlackPawn <= fromP && fromP <= BlackKing &&
4171 BlackPawn <= toP && toP <= BlackKing &&
4172 !(fromP == BlackKing && toP == BlackRook && frc))) {
4173 /* Clicked again on same color piece -- changed his mind */
4174 second = (x == fromX && y == fromY);
4175 if (appData.highlightDragging) {
4176 SetHighlights(x, y, -1, -1);
4180 if (OKToStartUserMove(x, y)) {
4183 DragPieceBegin(event->xbutton.x, event->xbutton.y);
4189 if (event->type == ButtonRelease && x == fromX && y == fromY) {
4190 DragPieceEnd(event->xbutton.x, event->xbutton.y);
4191 if (appData.animateDragging) {
4192 /* Undo animation damage if any */
4193 DrawPosition(FALSE, NULL);
4196 /* Second up/down in same square; just abort move */
4201 ClearPremoveHighlights();
4203 /* First upclick in same square; start click-click mode */
4204 SetHighlights(x, y, -1, -1);
4209 /* Completed move */
4212 saveAnimate = appData.animate;
4213 if (event->type == ButtonPress) {
4214 /* Finish clickclick move */
4215 if (appData.animate || appData.highlightLastMove) {
4216 SetHighlights(fromX, fromY, toX, toY);
4221 /* Finish drag move */
4222 if (appData.highlightLastMove) {
4223 SetHighlights(fromX, fromY, toX, toY);
4227 DragPieceEnd(event->xbutton.x, event->xbutton.y);
4228 /* Don't animate move and drag both */
4229 appData.animate = FALSE;
4231 if (IsPromotion(fromX, fromY, toX, toY)) {
4232 if (appData.alwaysPromoteToQueen) {
4233 UserMoveEvent(fromX, fromY, toX, toY, 'q');
4234 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
4235 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
4238 SetHighlights(fromX, fromY, toX, toY);
4242 UserMoveEvent(fromX, fromY, toX, toY, NULLCHAR);
4243 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
4244 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
4247 appData.animate = saveAnimate;
4248 if (appData.animate || appData.animateDragging) {
4249 /* Undo animation damage if needed */
4250 DrawPosition(FALSE, NULL);
4254 void AnimateUserMove (Widget w, XEvent * event,
4255 String * params, Cardinal * nParams)
4257 DragPieceMove(event->xmotion.x, event->xmotion.y);
4260 Widget CommentCreate(name, text, mutable, callback, lines)
4262 int /*Boolean*/ mutable;
4263 XtCallbackProc callback;
4267 Widget shell, layout, form, edit, b_ok, b_cancel, b_clear, b_close, b_edit;
4272 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4273 XtGetValues(boardWidget, args, j);
4276 XtSetArg(args[j], XtNresizable, True); j++;
4279 XtCreatePopupShell(name, topLevelShellWidgetClass,
4280 shellWidget, args, j);
4283 XtCreatePopupShell(name, transientShellWidgetClass,
4284 shellWidget, args, j);
4287 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
4288 layoutArgs, XtNumber(layoutArgs));
4290 XtCreateManagedWidget("form", formWidgetClass, layout,
4291 formArgs, XtNumber(formArgs));
4295 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
4296 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
4298 XtSetArg(args[j], XtNstring, text); j++;
4299 XtSetArg(args[j], XtNtop, XtChainTop); j++;
4300 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4301 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4302 XtSetArg(args[j], XtNright, XtChainRight); j++;
4303 XtSetArg(args[j], XtNresizable, True); j++;
4304 XtSetArg(args[j], XtNwidth, bw_width); j++; /*force wider than buttons*/
4306 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
4308 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
4309 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
4311 XtSetArg(args[j], XtNautoFill, True); j++;
4312 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
4314 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
4318 XtSetArg(args[j], XtNfromVert, edit); j++;
4319 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4320 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4321 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4322 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4324 XtCreateManagedWidget(_("ok"), commandWidgetClass, form, args, j);
4325 XtAddCallback(b_ok, XtNcallback, callback, (XtPointer) 0);
4328 XtSetArg(args[j], XtNfromVert, edit); j++;
4329 XtSetArg(args[j], XtNfromHoriz, b_ok); j++;
4330 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4331 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4332 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4333 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4335 XtCreateManagedWidget(_("cancel"), commandWidgetClass, form, args, j);
4336 XtAddCallback(b_cancel, XtNcallback, callback, (XtPointer) 0);
4339 XtSetArg(args[j], XtNfromVert, edit); j++;
4340 XtSetArg(args[j], XtNfromHoriz, b_cancel); j++;
4341 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4342 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4343 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4344 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4346 XtCreateManagedWidget(_("clear"), commandWidgetClass, form, args, j);
4347 XtAddCallback(b_clear, XtNcallback, callback, (XtPointer) 0);
4350 XtSetArg(args[j], XtNfromVert, edit); j++;
4351 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4352 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4353 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4354 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4356 XtCreateManagedWidget(_("close"), commandWidgetClass, form, args, j);
4357 XtAddCallback(b_close, XtNcallback, callback, (XtPointer) 0);
4360 XtSetArg(args[j], XtNfromVert, edit); j++;
4361 XtSetArg(args[j], XtNfromHoriz, b_close); j++;
4362 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4363 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4364 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4365 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4367 XtCreateManagedWidget(_("edit"), commandWidgetClass, form, args, j);
4368 XtAddCallback(b_edit, XtNcallback, callback, (XtPointer) 0);
4371 XtRealizeWidget(shell);
4373 if (commentX == -1) {
4376 Dimension pw_height;
4377 Dimension ew_height;
4380 XtSetArg(args[j], XtNheight, &ew_height); j++;
4381 XtGetValues(edit, args, j);
4384 XtSetArg(args[j], XtNheight, &pw_height); j++;
4385 XtGetValues(shell, args, j);
4386 commentH = pw_height + (lines - 1) * ew_height;
4387 commentW = bw_width - 16;
4389 XSync(xDisplay, False);
4391 /* This code seems to tickle an X bug if it is executed too soon
4392 after xboard starts up. The coordinates get transformed as if
4393 the main window was positioned at (0, 0).
4395 XtTranslateCoords(shellWidget,
4396 (bw_width - commentW) / 2, 0 - commentH / 2,
4397 &commentX, &commentY);
4399 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
4400 RootWindowOfScreen(XtScreen(shellWidget)),
4401 (bw_width - commentW) / 2, 0 - commentH / 2,
4406 if (commentY < 0) commentY = 0; /*avoid positioning top offscreen*/
4409 XtSetArg(args[j], XtNheight, commentH); j++;
4410 XtSetArg(args[j], XtNwidth, commentW); j++;
4411 XtSetArg(args[j], XtNx, commentX); j++;
4412 XtSetArg(args[j], XtNy, commentY); j++;
4413 XtSetValues(shell, args, j);
4414 XtSetKeyboardFocus(shell, edit);
4419 /* Used for analysis window and ICS input window */
4420 Widget MiscCreate(name, text, mutable, callback, lines)
4422 int /*Boolean*/ mutable;
4423 XtCallbackProc callback;
4427 Widget shell, layout, form, edit;
4429 Dimension bw_width, pw_height, ew_height, w, h;
4435 XtSetArg(args[j], XtNresizable, True); j++;
4438 XtCreatePopupShell(name, topLevelShellWidgetClass,
4439 shellWidget, args, j);
4442 XtCreatePopupShell(name, transientShellWidgetClass,
4443 shellWidget, args, j);
4446 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
4447 layoutArgs, XtNumber(layoutArgs));
4449 XtCreateManagedWidget("form", formWidgetClass, layout,
4450 formArgs, XtNumber(formArgs));
4454 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
4455 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
4457 XtSetArg(args[j], XtNstring, text); j++;
4458 XtSetArg(args[j], XtNtop, XtChainTop); j++;
4459 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4460 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4461 XtSetArg(args[j], XtNright, XtChainRight); j++;
4462 XtSetArg(args[j], XtNresizable, True); j++;
4464 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
4466 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
4467 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
4469 XtSetArg(args[j], XtNautoFill, True); j++;
4470 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
4472 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
4474 XtRealizeWidget(shell);
4477 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4478 XtGetValues(boardWidget, args, j);
4481 XtSetArg(args[j], XtNheight, &ew_height); j++;
4482 XtGetValues(edit, args, j);
4485 XtSetArg(args[j], XtNheight, &pw_height); j++;
4486 XtGetValues(shell, args, j);
4487 h = pw_height + (lines - 1) * ew_height;
4490 XSync(xDisplay, False);
4492 /* This code seems to tickle an X bug if it is executed too soon
4493 after xboard starts up. The coordinates get transformed as if
4494 the main window was positioned at (0, 0).
4496 XtTranslateCoords(shellWidget, (bw_width - w) / 2, 0 - h / 2, &x, &y);
4498 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
4499 RootWindowOfScreen(XtScreen(shellWidget)),
4500 (bw_width - w) / 2, 0 - h / 2, &xx, &yy, &junk);
4504 if (y < 0) y = 0; /*avoid positioning top offscreen*/
4507 XtSetArg(args[j], XtNheight, h); j++;
4508 XtSetArg(args[j], XtNwidth, w); j++;
4509 XtSetArg(args[j], XtNx, x); j++;
4510 XtSetArg(args[j], XtNy, y); j++;
4511 XtSetValues(shell, args, j);
4517 static int savedIndex; /* gross that this is global */
4519 void EditCommentPopUp(index, title, text)
4528 if (text == NULL) text = "";
4530 if (editShell == NULL) {
4532 CommentCreate(title, text, True, EditCommentCallback, 4);
4533 XtRealizeWidget(editShell);
4534 CatchDeleteWindow(editShell, "EditCommentPopDown");
4536 edit = XtNameToWidget(editShell, "*form.text");
4538 XtSetArg(args[j], XtNstring, text); j++;
4539 XtSetValues(edit, args, j);
4541 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4542 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4543 XtSetValues(editShell, args, j);
4546 XtPopup(editShell, XtGrabNone);
4550 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
4551 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
4555 void EditCommentCallback(w, client_data, call_data)
4557 XtPointer client_data, call_data;
4565 XtSetArg(args[j], XtNlabel, &name); j++;
4566 XtGetValues(w, args, j);
4568 if (strcmp(name, _("ok")) == 0) {
4569 edit = XtNameToWidget(editShell, "*form.text");
4571 XtSetArg(args[j], XtNstring, &val); j++;
4572 XtGetValues(edit, args, j);
4573 ReplaceComment(savedIndex, val);
4574 EditCommentPopDown();
4575 } else if (strcmp(name, _("cancel")) == 0) {
4576 EditCommentPopDown();
4577 } else if (strcmp(name, _("clear")) == 0) {
4578 edit = XtNameToWidget(editShell, "*form.text");
4579 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
4580 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
4584 void EditCommentPopDown()
4589 if (!editUp) return;
4591 XtSetArg(args[j], XtNx, &commentX); j++;
4592 XtSetArg(args[j], XtNy, &commentY); j++;
4593 XtSetArg(args[j], XtNheight, &commentH); j++;
4594 XtSetArg(args[j], XtNwidth, &commentW); j++;
4595 XtGetValues(editShell, args, j);
4596 XtPopdown(editShell);
4599 XtSetArg(args[j], XtNleftBitmap, None); j++;
4600 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
4604 void ICSInputBoxPopUp()
4609 char *title = _("ICS Input");
4612 if (ICSInputShell == NULL) {
4613 ICSInputShell = MiscCreate(title, "", True, NULL, 1);
4614 tr = XtParseTranslationTable(ICSInputTranslations);
4615 edit = XtNameToWidget(ICSInputShell, "*form.text");
4616 XtOverrideTranslations(edit, tr);
4617 XtRealizeWidget(ICSInputShell);
4618 CatchDeleteWindow(ICSInputShell, "ICSInputBoxPopDown");
4621 edit = XtNameToWidget(ICSInputShell, "*form.text");
4623 XtSetArg(args[j], XtNstring, ""); j++;
4624 XtSetValues(edit, args, j);
4626 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4627 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4628 XtSetValues(ICSInputShell, args, j);
4631 XtPopup(ICSInputShell, XtGrabNone);
4632 XtSetKeyboardFocus(ICSInputShell, edit);
4634 ICSInputBoxUp = True;
4636 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
4637 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
4641 void ICSInputSendText()
4648 edit = XtNameToWidget(ICSInputShell, "*form.text");
4650 XtSetArg(args[j], XtNstring, &val); j++;
4651 XtGetValues(edit, args, j);
4652 SendMultiLineToICS(val);
4653 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
4654 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
4657 void ICSInputBoxPopDown()
4662 if (!ICSInputBoxUp) return;
4664 XtPopdown(ICSInputShell);
4665 ICSInputBoxUp = False;
4667 XtSetArg(args[j], XtNleftBitmap, None); j++;
4668 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
4672 void CommentPopUp(title, text)
4679 if (commentShell == NULL) {
4681 CommentCreate(title, text, False, CommentCallback, 4);
4682 XtRealizeWidget(commentShell);
4683 CatchDeleteWindow(commentShell, "CommentPopDown");
4685 edit = XtNameToWidget(commentShell, "*form.text");
4687 XtSetArg(args[j], XtNstring, text); j++;
4688 XtSetValues(edit, args, j);
4690 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4691 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4692 XtSetValues(commentShell, args, j);
4695 XtPopup(commentShell, XtGrabNone);
4696 XSync(xDisplay, False);
4701 void AnalysisPopUp(title, text)
4708 if (analysisShell == NULL) {
4709 analysisShell = MiscCreate(title, text, False, NULL, 4);
4710 XtRealizeWidget(analysisShell);
4711 CatchDeleteWindow(analysisShell, "AnalysisPopDown");
4714 edit = XtNameToWidget(analysisShell, "*form.text");
4716 XtSetArg(args[j], XtNstring, text); j++;
4717 XtSetValues(edit, args, j);
4719 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4720 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4721 XtSetValues(analysisShell, args, j);
4725 XtPopup(analysisShell, XtGrabNone);
4727 XSync(xDisplay, False);
4732 void CommentCallback(w, client_data, call_data)
4734 XtPointer client_data, call_data;
4741 XtSetArg(args[j], XtNlabel, &name); j++;
4742 XtGetValues(w, args, j);
4744 if (strcmp(name, _("close")) == 0) {
4746 } else if (strcmp(name, _("edit")) == 0) {
4753 void CommentPopDown()
4758 if (!commentUp) return;
4760 XtSetArg(args[j], XtNx, &commentX); j++;
4761 XtSetArg(args[j], XtNy, &commentY); j++;
4762 XtSetArg(args[j], XtNwidth, &commentW); j++;
4763 XtSetArg(args[j], XtNheight, &commentH); j++;
4764 XtGetValues(commentShell, args, j);
4765 XtPopdown(commentShell);
4766 XSync(xDisplay, False);
4770 void AnalysisPopDown()
4772 if (!analysisUp) return;
4773 XtPopdown(analysisShell);
4774 XSync(xDisplay, False);
4776 if (appData.icsEngineAnalyze) ExitAnalyzeMode(); /* [DM] icsEngineAnalyze */
4780 void FileNamePopUp(label, def, proc, openMode)
4787 Widget popup, layout, dialog, edit;
4793 fileProc = proc; /* I can't see a way not */
4794 fileOpenMode = openMode; /* to use globals here */
4797 XtSetArg(args[i], XtNresizable, True); i++;
4798 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
4799 XtSetArg(args[i], XtNtitle, XtNewString(_("File name prompt"))); i++;
4800 fileNameShell = popup =
4801 XtCreatePopupShell("File name prompt", transientShellWidgetClass,
4802 shellWidget, args, i);
4805 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
4806 layoutArgs, XtNumber(layoutArgs));
4809 XtSetArg(args[i], XtNlabel, label); i++;
4810 XtSetArg(args[i], XtNvalue, def); i++;
4811 XtSetArg(args[i], XtNborderWidth, 0); i++;
4812 dialog = XtCreateManagedWidget("fileName", dialogWidgetClass,
4815 XawDialogAddButton(dialog, _("ok"), FileNameCallback, (XtPointer) dialog);
4816 XawDialogAddButton(dialog, _("cancel"), FileNameCallback,
4817 (XtPointer) dialog);
4819 XtRealizeWidget(popup);
4820 CatchDeleteWindow(popup, "FileNamePopDown");
4822 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
4823 &x, &y, &win_x, &win_y, &mask);
4825 XtSetArg(args[0], XtNx, x - 10);
4826 XtSetArg(args[1], XtNy, y - 30);
4827 XtSetValues(popup, args, 2);
4829 XtPopup(popup, XtGrabExclusive);
4832 edit = XtNameToWidget(dialog, "*value");
4833 XtSetKeyboardFocus(popup, edit);
4836 void FileNamePopDown()
4838 if (!filenameUp) return;
4839 XtPopdown(fileNameShell);
4840 XtDestroyWidget(fileNameShell);
4845 void FileNameCallback(w, client_data, call_data)
4847 XtPointer client_data, call_data;
4852 XtSetArg(args[0], XtNlabel, &name);
4853 XtGetValues(w, args, 1);
4855 if (strcmp(name, _("cancel")) == 0) {
4860 FileNameAction(w, NULL, NULL, NULL);
4863 void FileNameAction(w, event, prms, nprms)
4875 name = XawDialogGetValueString(w = XtParent(w));
4877 if ((name != NULL) && (*name != NULLCHAR)) {
4879 XtPopdown(w = XtParent(XtParent(w)));
4883 p = strrchr(buf, ' ');
4890 fullname = ExpandPathName(buf);
4892 ErrorPopUp(_("Error"), _("Can't open file"), FALSE);
4895 f = fopen(fullname, fileOpenMode);
4897 DisplayError(_("Failed to open file"), errno);
4899 (void) (*fileProc)(f, index, buf);
4906 XtPopdown(w = XtParent(XtParent(w)));
4912 void PromotionPopUp()
4915 Widget dialog, layout;
4917 Dimension bw_width, pw_width;
4921 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4922 XtGetValues(boardWidget, args, j);
4925 XtSetArg(args[j], XtNresizable, True); j++;
4926 XtSetArg(args[j], XtNtitle, XtNewString(_("Promotion"))); j++;
4928 XtCreatePopupShell("Promotion", transientShellWidgetClass,
4929 shellWidget, args, j);
4931 XtCreateManagedWidget(layoutName, formWidgetClass, promotionShell,
4932 layoutArgs, XtNumber(layoutArgs));
4935 XtSetArg(args[j], XtNlabel, _("Promote to what?")); j++;
4936 XtSetArg(args[j], XtNborderWidth, 0); j++;
4937 dialog = XtCreateManagedWidget("promotion", dialogWidgetClass,
4940 if(gameInfo.variant != VariantShogi) {
4941 XawDialogAddButton(dialog, _("Queen"), PromotionCallback,
4942 (XtPointer) dialog);
4943 XawDialogAddButton(dialog, _("Rook"), PromotionCallback,
4944 (XtPointer) dialog);
4945 XawDialogAddButton(dialog, _("Bishop"), PromotionCallback,
4946 (XtPointer) dialog);
4947 XawDialogAddButton(dialog, _("Knight"), PromotionCallback,
4948 (XtPointer) dialog);
4949 if (!appData.testLegality || gameInfo.variant == VariantSuicide ||
4950 gameInfo.variant == VariantGiveaway) {
4951 XawDialogAddButton(dialog, _("King"), PromotionCallback,
4952 (XtPointer) dialog);
4954 if(gameInfo.variant == VariantCapablanca ||
4955 gameInfo.variant == VariantGothic ||
4956 gameInfo.variant == VariantCapaRandom) {
4957 XawDialogAddButton(dialog, _("Archbishop"), PromotionCallback,
4958 (XtPointer) dialog);
4959 XawDialogAddButton(dialog, _("Chancellor"), PromotionCallback,
4960 (XtPointer) dialog);
4962 } else // [HGM] shogi
4964 XawDialogAddButton(dialog, _("Promote"), PromotionCallback,
4965 (XtPointer) dialog);
4966 XawDialogAddButton(dialog, _("Defer"), PromotionCallback,
4967 (XtPointer) dialog);
4969 XawDialogAddButton(dialog, _("cancel"), PromotionCallback,
4970 (XtPointer) dialog);
4972 XtRealizeWidget(promotionShell);
4973 CatchDeleteWindow(promotionShell, "PromotionPopDown");
4976 XtSetArg(args[j], XtNwidth, &pw_width); j++;
4977 XtGetValues(promotionShell, args, j);
4979 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
4980 lineGap + squareSize/3 +
4981 ((toY == BOARD_HEIGHT-1) ^ (flipView) ?
4982 0 : 6*(squareSize + lineGap)), &x, &y);
4985 XtSetArg(args[j], XtNx, x); j++;
4986 XtSetArg(args[j], XtNy, y); j++;
4987 XtSetValues(promotionShell, args, j);
4989 XtPopup(promotionShell, XtGrabNone);
4994 void PromotionPopDown()
4996 if (!promotionUp) return;
4997 XtPopdown(promotionShell);
4998 XtDestroyWidget(promotionShell);
4999 promotionUp = False;
5002 void PromotionCallback(w, client_data, call_data)
5004 XtPointer client_data, call_data;
5010 XtSetArg(args[0], XtNlabel, &name);
5011 XtGetValues(w, args, 1);
5015 if (fromX == -1) return;
5017 if (strcmp(name, _("cancel")) == 0) {
5021 } else if (strcmp(name, _("Knight")) == 0) {
5023 } else if (strcmp(name, _("Promote")) == 0) {
5025 } else if (strcmp(name, _("Defer")) == 0) {
5028 promoChar = ToLower(name[0]);
5031 UserMoveEvent(fromX, fromY, toX, toY, promoChar);
5033 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
5034 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
5039 void ErrorCallback(w, client_data, call_data)
5041 XtPointer client_data, call_data;
5044 XtPopdown(w = XtParent(XtParent(XtParent(w))));
5046 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5052 if (!errorUp) return;
5056 gtk_widget_destroy(GTK_WIDGET(GUI_Error));
5058 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5063 void ErrorPopUp(title, label, modal)
5064 char *title, *label;
5067 GUI_Error = gtk_message_dialog_new(GTK_WINDOW(GUI_Window),
5068 GTK_DIALOG_DESTROY_WITH_PARENT,
5073 gtk_window_set_title(GTK_WINDOW(GUI_Error),(gchar *) title);
5076 gtk_dialog_run(GTK_DIALOG(GUI_Error));
5077 gtk_widget_destroy(GTK_WIDGET(GUI_Error));
5081 g_signal_connect_swapped (GUI_Error, "response",
5082 G_CALLBACK (ErrorPopDownProc),
5085 gtk_widget_show(GTK_WIDGET(GUI_Error));
5091 /* Disable all user input other than deleting the window */
5092 static int frozen = 0;
5096 /* Grab by a widget that doesn't accept input */
5097 // XtAddGrab(messageWidget, TRUE, FALSE);
5101 /* Undo a FreezeUI */
5104 if (!frozen) return;
5105 // XtRemoveGrab(messageWidget);
5109 char *ModeToWidgetName(mode)
5113 case BeginningOfGame:
5114 if (appData.icsActive)
5115 return "menuMode.ICS Client";
5116 else if (appData.noChessProgram ||
5117 *appData.cmailGameName != NULLCHAR)
5118 return "menuMode.Edit Game";
5120 return "menuMode.Machine Black";
5121 case MachinePlaysBlack:
5122 return "menuMode.Machine Black";
5123 case MachinePlaysWhite:
5124 return "menuMode.Machine White";
5126 return "menuMode.Analysis Mode";
5128 return "menuMode.Analyze File";
5129 case TwoMachinesPlay:
5130 return "menuMode.Two Machines";
5132 return "menuMode.Edit Game";
5133 case PlayFromGameFile:
5134 return "menuFile.Load Game";
5136 return "menuMode.Edit Position";
5138 return "menuMode.Training";
5139 case IcsPlayingWhite:
5140 case IcsPlayingBlack:
5144 return "menuMode.ICS Client";
5151 void ModeHighlight()
5153 static int oldPausing = FALSE;
5154 static GameMode oldmode = (GameMode) -1;
5157 // todo this toggling of the pause button doesn't seem to work?
5158 // e.g. select pause from buttonbar doesn't activate menumode.pause
5160 // if (!boardWidget || !XtIsRealized(boardWidget)) return;
5162 if (pausing != oldPausing) {
5163 oldPausing = pausing;
5164 gtk_button_set_relief(GTK_BUTTON (gtk_builder_get_object (builder, "menuMode.Pause")),pausing?GTK_RELIEF_NORMAL:GTK_RELIEF_NONE);
5165 /* toggle background color in showbuttonbar */
5166 if (appData.showButtonBar) {
5168 gtk_button_pressed(GTK_BUTTON (gtk_builder_get_object (builder, "buttonbar.Pause")));
5170 gtk_button_released(GTK_BUTTON (gtk_builder_get_object (builder, "buttonbar.Pause")));
5175 wname = ModeToWidgetName(oldmode);
5177 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, wname)),True);
5181 /* Maybe all the enables should be handled here, not just this one */
5182 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuMode.Training")),
5183 gameMode == Training || gameMode == PlayFromGameFile);
5188 * Button/menu procedures
5191 int LoadGamePopUp(f, gameNumber, title)
5196 cmailMsgLoaded = FALSE;
5197 if (gameNumber == 0) {
5198 int error = GameListBuild(f);
5200 DisplayError(_("Cannot build game list"), error);
5201 } else if (!ListEmpty(&gameList) &&
5202 ((ListGame *) gameList.tailPred)->number > 1) {
5203 GameListPopUp(f, title);
5209 return LoadGame(f, gameNumber, title, FALSE);
5213 void LoadNextPositionProc(w, event, prms, nprms)
5222 void LoadPrevPositionProc(w, event, prms, nprms)
5231 void ReloadPositionProc(w, event, prms, nprms)
5240 void LoadPositionProc(w, event, prms, nprms)
5246 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
5249 FileNamePopUp(_("Load position file name?"), "", LoadPosition, "rb");
5252 void SaveGameProc(w, event, prms, nprms)
5258 FileNamePopUp(_("Save game file name?"),
5259 DefaultFileName(appData.oldSaveStyle ? "game" : "pgn"),
5263 void SavePositionProc(w, event, prms, nprms)
5269 FileNamePopUp(_("Save position file name?"),
5270 DefaultFileName(appData.oldSaveStyle ? "pos" : "fen"),
5274 void ReloadCmailMsgProc(w, event, prms, nprms)
5280 ReloadCmailMsgEvent(FALSE);
5283 void MailMoveProc(w, event, prms, nprms)
5292 /* this variable is shared between CopyPositionProc and SendPositionSelection */
5293 static char *selected_fen_position=NULL;
5296 SendPositionSelection(Widget w, Atom *selection, Atom *target,
5297 Atom *type_return, XtPointer *value_return,
5298 unsigned long *length_return, int *format_return)
5300 char *selection_tmp;
5302 if (!selected_fen_position) return False; /* should never happen */
5303 if (*target == XA_STRING){
5304 /* note: since no XtSelectionDoneProc was registered, Xt will
5305 * automatically call XtFree on the value returned. So have to
5306 * make a copy of it allocated with XtMalloc */
5307 selection_tmp= XtMalloc(strlen(selected_fen_position)+16);
5308 strcpy(selection_tmp, selected_fen_position);
5310 *value_return=selection_tmp;
5311 *length_return=strlen(selection_tmp);
5312 *type_return=XA_STRING;
5313 *format_return = 8; /* bits per byte */
5320 /* note: when called from menu all parameters are NULL, so no clue what the
5321 * Widget which was clicked on was, or what the click event was
5323 void CopyPositionProc(w, event, prms, nprms)
5331 if (selected_fen_position) free(selected_fen_position);
5332 selected_fen_position = (char *)PositionToFEN(currentMove, NULL);
5333 if (!selected_fen_position) return;
5334 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
5336 SendPositionSelection,
5337 NULL/* lose_ownership_proc */ ,
5338 NULL/* transfer_done_proc */);
5340 free(selected_fen_position);
5341 selected_fen_position=NULL;
5345 /* function called when the data to Paste is ready */
5347 PastePositionCB(Widget w, XtPointer client_data, Atom *selection,
5348 Atom *type, XtPointer value, unsigned long *len, int *format)
5351 if (value==NULL || *len==0) return; /* nothing had been selected to copy */
5352 fenstr[*len]='\0'; /* normally this string is terminated, but be safe */
5353 EditPositionPasteFEN(fenstr);
5357 /* called when Paste Position button is pressed,
5358 * all parameters will be NULL */
5359 void PastePositionProc(w, event, prms, nprms)
5365 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
5366 /* (XtSelectionCallbackProc) */ PastePositionCB,
5367 NULL, /* client_data passed to PastePositionCB */
5369 /* better to use the time field from the event that triggered the
5370 * call to this function, but that isn't trivial to get
5378 SendGameSelection(Widget w, Atom *selection, Atom *target,
5379 Atom *type_return, XtPointer *value_return,
5380 unsigned long *length_return, int *format_return)
5382 char *selection_tmp;
5384 if (*target == XA_STRING){
5385 FILE* f = fopen(gameCopyFilename, "r");
5388 if (f == NULL) return False;
5392 selection_tmp = XtMalloc(len + 1);
5393 count = fread(selection_tmp, 1, len, f);
5395 XtFree(selection_tmp);
5398 selection_tmp[len] = NULLCHAR;
5399 *value_return = selection_tmp;
5400 *length_return = len;
5401 *type_return = XA_STRING;
5402 *format_return = 8; /* bits per byte */
5409 /* note: when called from menu all parameters are NULL, so no clue what the
5410 * Widget which was clicked on was, or what the click event was
5412 void CopyGameProc(w, event, prms, nprms)
5420 ret = SaveGameToFile(gameCopyFilename, FALSE);
5423 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
5426 NULL/* lose_ownership_proc */ ,
5427 NULL/* transfer_done_proc */);
5430 /* function called when the data to Paste is ready */
5432 PasteGameCB(Widget w, XtPointer client_data, Atom *selection,
5433 Atom *type, XtPointer value, unsigned long *len, int *format)
5436 if (value == NULL || *len == 0) {
5437 return; /* nothing had been selected to copy */
5439 f = fopen(gamePasteFilename, "w");
5441 DisplayError(_("Can't open temp file"), errno);
5444 fwrite(value, 1, *len, f);
5447 LoadGameFromFile(gamePasteFilename, 0, gamePasteFilename, TRUE);
5450 /* called when Paste Game button is pressed,
5451 * all parameters will be NULL */
5452 void PasteGameProc(w, event, prms, nprms)
5458 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
5459 /* (XtSelectionCallbackProc) */ PasteGameCB,
5460 NULL, /* client_data passed to PasteGameCB */
5462 /* better to use the time field from the event that triggered the
5463 * call to this function, but that isn't trivial to get
5473 SaveGameProc(NULL, NULL, NULL, NULL);
5476 void AnalyzeModeProc(w, event, prms, nprms)
5484 if (!first.analysisSupport) {
5485 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
5486 DisplayError(buf, 0);
5489 /* [DM] icsEngineAnalyze [HGM] This is horrible code; reverse the gameMode and isEngineAnalyze tests! */
5490 if (appData.icsActive) {
5491 if (gameMode != IcsObserving) {
5492 sprintf(buf,_("You are not observing a game"));
5493 DisplayError(buf, 0);
5495 if (appData.icsEngineAnalyze) {
5496 if (appData.debugMode)
5497 fprintf(debugFP, _("Found unexpected active ICS engine analyze \n"));
5503 /* if enable, use want disable icsEngineAnalyze */
5504 if (appData.icsEngineAnalyze) {
5509 appData.icsEngineAnalyze = TRUE;
5510 if (appData.debugMode)
5511 fprintf(debugFP, _("ICS engine analyze starting... \n"));
5513 if (!appData.showThinking)
5514 ShowThinkingProc(w,event,prms,nprms);
5519 void AnalyzeFileProc(w, event, prms, nprms)
5525 if (!first.analysisSupport) {
5527 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
5528 DisplayError(buf, 0);
5533 if (!appData.showThinking)
5534 ShowThinkingProc(w,event,prms,nprms);
5537 FileNamePopUp(_("File to analyze"), "", LoadGamePopUp, "rb");
5538 AnalysisPeriodicEvent(1);
5542 void EditGameProc(w, event, prms, nprms)
5551 void EditPositionProc(w, event, prms, nprms)
5557 EditPositionEvent();
5560 void TrainingProc(w, event, prms, nprms)
5569 void EditCommentProc(w, event, prms, nprms)
5576 EditCommentPopDown();
5582 void IcsInputBoxProc(w, event, prms, nprms)
5588 if (ICSInputBoxUp) {
5589 ICSInputBoxPopDown();
5596 void EnterKeyProc(w, event, prms, nprms)
5602 if (ICSInputBoxUp == True)
5606 void AlwaysQueenProc(w, event, prms, nprms)
5614 appData.alwaysPromoteToQueen = !appData.alwaysPromoteToQueen;
5616 if (appData.alwaysPromoteToQueen) {
5617 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5619 XtSetArg(args[0], XtNleftBitmap, None);
5621 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
5625 void AnimateDraggingProc(w, event, prms, nprms)
5633 appData.animateDragging = !appData.animateDragging;
5635 if (appData.animateDragging) {
5636 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5639 XtSetArg(args[0], XtNleftBitmap, None);
5641 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Dragging"),
5645 void AnimateMovingProc(w, event, prms, nprms)
5653 appData.animate = !appData.animate;
5655 if (appData.animate) {
5656 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5659 XtSetArg(args[0], XtNleftBitmap, None);
5661 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
5665 void AutocommProc(w, event, prms, nprms)
5673 appData.autoComment = !appData.autoComment;
5675 if (appData.autoComment) {
5676 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5678 XtSetArg(args[0], XtNleftBitmap, None);
5680 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
5685 void AutoflagProc(w, event, prms, nprms)
5693 appData.autoCallFlag = !appData.autoCallFlag;
5695 if (appData.autoCallFlag) {
5696 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5698 XtSetArg(args[0], XtNleftBitmap, None);
5700 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
5704 void AutoflipProc(w, event, prms, nprms)
5712 appData.autoFlipView = !appData.autoFlipView;
5714 if (appData.autoFlipView) {
5715 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5717 XtSetArg(args[0], XtNleftBitmap, None);
5719 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flip View"),
5723 void AutobsProc(w, event, prms, nprms)
5731 appData.autoObserve = !appData.autoObserve;
5733 if (appData.autoObserve) {
5734 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5736 XtSetArg(args[0], XtNleftBitmap, None);
5738 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
5742 void AutoraiseProc(w, event, prms, nprms)
5750 appData.autoRaiseBoard = !appData.autoRaiseBoard;
5752 if (appData.autoRaiseBoard) {
5753 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5755 XtSetArg(args[0], XtNleftBitmap, None);
5757 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Raise Board"),
5761 void AutosaveProc(w, event, prms, nprms)
5769 appData.autoSaveGames = !appData.autoSaveGames;
5771 if (appData.autoSaveGames) {
5772 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5774 XtSetArg(args[0], XtNleftBitmap, None);
5776 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
5780 void BlindfoldProc(w, event, prms, nprms)
5788 appData.blindfold = !appData.blindfold;
5790 if (appData.blindfold) {
5791 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5793 XtSetArg(args[0], XtNleftBitmap, None);
5795 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Blindfold"),
5798 DrawPosition(True, NULL);
5801 void TestLegalityProc(w, event, prms, nprms)
5809 appData.testLegality = !appData.testLegality;
5811 if (appData.testLegality) {
5812 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5814 XtSetArg(args[0], XtNleftBitmap, None);
5816 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Test Legality"),
5821 void FlashMovesProc(w, event, prms, nprms)
5829 if (appData.flashCount == 0) {
5830 appData.flashCount = 3;
5832 appData.flashCount = -appData.flashCount;
5835 if (appData.flashCount > 0) {
5836 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5838 XtSetArg(args[0], XtNleftBitmap, None);
5840 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flash Moves"),
5844 void GetMoveListProc(w, event, prms, nprms)
5852 appData.getMoveList = !appData.getMoveList;
5854 if (appData.getMoveList) {
5855 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5858 XtSetArg(args[0], XtNleftBitmap, None);
5860 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
5865 void HighlightDraggingProc(w, event, prms, nprms)
5873 appData.highlightDragging = !appData.highlightDragging;
5875 if (appData.highlightDragging) {
5876 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5878 XtSetArg(args[0], XtNleftBitmap, None);
5880 XtSetValues(XtNameToWidget(menuBarWidget,
5881 "menuOptions.Highlight Dragging"), args, 1);
5885 void HighlightLastMoveProc(w, event, prms, nprms)
5893 appData.highlightLastMove = !appData.highlightLastMove;
5895 if (appData.highlightLastMove) {
5896 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5898 XtSetArg(args[0], XtNleftBitmap, None);
5900 XtSetValues(XtNameToWidget(menuBarWidget,
5901 "menuOptions.Highlight Last Move"), args, 1);
5904 void IcsAlarmProc(w, event, prms, nprms)
5912 appData.icsAlarm = !appData.icsAlarm;
5914 if (appData.icsAlarm) {
5915 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5917 XtSetArg(args[0], XtNleftBitmap, None);
5919 XtSetValues(XtNameToWidget(menuBarWidget,
5920 "menuOptions.ICS Alarm"), args, 1);
5923 void MoveSoundProc(w, event, prms, nprms)
5931 appData.ringBellAfterMoves = !appData.ringBellAfterMoves;
5933 if (appData.ringBellAfterMoves) {
5934 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5936 XtSetArg(args[0], XtNleftBitmap, None);
5938 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
5943 void OldSaveStyleProc(w, event, prms, nprms)
5951 appData.oldSaveStyle = !appData.oldSaveStyle;
5953 if (appData.oldSaveStyle) {
5954 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5956 XtSetArg(args[0], XtNleftBitmap, None);
5958 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Old Save Style"),
5962 void PeriodicUpdatesProc(w, event, prms, nprms)
5970 PeriodicUpdatesEvent(!appData.periodicUpdates);
5972 if (appData.periodicUpdates) {
5973 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5975 XtSetArg(args[0], XtNleftBitmap, None);
5977 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Periodic Updates"),
5981 void PonderNextMoveProc(w, event, prms, nprms)
5989 PonderNextMoveEvent(!appData.ponderNextMove);
5991 if (appData.ponderNextMove) {
5992 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5994 XtSetArg(args[0], XtNleftBitmap, None);
5996 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Ponder Next Move"),
6000 void PopupExitMessageProc(w, event, prms, nprms)
6008 appData.popupExitMessage = !appData.popupExitMessage;
6010 if (appData.popupExitMessage) {
6011 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6013 XtSetArg(args[0], XtNleftBitmap, None);
6015 XtSetValues(XtNameToWidget(menuBarWidget,
6016 "menuOptions.Popup Exit Message"), args, 1);
6019 void PopupMoveErrorsProc(w, event, prms, nprms)
6027 appData.popupMoveErrors = !appData.popupMoveErrors;
6029 if (appData.popupMoveErrors) {
6030 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6032 XtSetArg(args[0], XtNleftBitmap, None);
6034 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Popup Move Errors"),
6038 void PremoveProc(w, event, prms, nprms)
6046 appData.premove = !appData.premove;
6048 if (appData.premove) {
6049 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6051 XtSetArg(args[0], XtNleftBitmap, None);
6053 XtSetValues(XtNameToWidget(menuBarWidget,
6054 "menuOptions.Premove"), args, 1);
6057 void QuietPlayProc(w, event, prms, nprms)
6065 appData.quietPlay = !appData.quietPlay;
6067 if (appData.quietPlay) {
6068 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6070 XtSetArg(args[0], XtNleftBitmap, None);
6072 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Quiet Play"),
6076 void ShowThinkingProc(w, event, prms, nprms)
6084 appData.showThinking = !appData.showThinking; // [HGM] thinking: tken out of ShowThinkingEvent
6085 ShowThinkingEvent();
6087 // [HGM] thinking: currently no suc menu item; replaced by Hide Thinking (From Human)
6088 if (appData.showThinking) {
6089 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6091 XtSetArg(args[0], XtNleftBitmap, None);
6093 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Thinking"),
6098 void HideThinkingProc(w, event, prms, nprms)
6106 appData.hideThinkingFromHuman = !appData.hideThinkingFromHuman; // [HGM] thinking: tken out of ShowThinkingEvent
6107 ShowThinkingEvent();
6109 if (appData.hideThinkingFromHuman) {
6110 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6112 XtSetArg(args[0], XtNleftBitmap, None);
6114 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
6118 void DebugProc(w, event, prms, nprms)
6124 appData.debugMode = !appData.debugMode;
6127 void AboutGameProc(w, event, prms, nprms)
6136 void NothingProc(w, event, prms, nprms)
6145 void Iconify(w, event, prms, nprms)
6154 XtSetArg(args[0], XtNiconic, True);
6155 XtSetValues(shellWidget, args, 1);
6158 void DisplayMessage(message, extMessage)
6159 gchar *message, *extMessage;
6166 snprintf(buf, sizeof(buf), "%s %s", message, extMessage);
6169 message = extMessage;
6172 gtk_label_set_text( GTK_LABEL(gtk_builder_get_object (builder, "Messages")),message);
6177 void DisplayTitle(text)
6180 gchar title[MSG_SIZ];
6182 if (text == NULL) text = "";
6184 if (appData.titleInWindow)
6189 if (*text != NULLCHAR)
6191 strcpy(title, text);
6193 else if (appData.icsActive)
6195 snprintf(title, sizeof(title), "%s: %s", programName, appData.icsHost);
6197 else if (appData.cmailGameName[0] != NULLCHAR)
6199 snprintf(title,sizeof(title), "%s: %s", programName, "CMail");
6201 // [HGM] license: This stuff should really be done in back-end, but WinBoard already had a pop-up for it
6203 else if (gameInfo.variant == VariantGothic)
6205 strcpy(title, GOTHIC);
6209 else if (gameInfo.variant == VariantFalcon)
6211 strcpy(title, FALCON);
6214 else if (appData.noChessProgram)
6216 strcpy(title, programName);
6220 snprintf(title,sizeof(title), "%s: %s", programName, first.tidy);
6222 gtk_window_set_title(GTK_WINDOW(GUI_Window),title);
6228 void DisplayError(message, error)
6235 if (appData.debugMode || appData.matchMode) {
6236 fprintf(stderr, "%s: %s\n", programName, message);
6239 if (appData.debugMode || appData.matchMode) {
6240 fprintf(stderr, "%s: %s: %s\n",
6241 programName, message, strerror(error));
6243 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
6246 ErrorPopUp(_("Error"), message, FALSE);
6250 void DisplayMoveError(message)
6255 DrawPosition(FALSE, NULL);
6256 if (appData.debugMode || appData.matchMode) {
6257 fprintf(stderr, "%s: %s\n", programName, message);
6259 if (appData.popupMoveErrors) {
6260 ErrorPopUp(_("Error"), message, FALSE);
6262 DisplayMessage(message, "");
6267 void DisplayFatalError(message, error, status)
6273 errorExitStatus = status;
6275 fprintf(stderr, "%s: %s\n", programName, message);
6277 fprintf(stderr, "%s: %s: %s\n",
6278 programName, message, strerror(error));
6279 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
6282 if (appData.popupExitMessage && boardWidget && XtIsRealized(boardWidget)) {
6283 ErrorPopUp(status ? _("Fatal Error") : _("Exiting"), message, TRUE);
6289 void DisplayInformation(message)
6293 ErrorPopUp(_("Information"), message, TRUE);
6296 void DisplayNote(message)
6300 ErrorPopUp(_("Note"), message, FALSE);
6304 NullXErrorCheck(dpy, error_event)
6306 XErrorEvent *error_event;
6311 void DisplayIcsInteractionTitle(message)
6314 if (oldICSInteractionTitle == NULL) {
6315 /* Magic to find the old window title, adapted from vim */
6316 char *wina = getenv("WINDOWID");
6318 Window win = (Window) atoi(wina);
6319 Window root, parent, *children;
6320 unsigned int nchildren;
6321 int (*oldHandler)() = XSetErrorHandler(NullXErrorCheck);
6323 if (XFetchName(xDisplay, win, &oldICSInteractionTitle)) break;
6324 if (!XQueryTree(xDisplay, win, &root, &parent,
6325 &children, &nchildren)) break;
6326 if (children) XFree((void *)children);
6327 if (parent == root || parent == 0) break;
6330 XSetErrorHandler(oldHandler);
6332 if (oldICSInteractionTitle == NULL) {
6333 oldICSInteractionTitle = "xterm";
6336 printf("\033]0;%s\007", message);
6340 char pendingReplyPrefix[MSG_SIZ];
6341 ProcRef pendingReplyPR;
6343 void AskQuestionProc(w, event, prms, nprms)
6350 fprintf(stderr, _("AskQuestionProc needed 4 parameters, got %d\n"),
6354 AskQuestionEvent(prms[0], prms[1], prms[2], prms[3]);
6357 void AskQuestionPopDown()
6359 if (!askQuestionUp) return;
6360 XtPopdown(askQuestionShell);
6361 XtDestroyWidget(askQuestionShell);
6362 askQuestionUp = False;
6365 void AskQuestionReplyAction(w, event, prms, nprms)
6375 reply = XawDialogGetValueString(w = XtParent(w));
6376 strcpy(buf, pendingReplyPrefix);
6377 if (*buf) strcat(buf, " ");
6380 OutputToProcess(pendingReplyPR, buf, strlen(buf), &err);
6381 AskQuestionPopDown();
6383 if (err) DisplayFatalError(_("Error writing to chess program"), err, 0);
6386 void AskQuestionCallback(w, client_data, call_data)
6388 XtPointer client_data, call_data;
6393 XtSetArg(args[0], XtNlabel, &name);
6394 XtGetValues(w, args, 1);
6396 if (strcmp(name, _("cancel")) == 0) {
6397 AskQuestionPopDown();
6399 AskQuestionReplyAction(w, NULL, NULL, NULL);
6403 void AskQuestion(title, question, replyPrefix, pr)
6404 char *title, *question, *replyPrefix;
6408 Widget popup, layout, dialog, edit;
6414 strcpy(pendingReplyPrefix, replyPrefix);
6415 pendingReplyPR = pr;
6418 XtSetArg(args[i], XtNresizable, True); i++;
6419 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
6420 askQuestionShell = popup =
6421 XtCreatePopupShell(title, transientShellWidgetClass,
6422 shellWidget, args, i);
6425 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
6426 layoutArgs, XtNumber(layoutArgs));
6429 XtSetArg(args[i], XtNlabel, question); i++;
6430 XtSetArg(args[i], XtNvalue, ""); i++;
6431 XtSetArg(args[i], XtNborderWidth, 0); i++;
6432 dialog = XtCreateManagedWidget("question", dialogWidgetClass,
6435 XawDialogAddButton(dialog, _("enter"), AskQuestionCallback,
6436 (XtPointer) dialog);
6437 XawDialogAddButton(dialog, _("cancel"), AskQuestionCallback,
6438 (XtPointer) dialog);
6440 XtRealizeWidget(popup);
6441 CatchDeleteWindow(popup, "AskQuestionPopDown");
6443 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
6444 &x, &y, &win_x, &win_y, &mask);
6446 XtSetArg(args[0], XtNx, x - 10);
6447 XtSetArg(args[1], XtNy, y - 30);
6448 XtSetValues(popup, args, 2);
6450 XtPopup(popup, XtGrabExclusive);
6451 askQuestionUp = True;
6453 edit = XtNameToWidget(dialog, "*value");
6454 XtSetKeyboardFocus(popup, edit);
6462 if (*name == NULLCHAR) {
6464 } else if (strcmp(name, "$") == 0) {
6465 putc(BELLCHAR, stderr);
6468 snprintf(buf, sizeof(buf), "%s '%s' &", appData.soundProgram, name);
6476 PlaySound(appData.soundMove);
6482 PlaySound(appData.soundIcsWin);
6488 PlaySound(appData.soundIcsLoss);
6494 PlaySound(appData.soundIcsDraw);
6498 PlayIcsUnfinishedSound()
6500 PlaySound(appData.soundIcsUnfinished);
6506 PlaySound(appData.soundIcsAlarm);
6512 system("stty echo");
6518 system("stty -echo");
6522 Colorize(cc, continuation)
6527 int count, outCount, error;
6529 if (textColors[(int)cc].bg > 0) {
6530 if (textColors[(int)cc].fg > 0) {
6531 sprintf(buf, "\033[0;%d;%d;%dm", textColors[(int)cc].attr,
6532 textColors[(int)cc].fg, textColors[(int)cc].bg);
6534 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
6535 textColors[(int)cc].bg);
6538 if (textColors[(int)cc].fg > 0) {
6539 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
6540 textColors[(int)cc].fg);
6542 sprintf(buf, "\033[0;%dm", textColors[(int)cc].attr);
6545 count = strlen(buf);
6546 outCount = OutputToProcess(NoProc, buf, count, &error);
6547 if (outCount < count) {
6548 DisplayFatalError(_("Error writing to display"), error, 1);
6551 if (continuation) return;
6554 PlaySound(appData.soundShout);
6557 PlaySound(appData.soundSShout);
6560 PlaySound(appData.soundChannel1);
6563 PlaySound(appData.soundChannel);
6566 PlaySound(appData.soundKibitz);
6569 PlaySound(appData.soundTell);
6571 case ColorChallenge:
6572 PlaySound(appData.soundChallenge);
6575 PlaySound(appData.soundRequest);
6578 PlaySound(appData.soundSeek);
6589 return getpwuid(getuid())->pw_name;
6592 static char *ExpandPathName(path)
6595 static char static_buf[2000];
6596 char *d, *s, buf[2000];
6602 while (*s && isspace(*s))
6611 if (*(s+1) == '/') {
6612 strcpy(d, getpwuid(getuid())->pw_dir);
6617 *strchr(buf, '/') = 0;
6618 pwd = getpwnam(buf);
6621 fprintf(stderr, _("ERROR: Unknown user %s (in path %s)\n"),
6625 strcpy(d, pwd->pw_dir);
6626 strcat(d, strchr(s+1, '/'));
6637 static char host_name[MSG_SIZ];
6639 #if HAVE_GETHOSTNAME
6640 gethostname(host_name, MSG_SIZ);
6642 #else /* not HAVE_GETHOSTNAME */
6643 # if HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H
6644 sysinfo(SI_HOSTNAME, host_name, MSG_SIZ);
6646 # else /* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
6648 # endif/* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
6649 #endif /* not HAVE_GETHOSTNAME */
6652 guint delayedEventTimerTag = 0;
6653 DelayedEventCallback delayedEventCallback = 0;
6656 FireDelayedEvent(data)
6660 g_source_remove(delayedEventTimerTag);
6661 delayedEventTimerTag = 0;
6664 delayedEventCallback();
6670 ScheduleDelayedEvent(cb, millisec)
6671 DelayedEventCallback cb; guint millisec;
6673 delayedEventCallback = cb;
6674 delayedEventTimerTag = g_timeout_add(millisec,(GSourceFunc) FireDelayedEvent, NULL);
6678 DelayedEventCallback
6681 if (delayedEventTimerTag)
6683 return delayedEventCallback;
6692 CancelDelayedEvent()
6694 if (delayedEventTimerTag)
6696 g_source_remove(delayedEventTimerTag);
6697 delayedEventTimerTag = 0;
6703 guint loadGameTimerTag = 0;
6705 int LoadGameTimerRunning()
6707 return loadGameTimerTag != 0;
6710 int StopLoadGameTimer()
6712 if (loadGameTimerTag != 0) {
6713 g_source_remove(loadGameTimerTag);
6714 loadGameTimerTag = 0;
6722 LoadGameTimerCallback(data)
6726 g_source_remove(loadGameTimerTag);
6727 loadGameTimerTag = 0;
6734 StartLoadGameTimer(millisec)
6738 g_timeout_add( millisec, (GSourceFunc) LoadGameTimerCallback, NULL);
6742 guint analysisClockTag = 0;
6745 AnalysisClockCallback(data)
6748 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile
6749 || appData.icsEngineAnalyze)
6751 AnalysisPeriodicEvent(0);
6752 return 1; /* keep on going */
6754 return 0; /* stop timer */
6758 StartAnalysisClock()
6761 g_timeout_add( 2000,(GSourceFunc) AnalysisClockCallback, NULL);
6765 guint clockTimerTag = 0;
6767 int ClockTimerRunning()
6769 return clockTimerTag != 0;
6772 int StopClockTimer()
6774 if (clockTimerTag != 0)
6776 g_source_remove(clockTimerTag);
6787 ClockTimerCallback(data)
6791 g_source_remove(clockTimerTag);
6799 StartClockTimer(millisec)
6802 clockTimerTag = g_timeout_add(millisec,(GSourceFunc) ClockTimerCallback,NULL);
6807 DisplayTimerLabel(w, color, timer, highlight)
6816 if (appData.clockMode) {
6817 sprintf(buf, "%s: %s", color, TimeString(timer));
6819 sprintf(buf, "%s ", color);
6821 gtk_label_set_text(GTK_LABEL(w),buf);
6823 /* check for low time warning */
6824 // Pixel foregroundOrWarningColor = timerForegroundPixel;
6827 // appData.lowTimeWarning &&
6828 // (timer / 1000) < appData.icsAlarmTime)
6829 // foregroundOrWarningColor = lowTimeWarningColor;
6831 // if (appData.clockMode) {
6832 // sprintf(buf, "%s: %s", color, TimeString(timer));
6833 // XtSetArg(args[0], XtNlabel, buf);
6835 // sprintf(buf, "%s ", color);
6836 // XtSetArg(args[0], XtNlabel, buf);
6841 // XtSetArg(args[1], XtNbackground, foregroundOrWarningColor);
6842 // XtSetArg(args[2], XtNforeground, timerBackgroundPixel);
6844 // XtSetArg(args[1], XtNbackground, timerBackgroundPixel);
6845 // XtSetArg(args[2], XtNforeground, foregroundOrWarningColor);
6848 // XtSetValues(w, args, 3);
6853 DisplayWhiteClock(timeRemaining, highlight)
6857 if(appData.noGUI) return;
6859 DisplayTimerLabel(GUI_Whiteclock, _("White"), timeRemaining, highlight);
6860 if (highlight && WindowIcon == BlackIcon)
6862 WindowIcon = WhiteIcon;
6863 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
6868 DisplayBlackClock(timeRemaining, highlight)
6872 if(appData.noGUI) return;
6874 DisplayTimerLabel(GUI_Blackclock, _("Black"), timeRemaining, highlight);
6875 if (highlight && WindowIcon == WhiteIcon)
6877 WindowIcon = BlackIcon;
6878 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
6896 int StartChildProcess(cmdLine, dir, pr)
6903 int to_prog[2], from_prog[2];
6907 if (appData.debugMode) {
6908 fprintf(stderr, "StartChildProcess (dir=\"%s\") %s\n",dir, cmdLine);
6911 /* We do NOT feed the cmdLine to the shell; we just
6912 parse it into blank-separated arguments in the
6913 most simple-minded way possible.
6916 strcpy(buf, cmdLine);
6921 if (p == NULL) break;
6926 SetUpChildIO(to_prog, from_prog);
6928 if ((pid = fork()) == 0) {
6930 // [HGM] PSWBTM: made order resistant against case where fd of created pipe was 0 or 1
6931 close(to_prog[1]); // first close the unused pipe ends
6932 close(from_prog[0]);
6933 dup2(to_prog[0], 0); // to_prog was created first, nd is the only one to use 0 or 1
6934 dup2(from_prog[1], 1);
6935 if(to_prog[0] >= 2) close(to_prog[0]); // if 0 or 1, the dup2 already cosed the original
6936 close(from_prog[1]); // and closing again loses one of the pipes!
6937 if(fileno(stderr) >= 2) // better safe than sorry...
6938 dup2(1, fileno(stderr)); /* force stderr to the pipe */
6940 if (dir[0] != NULLCHAR && chdir(dir) != 0) {
6945 nice(appData.niceEngines); // [HGM] nice: adjust priority of engine proc
6947 execvp(argv[0], argv);
6949 /* If we get here, exec failed */
6954 /* Parent process */
6956 close(from_prog[1]);
6958 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
6961 cp->fdFrom = from_prog[0];
6962 cp->fdTo = to_prog[1];
6967 // [HGM] kill: implement the 'hard killing' of AS's Winboard_x
6968 static RETSIGTYPE AlarmCallBack(int n)
6974 DestroyChildProcess(pr, signalType)
6978 ChildProc *cp = (ChildProc *) pr;
6980 if (cp->kind != CPReal) return;
6982 if (signalType == 10) { // [HGM] kill: if it does not terminate in 3 sec, kill
6983 signal(SIGALRM, AlarmCallBack);
6985 if(wait((int *) 0) == -1) { // process does not terminate on its own accord
6986 kill(cp->pid, SIGKILL); // kill it forcefully
6987 wait((int *) 0); // and wait again
6991 kill(cp->pid, signalType == 9 ? SIGKILL : SIGTERM); // [HGM] kill: use hard kill if so requested
6993 /* Process is exiting either because of the kill or because of
6994 a quit command sent by the backend; either way, wait for it to die.
7003 InterruptChildProcess(pr)
7006 ChildProc *cp = (ChildProc *) pr;
7008 if (cp->kind != CPReal) return;
7009 (void) kill(cp->pid, SIGINT); /* stop it thinking */
7012 int OpenTelnet(host, port, pr)
7017 char cmdLine[MSG_SIZ];
7019 if (port[0] == NULLCHAR) {
7020 snprintf(cmdLine, sizeof(cmdLine), "%s %s", appData.telnetProgram, host);
7022 snprintf(cmdLine, sizeof(cmdLine), "%s %s %s", appData.telnetProgram, host, port);
7024 return StartChildProcess(cmdLine, "", pr);
7027 int OpenTCP(host, port, pr)
7033 DisplayFatalError(_("Socket support is not configured in"), 0, 2);
7034 #else /* !OMIT_SOCKETS */
7036 struct sockaddr_in sa;
7038 unsigned short uport;
7041 if ((s = socket(AF_INET, SOCK_STREAM, 6)) < 0) {
7045 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
7046 sa.sin_family = AF_INET;
7047 sa.sin_addr.s_addr = INADDR_ANY;
7048 uport = (unsigned short) 0;
7049 sa.sin_port = htons(uport);
7050 if (bind(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)) < 0) {
7054 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
7055 if (!(hp = gethostbyname(host))) {
7057 if (sscanf(host, "%d.%d.%d.%d", &b0, &b1, &b2, &b3) == 4) {
7058 hp = (struct hostent *) calloc(1, sizeof(struct hostent));
7059 hp->h_addrtype = AF_INET;
7061 hp->h_addr_list = (char **) calloc(2, sizeof(char *));
7062 hp->h_addr_list[0] = (char *) malloc(4);
7063 hp->h_addr_list[0][0] = b0;
7064 hp->h_addr_list[0][1] = b1;
7065 hp->h_addr_list[0][2] = b2;
7066 hp->h_addr_list[0][3] = b3;
7071 sa.sin_family = hp->h_addrtype;
7072 uport = (unsigned short) atoi(port);
7073 sa.sin_port = htons(uport);
7074 memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);
7076 if (connect(s, (struct sockaddr *) &sa,
7077 sizeof(struct sockaddr_in)) < 0) {
7081 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7088 #endif /* !OMIT_SOCKETS */
7093 int OpenCommPort(name, pr)
7100 fd = open(name, 2, 0);
7101 if (fd < 0) return errno;
7103 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7113 int OpenLoopback(pr)
7119 SetUpChildIO(to, from);
7121 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7124 cp->fdFrom = to[0]; /* note not from[0]; we are doing a loopback */
7131 int OpenRcmd(host, user, cmd, pr)
7132 char *host, *user, *cmd;
7135 DisplayFatalError(_("internal rcmd not implemented for Unix"), 0, 1);
7139 #define INPUT_SOURCE_BUF_SIZE 8192
7148 char buf[INPUT_SOURCE_BUF_SIZE];
7153 DoInputCallback(io,cond,data)
7158 /* read input from one of the input source (for example a chess program, ICS, etc).
7159 * and call a function that will handle the input
7162 int count; /* how many bytes did we read */
7166 /* All information (callback function, file descriptor, etc) is
7167 * saved in an InputSource structure
7169 InputSource *is = (InputSource *) data;
7173 count = read(is->fd, is->unused,
7174 INPUT_SOURCE_BUF_SIZE - (is->unused - is->buf));
7178 (is->func)(is, is->closure, is->buf, count, count ? errno : 0);
7181 is->unused += count;
7183 /* break input into lines and call the callback function on each
7186 while (p < is->unused)
7188 q = memchr(p, '\n', is->unused - p);
7189 if (q == NULL) break;
7191 (is->func)(is, is->closure, p, q - p, 0);
7194 /* remember not yet used part of the buffer */
7196 while (p < is->unused)
7204 /* read maximum length of input buffer and send the whole buffer
7205 * to the callback function
7207 count = read(is->fd, is->buf, INPUT_SOURCE_BUF_SIZE);
7212 (is->func)(is, is->closure, is->buf, count, error);
7218 InputSourceRef AddInputSource(pr, lineByLine, func, closure)
7225 GIOChannel *channel;
7226 ChildProc *cp = (ChildProc *) pr;
7228 is = (InputSource *) calloc(1, sizeof(InputSource));
7229 is->lineByLine = lineByLine;
7233 is->fd = fileno(stdin);
7235 is->kind = cp->kind;
7236 is->fd = cp->fdFrom;
7239 is->unused = is->buf;
7243 // is->xid = XtAppAddInput(appContext, is->fd,
7244 // (XtPointer) (XtInputReadMask),
7245 // (XtInputCallbackProc) DoInputCallback,
7249 /* TODO: will this work on windows?*/
7250 printf("DEBUG: fd=%d %d\n",is->fd,is);
7252 channel = g_io_channel_unix_new(is->fd);
7253 g_io_channel_set_close_on_unref (channel, TRUE);
7254 is->sid = g_io_add_watch(channel, G_IO_IN,(GIOFunc) DoInputCallback, is);
7255 is->closure = closure;
7256 return (InputSourceRef) is;
7260 RemoveInputSource(isr)
7263 InputSource *is = (InputSource *) isr;
7265 if (is->sid == 0) return;
7266 g_source_remove(is->sid);
7271 int OutputToProcess(pr, message, count, outError)
7277 ChildProc *cp = (ChildProc *) pr;
7281 outCount = fwrite(message, 1, count, stdout);
7283 outCount = write(cp->fdTo, message, count);
7293 /* Output message to process, with "ms" milliseconds of delay
7294 between each character. This is needed when sending the logon
7295 script to ICC, which for some reason doesn't like the
7296 instantaneous send. */
7297 int OutputToProcessDelayed(pr, message, count, outError, msdelay)
7304 ChildProc *cp = (ChildProc *) pr;
7309 r = write(cp->fdTo, message++, 1);
7322 /**** Animation code by Hugh Fisher, DCS, ANU.
7324 Known problem: if a window overlapping the board is
7325 moved away while a piece is being animated underneath,
7326 the newly exposed area won't be updated properly.
7327 I can live with this.
7329 Known problem: if you look carefully at the animation
7330 of pieces in mono mode, they are being drawn as solid
7331 shapes without interior detail while moving. Fixing
7332 this would be a major complication for minimal return.
7335 /* Masks for XPM pieces. Black and white pieces can have
7336 different shapes, but in the interest of retaining my
7337 sanity pieces must have the same outline on both light
7338 and dark squares, and all pieces must use the same
7339 background square colors/images. */
7341 static int xpmDone = 0;
7344 CreateAnimMasks (pieceDepth)
7351 unsigned long plane;
7354 /* just return for gtk at the moment */
7357 /* Need a bitmap just to get a GC with right depth */
7358 buf = XCreatePixmap(xDisplay, xBoardWindow,
7360 values.foreground = 1;
7361 values.background = 0;
7362 /* Don't use XtGetGC, not read only */
7363 maskGC = XCreateGC(xDisplay, buf,
7364 GCForeground | GCBackground, &values);
7365 XFreePixmap(xDisplay, buf);
7367 buf = XCreatePixmap(xDisplay, xBoardWindow,
7368 squareSize, squareSize, pieceDepth);
7369 values.foreground = XBlackPixel(xDisplay, xScreen);
7370 values.background = XWhitePixel(xDisplay, xScreen);
7371 bufGC = XCreateGC(xDisplay, buf,
7372 GCForeground | GCBackground, &values);
7374 for (piece = WhitePawn; piece <= BlackKing; piece++) {
7375 /* Begin with empty mask */
7376 if(!xpmDone) // [HGM] pieces: keep using existing
7377 xpmMask[piece] = XCreatePixmap(xDisplay, xBoardWindow,
7378 squareSize, squareSize, 1);
7379 XSetFunction(xDisplay, maskGC, GXclear);
7380 XFillRectangle(xDisplay, xpmMask[piece], maskGC,
7381 0, 0, squareSize, squareSize);
7383 /* Take a copy of the piece */
7388 XSetFunction(xDisplay, bufGC, GXcopy);
7389 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn],
7391 0, 0, squareSize, squareSize, 0, 0);
7393 /* XOR the background (light) over the piece */
7394 XSetFunction(xDisplay, bufGC, GXxor);
7396 XCopyArea(xDisplay, xpmLightSquare, buf, bufGC,
7397 0, 0, squareSize, squareSize, 0, 0);
7399 XSetForeground(xDisplay, bufGC, lightSquareColor);
7400 XFillRectangle(xDisplay, buf, bufGC, 0, 0, squareSize, squareSize);
7403 /* We now have an inverted piece image with the background
7404 erased. Construct mask by just selecting all the non-zero
7405 pixels - no need to reconstruct the original image. */
7406 XSetFunction(xDisplay, maskGC, GXor);
7408 /* Might be quicker to download an XImage and create bitmap
7409 data from it rather than this N copies per piece, but it
7410 only takes a fraction of a second and there is a much
7411 longer delay for loading the pieces. */
7412 for (n = 0; n < pieceDepth; n ++) {
7413 XCopyPlane(xDisplay, buf, xpmMask[piece], maskGC,
7414 0, 0, squareSize, squareSize,
7420 XFreePixmap(xDisplay, buf);
7421 XFreeGC(xDisplay, bufGC);
7422 XFreeGC(xDisplay, maskGC);
7426 InitAnimState (anim, info)
7428 XWindowAttributes * info;
7433 /* Each buffer is square size, same depth as window */
7434 // anim->saveBuf = XCreatePixmap(xDisplay, xBoardWindow,
7435 // squareSize, squareSize, info->depth);
7436 // anim->newBuf = XCreatePixmap(xDisplay, xBoardWindow,
7437 // squareSize, squareSize, info->depth);
7439 // /* Create a plain GC for blitting */
7440 // mask = GCForeground | GCBackground | GCFunction |
7441 // GCPlaneMask | GCGraphicsExposures;
7442 // values.foreground = XBlackPixel(xDisplay, xScreen);
7443 // values.background = XWhitePixel(xDisplay, xScreen);
7444 // values.function = GXcopy;
7445 // values.plane_mask = AllPlanes;
7446 // values.graphics_exposures = False;
7447 // anim->blitGC = XCreateGC(xDisplay, xBoardWindow, mask, &values);
7449 // /* Piece will be copied from an existing context at
7450 // the start of each new animation/drag. */
7451 // anim->pieceGC = XCreateGC(xDisplay, xBoardWindow, 0, &values);
7453 // /* Outline will be a read-only copy of an existing */
7454 // anim->outlineGC = None;
7460 static VariantClass old = (VariantClass) -1; // [HGM] pieces: redo every time variant changes
7461 XWindowAttributes info;
7463 /* for gtk at the moment just ... */
7466 if (xpmDone && gameInfo.variant == old) return;
7467 if(xpmDone) old = gameInfo.variant; // first time pieces might not be created yet
7468 // XGetWindowAttributes(xDisplay, xBoardWindow, &info);
7470 // InitAnimState(&game, &info);
7471 // InitAnimState(&player, &info);
7473 /* For XPM pieces, we need bitmaps to use as masks. */
7475 // CreateAnimMasks(info.depth);
7481 static Boolean frameWaiting;
7483 static RETSIGTYPE FrameAlarm (sig)
7486 frameWaiting = False;
7487 /* In case System-V style signals. Needed?? */
7488 signal(SIGALRM, FrameAlarm);
7495 struct itimerval delay;
7497 XSync(xDisplay, False);
7500 frameWaiting = True;
7501 signal(SIGALRM, FrameAlarm);
7502 delay.it_interval.tv_sec =
7503 delay.it_value.tv_sec = time / 1000;
7504 delay.it_interval.tv_usec =
7505 delay.it_value.tv_usec = (time % 1000) * 1000;
7506 setitimer(ITIMER_REAL, &delay, NULL);
7508 /* Ugh -- busy-wait! --tpm */
7509 while (frameWaiting);
7511 while (frameWaiting) pause();
7513 delay.it_interval.tv_sec = delay.it_value.tv_sec = 0;
7514 delay.it_interval.tv_usec = delay.it_value.tv_usec = 0;
7515 setitimer(ITIMER_REAL, &delay, NULL);
7525 // XSync(xDisplay, False);
7527 usleep(time * 1000);
7532 /* Convert board position to corner of screen rect and color */
7535 ScreenSquare(column, row, pt, color)
7536 int column; int row; XPoint * pt; int * color;
7539 pt->x = lineGap + ((BOARD_WIDTH-1)-column) * (squareSize + lineGap);
7540 pt->y = lineGap + row * (squareSize + lineGap);
7542 pt->x = lineGap + column * (squareSize + lineGap);
7543 pt->y = lineGap + ((BOARD_HEIGHT-1)-row) * (squareSize + lineGap);
7545 *color = SquareColor(row, column);
7548 /* Convert window coords to square */
7551 BoardSquare(x, y, column, row)
7552 int x; int y; int * column; int * row;
7554 *column = EventToSquare(x, BOARD_WIDTH);
7555 if (flipView && *column >= 0)
7556 *column = BOARD_WIDTH - 1 - *column;
7557 *row = EventToSquare(y, BOARD_HEIGHT);
7558 if (!flipView && *row >= 0)
7559 *row = BOARD_HEIGHT - 1 - *row;
7564 #undef Max /* just in case */
7566 #define Max(a, b) ((a) > (b) ? (a) : (b))
7567 #define Min(a, b) ((a) < (b) ? (a) : (b))
7570 SetRect(rect, x, y, width, height)
7571 XRectangle * rect; int x; int y; int width; int height;
7575 rect->width = width;
7576 rect->height = height;
7579 /* Test if two frames overlap. If they do, return
7580 intersection rect within old and location of
7581 that rect within new. */
7584 Intersect(old, new, size, area, pt)
7585 XPoint * old; XPoint * new;
7586 int size; XRectangle * area; XPoint * pt;
7588 if (old->x > new->x + size || new->x > old->x + size ||
7589 old->y > new->y + size || new->y > old->y + size) {
7592 SetRect(area, Max(new->x - old->x, 0), Max(new->y - old->y, 0),
7593 size - abs(old->x - new->x), size - abs(old->y - new->y));
7594 pt->x = Max(old->x - new->x, 0);
7595 pt->y = Max(old->y - new->y, 0);
7600 /* For two overlapping frames, return the rect(s)
7601 in the old that do not intersect with the new. */
7604 CalcUpdateRects(old, new, size, update, nUpdates)
7605 XPoint * old; XPoint * new; int size;
7606 XRectangle update[]; int * nUpdates;
7610 /* If old = new (shouldn't happen) then nothing to draw */
7611 if (old->x == new->x && old->y == new->y) {
7615 /* Work out what bits overlap. Since we know the rects
7616 are the same size we don't need a full intersect calc. */
7618 /* Top or bottom edge? */
7619 if (new->y > old->y) {
7620 SetRect(&(update[count]), old->x, old->y, size, new->y - old->y);
7622 } else if (old->y > new->y) {
7623 SetRect(&(update[count]), old->x, old->y + size - (old->y - new->y),
7624 size, old->y - new->y);
7627 /* Left or right edge - don't overlap any update calculated above. */
7628 if (new->x > old->x) {
7629 SetRect(&(update[count]), old->x, Max(new->y, old->y),
7630 new->x - old->x, size - abs(new->y - old->y));
7632 } else if (old->x > new->x) {
7633 SetRect(&(update[count]), new->x + size, Max(new->y, old->y),
7634 old->x - new->x, size - abs(new->y - old->y));
7641 /* Generate a series of frame coords from start->mid->finish.
7642 The movement rate doubles until the half way point is
7643 reached, then halves back down to the final destination,
7644 which gives a nice slow in/out effect. The algorithmn
7645 may seem to generate too many intermediates for short
7646 moves, but remember that the purpose is to attract the
7647 viewers attention to the piece about to be moved and
7648 then to where it ends up. Too few frames would be less
7652 Tween(start, mid, finish, factor, frames, nFrames)
7653 XPoint * start; XPoint * mid;
7654 XPoint * finish; int factor;
7655 XPoint frames[]; int * nFrames;
7657 int fraction, n, count;
7661 /* Slow in, stepping 1/16th, then 1/8th, ... */
7663 for (n = 0; n < factor; n++)
7665 for (n = 0; n < factor; n++) {
7666 frames[count].x = start->x + (mid->x - start->x) / fraction;
7667 frames[count].y = start->y + (mid->y - start->y) / fraction;
7669 fraction = fraction / 2;
7673 frames[count] = *mid;
7676 /* Slow out, stepping 1/2, then 1/4, ... */
7678 for (n = 0; n < factor; n++) {
7679 frames[count].x = finish->x - (finish->x - mid->x) / fraction;
7680 frames[count].y = finish->y - (finish->y - mid->y) / fraction;
7682 fraction = fraction * 2;
7687 /* Draw a piece on the screen without disturbing what's there */
7690 SelectGCMask(piece, clip, outline, mask)
7691 ChessSquare piece; GC * clip; GC * outline; Pixmap * mask;
7695 /* Bitmap for piece being moved. */
7696 if (appData.monoMode) {
7697 *mask = *pieceToSolid(piece);
7698 } else if (useImages) {
7700 *mask = xpmMask[piece];
7702 *mask = ximMaskPm[piece];
7705 *mask = *pieceToSolid(piece);
7708 /* GC for piece being moved. Square color doesn't matter, but
7709 since it gets modified we make a copy of the original. */
7711 if (appData.monoMode)
7716 if (appData.monoMode)
7721 // XCopyGC(xDisplay, source, 0xFFFFFFFF, *clip);
7723 /* Outline only used in mono mode and is not modified */
7725 *outline = bwPieceGC;
7727 *outline = wbPieceGC;
7731 OverlayPiece(piece, clip, outline, dest)
7732 ChessSquare piece; GC clip; GC outline; Drawable dest;
7737 /* Draw solid rectangle which will be clipped to shape of piece */
7738 // XFillRectangle(xDisplay, dest, clip,
7739 // 0, 0, squareSize, squareSize)
7741 if (appData.monoMode)
7742 /* Also draw outline in contrasting color for black
7743 on black / white on white cases */
7744 // XCopyPlane(xDisplay, *pieceToOutline(piece), dest, outline,
7745 // 0, 0, squareSize, squareSize, 0, 0, 1)
7748 /* Copy the piece */
7753 // XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
7755 // 0, 0, squareSize, squareSize,
7760 /* Animate the movement of a single piece */
7763 BeginAnimation(anim, piece, startColor, start)
7771 /* The old buffer is initialised with the start square (empty) */
7772 BlankSquare(0, 0, startColor, EmptySquare, anim->saveBuf);
7773 anim->prevFrame = *start;
7775 /* The piece will be drawn using its own bitmap as a matte */
7776 // SelectGCMask(piece, &anim->pieceGC, &anim->outlineGC, &mask);
7777 // XSetClipMask(xDisplay, anim->pieceGC, mask);
7781 AnimationFrame(anim, frame, piece)
7786 XRectangle updates[4];
7791 /* Save what we are about to draw into the new buffer */
7792 // XCopyArea(xDisplay, xBoardWindow, anim->newBuf, anim->blitGC,
7793 // frame->x, frame->y, squareSize, squareSize,
7796 /* Erase bits of the previous frame */
7797 if (Intersect(&anim->prevFrame, frame, squareSize, &overlap, &pt)) {
7798 /* Where the new frame overlapped the previous,
7799 the contents in newBuf are wrong. */
7800 // XCopyArea(xDisplay, anim->saveBuf, anim->newBuf, anim->blitGC,
7801 // overlap.x, overlap.y,
7802 // overlap.width, overlap.height,
7804 /* Repaint the areas in the old that don't overlap new */
7805 CalcUpdateRects(&anim->prevFrame, frame, squareSize, updates, &count);
7806 for (i = 0; i < count; i++)
7807 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
7808 // updates[i].x - anim->prevFrame.x,
7809 // updates[i].y - anim->prevFrame.y,
7810 // updates[i].width, updates[i].height,
7811 // updates[i].x, updates[i].y)
7814 /* Easy when no overlap */
7815 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
7816 // 0, 0, squareSize, squareSize,
7817 // anim->prevFrame.x, anim->prevFrame.y);
7820 /* Save this frame for next time round */
7821 // XCopyArea(xDisplay, anim->newBuf, anim->saveBuf, anim->blitGC,
7822 // 0, 0, squareSize, squareSize,
7824 anim->prevFrame = *frame;
7826 /* Draw piece over original screen contents, not current,
7827 and copy entire rect. Wipes out overlapping piece images. */
7828 OverlayPiece(piece, anim->pieceGC, anim->outlineGC, anim->newBuf);
7829 // XCopyArea(xDisplay, anim->newBuf, xBoardWindow, anim->blitGC,
7830 // 0, 0, squareSize, squareSize,
7831 // frame->x, frame->y);
7835 EndAnimation (anim, finish)
7839 XRectangle updates[4];
7844 /* The main code will redraw the final square, so we
7845 only need to erase the bits that don't overlap. */
7846 if (Intersect(&anim->prevFrame, finish, squareSize, &overlap, &pt)) {
7847 CalcUpdateRects(&anim->prevFrame, finish, squareSize, updates, &count);
7848 for (i = 0; i < count; i++)
7849 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
7850 // updates[i].x - anim->prevFrame.x,
7851 // updates[i].y - anim->prevFrame.y,
7852 // updates[i].width, updates[i].height,
7853 // updates[i].x, updates[i].y)
7856 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
7857 // 0, 0, squareSize, squareSize,
7858 // anim->prevFrame.x, anim->prevFrame.y);
7863 FrameSequence(anim, piece, startColor, start, finish, frames, nFrames)
7865 ChessSquare piece; int startColor;
7866 XPoint * start; XPoint * finish;
7867 XPoint frames[]; int nFrames;
7871 BeginAnimation(anim, piece, startColor, start);
7872 for (n = 0; n < nFrames; n++) {
7873 AnimationFrame(anim, &(frames[n]), piece);
7874 FrameDelay(appData.animSpeed);
7876 EndAnimation(anim, finish);
7879 /* Main control logic for deciding what to animate and how */
7882 AnimateMove(board, fromX, fromY, toX, toY)
7891 XPoint start, finish, mid;
7892 XPoint frames[kFactor * 2 + 1];
7893 int nFrames, startColor, endColor;
7895 /* Are we animating? */
7896 if (!appData.animate || appData.blindfold)
7899 if(board[toY][toX] == WhiteRook && board[fromY][fromX] == WhiteKing ||
7900 board[toY][toX] == BlackRook && board[fromY][fromX] == BlackKing)
7901 return; // [HGM] FRC: no animtion of FRC castlings, as to-square is not true to-square
7903 if (fromY < 0 || fromX < 0 || toX < 0 || toY < 0) return;
7904 piece = board[fromY][fromX];
7905 if (piece >= EmptySquare) return;
7910 hop = (piece == WhiteKnight || piece == BlackKnight);
7913 if (appData.debugMode) {
7914 fprintf(debugFP, hop ? _("AnimateMove: piece %d hops from %d,%d to %d,%d \n") :
7915 _("AnimateMove: piece %d slides from %d,%d to %d,%d \n"),
7916 piece, fromX, fromY, toX, toY); }
7918 ScreenSquare(fromX, fromY, &start, &startColor);
7919 ScreenSquare(toX, toY, &finish, &endColor);
7922 /* Knight: make diagonal movement then straight */
7923 if (abs(toY - fromY) < abs(toX - fromX)) {
7924 mid.x = start.x + (finish.x - start.x) / 2;
7928 mid.y = start.y + (finish.y - start.y) / 2;
7931 mid.x = start.x + (finish.x - start.x) / 2;
7932 mid.y = start.y + (finish.y - start.y) / 2;
7935 /* Don't use as many frames for very short moves */
7936 if (abs(toY - fromY) + abs(toX - fromX) <= 2)
7937 Tween(&start, &mid, &finish, kFactor - 1, frames, &nFrames);
7939 Tween(&start, &mid, &finish, kFactor, frames, &nFrames);
7940 FrameSequence(&game, piece, startColor, &start, &finish, frames, nFrames);
7942 /* Be sure end square is redrawn */
7943 damage[toY][toX] = True;
7947 DragPieceBegin(x, y)
7950 int boardX, boardY, color;
7953 /* Are we animating? */
7954 if (!appData.animateDragging || appData.blindfold)
7957 /* Figure out which square we start in and the
7958 mouse position relative to top left corner. */
7959 BoardSquare(x, y, &boardX, &boardY);
7960 player.startBoardX = boardX;
7961 player.startBoardY = boardY;
7962 ScreenSquare(boardX, boardY, &corner, &color);
7963 player.startSquare = corner;
7964 player.startColor = color;
7966 /* Start from exactly where the piece is. This can be confusing
7967 if you start dragging far from the center of the square; most
7968 or all of the piece can be over a different square from the one
7969 the mouse pointer is in. */
7970 player.mouseDelta.x = x - corner.x;
7971 player.mouseDelta.y = y - corner.y;
7973 /* As soon as we start dragging, the piece will jump slightly to
7974 be centered over the mouse pointer. */
7975 player.mouseDelta.x = squareSize/2;
7976 player.mouseDelta.y = squareSize/2;
7978 /* Initialise animation */
7979 player.dragPiece = PieceForSquare(boardX, boardY);
7981 if (player.dragPiece >= 0 && player.dragPiece < EmptySquare) {
7982 player.dragActive = True;
7983 BeginAnimation(&player, player.dragPiece, color, &corner);
7984 /* Mark this square as needing to be redrawn. Note that
7985 we don't remove the piece though, since logically (ie
7986 as seen by opponent) the move hasn't been made yet. */
7987 if(boardX == BOARD_RGHT+1 && PieceForSquare(boardX-1, boardY) > 1 ||
7988 boardX == BOARD_LEFT-2 && PieceForSquare(boardX+1, boardY) > 1)
7989 // XCopyArea(xDisplay, xBoardWindow, player.saveBuf, player.blitGC,
7990 // corner.x, corner.y, squareSize, squareSize,
7991 // 0, 0); // [HGM] zh: unstack in stead of grab
7992 damage[boardY][boardX] = True;
7994 player.dragActive = False;
8004 /* Are we animating? */
8005 if (!appData.animateDragging || appData.blindfold)
8009 if (! player.dragActive)
8011 /* Move piece, maintaining same relative position
8012 of mouse within square */
8013 corner.x = x - player.mouseDelta.x;
8014 corner.y = y - player.mouseDelta.y;
8015 AnimationFrame(&player, &corner, player.dragPiece);
8017 if (appData.highlightDragging) {
8019 BoardSquare(x, y, &boardX, &boardY);
8020 SetHighlights(fromX, fromY, boardX, boardY);
8029 int boardX, boardY, color;
8032 /* Are we animating? */
8033 if (!appData.animateDragging || appData.blindfold)
8037 if (! player.dragActive)
8039 /* Last frame in sequence is square piece is
8040 placed on, which may not match mouse exactly. */
8041 BoardSquare(x, y, &boardX, &boardY);
8042 ScreenSquare(boardX, boardY, &corner, &color);
8043 EndAnimation(&player, &corner);
8045 /* Be sure end square is redrawn */
8046 damage[boardY][boardX] = True;
8048 /* This prevents weird things happening with fast successive
8049 clicks which on my Sun at least can cause motion events
8050 without corresponding press/release. */
8051 player.dragActive = False;
8054 /* Handle expose event while piece being dragged */
8059 if (!player.dragActive || appData.blindfold)
8062 /* What we're doing: logically, the move hasn't been made yet,
8063 so the piece is still in it's original square. But visually
8064 it's being dragged around the board. So we erase the square
8065 that the piece is on and draw it at the last known drag point. */
8066 BlankSquare(player.startSquare.x, player.startSquare.y,
8067 player.startColor, EmptySquare, xBoardWindow);
8068 AnimationFrame(&player, &player.prevFrame, player.dragPiece);
8069 damage[player.startBoardY][player.startBoardX] = TRUE;
8073 SetProgramStats( FrontEndProgramStats * stats )
8076 // [HGM] done, but perhaps backend should call this directly?
8077 EngineOutputUpdate( stats );