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 CopyPositionProc P((Widget w, XEvent *event, String *prms,
300 void PastePositionProc P((Widget w, XEvent *event, String *prms,
302 void CopyGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
303 void PasteGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
304 void SaveGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
305 void SavePositionProc P((Widget w, XEvent *event,
306 String *prms, Cardinal *nprms));
307 void MailMoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
308 void ReloadCmailMsgProc P((Widget w, XEvent *event, String *prms,
310 void AnalyzeModeProc P((Widget w, XEvent *event,
311 String *prms, Cardinal *nprms));
312 void AnalyzeFileProc P((Widget w, XEvent *event,
313 String *prms, Cardinal *nprms));
314 void EditGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
315 void EditPositionProc P((Widget w, XEvent *event,
316 String *prms, Cardinal *nprms));
317 void TrainingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
318 void EditCommentProc P((Widget w, XEvent *event,
319 String *prms, Cardinal *nprms));
320 void IcsInputBoxProc P((Widget w, XEvent *event,
321 String *prms, Cardinal *nprms));
322 void EnterKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
323 void AlwaysQueenProc P((Widget w, XEvent *event, String *prms,
325 void AnimateDraggingProc P((Widget w, XEvent *event, String *prms,
327 void AnimateMovingProc P((Widget w, XEvent *event, String *prms,
329 void AutocommProc P((Widget w, XEvent *event, String *prms,
331 void AutoflagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
332 void AutoflipProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
333 void AutobsProc P((Widget w, XEvent *event, String *prms,
335 void AutoraiseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
336 void AutosaveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
337 void BlindfoldProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
338 void FlashMovesProc P((Widget w, XEvent *event, String *prms,
340 void HighlightDraggingProc P((Widget w, XEvent *event, String *prms,
342 void HighlightLastMoveProc P((Widget w, XEvent *event, String *prms,
344 void MoveSoundProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
345 void IcsAlarmProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
346 void OldSaveStyleProc P((Widget w, XEvent *event, String *prms,
348 void PeriodicUpdatesProc P((Widget w, XEvent *event, String *prms,
350 void PonderNextMoveProc P((Widget w, XEvent *event, String *prms,
352 void PopupMoveErrorsProc P((Widget w, XEvent *event, String *prms,
354 void PopupExitMessageProc P((Widget w, XEvent *event, String *prms,
356 void PremoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
357 void QuietPlayProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
358 void TestLegalityProc P((Widget w, XEvent *event, String *prms,
360 void AboutGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
361 void DebugProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
362 void NothingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
363 void Iconify P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
364 void DisplayMove P((int moveNumber));
365 void DisplayTitle P((char *title));
366 void ICSInitScript P((void));
367 int LoadGamePopUp P((FILE *f, int gameNumber, char *title));
368 void ErrorPopUp P((char *title, char *text, int modal));
369 void ErrorPopDown P((void));
370 static char *ExpandPathName P((char *path));
371 static void CreateAnimVars P((void));
372 void DragPieceBegin P((int x, int y));
373 static void DragPieceMove P((int x, int y));
374 void DragPieceEnd P((int x, int y));
375 static void DrawDragPiece P((void));
376 char *ModeToWidgetName P((GameMode mode));
377 void EngineOutputUpdate( FrontEndProgramStats * stats );
378 void ShuffleMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
379 void EngineMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
380 void UciMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
381 void TimeControlProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
382 void NewVariantProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
383 void FirstSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
384 void SecondSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
385 void ShufflePopDown P(());
386 void EnginePopDown P(());
387 void UciPopDown P(());
388 void TimeControlPopDown P(());
389 void NewVariantPopDown P(());
390 void SettingsPopDown P(());
391 void SetMenuEnables P((Enables *enab));
394 * XBoard depends on Xt R4 or higher
396 int xtVersion = XtSpecificationRelease;
401 Pixel lightSquareColor, darkSquareColor, whitePieceColor, blackPieceColor,
402 jailSquareColor, highlightSquareColor, premoveHighlightColor;
403 Pixel lowTimeWarningColor;
405 #define LINE_TYPE_NORMAL 0
406 #define LINE_TYPE_HIGHLIGHT 1
407 #define LINE_TYPE_PRE 2
410 GC lightSquareGC, darkSquareGC, jailSquareGC, wdPieceGC, wlPieceGC,
411 bdPieceGC, blPieceGC, wbPieceGC, bwPieceGC, coordGC,
412 wjPieceGC, bjPieceGC;
413 Pixmap iconPixmap, wIconPixmap, bIconPixmap, xMarkPixmap;
414 Widget shellWidget, layoutWidget, formWidget, boardWidget, messageWidget,
415 whiteTimerWidget, blackTimerWidget, titleWidget, widgetList[16],
416 commentShell, promotionShell, whitePieceMenu, blackPieceMenu, dropMenu,
417 menuBarWidget, buttonBarWidget, editShell, errorShell, analysisShell,
418 ICSInputShell, fileNameShell, askQuestionShell;
419 Font clockFontID, coordFontID, countFontID;
420 XFontStruct *clockFontStruct, *coordFontStruct, *countFontStruct;
421 XtAppContext appContext;
423 char *oldICSInteractionTitle;
427 char installDir[] = "."; // [HGM] UCI: needed for UCI; probably needs run-time initializtion
429 Position commentX = -1, commentY = -1;
430 Dimension commentW, commentH;
432 int squareSize, smallLayout = 0, tinyLayout = 0,
433 marginW, marginH, // [HGM] for run-time resizing
434 fromX = -1, fromY = -1, toX, toY, commentUp = False, analysisUp = False,
435 ICSInputBoxUp = False, askQuestionUp = False,
436 filenameUp = False, promotionUp = False, pmFromX = -1, pmFromY = -1,
437 editUp = False, errorUp = False, errorExitStatus = -1, lineGap;
438 Pixel timerForegroundPixel, timerBackgroundPixel;
439 Pixel buttonForegroundPixel, buttonBackgroundPixel;
440 char *chessDir, *programName, *programVersion,
441 *gameCopyFilename, *gamePasteFilename;
445 Pixmap pieceBitmap[2][(int)BlackPawn];
446 Pixmap pieceBitmap2[2][(int)BlackPawn+4]; /* [HGM] pieces */
447 Pixmap xpmPieceBitmap[4][(int)BlackPawn]; /* LL, LD, DL, DD actually used*/
448 Pixmap xpmPieceBitmap2[4][(int)BlackPawn+4]; /* LL, LD, DL, DD set to select from */
449 Pixmap xpmLightSquare, xpmDarkSquare, xpmJailSquare;
450 int useImages=0, useImageSqs;
451 XImage *ximPieceBitmap[4][(int)BlackPawn+4]; /* LL, LD, DL, DD */
452 Pixmap ximMaskPm[(int)BlackPawn]; /* clipmasks, used for XIM pieces */
453 Pixmap ximMaskPm2[(int)BlackPawn+4]; /* clipmasks, used for XIM pieces */
454 XImage *ximLightSquare, *ximDarkSquare;
457 #define pieceToSolid(piece) &pieceBitmap[SOLID][(piece) % (int)BlackPawn]
458 #define pieceToOutline(piece) &pieceBitmap[OUTLINE][(piece) % (int)BlackPawn]
460 #define White(piece) ((int)(piece) < (int)BlackPawn)
462 /* Variables for doing smooth animation. This whole thing
463 would be much easier if the board was double-buffered,
464 but that would require a fairly major rewrite. */
469 GC blitGC, pieceGC, outlineGC;
470 XPoint startSquare, prevFrame, mouseDelta;
474 int startBoardX, startBoardY;
477 /* There can be two pieces being animated at once: a player
478 can begin dragging a piece before the remote opponent has moved. */
480 static AnimState game, player;
482 /* Bitmaps for use as masks when drawing XPM pieces.
483 Need one for each black and white piece. */
484 static Pixmap xpmMask[BlackKing + 1];
486 /* This magic number is the number of intermediate frames used
487 in each half of the animation. For short moves it's reduced
488 by 1. The total number of frames will be factor * 2 + 1. */
491 SizeDefaults sizeDefaults[] = SIZE_DEFAULTS;
493 Enables icsEnables[] = {
494 { "menuFile.Mail Move", False },
495 { "menuFile.Reload CMail Message", False },
496 { "menuMode.Machine Black", False },
497 { "menuMode.Machine White", False },
498 { "menuMode.Analysis Mode", False },
499 { "menuMode.Analyze File", False },
500 { "menuMode.Two Machines", False },
502 { "menuHelp.Hint", False },
503 { "menuHelp.Book", False },
504 { "menuStep.Move Now", False },
505 { "menuOptions.Periodic Updates", False },
506 { "menuOptions.Hide Thinking", False },
507 { "menuOptions.Ponder Next Move", False },
512 Enables ncpEnables[] = {
513 { "menuFile.Mail Move", False },
514 { "menuFile.Reload CMail Message", False },
515 { "menuMode.Machine White", False },
516 { "menuMode.Machine Black", False },
517 { "menuMode.Analysis Mode", False },
518 { "menuMode.Analyze File", False },
519 { "menuMode.Two Machines", False },
520 { "menuMode.ICS Client", False },
521 { "menuMode.ICS Input Box", False },
523 { "menuStep.Revert", False },
524 { "menuStep.Move Now", False },
525 { "menuStep.Retract Move", False },
526 { "menuOptions.Auto Comment", False },
527 { "menuOptions.Auto Flag", False },
528 { "menuOptions.Auto Flip View", False },
529 { "menuOptions.Auto Observe", False },
530 { "menuOptions.Auto Raise Board", False },
531 { "menuOptions.Get Move List", False },
532 { "menuOptions.ICS Alarm", False },
533 { "menuOptions.Move Sound", False },
534 { "menuOptions.Quiet Play", False },
535 { "menuOptions.Hide Thinking", False },
536 { "menuOptions.Periodic Updates", False },
537 { "menuOptions.Ponder Next Move", False },
538 { "menuHelp.Hint", False },
539 { "menuHelp.Book", False },
543 Enables gnuEnables[] = {
544 { "menuMode.ICS Client", False },
545 { "menuMode.ICS Input Box", False },
546 { "menuAction.Accept", False },
547 { "menuAction.Decline", False },
548 { "menuAction.Rematch", False },
549 { "menuAction.Adjourn", False },
550 { "menuAction.Stop Examining", False },
551 { "menuAction.Stop Observing", False },
552 { "menuStep.Revert", False },
553 { "menuOptions.Auto Comment", False },
554 { "menuOptions.Auto Observe", False },
555 { "menuOptions.Auto Raise Board", False },
556 { "menuOptions.Get Move List", False },
557 { "menuOptions.Premove", False },
558 { "menuOptions.Quiet Play", False },
560 /* The next two options rely on SetCmailMode being called *after* */
561 /* SetGNUMode so that when GNU is being used to give hints these */
562 /* menu options are still available */
564 { "menuFile.Mail Move", False },
565 { "menuFile.Reload CMail Message", False },
569 Enables cmailEnables[] = {
571 { "menuAction.Call Flag", False },
572 { "menuAction.Draw", True },
573 { "menuAction.Adjourn", False },
574 { "menuAction.Abort", False },
575 { "menuAction.Stop Observing", False },
576 { "menuAction.Stop Examining", False },
577 { "menuFile.Mail Move", True },
578 { "menuFile.Reload CMail Message", True },
582 Enables trainingOnEnables[] = {
583 { "menuMode.Edit Comment", False },
584 { "menuMode.Pause", False },
585 { "menuStep.Forward", False },
586 { "menuStep.Backward", False },
587 { "menuStep.Forward to End", False },
588 { "menuStep.Back to Start", False },
589 { "menuStep.Move Now", False },
590 { "menuStep.Truncate Game", False },
594 Enables trainingOffEnables[] = {
595 { "menuMode.Edit Comment", True },
596 { "menuMode.Pause", True },
597 { "menuStep.Forward", True },
598 { "menuStep.Backward", True },
599 { "menuStep.Forward to End", True },
600 { "menuStep.Back to Start", True },
601 { "menuStep.Move Now", True },
602 { "menuStep.Truncate Game", True },
606 Enables machineThinkingEnables[] = {
607 { "menuFile.Load Game", False },
608 { "menuFile.Load Next Game", False },
609 { "menuFile.Load Previous Game", False },
610 { "menuFile.Reload Same Game", False },
611 { "menuFile.Paste Game", False },
612 { "menuFile.Load Position", False },
613 { "menuFile.Load Next Position", False },
614 { "menuFile.Load Previous Position", False },
615 { "menuFile.Reload Same Position", False },
616 { "menuFile.Paste Position", False },
617 { "menuMode.Machine White", False },
618 { "menuMode.Machine Black", False },
619 { "menuMode.Two Machines", False },
620 { "menuStep.Retract Move", False },
624 Enables userThinkingEnables[] = {
625 { "menuFile.Load Game", True },
626 { "menuFile.Load Next Game", True },
627 { "menuFile.Load Previous Game", True },
628 { "menuFile.Reload Same Game", True },
629 { "menuFile.Paste Game", True },
630 { "menuFile.Load Position", True },
631 { "menuFile.Load Next Position", True },
632 { "menuFile.Load Previous Position", True },
633 { "menuFile.Reload Same Position", True },
634 { "menuFile.Paste Position", True },
635 { "menuMode.Machine White", True },
636 { "menuMode.Machine Black", True },
637 { "menuMode.Two Machines", True },
638 { "menuStep.Retract Move", True },
644 MenuItem fileMenu[] = {
645 {N_("New Shuffle Game ..."), ShuffleMenuProc},
646 {N_("New Variant ..."), NewVariantProc}, // [HGM] variant: not functional yet
647 {"----", NothingProc},
648 {N_("Save Game"), SaveGameProc},
649 {"----", NothingProc},
650 {N_("Copy Game"), CopyGameProc},
651 {N_("Paste Game"), PasteGameProc},
652 {"----", NothingProc},
653 {N_("Load Position"), LoadPositionProc},
654 // {N_("Load Next Position"), LoadNextPositionProc},
655 // {N_("Load Previous Position"), LoadPrevPositionProc},
656 // {N_("Reload Same Position"), ReloadPositionProc},
657 {N_("Save Position"), SavePositionProc},
658 {"----", NothingProc},
659 {N_("Copy Position"), CopyPositionProc},
660 {N_("Paste Position"), PastePositionProc},
661 {"----", NothingProc},
662 {N_("Mail Move"), MailMoveProc},
663 {N_("Reload CMail Message"), ReloadCmailMsgProc},
664 {"----", NothingProc},
668 MenuItem modeMenu[] = {
669 // {N_("Machine White"), MachineWhiteProc},
670 // {N_("Machine Black"), MachineBlackProc},
671 // {N_("Two Machines"), TwoMachinesProc},
672 {N_("Analysis Mode"), AnalyzeModeProc},
673 {N_("Analyze File"), AnalyzeFileProc },
674 // {N_("ICS Client"), IcsClientProc},
675 {N_("Edit Game"), EditGameProc},
676 {N_("Edit Position"), EditPositionProc},
677 {N_("Training"), TrainingProc},
678 {"----", NothingProc},
679 {N_("Show Engine Output"), EngineOutputProc},
680 {N_("Show Evaluation Graph"), NothingProc}, // [HGM] evalgr: not functional yet
681 {N_("Show Game List"), ShowGameListProc},
682 // {"Show Move History", HistoryShowProc}, // [HGM] hist: activate 4.2.7 code
683 {"----", NothingProc},
684 {N_("Edit Tags"), EditTagsProc},
685 {N_("Edit Comment"), EditCommentProc},
686 {N_("ICS Input Box"), IcsInputBoxProc},
690 MenuItem optionsMenu[] = {
691 // {N_("Flip View"), FlipViewProc},
692 // {"----", NothingProc},
693 {N_("Adjudications ..."), EngineMenuProc},
694 {N_("General Settings ..."), UciMenuProc},
695 {N_("Engine #1 Settings ..."), FirstSettingsProc},
696 {N_("Engine #2 Settings ..."), SecondSettingsProc},
697 {N_("Time Control ..."), TimeControlProc},
698 {"----", NothingProc},
699 {N_("Always Queen"), AlwaysQueenProc},
700 {N_("Animate Dragging"), AnimateDraggingProc},
701 {N_("Animate Moving"), AnimateMovingProc},
702 {N_("Auto Comment"), AutocommProc},
703 {N_("Auto Flag"), AutoflagProc},
704 {N_("Auto Flip View"), AutoflipProc},
705 {N_("Auto Observe"), AutobsProc},
706 {N_("Auto Raise Board"), AutoraiseProc},
707 {N_("Auto Save"), AutosaveProc},
708 {N_("Blindfold"), BlindfoldProc},
709 {N_("Flash Moves"), FlashMovesProc},
710 // {N_("Get Move List"), GetMoveListProc},
712 {N_("Highlight Dragging"), HighlightDraggingProc},
714 {N_("Highlight Last Move"), HighlightLastMoveProc},
715 {N_("Move Sound"), MoveSoundProc},
716 {N_("ICS Alarm"), IcsAlarmProc},
717 {N_("Old Save Style"), OldSaveStyleProc},
718 {N_("Periodic Updates"), PeriodicUpdatesProc},
719 {N_("Ponder Next Move"), PonderNextMoveProc},
720 {N_("Popup Exit Message"), PopupExitMessageProc},
721 {N_("Popup Move Errors"), PopupMoveErrorsProc},
722 {N_("Premove"), PremoveProc},
723 {N_("Quiet Play"), QuietPlayProc},
724 // {N_("Hide Thinking"), HideThinkingProc},
725 {N_("Test Legality"), TestLegalityProc},
730 {N_("File"), fileMenu},
731 {N_("Mode"), modeMenu},
732 {N_("Options"), optionsMenu},
736 #define PAUSE_BUTTON N_("P")
737 MenuItem buttonBar[] = {
738 // {"<<", ToStartProc},
739 // {"<", BackwardProc},
740 // {PAUSE_BUTTON, PauseProc},
741 // {">", ForwardProc},
742 // {">>", ToEndProc},
746 #define PIECE_MENU_SIZE 18
747 String pieceMenuStrings[2][PIECE_MENU_SIZE] = {
748 { N_("White"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
749 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
750 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
751 N_("Empty square"), N_("Clear board") },
752 { N_("Black"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
753 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
754 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
755 N_("Empty square"), N_("Clear board") }
757 /* must be in same order as PieceMenuStrings! */
758 ChessSquare pieceMenuTranslation[2][PIECE_MENU_SIZE] = {
759 { WhitePlay, (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
760 WhiteRook, WhiteQueen, WhiteKing, (ChessSquare) 0, WhiteAlfil,
761 WhiteCannon, WhiteAngel, WhiteMarshall, (ChessSquare) 0,
762 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
763 { BlackPlay, (ChessSquare) 0, BlackPawn, BlackKnight, BlackBishop,
764 BlackRook, BlackQueen, BlackKing, (ChessSquare) 0, BlackAlfil,
765 BlackCannon, BlackAngel, BlackMarshall, (ChessSquare) 0,
766 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
769 #define DROP_MENU_SIZE 6
770 String dropMenuStrings[DROP_MENU_SIZE] = {
771 "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"), N_("Queen")
773 /* must be in same order as PieceMenuStrings! */
774 ChessSquare dropMenuTranslation[DROP_MENU_SIZE] = {
775 (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
776 WhiteRook, WhiteQueen
784 DropMenuEnables dmEnables[] = {
793 { XtNborderWidth, 0 },
794 { XtNdefaultDistance, 0 },
798 { XtNborderWidth, 0 },
799 { XtNresizable, (XtArgVal) True },
803 { XtNborderWidth, 0 },
808 XtResource clientResources[] = {
809 { "whitePieceColor", "whitePieceColor", XtRString, sizeof(String),
810 XtOffset(AppDataPtr, whitePieceColor), XtRString,
812 { "blackPieceColor", "blackPieceColor", XtRString, sizeof(String),
813 XtOffset(AppDataPtr, blackPieceColor), XtRString,
815 { "lightSquareColor", "lightSquareColor", XtRString,
816 sizeof(String), XtOffset(AppDataPtr, lightSquareColor),
817 XtRString, LIGHT_SQUARE_COLOR },
818 { "darkSquareColor", "darkSquareColor", XtRString, sizeof(String),
819 XtOffset(AppDataPtr, darkSquareColor), XtRString,
821 { "highlightSquareColor", "highlightSquareColor", XtRString,
822 sizeof(String), XtOffset(AppDataPtr, highlightSquareColor),
823 XtRString, HIGHLIGHT_SQUARE_COLOR },
824 { "premoveHighlightColor", "premoveHighlightColor", XtRString,
825 sizeof(String), XtOffset(AppDataPtr, premoveHighlightColor),
826 XtRString, PREMOVE_HIGHLIGHT_COLOR },
827 { "movesPerSession", "movesPerSession", XtRInt, sizeof(int),
828 XtOffset(AppDataPtr, movesPerSession), XtRImmediate,
829 (XtPointer) MOVES_PER_SESSION },
830 { "timeIncrement", "timeIncrement", XtRInt, sizeof(int),
831 XtOffset(AppDataPtr, timeIncrement), XtRImmediate,
832 (XtPointer) TIME_INCREMENT },
833 { "initString", "initString", XtRString, sizeof(String),
834 XtOffset(AppDataPtr, initString), XtRString, INIT_STRING },
835 { "secondInitString", "secondInitString", XtRString, sizeof(String),
836 XtOffset(AppDataPtr, secondInitString), XtRString, INIT_STRING },
837 { "firstComputerString", "firstComputerString", XtRString,
838 sizeof(String), XtOffset(AppDataPtr, firstComputerString), XtRString,
840 { "secondComputerString", "secondComputerString", XtRString,
841 sizeof(String), XtOffset(AppDataPtr, secondComputerString), XtRString,
843 { "firstChessProgram", "firstChessProgram", XtRString,
844 sizeof(String), XtOffset(AppDataPtr, firstChessProgram),
845 XtRString, FIRST_CHESS_PROGRAM },
846 { "secondChessProgram", "secondChessProgram", XtRString,
847 sizeof(String), XtOffset(AppDataPtr, secondChessProgram),
848 XtRString, SECOND_CHESS_PROGRAM },
849 { "firstPlaysBlack", "firstPlaysBlack", XtRBoolean,
850 sizeof(Boolean), XtOffset(AppDataPtr, firstPlaysBlack),
851 XtRImmediate, (XtPointer) False },
852 { "noChessProgram", "noChessProgram", XtRBoolean,
853 sizeof(Boolean), XtOffset(AppDataPtr, noChessProgram),
854 XtRImmediate, (XtPointer) False },
855 { "firstHost", "firstHost", XtRString, sizeof(String),
856 XtOffset(AppDataPtr, firstHost), XtRString, FIRST_HOST },
857 { "secondHost", "secondHost", XtRString, sizeof(String),
858 XtOffset(AppDataPtr, secondHost), XtRString, SECOND_HOST },
859 { "firstDirectory", "firstDirectory", XtRString, sizeof(String),
860 XtOffset(AppDataPtr, firstDirectory), XtRString, "." },
861 { "secondDirectory", "secondDirectory", XtRString, sizeof(String),
862 XtOffset(AppDataPtr, secondDirectory), XtRString, "." },
863 { "bitmapDirectory", "bitmapDirectory", XtRString,
864 sizeof(String), XtOffset(AppDataPtr, bitmapDirectory),
866 { "remoteShell", "remoteShell", XtRString, sizeof(String),
867 XtOffset(AppDataPtr, remoteShell), XtRString, REMOTE_SHELL },
868 { "remoteUser", "remoteUser", XtRString, sizeof(String),
869 XtOffset(AppDataPtr, remoteUser), XtRString, "" },
870 { "timeDelay", "timeDelay", XtRFloat, sizeof(float),
871 XtOffset(AppDataPtr, timeDelay), XtRString,
872 (XtPointer) TIME_DELAY_QUOTE },
873 { "timeControl", "timeControl", XtRString, sizeof(String),
874 XtOffset(AppDataPtr, timeControl), XtRString,
875 (XtPointer) TIME_CONTROL },
876 { "internetChessServerMode", "internetChessServerMode",
877 XtRBoolean, sizeof(Boolean),
878 XtOffset(AppDataPtr, icsActive), XtRImmediate,
880 { "internetChessServerHost", "internetChessServerHost",
881 XtRString, sizeof(String),
882 XtOffset(AppDataPtr, icsHost),
883 XtRString, (XtPointer) ICS_HOST },
884 { "internetChessServerPort", "internetChessServerPort",
885 XtRString, sizeof(String),
886 XtOffset(AppDataPtr, icsPort), XtRString,
887 (XtPointer) ICS_PORT },
888 { "internetChessServerCommPort", "internetChessServerCommPort",
889 XtRString, sizeof(String),
890 XtOffset(AppDataPtr, icsCommPort), XtRString,
892 { "internetChessServerLogonScript", "internetChessServerLogonScript",
893 XtRString, sizeof(String),
894 XtOffset(AppDataPtr, icsLogon), XtRString,
896 { "internetChessServerHelper", "internetChessServerHelper",
897 XtRString, sizeof(String),
898 XtOffset(AppDataPtr, icsHelper), XtRString, "" },
899 { "internetChessServerInputBox", "internetChessServerInputBox",
900 XtRBoolean, sizeof(Boolean),
901 XtOffset(AppDataPtr, icsInputBox), XtRImmediate,
903 { "icsAlarm", "icsAlarm",
904 XtRBoolean, sizeof(Boolean),
905 XtOffset(AppDataPtr, icsAlarm), XtRImmediate,
907 { "icsAlarmTime", "icsAlarmTime",
909 XtOffset(AppDataPtr, icsAlarmTime), XtRImmediate,
911 { "useTelnet", "useTelnet", XtRBoolean, sizeof(Boolean),
912 XtOffset(AppDataPtr, useTelnet), XtRImmediate,
914 { "telnetProgram", "telnetProgram", XtRString, sizeof(String),
915 XtOffset(AppDataPtr, telnetProgram), XtRString, TELNET_PROGRAM },
916 { "gateway", "gateway", XtRString, sizeof(String),
917 XtOffset(AppDataPtr, gateway), XtRString, "" },
918 { "loadGameFile", "loadGameFile", XtRString, sizeof(String),
919 XtOffset(AppDataPtr, loadGameFile), XtRString, "" },
920 { "loadGameIndex", "loadGameIndex",
922 XtOffset(AppDataPtr, loadGameIndex), XtRImmediate,
924 { "saveGameFile", "saveGameFile", XtRString, sizeof(String),
925 XtOffset(AppDataPtr, saveGameFile), XtRString, "" },
926 { "autoRaiseBoard", "autoRaiseBoard", XtRBoolean,
927 sizeof(Boolean), XtOffset(AppDataPtr, autoRaiseBoard),
928 XtRImmediate, (XtPointer) True },
929 { "autoSaveGames", "autoSaveGames", XtRBoolean,
930 sizeof(Boolean), XtOffset(AppDataPtr, autoSaveGames),
931 XtRImmediate, (XtPointer) False },
932 { "blindfold", "blindfold", XtRBoolean,
933 sizeof(Boolean), XtOffset(AppDataPtr, blindfold),
934 XtRImmediate, (XtPointer) False },
935 { "loadPositionFile", "loadPositionFile", XtRString,
936 sizeof(String), XtOffset(AppDataPtr, loadPositionFile),
938 { "loadPositionIndex", "loadPositionIndex",
940 XtOffset(AppDataPtr, loadPositionIndex), XtRImmediate,
942 { "savePositionFile", "savePositionFile", XtRString,
943 sizeof(String), XtOffset(AppDataPtr, savePositionFile),
945 { "matchMode", "matchMode", XtRBoolean, sizeof(Boolean),
946 XtOffset(AppDataPtr, matchMode), XtRImmediate, (XtPointer) False },
947 { "matchGames", "matchGames", XtRInt, sizeof(int),
948 XtOffset(AppDataPtr, matchGames), XtRImmediate,
950 { "monoMode", "monoMode", XtRBoolean, sizeof(Boolean),
951 XtOffset(AppDataPtr, monoMode), XtRImmediate,
953 { "debugMode", "debugMode", XtRBoolean, sizeof(Boolean),
954 XtOffset(AppDataPtr, debugMode), XtRImmediate,
956 { "clockMode", "clockMode", XtRBoolean, sizeof(Boolean),
957 XtOffset(AppDataPtr, clockMode), XtRImmediate,
959 { "boardSize", "boardSize", XtRString, sizeof(String),
960 XtOffset(AppDataPtr, boardSize), XtRString, "" },
961 { "searchTime", "searchTime", XtRString, sizeof(String),
962 XtOffset(AppDataPtr, searchTime), XtRString,
964 { "searchDepth", "searchDepth", XtRInt, sizeof(int),
965 XtOffset(AppDataPtr, searchDepth), XtRImmediate,
967 { "showCoords", "showCoords", XtRBoolean, sizeof(Boolean),
968 XtOffset(AppDataPtr, showCoords), XtRImmediate,
970 { "showJail", "showJail", XtRInt, sizeof(int),
971 XtOffset(AppDataPtr, showJail), XtRImmediate,
973 { "showThinking", "showThinking", XtRBoolean, sizeof(Boolean),
974 XtOffset(AppDataPtr, showThinking), XtRImmediate,
976 { "ponderNextMove", "ponderNextMove", XtRBoolean, sizeof(Boolean),
977 XtOffset(AppDataPtr, ponderNextMove), XtRImmediate,
979 { "periodicUpdates", "periodicUpdates", XtRBoolean, sizeof(Boolean),
980 XtOffset(AppDataPtr, periodicUpdates), XtRImmediate,
982 { "clockFont", "clockFont", XtRString, sizeof(String),
983 XtOffset(AppDataPtr, clockFont), XtRString, CLOCK_FONT },
984 { "coordFont", "coordFont", XtRString, sizeof(String),
985 XtOffset(AppDataPtr, coordFont), XtRString, COORD_FONT },
986 { "font", "font", XtRString, sizeof(String),
987 XtOffset(AppDataPtr, font), XtRString, DEFAULT_FONT },
988 { "ringBellAfterMoves", "ringBellAfterMoves",
989 XtRBoolean, sizeof(Boolean),
990 XtOffset(AppDataPtr, ringBellAfterMoves),
991 XtRImmediate, (XtPointer) False },
992 { "autoCallFlag", "autoCallFlag", XtRBoolean,
993 sizeof(Boolean), XtOffset(AppDataPtr, autoCallFlag),
994 XtRImmediate, (XtPointer) False },
995 { "autoFlipView", "autoFlipView", XtRBoolean,
996 sizeof(Boolean), XtOffset(AppDataPtr, autoFlipView),
997 XtRImmediate, (XtPointer) True },
998 { "autoObserve", "autoObserve", XtRBoolean,
999 sizeof(Boolean), XtOffset(AppDataPtr, autoObserve),
1000 XtRImmediate, (XtPointer) False },
1001 { "autoComment", "autoComment", XtRBoolean,
1002 sizeof(Boolean), XtOffset(AppDataPtr, autoComment),
1003 XtRImmediate, (XtPointer) False },
1004 { "getMoveList", "getMoveList", XtRBoolean,
1005 sizeof(Boolean), XtOffset(AppDataPtr, getMoveList),
1006 XtRImmediate, (XtPointer) True },
1008 { "highlightDragging", "highlightDragging", XtRBoolean,
1009 sizeof(Boolean), XtOffset(AppDataPtr, highlightDragging),
1010 XtRImmediate, (XtPointer) False },
1012 { "highlightLastMove", "highlightLastMove", XtRBoolean,
1013 sizeof(Boolean), XtOffset(AppDataPtr, highlightLastMove),
1014 XtRImmediate, (XtPointer) False },
1015 { "premove", "premove", XtRBoolean,
1016 sizeof(Boolean), XtOffset(AppDataPtr, premove),
1017 XtRImmediate, (XtPointer) True },
1018 { "testLegality", "testLegality", XtRBoolean,
1019 sizeof(Boolean), XtOffset(AppDataPtr, testLegality),
1020 XtRImmediate, (XtPointer) True },
1021 { "flipView", "flipView", XtRBoolean,
1022 sizeof(Boolean), XtOffset(AppDataPtr, flipView),
1023 XtRImmediate, (XtPointer) False },
1024 { "cmail", "cmailGameName", XtRString, sizeof(String),
1025 XtOffset(AppDataPtr, cmailGameName), XtRString, "" },
1026 { "alwaysPromoteToQueen", "alwaysPromoteToQueen", XtRBoolean,
1027 sizeof(Boolean), XtOffset(AppDataPtr, alwaysPromoteToQueen),
1028 XtRImmediate, (XtPointer) False },
1029 { "oldSaveStyle", "oldSaveStyle", XtRBoolean,
1030 sizeof(Boolean), XtOffset(AppDataPtr, oldSaveStyle),
1031 XtRImmediate, (XtPointer) False },
1032 { "quietPlay", "quietPlay", XtRBoolean,
1033 sizeof(Boolean), XtOffset(AppDataPtr, quietPlay),
1034 XtRImmediate, (XtPointer) False },
1035 { "titleInWindow", "titleInWindow", XtRBoolean,
1036 sizeof(Boolean), XtOffset(AppDataPtr, titleInWindow),
1037 XtRImmediate, (XtPointer) False },
1038 { "localLineEditing", "localLineEditing", XtRBoolean,
1039 sizeof(Boolean), XtOffset(AppDataPtr, localLineEditing),
1040 XtRImmediate, (XtPointer) True }, /* not implemented, must be True */
1042 { "zippyTalk", "zippyTalk", XtRBoolean,
1043 sizeof(Boolean), XtOffset(AppDataPtr, zippyTalk),
1044 XtRImmediate, (XtPointer) ZIPPY_TALK },
1045 { "zippyPlay", "zippyPlay", XtRBoolean,
1046 sizeof(Boolean), XtOffset(AppDataPtr, zippyPlay),
1047 XtRImmediate, (XtPointer) ZIPPY_PLAY },
1048 { "zippyLines", "zippyLines", XtRString, sizeof(String),
1049 XtOffset(AppDataPtr, zippyLines), XtRString, ZIPPY_LINES },
1050 { "zippyPinhead", "zippyPinhead", XtRString, sizeof(String),
1051 XtOffset(AppDataPtr, zippyPinhead), XtRString, ZIPPY_PINHEAD },
1052 { "zippyPassword", "zippyPassword", XtRString, sizeof(String),
1053 XtOffset(AppDataPtr, zippyPassword), XtRString, ZIPPY_PASSWORD },
1054 { "zippyPassword2", "zippyPassword2", XtRString, sizeof(String),
1055 XtOffset(AppDataPtr, zippyPassword2), XtRString, ZIPPY_PASSWORD2 },
1056 { "zippyWrongPassword", "zippyWrongPassword", XtRString, sizeof(String),
1057 XtOffset(AppDataPtr, zippyWrongPassword), XtRString,
1058 ZIPPY_WRONG_PASSWORD },
1059 { "zippyAcceptOnly", "zippyAcceptOnly", XtRString, sizeof(String),
1060 XtOffset(AppDataPtr, zippyAcceptOnly), XtRString, ZIPPY_ACCEPT_ONLY },
1061 { "zippyUseI", "zippyUseI", XtRBoolean,
1062 sizeof(Boolean), XtOffset(AppDataPtr, zippyUseI),
1063 XtRImmediate, (XtPointer) ZIPPY_USE_I },
1064 { "zippyBughouse", "zippyBughouse", XtRInt,
1065 sizeof(int), XtOffset(AppDataPtr, zippyBughouse),
1066 XtRImmediate, (XtPointer) ZIPPY_BUGHOUSE },
1067 { "zippyNoplayCrafty", "zippyNoplayCrafty", XtRBoolean,
1068 sizeof(Boolean), XtOffset(AppDataPtr, zippyNoplayCrafty),
1069 XtRImmediate, (XtPointer) ZIPPY_NOPLAY_CRAFTY },
1070 { "zippyGameEnd", "zippyGameEnd", XtRString, sizeof(String),
1071 XtOffset(AppDataPtr, zippyGameEnd), XtRString, ZIPPY_GAME_END },
1072 { "zippyGameStart", "zippyGameStart", XtRString, sizeof(String),
1073 XtOffset(AppDataPtr, zippyGameStart), XtRString, ZIPPY_GAME_START },
1074 { "zippyAdjourn", "zippyAdjourn", XtRBoolean,
1075 sizeof(Boolean), XtOffset(AppDataPtr, zippyAdjourn),
1076 XtRImmediate, (XtPointer) ZIPPY_ADJOURN },
1077 { "zippyAbort", "zippyAbort", XtRBoolean,
1078 sizeof(Boolean), XtOffset(AppDataPtr, zippyAbort),
1079 XtRImmediate, (XtPointer) ZIPPY_ABORT },
1080 { "zippyVariants", "zippyVariants", XtRString, sizeof(String),
1081 XtOffset(AppDataPtr, zippyVariants), XtRString, ZIPPY_VARIANTS },
1082 { "zippyMaxGames", "zippyMaxGames", XtRInt, sizeof(int),
1083 XtOffset(AppDataPtr, zippyMaxGames), XtRImmediate,
1084 (XtPointer) ZIPPY_MAX_GAMES },
1085 { "zippyReplayTimeout", "zippyReplayTimeout", XtRInt, sizeof(int),
1086 XtOffset(AppDataPtr, zippyReplayTimeout), XtRImmediate,
1087 (XtPointer) ZIPPY_REPLAY_TIMEOUT },
1088 { "zippyShortGame", "zippyShortGame", XtRInt, sizeof(int),
1089 XtOffset(AppDataPtr, zippyShortGame), XtRImmediate,
1092 { "flashCount", "flashCount", XtRInt, sizeof(int),
1093 XtOffset(AppDataPtr, flashCount), XtRImmediate,
1094 (XtPointer) FLASH_COUNT },
1095 { "flashRate", "flashRate", XtRInt, sizeof(int),
1096 XtOffset(AppDataPtr, flashRate), XtRImmediate,
1097 (XtPointer) FLASH_RATE },
1098 { "pixmapDirectory", "pixmapDirectory", XtRString,
1099 sizeof(String), XtOffset(AppDataPtr, pixmapDirectory),
1101 { "msLoginDelay", "msLoginDelay", XtRInt, sizeof(int),
1102 XtOffset(AppDataPtr, msLoginDelay), XtRImmediate,
1103 (XtPointer) MS_LOGIN_DELAY },
1104 { "colorizeMessages", "colorizeMessages", XtRBoolean,
1105 sizeof(Boolean), XtOffset(AppDataPtr, colorize),
1106 XtRImmediate, (XtPointer) False },
1107 { "colorShout", "colorShout", XtRString,
1108 sizeof(String), XtOffset(AppDataPtr, colorShout),
1109 XtRString, COLOR_SHOUT },
1110 { "colorSShout", "colorSShout", XtRString,
1111 sizeof(String), XtOffset(AppDataPtr, colorSShout),
1112 XtRString, COLOR_SSHOUT },
1113 { "colorChannel1", "colorChannel1", XtRString,
1114 sizeof(String), XtOffset(AppDataPtr, colorChannel1),
1115 XtRString, COLOR_CHANNEL1 },
1116 { "colorChannel", "colorChannel", XtRString,
1117 sizeof(String), XtOffset(AppDataPtr, colorChannel),
1118 XtRString, COLOR_CHANNEL },
1119 { "colorKibitz", "colorKibitz", XtRString,
1120 sizeof(String), XtOffset(AppDataPtr, colorKibitz),
1121 XtRString, COLOR_KIBITZ },
1122 { "colorTell", "colorTell", XtRString,
1123 sizeof(String), XtOffset(AppDataPtr, colorTell),
1124 XtRString, COLOR_TELL },
1125 { "colorChallenge", "colorChallenge", XtRString,
1126 sizeof(String), XtOffset(AppDataPtr, colorChallenge),
1127 XtRString, COLOR_CHALLENGE },
1128 { "colorRequest", "colorRequest", XtRString,
1129 sizeof(String), XtOffset(AppDataPtr, colorRequest),
1130 XtRString, COLOR_REQUEST },
1131 { "colorSeek", "colorSeek", XtRString,
1132 sizeof(String), XtOffset(AppDataPtr, colorSeek),
1133 XtRString, COLOR_SEEK },
1134 { "colorNormal", "colorNormal", XtRString,
1135 sizeof(String), XtOffset(AppDataPtr, colorNormal),
1136 XtRString, COLOR_NORMAL },
1137 { "soundProgram", "soundProgram", XtRString,
1138 sizeof(String), XtOffset(AppDataPtr, soundProgram),
1139 XtRString, "play" },
1140 { "soundShout", "soundShout", XtRString,
1141 sizeof(String), XtOffset(AppDataPtr, soundShout),
1143 { "soundSShout", "soundSShout", XtRString,
1144 sizeof(String), XtOffset(AppDataPtr, soundSShout),
1146 { "soundChannel1", "soundChannel1", XtRString,
1147 sizeof(String), XtOffset(AppDataPtr, soundChannel1),
1149 { "soundChannel", "soundChannel", XtRString,
1150 sizeof(String), XtOffset(AppDataPtr, soundChannel),
1152 { "soundKibitz", "soundKibitz", XtRString,
1153 sizeof(String), XtOffset(AppDataPtr, soundKibitz),
1155 { "soundTell", "soundTell", XtRString,
1156 sizeof(String), XtOffset(AppDataPtr, soundTell),
1158 { "soundChallenge", "soundChallenge", XtRString,
1159 sizeof(String), XtOffset(AppDataPtr, soundChallenge),
1161 { "soundRequest", "soundRequest", XtRString,
1162 sizeof(String), XtOffset(AppDataPtr, soundRequest),
1164 { "soundSeek", "soundSeek", XtRString,
1165 sizeof(String), XtOffset(AppDataPtr, soundSeek),
1167 { "soundMove", "soundMove", XtRString,
1168 sizeof(String), XtOffset(AppDataPtr, soundMove),
1170 { "soundIcsWin", "soundIcsWin", XtRString,
1171 sizeof(String), XtOffset(AppDataPtr, soundIcsWin),
1173 { "soundIcsLoss", "soundIcsLoss", XtRString,
1174 sizeof(String), XtOffset(AppDataPtr, soundIcsLoss),
1176 { "soundIcsDraw", "soundIcsDraw", XtRString,
1177 sizeof(String), XtOffset(AppDataPtr, soundIcsDraw),
1179 { "soundIcsUnfinished", "soundIcsUnfinished", XtRString,
1180 sizeof(String), XtOffset(AppDataPtr, soundIcsUnfinished),
1182 { "soundIcsAlarm", "soundIcsAlarm", XtRString,
1183 sizeof(String), XtOffset(AppDataPtr, soundIcsAlarm),
1185 { "reuseFirst", "reuseFirst", XtRBoolean,
1186 sizeof(Boolean), XtOffset(AppDataPtr, reuseFirst),
1187 XtRImmediate, (XtPointer) True },
1188 { "reuseSecond", "reuseSecond", XtRBoolean,
1189 sizeof(Boolean), XtOffset(AppDataPtr, reuseSecond),
1190 XtRImmediate, (XtPointer) True },
1191 { "animateDragging", "animateDragging", XtRBoolean,
1192 sizeof(Boolean), XtOffset(AppDataPtr, animateDragging),
1193 XtRImmediate, (XtPointer) True },
1194 { "animateMoving", "animateMoving", XtRBoolean,
1195 sizeof(Boolean), XtOffset(AppDataPtr, animate),
1196 XtRImmediate, (XtPointer) True },
1197 { "animateSpeed", "animateSpeed", XtRInt,
1198 sizeof(int), XtOffset(AppDataPtr, animSpeed),
1199 XtRImmediate, (XtPointer)10 },
1200 { "popupExitMessage", "popupExitMessage", XtRBoolean,
1201 sizeof(Boolean), XtOffset(AppDataPtr, popupExitMessage),
1202 XtRImmediate, (XtPointer) True },
1203 { "popupMoveErrors", "popupMoveErrors", XtRBoolean,
1204 sizeof(Boolean), XtOffset(AppDataPtr, popupMoveErrors),
1205 XtRImmediate, (XtPointer) False },
1206 { "fontSizeTolerance", "fontSizeTolerance", XtRInt,
1207 sizeof(int), XtOffset(AppDataPtr, fontSizeTolerance),
1208 XtRImmediate, (XtPointer)4 },
1209 { "initialMode", "initialMode", XtRString,
1210 sizeof(String), XtOffset(AppDataPtr, initialMode),
1211 XtRImmediate, (XtPointer) "" },
1212 { "variant", "variant", XtRString,
1213 sizeof(String), XtOffset(AppDataPtr, variant),
1214 XtRImmediate, (XtPointer) "normal" },
1215 { "firstProtocolVersion", "firstProtocolVersion", XtRInt,
1216 sizeof(int), XtOffset(AppDataPtr, firstProtocolVersion),
1217 XtRImmediate, (XtPointer)PROTOVER },
1218 { "secondProtocolVersion", "secondProtocolVersion", XtRInt,
1219 sizeof(int), XtOffset(AppDataPtr, secondProtocolVersion),
1220 XtRImmediate, (XtPointer)PROTOVER },
1221 { "showButtonBar", "showButtonBar", XtRBoolean,
1222 sizeof(Boolean), XtOffset(AppDataPtr, showButtonBar),
1223 XtRImmediate, (XtPointer) True },
1224 { "lowTimeWarningColor", "lowTimeWarningColor", XtRString,
1225 sizeof(String), XtOffset(AppDataPtr, lowTimeWarningColor),
1226 XtRString, COLOR_LOWTIMEWARNING },
1227 { "lowTimeWarning", "lowTimeWarning", XtRBoolean,
1228 sizeof(Boolean), XtOffset(AppDataPtr, lowTimeWarning),
1229 XtRImmediate, (XtPointer) False },
1230 {"icsEngineAnalyze", "icsEngineAnalyze", XtRBoolean, /* [DM] icsEngineAnalyze */
1231 sizeof(Boolean), XtOffset(AppDataPtr, icsEngineAnalyze),
1232 XtRImmediate, (XtPointer) False },
1233 { "firstScoreAbs", "firstScoreAbs", XtRBoolean,
1234 sizeof(Boolean), XtOffset(AppDataPtr, firstScoreIsAbsolute),
1235 XtRImmediate, (XtPointer) False },
1236 { "secondScoreAbs", "secondScoreAbs", XtRBoolean,
1237 sizeof(Boolean), XtOffset(AppDataPtr, secondScoreIsAbsolute),
1238 XtRImmediate, (XtPointer) False },
1239 { "pgnExtendedInfo", "pgnExtendedInfo", XtRBoolean,
1240 sizeof(Boolean), XtOffset(AppDataPtr, saveExtendedInfoInPGN),
1241 XtRImmediate, (XtPointer) False },
1242 { "hideThinkingFromHuman", "hideThinkingFromHuman", XtRBoolean,
1243 sizeof(Boolean), XtOffset(AppDataPtr, hideThinkingFromHuman),
1244 XtRImmediate, (XtPointer) True },
1245 { "adjudicateLossThreshold", "adjudicateLossThreshold", XtRInt,
1246 sizeof(int), XtOffset(AppDataPtr, adjudicateLossThreshold),
1247 XtRImmediate, (XtPointer) 0},
1248 { "adjudicateDrawMoves", "adjudicateDrawMoves", XtRInt,
1249 sizeof(int), XtOffset(AppDataPtr, adjudicateDrawMoves),
1250 XtRImmediate, (XtPointer) 0},
1251 { "pgnEventHeader", "pgnEventHeader", XtRString,
1252 sizeof(String), XtOffset(AppDataPtr, pgnEventHeader),
1253 XtRImmediate, (XtPointer) "Computer Chess Game" },
1254 { "defaultFrcPosition", "defaultFrcPositon", XtRInt,
1255 sizeof(int), XtOffset(AppDataPtr, defaultFrcPosition),
1256 XtRImmediate, (XtPointer) -1},
1257 { "gameListTags", "gameListTags", XtRString,
1258 sizeof(String), XtOffset(AppDataPtr, gameListTags),
1259 XtRImmediate, (XtPointer) GLT_DEFAULT_TAGS },
1261 // [HGM] 4.3.xx options
1262 { "boardWidth", "boardWidth", XtRInt,
1263 sizeof(int), XtOffset(AppDataPtr, NrFiles),
1264 XtRImmediate, (XtPointer) -1},
1265 { "boardHeight", "boardHeight", XtRInt,
1266 sizeof(int), XtOffset(AppDataPtr, NrRanks),
1267 XtRImmediate, (XtPointer) -1},
1268 { "matchPause", "matchPause", XtRInt,
1269 sizeof(int), XtOffset(AppDataPtr, matchPause),
1270 XtRImmediate, (XtPointer) 10000},
1271 { "holdingsSize", "holdingsSize", XtRInt,
1272 sizeof(int), XtOffset(AppDataPtr, holdingsSize),
1273 XtRImmediate, (XtPointer) -1},
1274 { "flipBlack", "flipBlack", XtRBoolean,
1275 sizeof(Boolean), XtOffset(AppDataPtr, upsideDown),
1276 XtRImmediate, (XtPointer) False},
1277 { "allWhite", "allWhite", XtRBoolean,
1278 sizeof(Boolean), XtOffset(AppDataPtr, allWhite),
1279 XtRImmediate, (XtPointer) False},
1280 { "pieceToCharTable", "pieceToCharTable", XtRString,
1281 sizeof(String), XtOffset(AppDataPtr, pieceToCharTable),
1282 XtRImmediate, (XtPointer) 0},
1283 { "alphaRank", "alphaRank", XtRBoolean,
1284 sizeof(Boolean), XtOffset(AppDataPtr, alphaRank),
1285 XtRImmediate, (XtPointer) False},
1286 { "testClaims", "testClaims", XtRBoolean,
1287 sizeof(Boolean), XtOffset(AppDataPtr, testClaims),
1288 XtRImmediate, (XtPointer) True},
1289 { "checkMates", "checkMates", XtRBoolean,
1290 sizeof(Boolean), XtOffset(AppDataPtr, checkMates),
1291 XtRImmediate, (XtPointer) True},
1292 { "materialDraws", "materialDraws", XtRBoolean,
1293 sizeof(Boolean), XtOffset(AppDataPtr, materialDraws),
1294 XtRImmediate, (XtPointer) True},
1295 { "trivialDraws", "trivialDraws", XtRBoolean,
1296 sizeof(Boolean), XtOffset(AppDataPtr, trivialDraws),
1297 XtRImmediate, (XtPointer) False},
1298 { "ruleMoves", "ruleMoves", XtRInt,
1299 sizeof(int), XtOffset(AppDataPtr, ruleMoves),
1300 XtRImmediate, (XtPointer) 51},
1301 { "repeatsToDraw", "repeatsToDraw", XtRInt,
1302 sizeof(int), XtOffset(AppDataPtr, drawRepeats),
1303 XtRImmediate, (XtPointer) 6},
1304 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1305 sizeof(int), XtOffset(AppDataPtr, engineComments),
1306 XtRImmediate, (XtPointer) 1},
1307 { "userName", "userName", XtRString,
1308 sizeof(int), XtOffset(AppDataPtr, userName),
1309 XtRImmediate, (XtPointer) 0},
1310 { "autoKibitz", "autoKibitz", XtRBoolean,
1311 sizeof(Boolean), XtOffset(AppDataPtr, autoKibitz),
1312 XtRImmediate, (XtPointer) False},
1313 { "firstTimeOdds", "firstTimeOdds", XtRInt,
1314 sizeof(int), XtOffset(AppDataPtr, firstTimeOdds),
1315 XtRImmediate, (XtPointer) 1},
1316 { "secondTimeOdds", "secondTimeOdds", XtRInt,
1317 sizeof(int), XtOffset(AppDataPtr, secondTimeOdds),
1318 XtRImmediate, (XtPointer) 1},
1319 { "timeOddsMode", "timeOddsMode", XtRInt,
1320 sizeof(int), XtOffset(AppDataPtr, timeOddsMode),
1321 XtRImmediate, (XtPointer) 0},
1322 { "firstAccumulateTC", "firstAccumulateTC", XtRInt,
1323 sizeof(int), XtOffset(AppDataPtr, firstAccumulateTC),
1324 XtRImmediate, (XtPointer) 1},
1325 { "secondAccumulateTC", "secondAccumulateTC", XtRInt,
1326 sizeof(int), XtOffset(AppDataPtr, secondAccumulateTC),
1327 XtRImmediate, (XtPointer) 1},
1328 { "firstNPS", "firstNPS", XtRInt,
1329 sizeof(int), XtOffset(AppDataPtr, firstNPS),
1330 XtRImmediate, (XtPointer) -1},
1331 { "secondNPS", "secondNPS", XtRInt,
1332 sizeof(int), XtOffset(AppDataPtr, secondNPS),
1333 XtRImmediate, (XtPointer) -1},
1334 { "serverMoves", "serverMoves", XtRString,
1335 sizeof(String), XtOffset(AppDataPtr, serverMovesName),
1336 XtRImmediate, (XtPointer) 0},
1337 { "serverPause", "serverPause", XtRInt,
1338 sizeof(int), XtOffset(AppDataPtr, serverPause),
1339 XtRImmediate, (XtPointer) 0},
1340 { "suppressLoadMoves", "suppressLoadMoves", XtRBoolean,
1341 sizeof(Boolean), XtOffset(AppDataPtr, suppressLoadMoves),
1342 XtRImmediate, (XtPointer) False},
1343 { "userName", "userName", XtRString,
1344 sizeof(String), XtOffset(AppDataPtr, userName),
1345 XtRImmediate, (XtPointer) 0},
1346 { "egtFormats", "egtFormats", XtRString,
1347 sizeof(String), XtOffset(AppDataPtr, egtFormats),
1348 XtRImmediate, (XtPointer) 0},
1349 { "rewindIndex", "rewindIndex", XtRInt,
1350 sizeof(int), XtOffset(AppDataPtr, rewindIndex),
1351 XtRImmediate, (XtPointer) 0},
1352 { "sameColorGames", "sameColorGames", XtRInt,
1353 sizeof(int), XtOffset(AppDataPtr, sameColorGames),
1354 XtRImmediate, (XtPointer) 0},
1355 { "smpCores", "smpCores", XtRInt,
1356 sizeof(int), XtOffset(AppDataPtr, smpCores),
1357 XtRImmediate, (XtPointer) 1},
1358 { "niceEngines", "niceEngines", XtRInt,
1359 sizeof(int), XtOffset(AppDataPtr, niceEngines),
1360 XtRImmediate, (XtPointer) 0},
1361 { "nameOfDebugFile", "nameOfDebugFile", XtRString,
1362 sizeof(String), XtOffset(AppDataPtr, nameOfDebugFile),
1363 XtRImmediate, (XtPointer) "xboard.debug"},
1364 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1365 sizeof(int), XtOffset(AppDataPtr, engineComments),
1366 XtRImmediate, (XtPointer) 1},
1367 { "noGUI", "noGUI", XtRBoolean,
1368 sizeof(Boolean), XtOffset(AppDataPtr, noGUI),
1369 XtRImmediate, (XtPointer) 0},
1370 { "firstOptions", "firstOptions", XtRString,
1371 sizeof(String), XtOffset(AppDataPtr, firstOptions),
1372 XtRImmediate, (XtPointer) "" },
1373 { "secondOptions", "secondOptions", XtRString,
1374 sizeof(String), XtOffset(AppDataPtr, secondOptions),
1375 XtRImmediate, (XtPointer) "" },
1376 { "firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XtRString,
1377 sizeof(String), XtOffset(AppDataPtr, fenOverride1),
1378 XtRImmediate, (XtPointer) 0 },
1379 { "secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XtRString,
1380 sizeof(String), XtOffset(AppDataPtr, fenOverride2),
1381 XtRImmediate, (XtPointer) 0 },
1383 // [HGM] Winboard_x UCI options
1384 { "firstIsUCI", "firstIsUCI", XtRBoolean,
1385 sizeof(Boolean), XtOffset(AppDataPtr, firstIsUCI),
1386 XtRImmediate, (XtPointer) False},
1387 { "secondIsUCI", "secondIsUCI", XtRBoolean,
1388 sizeof(Boolean), XtOffset(AppDataPtr, secondIsUCI),
1389 XtRImmediate, (XtPointer) False},
1390 { "firstHasOwnBookUCI", "firstHasOwnBookUCI", XtRBoolean,
1391 sizeof(Boolean), XtOffset(AppDataPtr, firstHasOwnBookUCI),
1392 XtRImmediate, (XtPointer) True},
1393 { "secondHasOwnBookUCI", "secondHasOwnBookUCI", XtRBoolean,
1394 sizeof(Boolean), XtOffset(AppDataPtr, secondHasOwnBookUCI),
1395 XtRImmediate, (XtPointer) True},
1396 { "usePolyglotBook", "usePolyglotBook", XtRBoolean,
1397 sizeof(Boolean), XtOffset(AppDataPtr, usePolyglotBook),
1398 XtRImmediate, (XtPointer) False},
1399 { "defaultHashSize", "defaultHashSize", XtRInt,
1400 sizeof(int), XtOffset(AppDataPtr, defaultHashSize),
1401 XtRImmediate, (XtPointer) 64},
1402 { "defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XtRInt,
1403 sizeof(int), XtOffset(AppDataPtr, defaultCacheSizeEGTB),
1404 XtRImmediate, (XtPointer) 4},
1405 { "polyglotDir", "polyglotDir", XtRString,
1406 sizeof(String), XtOffset(AppDataPtr, polyglotDir),
1407 XtRImmediate, (XtPointer) "." },
1408 { "polyglotBook", "polyglotBook", XtRString,
1409 sizeof(String), XtOffset(AppDataPtr, polyglotBook),
1410 XtRImmediate, (XtPointer) "" },
1411 { "defaultPathEGTB", "defaultPathEGTB", XtRString,
1412 sizeof(String), XtOffset(AppDataPtr, defaultPathEGTB),
1413 XtRImmediate, (XtPointer) "/usr/local/share/egtb"},
1414 { "delayBeforeQuit", "delayBeforeQuit", XtRInt,
1415 sizeof(int), XtOffset(AppDataPtr, delayBeforeQuit),
1416 XtRImmediate, (XtPointer) 0},
1417 { "delayAfterQuit", "delayAfterQuit", XtRInt,
1418 sizeof(int), XtOffset(AppDataPtr, delayAfterQuit),
1419 XtRImmediate, (XtPointer) 0},
1420 { "keepAlive", "keepAlive", XtRInt,
1421 sizeof(int), XtOffset(AppDataPtr, keepAlive),
1422 XtRImmediate, (XtPointer) 0},
1423 { "forceIllegalMoves", "forceIllegalMoves", XtRBoolean,
1424 sizeof(Boolean), XtOffset(AppDataPtr, forceIllegal),
1425 XtRImmediate, (XtPointer) False},
1428 XrmOptionDescRec shellOptions[] = {
1429 { "-whitePieceColor", "whitePieceColor", XrmoptionSepArg, NULL },
1430 { "-blackPieceColor", "blackPieceColor", XrmoptionSepArg, NULL },
1431 { "-lightSquareColor", "lightSquareColor", XrmoptionSepArg, NULL },
1432 { "-darkSquareColor", "darkSquareColor", XrmoptionSepArg, NULL },
1433 { "-highlightSquareColor", "highlightSquareColor", XrmoptionSepArg, NULL },
1434 { "-premoveHighlightColor", "premoveHighlightColor", XrmoptionSepArg,NULL},
1435 { "-movesPerSession", "movesPerSession", XrmoptionSepArg, NULL },
1436 { "-mps", "movesPerSession", XrmoptionSepArg, NULL },
1437 { "-timeIncrement", "timeIncrement", XrmoptionSepArg, NULL },
1438 { "-inc", "timeIncrement", XrmoptionSepArg, NULL },
1439 { "-initString", "initString", XrmoptionSepArg, NULL },
1440 { "-firstInitString", "initString", XrmoptionSepArg, NULL },
1441 { "-secondInitString", "secondInitString", XrmoptionSepArg, NULL },
1442 { "-firstComputerString", "firstComputerString", XrmoptionSepArg, NULL },
1443 { "-secondComputerString", "secondComputerString", XrmoptionSepArg, NULL },
1444 { "-firstChessProgram", "firstChessProgram", XrmoptionSepArg, NULL },
1445 { "-fcp", "firstChessProgram", XrmoptionSepArg, NULL },
1446 { "-secondChessProgram", "secondChessProgram", XrmoptionSepArg, NULL },
1447 { "-scp", "secondChessProgram", XrmoptionSepArg, NULL },
1448 { "-firstPlaysBlack", "firstPlaysBlack", XrmoptionSepArg, NULL },
1449 { "-fb", "firstPlaysBlack", XrmoptionNoArg, "True" },
1450 { "-xfb", "firstPlaysBlack", XrmoptionNoArg, "False" },
1451 { "-noChessProgram", "noChessProgram", XrmoptionSepArg, NULL },
1452 { "-ncp", "noChessProgram", XrmoptionNoArg, "True" },
1453 { "-xncp", "noChessProgram", XrmoptionNoArg, "False" },
1454 { "-firstHost", "firstHost", XrmoptionSepArg, NULL },
1455 { "-fh", "firstHost", XrmoptionSepArg, NULL },
1456 { "-secondHost", "secondHost", XrmoptionSepArg, NULL },
1457 { "-sh", "secondHost", XrmoptionSepArg, NULL },
1458 { "-firstDirectory", "firstDirectory", XrmoptionSepArg, NULL },
1459 { "-fd", "firstDirectory", XrmoptionSepArg, NULL },
1460 { "-secondDirectory", "secondDirectory", XrmoptionSepArg, NULL },
1461 { "-sd", "secondDirectory", XrmoptionSepArg, NULL },
1462 { "-bitmapDirectory", "bitmapDirectory", XrmoptionSepArg, NULL },
1463 { "-bm", "bitmapDirectory", XrmoptionSepArg, NULL },
1464 { "-remoteShell", "remoteShell", XrmoptionSepArg, NULL },
1465 { "-rsh", "remoteShell", XrmoptionSepArg, NULL },
1466 { "-remoteUser", "remoteUser", XrmoptionSepArg, NULL },
1467 { "-ruser", "remoteUser", XrmoptionSepArg, NULL },
1468 { "-timeDelay", "timeDelay", XrmoptionSepArg, NULL },
1469 { "-td", "timeDelay", XrmoptionSepArg, NULL },
1470 { "-timeControl", "timeControl", XrmoptionSepArg, NULL },
1471 { "-tc", "timeControl", XrmoptionSepArg, NULL },
1472 { "-internetChessServerMode", "internetChessServerMode",
1473 XrmoptionSepArg, NULL },
1474 { "-ics", "internetChessServerMode", XrmoptionNoArg, "True" },
1475 { "-xics", "internetChessServerMode", XrmoptionNoArg, "False" },
1476 { "-internetChessServerHost", "internetChessServerHost",
1477 XrmoptionSepArg, NULL },
1478 { "-icshost", "internetChessServerHost", XrmoptionSepArg, NULL },
1479 { "-internetChessServerPort", "internetChessServerPort",
1480 XrmoptionSepArg, NULL },
1481 { "-icsport", "internetChessServerPort", XrmoptionSepArg, NULL },
1482 { "-internetChessServerCommPort", "internetChessServerCommPort",
1483 XrmoptionSepArg, NULL },
1484 { "-icscomm", "internetChessServerCommPort", XrmoptionSepArg, NULL },
1485 { "-internetChessServerLogonScript", "internetChessServerLogonScript",
1486 XrmoptionSepArg, NULL },
1487 { "-icslogon", "internetChessServerLogonScript", XrmoptionSepArg, NULL },
1488 { "-internetChessServerHelper", "internetChessServerHelper",
1489 XrmoptionSepArg, NULL },
1490 { "-icshelper", "internetChessServerHelper", XrmoptionSepArg, NULL },
1491 { "-internetChessServerInputBox", "internetChessServerInputBox",
1492 XrmoptionSepArg, NULL },
1493 { "-icsinput", "internetChessServerInputBox", XrmoptionNoArg, "True" },
1494 { "-xicsinput", "internetChessServerInputBox", XrmoptionNoArg, "False" },
1495 { "-icsAlarm", "icsAlarm", XrmoptionSepArg, NULL },
1496 { "-alarm", "icsAlarm", XrmoptionNoArg, "True" },
1497 { "-xalarm", "icsAlarm", XrmoptionNoArg, "False" },
1498 { "-icsAlarmTime", "icsAlarmTime", XrmoptionSepArg, NULL },
1499 { "-useTelnet", "useTelnet", XrmoptionSepArg, NULL },
1500 { "-telnet", "useTelnet", XrmoptionNoArg, "True" },
1501 { "-xtelnet", "useTelnet", XrmoptionNoArg, "False" },
1502 { "-telnetProgram", "telnetProgram", XrmoptionSepArg, NULL },
1503 { "-gateway", "gateway", XrmoptionSepArg, NULL },
1504 { "-loadGameFile", "loadGameFile", XrmoptionSepArg, NULL },
1505 { "-lgf", "loadGameFile", XrmoptionSepArg, NULL },
1506 { "-loadGameIndex", "loadGameIndex", XrmoptionSepArg, NULL },
1507 { "-lgi", "loadGameIndex", XrmoptionSepArg, NULL },
1508 { "-saveGameFile", "saveGameFile", XrmoptionSepArg, NULL },
1509 { "-sgf", "saveGameFile", XrmoptionSepArg, NULL },
1510 { "-autoSaveGames", "autoSaveGames", XrmoptionSepArg, NULL },
1511 { "-autosave", "autoSaveGames", XrmoptionNoArg, "True" },
1512 { "-xautosave", "autoSaveGames", XrmoptionNoArg, "False" },
1513 { "-autoRaiseBoard", "autoRaiseBoard", XrmoptionSepArg, NULL },
1514 { "-autoraise", "autoRaiseBoard", XrmoptionNoArg, "True" },
1515 { "-xautoraise", "autoRaiseBoard", XrmoptionNoArg, "False" },
1516 { "-blindfold", "blindfold", XrmoptionSepArg, NULL },
1517 { "-blind", "blindfold", XrmoptionNoArg, "True" },
1518 { "-xblind", "blindfold", XrmoptionNoArg, "False" },
1519 { "-loadPositionFile", "loadPositionFile", XrmoptionSepArg, NULL },
1520 { "-lpf", "loadPositionFile", XrmoptionSepArg, NULL },
1521 { "-loadPositionIndex", "loadPositionIndex", XrmoptionSepArg, NULL },
1522 { "-lpi", "loadPositionIndex", XrmoptionSepArg, NULL },
1523 { "-savePositionFile", "savePositionFile", XrmoptionSepArg, NULL },
1524 { "-spf", "savePositionFile", XrmoptionSepArg, NULL },
1525 { "-matchMode", "matchMode", XrmoptionSepArg, NULL },
1526 { "-mm", "matchMode", XrmoptionNoArg, "True" },
1527 { "-xmm", "matchMode", XrmoptionNoArg, "False" },
1528 { "-matchGames", "matchGames", XrmoptionSepArg, NULL },
1529 { "-mg", "matchGames", XrmoptionSepArg, NULL },
1530 { "-monoMode", "monoMode", XrmoptionSepArg, NULL },
1531 { "-mono", "monoMode", XrmoptionNoArg, "True" },
1532 { "-xmono", "monoMode", XrmoptionNoArg, "False" },
1533 { "-debugMode", "debugMode", XrmoptionSepArg, NULL },
1534 { "-debug", "debugMode", XrmoptionNoArg, "True" },
1535 { "-xdebug", "debugMode", XrmoptionNoArg, "False" },
1536 { "-clockMode", "clockMode", XrmoptionSepArg, NULL },
1537 { "-clock", "clockMode", XrmoptionNoArg, "True" },
1538 { "-xclock", "clockMode", XrmoptionNoArg, "False" },
1539 { "-boardSize", "boardSize", XrmoptionSepArg, NULL },
1540 { "-size", "boardSize", XrmoptionSepArg, NULL },
1541 { "-searchTime", "searchTime", XrmoptionSepArg, NULL },
1542 { "-st", "searchTime", XrmoptionSepArg, NULL },
1543 { "-searchDepth", "searchDepth", XrmoptionSepArg, NULL },
1544 { "-depth", "searchDepth", XrmoptionSepArg, NULL },
1545 { "-showCoords", "showCoords", XrmoptionSepArg, NULL },
1546 { "-coords", "showCoords", XrmoptionNoArg, "True" },
1547 { "-xcoords", "showCoords", XrmoptionNoArg, "False" },
1549 { "-showJail", "showJail", XrmoptionSepArg, NULL },
1550 { "-jail", "showJail", XrmoptionNoArg, "1" },
1551 { "-sidejail", "showJail", XrmoptionNoArg, "2" },
1552 { "-xjail", "showJail", XrmoptionNoArg, "0" },
1554 { "-showThinking", "showThinking", XrmoptionSepArg, NULL },
1555 { "-thinking", "showThinking", XrmoptionNoArg, "True" },
1556 { "-xthinking", "showThinking", XrmoptionNoArg, "False" },
1557 { "-ponderNextMove", "ponderNextMove", XrmoptionSepArg, NULL },
1558 { "-ponder", "ponderNextMove", XrmoptionNoArg, "True" },
1559 { "-xponder", "ponderNextMove", XrmoptionNoArg, "False" },
1560 { "-periodicUpdates", "periodicUpdates", XrmoptionSepArg, NULL },
1561 { "-periodic", "periodicUpdates", XrmoptionNoArg, "True" },
1562 { "-xperiodic", "periodicUpdates", XrmoptionNoArg, "False" },
1563 { "-clockFont", "clockFont", XrmoptionSepArg, NULL },
1564 { "-coordFont", "coordFont", XrmoptionSepArg, NULL },
1565 { "-font", "font", XrmoptionSepArg, NULL },
1566 { "-ringBellAfterMoves", "ringBellAfterMoves", XrmoptionSepArg, NULL },
1567 { "-bell", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1568 { "-xbell", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1569 { "-movesound", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1570 { "-xmovesound", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1571 { "-autoCallFlag", "autoCallFlag", XrmoptionSepArg, NULL },
1572 { "-autoflag", "autoCallFlag", XrmoptionNoArg, "True" },
1573 { "-xautoflag", "autoCallFlag", XrmoptionNoArg, "False" },
1574 { "-autoFlipView", "autoFlipView", XrmoptionSepArg, NULL },
1575 { "-autoflip", "autoFlipView", XrmoptionNoArg, "True" },
1576 { "-xautoflip", "autoFlipView", XrmoptionNoArg, "False" },
1577 { "-autoObserve", "autoObserve", XrmoptionSepArg, NULL },
1578 { "-autobs", "autoObserve", XrmoptionNoArg, "True" },
1579 { "-xautobs", "autoObserve", XrmoptionNoArg, "False" },
1580 { "-autoComment", "autoComment", XrmoptionSepArg, NULL },
1581 { "-autocomm", "autoComment", XrmoptionNoArg, "True" },
1582 { "-xautocomm", "autoComment", XrmoptionNoArg, "False" },
1583 { "-getMoveList", "getMoveList", XrmoptionSepArg, NULL },
1584 { "-moves", "getMoveList", XrmoptionNoArg, "True" },
1585 { "-xmoves", "getMoveList", XrmoptionNoArg, "False" },
1587 { "-highlightDragging", "highlightDragging", XrmoptionSepArg, NULL },
1588 { "-highdrag", "highlightDragging", XrmoptionNoArg, "True" },
1589 { "-xhighdrag", "highlightDragging", XrmoptionNoArg, "False" },
1591 { "-highlightLastMove", "highlightLastMove", XrmoptionSepArg, NULL },
1592 { "-highlight", "highlightLastMove", XrmoptionNoArg, "True" },
1593 { "-xhighlight", "highlightLastMove", XrmoptionNoArg, "False" },
1594 { "-premove", "premove", XrmoptionSepArg, NULL },
1595 { "-pre", "premove", XrmoptionNoArg, "True" },
1596 { "-xpre", "premove", XrmoptionNoArg, "False" },
1597 { "-testLegality", "testLegality", XrmoptionSepArg, NULL },
1598 { "-legal", "testLegality", XrmoptionNoArg, "True" },
1599 { "-xlegal", "testLegality", XrmoptionNoArg, "False" },
1600 { "-flipView", "flipView", XrmoptionSepArg, NULL },
1601 { "-flip", "flipView", XrmoptionNoArg, "True" },
1602 { "-xflip", "flipView", XrmoptionNoArg, "False" },
1603 { "-cmail", "cmailGameName", XrmoptionSepArg, NULL },
1604 { "-alwaysPromoteToQueen", "alwaysPromoteToQueen",
1605 XrmoptionSepArg, NULL },
1606 { "-queen", "alwaysPromoteToQueen", XrmoptionNoArg, "True" },
1607 { "-xqueen", "alwaysPromoteToQueen", XrmoptionNoArg, "False" },
1608 { "-oldSaveStyle", "oldSaveStyle", XrmoptionSepArg, NULL },
1609 { "-oldsave", "oldSaveStyle", XrmoptionNoArg, "True" },
1610 { "-xoldsave", "oldSaveStyle", XrmoptionNoArg, "False" },
1611 { "-quietPlay", "quietPlay", XrmoptionSepArg, NULL },
1612 { "-quiet", "quietPlay", XrmoptionNoArg, "True" },
1613 { "-xquiet", "quietPlay", XrmoptionNoArg, "False" },
1614 { "-titleInWindow", "titleInWindow", XrmoptionSepArg, NULL },
1615 { "-title", "titleInWindow", XrmoptionNoArg, "True" },
1616 { "-xtitle", "titleInWindow", XrmoptionNoArg, "False" },
1618 { "-zippyTalk", "zippyTalk", XrmoptionSepArg, NULL },
1619 { "-zt", "zippyTalk", XrmoptionNoArg, "True" },
1620 { "-xzt", "zippyTalk", XrmoptionNoArg, "False" },
1621 { "-zippyPlay", "zippyPlay", XrmoptionSepArg, NULL },
1622 { "-zp", "zippyPlay", XrmoptionNoArg, "True" },
1623 { "-xzp", "zippyPlay", XrmoptionNoArg, "False" },
1624 { "-zippyLines", "zippyLines", XrmoptionSepArg, NULL },
1625 { "-zippyPinhead", "zippyPinhead", XrmoptionSepArg, NULL },
1626 { "-zippyPassword", "zippyPassword", XrmoptionSepArg, NULL },
1627 { "-zippyPassword2", "zippyPassword2", XrmoptionSepArg, NULL },
1628 { "-zippyWrongPassword", "zippyWrongPassword", XrmoptionSepArg, NULL },
1629 { "-zippyAcceptOnly", "zippyAcceptOnly", XrmoptionSepArg, NULL },
1630 { "-zippyUseI", "zippyUseI", XrmoptionSepArg, NULL },
1631 { "-zui", "zippyUseI", XrmoptionNoArg, "True" },
1632 { "-xzui", "zippyUseI", XrmoptionNoArg, "False" },
1633 { "-zippyBughouse", "zippyBughouse", XrmoptionSepArg, NULL },
1634 { "-zippyNoplayCrafty", "zippyNoplayCrafty", XrmoptionSepArg, NULL },
1635 { "-znc", "zippyNoplayCrafty", XrmoptionNoArg, "True" },
1636 { "-xznc", "zippyNoplayCrafty", XrmoptionNoArg, "False" },
1637 { "-zippyGameEnd", "zippyGameEnd", XrmoptionSepArg, NULL },
1638 { "-zippyGameStart", "zippyGameStart", XrmoptionSepArg, NULL },
1639 { "-zippyAdjourn", "zippyAdjourn", XrmoptionSepArg, NULL },
1640 { "-zadj", "zippyAdjourn", XrmoptionNoArg, "True" },
1641 { "-xzadj", "zippyAdjourn", XrmoptionNoArg, "False" },
1642 { "-zippyAbort", "zippyAbort", XrmoptionSepArg, NULL },
1643 { "-zab", "zippyAbort", XrmoptionNoArg, "True" },
1644 { "-xzab", "zippyAbort", XrmoptionNoArg, "False" },
1645 { "-zippyVariants", "zippyVariants", XrmoptionSepArg, NULL },
1646 { "-zippyMaxGames", "zippyMaxGames", XrmoptionSepArg, NULL },
1647 { "-zippyReplayTimeout", "zippyReplayTimeout", XrmoptionSepArg, NULL },
1648 { "-zippyShortGame", "zippyShortGame", XrmoptionSepArg, NULL },
1650 { "-flashCount", "flashCount", XrmoptionSepArg, NULL },
1651 { "-flash", "flashCount", XrmoptionNoArg, "3" },
1652 { "-xflash", "flashCount", XrmoptionNoArg, "0" },
1653 { "-flashRate", "flashRate", XrmoptionSepArg, NULL },
1654 { "-pixmapDirectory", "pixmapDirectory", XrmoptionSepArg, NULL },
1655 { "-msLoginDelay", "msLoginDelay", XrmoptionSepArg, NULL },
1656 { "-pixmap", "pixmapDirectory", XrmoptionSepArg, NULL },
1657 { "-colorizeMessages", "colorizeMessages", XrmoptionSepArg, NULL },
1658 { "-colorize", "colorizeMessages", XrmoptionNoArg, "True" },
1659 { "-xcolorize", "colorizeMessages", XrmoptionNoArg, "False" },
1660 { "-colorShout", "colorShout", XrmoptionSepArg, NULL },
1661 { "-colorSShout", "colorSShout", XrmoptionSepArg, NULL },
1662 { "-colorCShout", "colorSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1663 { "-colorChannel1", "colorChannel1", XrmoptionSepArg, NULL },
1664 { "-colorChannel", "colorChannel", XrmoptionSepArg, NULL },
1665 { "-colorKibitz", "colorKibitz", XrmoptionSepArg, NULL },
1666 { "-colorTell", "colorTell", XrmoptionSepArg, NULL },
1667 { "-colorChallenge", "colorChallenge", XrmoptionSepArg, NULL },
1668 { "-colorRequest", "colorRequest", XrmoptionSepArg, NULL },
1669 { "-colorSeek", "colorSeek", XrmoptionSepArg, NULL },
1670 { "-colorNormal", "colorNormal", XrmoptionSepArg, NULL },
1671 { "-soundProgram", "soundProgram", XrmoptionSepArg, NULL },
1672 { "-soundShout", "soundShout", XrmoptionSepArg, NULL },
1673 { "-soundSShout", "soundSShout", XrmoptionSepArg, NULL },
1674 { "-soundCShout", "soundSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1675 { "-soundChannel1", "soundChannel1", XrmoptionSepArg, NULL },
1676 { "-soundChannel", "soundChannel", XrmoptionSepArg, NULL },
1677 { "-soundKibitz", "soundKibitz", XrmoptionSepArg, NULL },
1678 { "-soundTell", "soundTell", XrmoptionSepArg, NULL },
1679 { "-soundChallenge", "soundChallenge", XrmoptionSepArg, NULL },
1680 { "-soundRequest", "soundRequest", XrmoptionSepArg, NULL },
1681 { "-soundSeek", "soundSeek", XrmoptionSepArg, NULL },
1682 { "-soundMove", "soundMove", XrmoptionSepArg, NULL },
1683 { "-soundIcsWin", "soundIcsWin", XrmoptionSepArg, NULL },
1684 { "-soundIcsLoss", "soundIcsLoss", XrmoptionSepArg, NULL },
1685 { "-soundIcsDraw", "soundIcsDraw", XrmoptionSepArg, NULL },
1686 { "-soundIcsUnfinished", "soundIcsUnfinished", XrmoptionSepArg, NULL },
1687 { "-soundIcsAlarm", "soundIcsAlarm", XrmoptionSepArg, NULL },
1688 { "-reuseFirst", "reuseFirst", XrmoptionSepArg, NULL },
1689 { "-reuseChessPrograms", "reuseFirst", XrmoptionSepArg, NULL }, /*compat*/
1690 { "-reuse", "reuseFirst", XrmoptionNoArg, "True" },
1691 { "-xreuse", "reuseFirst", XrmoptionNoArg, "False" },
1692 { "-reuseSecond", "reuseSecond", XrmoptionSepArg, NULL },
1693 { "-reuse2", "reuseSecond", XrmoptionNoArg, "True" },
1694 { "-xreuse2", "reuseSecond", XrmoptionNoArg, "False" },
1695 { "-animateMoving", "animateMoving", XrmoptionSepArg, NULL },
1696 { "-animate", "animateMoving", XrmoptionNoArg, "True" },
1697 { "-xanimate", "animateMoving", XrmoptionNoArg, "False" },
1698 { "-animateDragging", "animateDragging", XrmoptionSepArg, NULL },
1699 { "-drag", "animateDragging", XrmoptionNoArg, "True" },
1700 { "-xdrag", "animateDragging", XrmoptionNoArg, "False" },
1701 { "-animateSpeed", "animateSpeed", XrmoptionSepArg, NULL },
1702 { "-popupExitMessage", "popupExitMessage", XrmoptionSepArg, NULL },
1703 { "-exit", "popupExitMessage", XrmoptionNoArg, "True" },
1704 { "-xexit", "popupExitMessage", XrmoptionNoArg, "False" },
1705 { "-popupMoveErrors", "popupMoveErrors", XrmoptionSepArg, NULL },
1706 { "-popup", "popupMoveErrors", XrmoptionNoArg, "True" },
1707 { "-xpopup", "popupMoveErrors", XrmoptionNoArg, "False" },
1708 { "-fontSizeTolerance", "fontSizeTolerance", XrmoptionSepArg, NULL },
1709 { "-initialMode", "initialMode", XrmoptionSepArg, NULL },
1710 { "-mode", "initialMode", XrmoptionSepArg, NULL },
1711 { "-variant", "variant", XrmoptionSepArg, NULL },
1712 { "-firstProtocolVersion", "firstProtocolVersion", XrmoptionSepArg, NULL },
1713 { "-secondProtocolVersion","secondProtocolVersion",XrmoptionSepArg, NULL },
1714 { "-showButtonBar", "showButtonBar", XrmoptionSepArg, NULL },
1715 { "-buttons", "showButtonBar", XrmoptionNoArg, "True" },
1716 { "-xbuttons", "showButtonBar", XrmoptionNoArg, "False" },
1717 { "-lowTimeWarningColor", "lowTimeWarningColor", XrmoptionSepArg, NULL },
1718 { "-lowTimeWarning", "lowTimeWarning", XrmoptionSepArg, NULL },
1719 /* [AS,HR] New features */
1720 { "-firstScoreAbs", "firstScoreAbs", XrmoptionSepArg, NULL },
1721 { "-secondScoreAbs", "secondScoreAbs", XrmoptionSepArg, NULL },
1722 { "-pgnExtendedInfo", "pgnExtendedInfo", XrmoptionSepArg, NULL },
1723 { "-hideThinkingFromHuman", "hideThinkingFromHuman", XrmoptionSepArg, NULL },
1724 { "-adjudicateLossThreshold", "adjudicateLossThreshold", XrmoptionSepArg, NULL },
1725 { "-adjudicateDrawMoves", "adjudicateDrawMoves", XrmoptionSepArg, NULL },
1726 { "-pgnEventHeader", "pgnEventHeader", XrmoptionSepArg, NULL },
1727 { "-firstIsUCI", "firstIsUCI", XrmoptionSepArg, NULL },
1728 { "-secondIsUCI", "secondIsUCI", XrmoptionSepArg, NULL },
1729 { "-fUCI", "firstIsUCI", XrmoptionNoArg, "True" },
1730 { "-sUCI", "secondIsUCI", XrmoptionNoArg, "True" },
1731 { "-firstHasOwnBookUCI", "firstHasOwnBookUCI", XrmoptionSepArg, NULL },
1732 { "-secondHasOwnBookUCI", "secondHasOwnBookUCI", XrmoptionSepArg, NULL },
1733 { "-fNoOwnBookUCI", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1734 { "-sNoOwnBookUCI", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1735 { "-firstXBook", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1736 { "-secondXBook", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1737 { "-polyglotDir", "polyglotDir", XrmoptionSepArg, NULL },
1738 { "-usePolyglotBook", "usePolyglotBook", XrmoptionSepArg, NULL },
1739 { "-polyglotBook", "polyglotBook", XrmoptionSepArg, NULL },
1740 { "-defaultHashSize", "defaultHashSize", XrmoptionSepArg, NULL },
1741 { "-defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XrmoptionSepArg, NULL },
1742 { "-defaultPathEGTB", "defaultPathEGTB", XrmoptionSepArg, NULL },
1743 { "-defaultFrcPosition", "defaultFrcPosition", XrmoptionSepArg, NULL },
1744 { "-gameListTags", "gameListTags", XrmoptionSepArg, NULL },
1745 // [HGM] I am sure AS added many more options, but we have to fish them out, from the list in winboard.c
1747 /* [HGM,HR] User-selectable board size */
1748 { "-boardWidth", "boardWidth", XrmoptionSepArg, NULL },
1749 { "-boardHeight", "boardHeight", XrmoptionSepArg, NULL },
1750 { "-matchPause", "matchPause", XrmoptionSepArg, NULL },
1752 /* [HGM] new arguments of 4.3.xx. All except first three are back-end options, which should work immediately */
1753 { "-holdingsSize", "holdingsSize", XrmoptionSepArg, NULL }, // requires extensive front-end changes to work
1754 { "-flipBlack", "flipBlack", XrmoptionSepArg, NULL }, // requires front-end changes to work
1755 { "-allWhite", "allWhite", XrmoptionSepArg, NULL }, // requires front-end changes to work
1756 { "-pieceToCharTable", "pieceToCharTable", XrmoptionSepArg, NULL },
1757 { "-alphaRank", "alphaRank", XrmoptionSepArg, NULL },
1758 { "-testClaims", "testClaims", XrmoptionSepArg, NULL },
1759 { "-checkMates", "checkMates", XrmoptionSepArg, NULL },
1760 { "-materialDraws", "materialDraws", XrmoptionSepArg, NULL },
1761 { "-trivialDraws", "trivialDraws", XrmoptionSepArg, NULL },
1762 { "-ruleMoves", "ruleMoves", XrmoptionSepArg, NULL },
1763 { "-repeatsToDraw", "repeatsToDraw", XrmoptionSepArg, NULL },
1764 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1765 { "-userName", "userName", XrmoptionSepArg, NULL },
1766 { "-autoKibitz", "autoKibitz", XrmoptionNoArg, "True" },
1767 { "-firstTimeOdds", "firstTimeOdds", XrmoptionSepArg, NULL },
1768 { "-secondTimeOdds", "secondTimeOdds", XrmoptionSepArg, NULL },
1769 { "-timeOddsMode", "timeOddsMode", XrmoptionSepArg, NULL },
1770 { "-firstAccumulateTC", "firstAccumulateTC", XrmoptionSepArg, NULL },
1771 { "-secondAccumulateTC", "secondAccumulateTC", XrmoptionSepArg, NULL },
1772 { "-firstNPS", "firstNPS", XrmoptionSepArg, NULL },
1773 { "-secondNPS", "secondNPS", XrmoptionSepArg, NULL },
1774 { "-serverMoves", "serverMoves", XrmoptionSepArg, NULL },
1775 { "-serverPause", "serverPause", XrmoptionSepArg, NULL },
1776 { "-suppressLoadMoves", "suppressLoadMoves", XrmoptionSepArg, NULL },
1777 { "-egtFormats", "egtFormats", XrmoptionSepArg, NULL },
1778 { "-userName", "userName", XrmoptionSepArg, NULL },
1779 { "-smpCores", "smpCores", XrmoptionSepArg, NULL },
1780 { "-sameColorGames", "sameColorGames", XrmoptionSepArg, NULL },
1781 { "-rewindIndex", "rewindIndex", XrmoptionSepArg, NULL },
1782 { "-niceEngines", "niceEngines", XrmoptionSepArg, NULL },
1783 { "-delayBeforeQuit", "delayBeforeQuit", XrmoptionSepArg, NULL },
1784 { "-delayAfterQuit", "delayAfterQuit", XrmoptionSepArg, NULL },
1785 { "-nameOfDebugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1786 { "-debugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1787 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1788 { "-noGUI", "noGUI", XrmoptionNoArg, "True" },
1789 { "-firstOptions", "firstOptions", XrmoptionSepArg, NULL },
1790 { "-secondOptions", "secondOptions", XrmoptionSepArg, NULL },
1791 { "-firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1792 { "-secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1793 { "-keepAlive", "keepAlive", XrmoptionSepArg, NULL },
1794 { "-forceIllegalMoves", "forceIllegalMoves", XrmoptionNoArg, "True" },
1798 XtActionsRec boardActions[] = {
1799 { "HandleUserMove", HandleUserMove },
1800 { "AnimateUserMove", AnimateUserMove },
1801 { "FileNameAction", FileNameAction },
1802 { "AskQuestionProc", AskQuestionProc },
1803 { "AskQuestionReplyAction", AskQuestionReplyAction },
1804 { "PieceMenuPopup", PieceMenuPopup },
1805 { "WhiteClock", WhiteClock },
1806 { "BlackClock", BlackClock },
1807 { "Iconify", Iconify },
1808 { "LoadSelectedProc", LoadSelectedProc },
1809 { "LoadPositionProc", LoadPositionProc },
1810 // { "LoadNextPositionProc", LoadNextPositionProc },
1811 // { "LoadPrevPositionProc", LoadPrevPositionProc },
1812 // { "ReloadPositionProc", ReloadPositionProc },
1813 { "CopyPositionProc", CopyPositionProc },
1814 { "PastePositionProc", PastePositionProc },
1815 { "CopyGameProc", CopyGameProc },
1816 { "PasteGameProc", PasteGameProc },
1817 { "SaveGameProc", SaveGameProc },
1818 { "SavePositionProc", SavePositionProc },
1819 { "MailMoveProc", MailMoveProc },
1820 { "ReloadCmailMsgProc", ReloadCmailMsgProc },
1821 // { "MachineWhiteProc", MachineWhiteProc },
1822 // { "MachineBlackProc", MachineBlackProc },
1823 { "AnalysisModeProc", AnalyzeModeProc },
1824 { "AnalyzeFileProc", AnalyzeFileProc },
1825 // { "TwoMachinesProc", TwoMachinesProc },
1826 // { "IcsClientProc", IcsClientProc },
1827 { "EditGameProc", EditGameProc },
1828 { "EditPositionProc", EditPositionProc },
1829 { "TrainingProc", EditPositionProc },
1830 { "EngineOutputProc", EngineOutputProc}, // [HGM] Winboard_x engine-output window
1831 { "ShowGameListProc", ShowGameListProc },
1832 // { "ShowMoveListProc", HistoryShowProc},
1833 { "EditTagsProc", EditCommentProc },
1834 { "EditCommentProc", EditCommentProc },
1835 { "IcsAlarmProc", IcsAlarmProc },
1836 { "IcsInputBoxProc", IcsInputBoxProc },
1837 // { "AcceptProc", AcceptProc },
1838 // { "DeclineProc", DeclineProc },
1839 // { "RematchProc", RematchProc },
1840 // { "CallFlagProc", CallFlagProc },
1841 // { "DrawProc", DrawProc },
1842 // { "AdjournProc", AdjournProc },
1843 // { "AbortProc", AbortProc },
1844 // { "ResignProc", ResignProc },
1845 // { "AdjuWhiteProc", AdjuWhiteProc },
1846 // { "AdjuBlackProc", AdjuBlackProc },
1847 // { "AdjuDrawProc", AdjuDrawProc },
1848 { "EnterKeyProc", EnterKeyProc },
1849 // { "StopObservingProc", StopObservingProc },
1850 // { "StopExaminingProc", StopExaminingProc },
1851 // { "BackwardProc", BackwardProc },
1852 // { "ForwardProc", ForwardProc },
1853 // { "ToStartProc", ToStartProc },
1854 // { "ToEndProc", ToEndProc },
1855 // { "RevertProc", RevertProc },
1856 // { "TruncateGameProc", TruncateGameProc },
1857 // { "MoveNowProc", MoveNowProc },
1858 // { "RetractMoveProc", RetractMoveProc },
1859 { "AlwaysQueenProc", AlwaysQueenProc },
1860 { "AnimateDraggingProc", AnimateDraggingProc },
1861 { "AnimateMovingProc", AnimateMovingProc },
1862 { "AutoflagProc", AutoflagProc },
1863 { "AutoflipProc", AutoflipProc },
1864 { "AutobsProc", AutobsProc },
1865 { "AutoraiseProc", AutoraiseProc },
1866 { "AutosaveProc", AutosaveProc },
1867 { "BlindfoldProc", BlindfoldProc },
1868 { "FlashMovesProc", FlashMovesProc },
1869 // { "FlipViewProc", FlipViewProc },
1870 // { "GetMoveListProc", GetMoveListProc },
1872 { "HighlightDraggingProc", HighlightDraggingProc },
1874 { "HighlightLastMoveProc", HighlightLastMoveProc },
1875 { "IcsAlarmProc", IcsAlarmProc },
1876 { "MoveSoundProc", MoveSoundProc },
1877 { "OldSaveStyleProc", OldSaveStyleProc },
1878 { "PeriodicUpdatesProc", PeriodicUpdatesProc },
1879 { "PonderNextMoveProc", PonderNextMoveProc },
1880 { "PopupExitMessageProc", PopupExitMessageProc },
1881 { "PopupMoveErrorsProc", PopupMoveErrorsProc },
1882 { "PremoveProc", PremoveProc },
1883 { "QuietPlayProc", QuietPlayProc },
1884 // { "ShowThinkingProc", ShowThinkingProc },
1885 // { "HideThinkingProc", HideThinkingProc },
1886 { "TestLegalityProc", TestLegalityProc },
1887 // { "InfoProc", InfoProc },
1888 // { "ManProc", ManProc },
1889 // { "HintProc", HintProc },
1890 // { "BookProc", BookProc },
1891 { "AboutGameProc", AboutGameProc },
1892 { "DebugProc", DebugProc },
1893 { "NothingProc", NothingProc },
1894 { "CommentPopDown", (XtActionProc) CommentPopDown },
1895 { "EditCommentPopDown", (XtActionProc) EditCommentPopDown },
1896 { "TagsPopDown", (XtActionProc) TagsPopDown },
1897 { "ErrorPopDown", (XtActionProc) ErrorPopDown },
1898 { "ICSInputBoxPopDown", (XtActionProc) ICSInputBoxPopDown },
1899 { "AnalysisPopDown", (XtActionProc) AnalysisPopDown },
1900 { "FileNamePopDown", (XtActionProc) FileNamePopDown },
1901 { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown },
1902 { "GameListPopDown", (XtActionProc) GameListPopDown },
1903 { "PromotionPopDown", (XtActionProc) PromotionPopDown },
1904 // { "HistoryPopDown", (XtActionProc) HistoryPopDown },
1905 { "EngineOutputPopDown", (XtActionProc) EngineOutputPopDown },
1906 { "ShufflePopDown", (XtActionProc) ShufflePopDown },
1907 { "EnginePopDown", (XtActionProc) EnginePopDown },
1908 { "UciPopDown", (XtActionProc) UciPopDown },
1909 { "TimeControlPopDown", (XtActionProc) TimeControlPopDown },
1910 { "NewVariantPopDown", (XtActionProc) NewVariantPopDown },
1911 { "SettingsPopDown", (XtActionProc) SettingsPopDown },
1915 char ICSInputTranslations[] =
1916 "<Key>Return: EnterKeyProc() \n";
1918 String xboardResources[] = {
1919 "*fileName*value.translations: #override\\n <Key>Return: FileNameAction()",
1920 "*question*value.translations: #override\\n <Key>Return: AskQuestionReplyAction()",
1921 "*errorpopup*translations: #override\\n <Key>Return: ErrorPopDown()",
1925 static char *cnames[9] = { "black", "red", "green", "yellow", "blue",
1926 "magenta", "cyan", "white" };
1930 TextColors textColors[(int)NColorClasses];
1932 /* String is: "fg, bg, attr". Which is 0, 1, 2 */
1934 parse_color(str, which)
1938 char *p, buf[100], *d;
1941 if (strlen(str) > 99) /* watch bounds on buf */
1946 for (i=0; i<which; ++i) {
1953 /* Could be looking at something like:
1955 .. in which case we want to stop on a comma also */
1956 while (*p && *p != ',' && !isalpha(*p) && !isdigit(*p))
1960 return -1; /* Use default for empty field */
1963 if (which == 2 || isdigit(*p))
1966 while (*p && isalpha(*p))
1971 for (i=0; i<8; ++i) {
1972 if (!StrCaseCmp(buf, cnames[i]))
1973 return which? (i+40) : (i+30);
1975 if (!StrCaseCmp(buf, "default")) return -1;
1977 fprintf(stderr, _("%s: unrecognized color %s\n"), programName, buf);
1982 parse_cpair(cc, str)
1986 if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {
1987 fprintf(stderr, _("%s: can't parse foreground color in `%s'\n"),
1992 /* bg and attr are optional */
1993 textColors[(int)cc].bg = parse_color(str, 1);
1994 if ((textColors[(int)cc].attr = parse_color(str, 2)) < 0) {
1995 textColors[(int)cc].attr = 0;
2001 /* Arrange to catch delete-window events */
2002 Atom wm_delete_window;
2004 CatchDeleteWindow(Widget w, String procname)
2007 XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
2008 snprintf(buf, sizeof(buf), "<Message>WM_PROTOCOLS: %s() \n", procname);
2009 XtAugmentTranslations(w, XtParseTranslationTable(buf));
2015 /* this should raise the board to the top */
2016 gtk_window_present(GTK_WINDOW(GUI_Window));
2020 #define BoardSize int
2021 void InitDrawingSizes(BoardSize boardSize, int flags)
2022 { // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
2023 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2025 XtGeometryResult gres;
2028 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2029 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2031 timerWidth = (boardWidth - sep) / 2;
2033 if (appData.titleInWindow)
2038 w = boardWidth - 2*bor;
2042 w = boardWidth - w - sep - 2*bor - 2; // WIDTH_FUDGE
2046 if(!formWidget) return;
2049 * Inhibit shell resizing.
2052 // [HGM] pieces: tailor piece bitmaps to needs of specific variant
2055 for(i=0; i<4; i++) {
2057 for(p=0; p<=(int)WhiteKing; p++)
2058 xpmPieceBitmap[i][p] = xpmPieceBitmap2[i][p]; // defaults
2059 if(gameInfo.variant == VariantShogi) {
2060 xpmPieceBitmap[i][(int)WhiteCannon] = xpmPieceBitmap2[i][(int)WhiteKing+1];
2061 xpmPieceBitmap[i][(int)WhiteNightrider] = xpmPieceBitmap2[i][(int)WhiteKing+2];
2062 xpmPieceBitmap[i][(int)WhiteSilver] = xpmPieceBitmap2[i][(int)WhiteKing+3];
2063 xpmPieceBitmap[i][(int)WhiteGrasshopper] = xpmPieceBitmap2[i][(int)WhiteKing+4];
2064 xpmPieceBitmap[i][(int)WhiteQueen] = xpmPieceBitmap2[i][(int)WhiteLance];
2067 if(gameInfo.variant == VariantGothic) {
2068 xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteSilver];
2072 // [HGM] why are thee ximMasks used at all? the ximPieceBitmaps seem to be never used!
2073 for(p=0; p<=(int)WhiteKing; p++)
2074 ximMaskPm[p] = ximMaskPm2[p]; // defaults
2075 if(gameInfo.variant == VariantShogi) {
2076 ximMaskPm[(int)WhiteCannon] = ximMaskPm2[(int)WhiteKing+1];
2077 ximMaskPm[(int)WhiteNightrider] = ximMaskPm2[(int)WhiteKing+2];
2078 ximMaskPm[(int)WhiteSilver] = ximMaskPm2[(int)WhiteKing+3];
2079 ximMaskPm[(int)WhiteGrasshopper] = ximMaskPm2[(int)WhiteKing+4];
2080 ximMaskPm[(int)WhiteQueen] = ximMaskPm2[(int)WhiteLance];
2083 if(gameInfo.variant == VariantGothic) {
2084 ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[(int)WhiteSilver];
2090 for(i=0; i<2; i++) {
2092 for(p=0; p<=(int)WhiteKing; p++)
2093 pieceBitmap[i][p] = pieceBitmap2[i][p]; // defaults
2094 if(gameInfo.variant == VariantShogi) {
2095 pieceBitmap[i][(int)WhiteCannon] = pieceBitmap2[i][(int)WhiteKing+1];
2096 pieceBitmap[i][(int)WhiteNightrider] = pieceBitmap2[i][(int)WhiteKing+2];
2097 pieceBitmap[i][(int)WhiteSilver] = pieceBitmap2[i][(int)WhiteKing+3];
2098 pieceBitmap[i][(int)WhiteGrasshopper] = pieceBitmap2[i][(int)WhiteKing+4];
2099 pieceBitmap[i][(int)WhiteQueen] = pieceBitmap2[i][(int)WhiteLance];
2102 if(gameInfo.variant == VariantGothic) {
2103 pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteSilver];
2113 void EscapeExpand(char *p, char *q)
2114 { // [HGM] initstring: routine to shape up string arguments
2115 while(*p++ = *q++) if(p[-1] == '\\')
2117 case 'n': p[-1] = '\n'; break;
2118 case 'r': p[-1] = '\r'; break;
2119 case 't': p[-1] = '\t'; break;
2120 case '\\': p[-1] = '\\'; break;
2121 case 0: *p = 0; return;
2122 default: p[-1] = q[-1]; break;
2131 int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
2132 XSetWindowAttributes window_attributes;
2134 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2135 XrmValue vFrom, vTo;
2136 XtGeometryResult gres;
2139 int forceMono = False;
2143 // [HGM] before anything else, expand any indirection files amongst options
2144 char *argvCopy[1000]; // 1000 seems enough
2145 char newArgs[10000]; // holds actual characters
2148 srandom(time(0)); // [HGM] book: make random truly random
2151 for(i=0; i<argc; i++) {
2152 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2153 //fprintf(stderr, "arg %s\n", argv[i]);
2154 if(argv[i][0] != '@') argvCopy[j++] = argv[i]; else {
2156 FILE *f = fopen(argv[i]+1, "rb");
2157 if(f == NULL) { fprintf(stderr, _("ignore %s\n"), argv[i]); continue; } // do not expand non-existing
2158 argvCopy[j++] = newArgs + k; // get ready for first argument from file
2159 while((c = fgetc(f)) != EOF) { // each line of file inserts 1 argument in the list
2161 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2162 newArgs[k++] = 0; // terminate current arg
2163 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2164 argvCopy[j++] = newArgs + k; // get ready for next
2166 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2180 setbuf(stdout, NULL);
2181 setbuf(stderr, NULL);
2184 programName = strrchr(argv[0], '/');
2185 if (programName == NULL)
2186 programName = argv[0];
2191 XtSetLanguageProc(NULL, NULL, NULL);
2192 bindtextdomain(PACKAGE, LOCALEDIR);
2193 textdomain(PACKAGE);
2197 XtAppInitialize(&appContext, "XBoard", shellOptions,
2198 XtNumber(shellOptions),
2199 &argc, argv, xboardResources, NULL, 0);
2202 gtk_init (&argc, &argv);
2204 /* parse glade file to build widgets */
2206 builder = gtk_builder_new ();
2207 gtk_builder_add_from_file (builder, "gtk-interface.xml", NULL);
2209 /* test if everything worked ok */
2211 GUI_Window = GTK_WIDGET (gtk_builder_get_object (builder, "MainWindow"));
2212 if(!GUI_Window) printf("Error: gtk_builder didn't work!\n");
2214 GUI_History = GTK_WIDGET (gtk_builder_get_object (builder, "MoveHistory"));
2215 if(!GUI_History) printf("Error: gtk_builder didn't work!\n");
2217 GUI_Menubar = GTK_WIDGET (gtk_builder_get_object (builder, "MenuBar"));
2218 if(!GUI_Menubar) printf("Error: gtk_builder didn't work!\n");
2219 GUI_Timer = GTK_WIDGET (gtk_builder_get_object (builder, "Timer"));
2220 if(!GUI_Timer) printf("Error: gtk_builder didn't work!\n");
2221 GUI_Buttonbar = GTK_WIDGET (gtk_builder_get_object (builder, "ButtonBar"));
2222 if(!GUI_Buttonbar) printf("Error: gtk_builder didn't work!\n");
2223 GUI_Board = GTK_WIDGET (gtk_builder_get_object (builder, "Board"));
2224 if(!GUI_Board) printf("Error: gtk_builder didn't work!\n");
2226 GUI_Whiteclock = GTK_WIDGET (gtk_builder_get_object (builder, "WhiteClock"));
2227 if(!GUI_Whiteclock) printf("Error: gtk_builder didn't work!\n");
2229 GUI_Blackclock = GTK_WIDGET (gtk_builder_get_object (builder, "BlackClock"));
2230 if(!GUI_Blackclock) printf("Error: gtk_builder didn't work!\n");
2232 LIST_MoveHistory = GTK_LIST_STORE (gtk_builder_get_object (builder, "MoveHistoryStore"));
2233 if(!LIST_MoveHistory) printf("Error: gtk_builder didn't work!\n");
2236 gtk_builder_connect_signals (builder, NULL);
2238 // don't unref the builder, since we use it to get references to widgets
2239 // g_object_unref (G_OBJECT (builder));
2241 /* end parse glade file */
2245 fprintf(stderr, _("%s: unrecognized argument %s\n"),
2246 programName, argv[1]);
2248 fprintf(stderr, "Recognized options:\n");
2249 for(i = 0; i < XtNumber(shellOptions); i++)
2251 /* print first column */
2252 j = fprintf(stderr, " %s%s", shellOptions[i].option,
2253 (shellOptions[i].argKind == XrmoptionSepArg
2255 /* print second column and end line */
2256 if (++i < XtNumber(shellOptions))
2258 fprintf(stderr, "%*c%s%s\n", 40 - j, ' ',
2259 shellOptions[i].option,
2260 (shellOptions[i].argKind == XrmoptionSepArg
2265 fprintf(stderr, "\n");
2272 if (p == NULL) p = "/tmp";
2273 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
2274 gameCopyFilename = (char*) malloc(i);
2275 gamePasteFilename = (char*) malloc(i);
2276 snprintf(gameCopyFilename,i, "%s/.xboard%05uc.pgn", p, getpid());
2277 snprintf(gamePasteFilename,i, "%s/.xboard%05up.pgn", p, getpid());
2279 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
2280 clientResources, XtNumber(clientResources),
2283 { // [HGM] initstring: kludge to fix bad bug. expand '\n' characters in init string and computer string.
2284 static char buf[MSG_SIZ];
2285 EscapeExpand(buf, appData.initString);
2286 appData.initString = strdup(buf);
2287 EscapeExpand(buf, appData.secondInitString);
2288 appData.secondInitString = strdup(buf);
2289 EscapeExpand(buf, appData.firstComputerString);
2290 appData.firstComputerString = strdup(buf);
2291 EscapeExpand(buf, appData.secondComputerString);
2292 appData.secondComputerString = strdup(buf);
2295 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
2298 if (chdir(chessDir) != 0) {
2299 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
2305 if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) {
2306 /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */
2307 if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL) {
2308 printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile);
2311 setbuf(debugFP, NULL);
2314 /* [HGM,HR] make sure board size is acceptable */
2315 if(appData.NrFiles > BOARD_SIZE ||
2316 appData.NrRanks > BOARD_SIZE )
2317 DisplayFatalError(_("Recompile with BOARD_SIZE > 12, to support this size"), 0, 2);
2320 /* This feature does not work; animation needs a rewrite */
2321 appData.highlightDragging = FALSE;
2325 xDisplay = XtDisplay(shellWidget);
2326 xScreen = DefaultScreen(xDisplay);
2327 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
2329 gameInfo.variant = StringToVariant(appData.variant);
2330 InitPosition(FALSE);
2332 /* calc board size */
2333 if (isdigit(appData.boardSize[0]))
2335 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
2336 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
2337 &fontPxlSize, &smallLayout, &tinyLayout);
2340 fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
2341 programName, appData.boardSize);
2346 /* Find some defaults; use the nearest known size */
2347 SizeDefaults *szd, *nearest;
2348 int distance = 99999;
2349 nearest = szd = sizeDefaults;
2350 while (szd->name != NULL)
2352 if (abs(szd->squareSize - squareSize) < distance)
2355 distance = abs(szd->squareSize - squareSize);
2356 if (distance == 0) break;
2360 if (i < 2) lineGap = nearest->lineGap;
2361 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
2362 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
2363 if (i < 5) fontPxlSize = nearest->fontPxlSize;
2364 if (i < 6) smallLayout = nearest->smallLayout;
2365 if (i < 7) tinyLayout = nearest->tinyLayout;
2370 SizeDefaults *szd = sizeDefaults;
2371 if (*appData.boardSize == NULLCHAR)
2373 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize
2374 || DisplayHeight(xDisplay, xScreen) < szd->minScreenSize)
2378 if (szd->name == NULL) szd--;
2382 while (szd->name != NULL
2383 && StrCaseCmp(szd->name, appData.boardSize) != 0)
2385 if (szd->name == NULL)
2387 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
2388 programName, appData.boardSize);
2392 squareSize = szd->squareSize;
2393 lineGap = szd->lineGap;
2394 clockFontPxlSize = szd->clockFontPxlSize;
2395 coordFontPxlSize = szd->coordFontPxlSize;
2396 fontPxlSize = szd->fontPxlSize;
2397 smallLayout = szd->smallLayout;
2398 tinyLayout = szd->tinyLayout;
2400 /* end figuring out what size to use */
2402 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2403 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2406 * Determine what fonts to use.
2408 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
2409 clockFontID = XLoadFont(xDisplay, appData.clockFont);
2410 clockFontStruct = XQueryFont(xDisplay, clockFontID);
2411 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
2412 coordFontID = XLoadFont(xDisplay, appData.coordFont);
2413 coordFontStruct = XQueryFont(xDisplay, coordFontID);
2414 appData.font = FindFont(appData.font, fontPxlSize);
2415 countFontID = XLoadFont(xDisplay, appData.coordFont); // [HGM] holdings
2416 countFontStruct = XQueryFont(xDisplay, countFontID);
2417 // appData.font = FindFont(appData.font, fontPxlSize);
2419 xdb = XtDatabase(xDisplay);
2420 XrmPutStringResource(&xdb, "*font", appData.font);
2423 * Detect if there are not enough colors available and adapt.
2425 if (DefaultDepth(xDisplay, xScreen) <= 2) {
2426 appData.monoMode = True;
2429 if (!appData.monoMode) {
2430 vFrom.addr = (caddr_t) appData.lightSquareColor;
2431 vFrom.size = strlen(appData.lightSquareColor);
2432 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2433 if (vTo.addr == NULL) {
2434 appData.monoMode = True;
2437 lightSquareColor = *(Pixel *) vTo.addr;
2440 if (!appData.monoMode) {
2441 vFrom.addr = (caddr_t) appData.darkSquareColor;
2442 vFrom.size = strlen(appData.darkSquareColor);
2443 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2444 if (vTo.addr == NULL) {
2445 appData.monoMode = True;
2448 darkSquareColor = *(Pixel *) vTo.addr;
2451 if (!appData.monoMode) {
2452 vFrom.addr = (caddr_t) appData.whitePieceColor;
2453 vFrom.size = strlen(appData.whitePieceColor);
2454 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2455 if (vTo.addr == NULL) {
2456 appData.monoMode = True;
2459 whitePieceColor = *(Pixel *) vTo.addr;
2462 if (!appData.monoMode) {
2463 vFrom.addr = (caddr_t) appData.blackPieceColor;
2464 vFrom.size = strlen(appData.blackPieceColor);
2465 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2466 if (vTo.addr == NULL) {
2467 appData.monoMode = True;
2470 blackPieceColor = *(Pixel *) vTo.addr;
2474 if (!appData.monoMode) {
2475 vFrom.addr = (caddr_t) appData.highlightSquareColor;
2476 vFrom.size = strlen(appData.highlightSquareColor);
2477 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2478 if (vTo.addr == NULL) {
2479 appData.monoMode = True;
2482 highlightSquareColor = *(Pixel *) vTo.addr;
2486 if (!appData.monoMode) {
2487 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
2488 vFrom.size = strlen(appData.premoveHighlightColor);
2489 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2490 if (vTo.addr == NULL) {
2491 appData.monoMode = True;
2494 premoveHighlightColor = *(Pixel *) vTo.addr;
2499 fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2502 if (appData.bitmapDirectory == NULL ||
2503 appData.bitmapDirectory[0] == NULLCHAR)
2504 appData.bitmapDirectory = DEF_BITMAP_DIR;
2507 if (appData.lowTimeWarning && !appData.monoMode) {
2508 vFrom.addr = (caddr_t) appData.lowTimeWarningColor;
2509 vFrom.size = strlen(appData.lowTimeWarningColor);
2510 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2511 if (vTo.addr == NULL)
2512 appData.monoMode = True;
2514 lowTimeWarningColor = *(Pixel *) vTo.addr;
2517 if (appData.monoMode && appData.debugMode) {
2518 fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2519 (unsigned long) XWhitePixel(xDisplay, xScreen),
2520 (unsigned long) XBlackPixel(xDisplay, xScreen));
2523 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
2524 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
2525 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
2526 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
2527 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
2528 parse_cpair(ColorTell, appData.colorTell) < 0 ||
2529 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
2530 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
2531 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
2532 parse_cpair(ColorNormal, appData.colorNormal) < 0)
2534 if (appData.colorize) {
2536 _("%s: can't parse color names; disabling colorization\n"),
2539 appData.colorize = FALSE;
2541 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2542 textColors[ColorNone].attr = 0;
2544 // XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2550 layoutName = "tinyLayout";
2551 } else if (smallLayout) {
2552 layoutName = "smallLayout";
2554 layoutName = "normalLayout";
2557 if (appData.titleInWindow) {
2558 /* todo check what this appdata does */
2561 if (appData.showButtonBar) {
2562 /* TODO hide button bar if requested */
2566 if (appData.titleInWindow)
2571 if (appData.showButtonBar)
2578 if (appData.showButtonBar)
2588 /* set some checkboxes in the menu according to appData */
2590 if (appData.alwaysPromoteToQueen)
2591 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Always Queen")),TRUE);
2593 if (appData.animateDragging)
2594 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Animate Dragging")),TRUE);
2596 if (appData.animate)
2597 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Animate Moving")),TRUE);
2599 if (appData.autoComment)
2600 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Comment")),TRUE);
2602 if (appData.autoCallFlag)
2603 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Flag")),TRUE);
2605 if (appData.autoFlipView)
2606 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Flip View")),TRUE);
2608 if (appData.autoObserve)
2609 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Observe")),TRUE);
2611 if (appData.autoRaiseBoard)
2612 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Raise Board")),TRUE);
2614 if (appData.autoSaveGames)
2615 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Save")),TRUE);
2617 if (appData.saveGameFile[0] != NULLCHAR)
2619 /* Can't turn this off from menu */
2620 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Save")),TRUE);
2621 gtk_action_set_sensitive(GTK_ACTION (gtk_builder_get_object (builder, "menuOptions.Auto Save")),FALSE);
2624 if (appData.blindfold)
2625 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Blindfold")),TRUE);
2627 if (appData.flashCount > 0)
2628 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Flash Moves")),TRUE);
2630 if (appData.getMoveList)
2631 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Get Move List")),TRUE);
2634 if (appData.highlightDragging)
2635 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Highlight Dragging")),TRUE);
2638 if (appData.highlightLastMove)
2639 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Highlight Last Move")),TRUE);
2641 if (appData.icsAlarm)
2642 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.ICS Alarm")),TRUE);
2644 if (appData.ringBellAfterMoves)
2645 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Move Sound")),TRUE);
2647 if (appData.oldSaveStyle)
2648 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Old Save Style")),TRUE);
2650 if (appData.periodicUpdates)
2651 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Periodic Updates")),TRUE);
2653 if (appData.ponderNextMove)
2654 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Ponder Next Move")),TRUE);
2656 if (appData.popupExitMessage)
2657 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Popup Exit Message")),TRUE);
2659 if (appData.popupMoveErrors)
2660 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Popup Move Errors")),TRUE);
2662 if (appData.premove)
2663 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Premove")),TRUE);
2665 if (appData.quietPlay)
2666 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Quit Play")),TRUE);
2668 if (appData.showCoords)
2669 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Show Coords")),TRUE);
2671 if (appData.showThinking)
2672 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Show Thinking")),TRUE);
2674 if (appData.testLegality)
2675 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Test Legality")),TRUE);
2677 /* end setting check boxes */
2679 /* load square colors */
2680 SVGLightSquare = load_pixbuf("svg/LightSquare.svg",squareSize);
2681 SVGDarkSquare = load_pixbuf("svg/DarkSquare.svg",squareSize);
2682 SVGNeutralSquare = load_pixbuf("svg/NeutralSquare.svg",squareSize);
2684 /* use two icons to indicate if it is white's or black's turn */
2685 WhiteIcon = load_pixbuf("svg/icon_white.svg",0);
2686 BlackIcon = load_pixbuf("svg/icon_black.svg",0);
2687 WindowIcon = WhiteIcon;
2688 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
2691 /* realize window */
2692 gtk_widget_show (GUI_Window);
2694 /* recalc boardsize */
2699 if (appData.animate || appData.animateDragging)
2704 if (errorExitStatus == -1) {
2705 if (appData.icsActive) {
2706 /* We now wait until we see "login:" from the ICS before
2707 sending the logon script (problems with timestamp otherwise) */
2708 /*ICSInitScript();*/
2709 if (appData.icsInputBox) ICSInputBoxPopUp();
2712 signal(SIGINT, IntSigHandler);
2713 signal(SIGTERM, IntSigHandler);
2714 if (*appData.cmailGameName != NULLCHAR) {
2715 signal(SIGUSR1, CmailSigHandler);
2718 gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes()
2722 * Create a cursor for the board widget.
2723 * (This needs to be called after the window has been created to have access to board-window)
2726 BoardCursor = gdk_cursor_new(GDK_HAND2);
2727 gdk_window_set_cursor(GUI_Board->window, BoardCursor);
2728 gdk_cursor_destroy(BoardCursor);
2733 if (appData.debugMode) fclose(debugFP); // [DM] debug
2740 if (appData.icsActive && oldICSInteractionTitle != NULL) {
2741 DisplayIcsInteractionTitle(oldICSInteractionTitle);
2743 unlink(gameCopyFilename);
2744 unlink(gamePasteFilename);
2755 CmailSigHandler(sig)
2761 signal(SIGUSR1, SIG_IGN); /* suspend handler */
2763 /* Activate call-back function CmailSigHandlerCallBack() */
2764 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
2766 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
2770 CmailSigHandlerCallBack(isr, closure, message, count, error)
2778 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
2780 /**** end signal code ****/
2790 f = fopen(appData.icsLogon, "r");
2796 strcat(buf, appData.icsLogon);
2797 f = fopen(buf, "r");
2801 ProcessICSInitScript(f);
2808 EditCommentPopDown();
2814 SetMenuEnables(enab)
2819 if (!builder) return;
2820 while (enab->name != NULL) {
2821 o = gtk_builder_get_object(builder, enab->name);
2822 if(GTK_IS_WIDGET(o))
2823 gtk_widget_set_sensitive(GTK_WIDGET (o),enab->value);
2826 if(GTK_IS_ACTION(o))
2827 gtk_action_set_sensitive(GTK_ACTION (o),enab->value);
2829 DisplayError(enab->name, 0);
2837 SetMenuEnables(icsEnables);
2840 if (appData.zippyPlay && !appData.noChessProgram) /* [DM] icsEngineAnalyze */
2841 {}; // XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
2848 SetMenuEnables(ncpEnables);
2854 SetMenuEnables(gnuEnables);
2860 SetMenuEnables(cmailEnables);
2866 SetMenuEnables(trainingOnEnables);
2867 if (appData.showButtonBar) {
2868 // XtSetSensitive(buttonBarWidget, False);
2874 SetTrainingModeOff()
2876 SetMenuEnables(trainingOffEnables);
2877 if (appData.showButtonBar) {
2878 // XtSetSensitive(buttonBarWidget, True);
2883 SetUserThinkingEnables()
2885 if (appData.noChessProgram) return;
2886 SetMenuEnables(userThinkingEnables);
2890 SetMachineThinkingEnables()
2892 if (appData.noChessProgram) return;
2893 SetMenuEnables(machineThinkingEnables);
2895 case MachinePlaysBlack:
2896 case MachinePlaysWhite:
2897 case TwoMachinesPlay:
2898 // XtSetSensitive(XtNameToWidget(menuBarWidget,
2899 // ModeToWidgetName(gameMode)), True);
2906 #define Abs(n) ((n)<0 ? -(n) : (n))
2909 * Find a font that matches "pattern" that is as close as
2910 * possible to the targetPxlSize. Prefer fonts that are k
2911 * pixels smaller to fonts that are k pixels larger. The
2912 * pattern must be in the X Consortium standard format,
2913 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
2914 * The return value should be freed with XtFree when no
2917 char *FindFont(pattern, targetPxlSize)
2921 char **fonts, *p, *best, *scalable, *scalableTail;
2922 int i, j, nfonts, minerr, err, pxlSize;
2925 char **missing_list;
2927 char *def_string, *base_fnt_lst, strInt[3];
2929 XFontStruct **fnt_list;
2931 base_fnt_lst = calloc(1, strlen(pattern) + 3);
2932 sprintf(strInt, "%d", targetPxlSize);
2933 p = strstr(pattern, "--");
2934 strncpy(base_fnt_lst, pattern, p - pattern + 2);
2935 strcat(base_fnt_lst, strInt);
2936 strcat(base_fnt_lst, strchr(p + 2, '-'));
2938 if ((fntSet = XCreateFontSet(xDisplay,
2942 &def_string)) == NULL) {
2944 fprintf(stderr, _("Unable to create font set.\n"));
2948 nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
2950 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
2952 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
2953 programName, pattern);
2961 for (i=0; i<nfonts; i++) {
2964 if (*p != '-') continue;
2966 if (*p == NULLCHAR) break;
2967 if (*p++ == '-') j++;
2969 if (j < 7) continue;
2972 scalable = fonts[i];
2975 err = pxlSize - targetPxlSize;
2976 if (Abs(err) < Abs(minerr) ||
2977 (minerr > 0 && err < 0 && -err == minerr)) {
2983 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
2984 /* If the error is too big and there is a scalable font,
2985 use the scalable font. */
2986 int headlen = scalableTail - scalable;
2987 p = (char *) XtMalloc(strlen(scalable) + 10);
2988 while (isdigit(*scalableTail)) scalableTail++;
2989 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
2991 p = (char *) XtMalloc(strlen(best) + 1);
2994 if (appData.debugMode) {
2995 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
2996 pattern, targetPxlSize, p);
2999 if (missing_count > 0)
3000 XFreeStringList(missing_list);
3001 XFreeFontSet(xDisplay, fntSet);
3003 XFreeFontNames(fonts);
3010 /* GCs are not needed anymore for GTK just left them in here for the moment, since there is a lot of X-code still around that's wants them*/
3012 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
3013 | GCBackground | GCFunction | GCPlaneMask;
3014 XGCValues gc_values;
3017 gc_values.plane_mask = AllPlanes;
3018 gc_values.line_width = lineGap;
3019 gc_values.line_style = LineSolid;
3020 gc_values.function = GXcopy;
3022 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3023 gc_values.background = XWhitePixel(xDisplay, xScreen);
3024 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
3025 XSetFont(xDisplay, coordGC, coordFontID);
3027 if (appData.monoMode) {
3028 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3029 gc_values.background = XBlackPixel(xDisplay, xScreen);
3030 lightSquareGC = wbPieceGC
3031 = XtGetGC(shellWidget, value_mask, &gc_values);
3033 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3034 gc_values.background = XWhitePixel(xDisplay, xScreen);
3035 darkSquareGC = bwPieceGC
3036 = XtGetGC(shellWidget, value_mask, &gc_values);
3038 if (DefaultDepth(xDisplay, xScreen) == 1) {
3039 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3040 gc_values.function = GXcopyInverted;
3041 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3042 gc_values.function = GXcopy;
3043 if (XBlackPixel(xDisplay, xScreen) == 1) {
3044 bwPieceGC = darkSquareGC;
3045 wbPieceGC = copyInvertedGC;
3047 bwPieceGC = copyInvertedGC;
3048 wbPieceGC = lightSquareGC;
3052 gc_values.foreground = lightSquareColor;
3053 gc_values.background = darkSquareColor;
3054 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3056 gc_values.foreground = darkSquareColor;
3057 gc_values.background = lightSquareColor;
3058 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3060 gc_values.foreground = jailSquareColor;
3061 gc_values.background = jailSquareColor;
3062 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3064 gc_values.foreground = whitePieceColor;
3065 gc_values.background = darkSquareColor;
3066 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3068 gc_values.foreground = whitePieceColor;
3069 gc_values.background = lightSquareColor;
3070 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3072 gc_values.foreground = whitePieceColor;
3073 gc_values.background = jailSquareColor;
3074 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3076 gc_values.foreground = blackPieceColor;
3077 gc_values.background = darkSquareColor;
3078 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3080 gc_values.foreground = blackPieceColor;
3081 gc_values.background = lightSquareColor;
3082 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3084 gc_values.foreground = blackPieceColor;
3085 gc_values.background = jailSquareColor;
3086 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3095 for(i=0;i<MAXPIECES;i++)
3099 g_free(SVGpieces[i]);
3106 SVGLightSquare = load_pixbuf("svg/LightSquare.svg",squareSize);
3107 SVGDarkSquare = load_pixbuf("svg/DarkSquare.svg",squareSize);
3108 SVGNeutralSquare = load_pixbuf("svg/NeutralSquare.svg",squareSize);
3111 /* get some defaults going */
3112 for(i=WhitePawn; i<DemotePiece+1; i++)
3113 SVGpieces[i] = load_pixbuf("svg/NeutralSquare.svg",squareSize);
3115 SVGpieces[WhitePawn] = load_pixbuf("svg/WhitePawn.svg",squareSize);
3116 SVGpieces[WhiteKnight] = load_pixbuf("svg/WhiteKnight.svg",squareSize);
3117 SVGpieces[WhiteBishop] = load_pixbuf("svg/WhiteBishop.svg",squareSize);
3118 SVGpieces[WhiteRook] = load_pixbuf("svg/WhiteRook.svg",squareSize);
3119 SVGpieces[WhiteQueen] = load_pixbuf("svg/WhiteQueen.svg",squareSize);
3120 SVGpieces[WhiteKing] = load_pixbuf("svg/WhiteKing.svg",squareSize);
3122 SVGpieces[BlackPawn] = load_pixbuf("svg/BlackPawn.svg",squareSize);
3123 SVGpieces[BlackKnight] = load_pixbuf("svg/BlackKnight.svg",squareSize);
3124 SVGpieces[BlackBishop] = load_pixbuf("svg/BlackBishop.svg",squareSize);
3125 SVGpieces[BlackRook] = load_pixbuf("svg/BlackRook.svg",squareSize);
3126 SVGpieces[BlackQueen] = load_pixbuf("svg/BlackQueen.svg",squareSize);
3127 SVGpieces[BlackKing] = load_pixbuf("svg/BlackKing.svg",squareSize);
3133 static void MenuBarSelect(w, addr, index)
3138 XtActionProc proc = (XtActionProc) addr;
3140 (proc)(NULL, NULL, NULL, NULL);
3143 void CreateMenuBarPopup(parent, name, mb)
3153 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3156 XtSetArg(args[j], XtNleftMargin, 20); j++;
3157 XtSetArg(args[j], XtNrightMargin, 20); j++;
3159 while (mi->string != NULL) {
3160 if (strcmp(mi->string, "----") == 0) {
3161 entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
3164 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string)));
3165 entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass,
3167 XtAddCallback(entry, XtNcallback,
3168 (XtCallbackProc) MenuBarSelect,
3169 (caddr_t) mi->proc);
3175 Widget CreateMenuBar(mb)
3179 Widget anchor, menuBar;
3181 char menuName[MSG_SIZ];
3184 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3185 XtSetArg(args[j], XtNvSpace, 0); j++;
3186 XtSetArg(args[j], XtNborderWidth, 0); j++;
3187 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
3188 formWidget, args, j);
3190 while (mb->name != NULL) {
3191 strcpy(menuName, "menu");
3192 strcat(menuName, mb->name);
3194 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
3197 shortName[0] = _(mb->name)[0];
3198 shortName[1] = NULLCHAR;
3199 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
3202 XtSetArg(args[j], XtNlabel, XtNewString(_(mb->name))); j++;
3205 XtSetArg(args[j], XtNborderWidth, 0); j++;
3206 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
3208 CreateMenuBarPopup(menuBar, menuName, mb);
3214 Widget CreateButtonBar(mi)
3218 Widget button, buttonBar;
3222 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3224 XtSetArg(args[j], XtNhSpace, 0); j++;
3226 XtSetArg(args[j], XtNborderWidth, 0); j++;
3227 XtSetArg(args[j], XtNvSpace, 0); j++;
3228 buttonBar = XtCreateWidget("buttonBar", boxWidgetClass,
3229 formWidget, args, j);
3231 while (mi->string != NULL) {
3234 XtSetArg(args[j], XtNinternalWidth, 2); j++;
3235 XtSetArg(args[j], XtNborderWidth, 0); j++;
3237 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string))); j++;
3238 button = XtCreateManagedWidget(mi->string, commandWidgetClass,
3239 buttonBar, args, j);
3240 XtAddCallback(button, XtNcallback,
3241 (XtCallbackProc) MenuBarSelect,
3242 (caddr_t) mi->proc);
3249 CreatePieceMenu(name, color)
3256 ChessSquare selection;
3258 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3259 boardWidget, args, 0);
3261 for (i = 0; i < PIECE_MENU_SIZE; i++) {
3262 String item = pieceMenuStrings[color][i];
3264 if (strcmp(item, "----") == 0) {
3265 entry = XtCreateManagedWidget(item, smeLineObjectClass,
3268 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3269 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3271 selection = pieceMenuTranslation[color][i];
3272 XtAddCallback(entry, XtNcallback,
3273 (XtCallbackProc) PieceMenuSelect,
3274 (caddr_t) selection);
3275 if (selection == WhitePawn || selection == BlackPawn) {
3276 XtSetArg(args[0], XtNpopupOnEntry, entry);
3277 XtSetValues(menu, args, 1);
3290 ChessSquare selection;
3292 // whitePieceMenu = CreatePieceMenu("menuW", 0);
3293 // blackPieceMenu = CreatePieceMenu("menuB", 1);
3295 // XtRegisterGrabAction(PieceMenuPopup, True,
3296 // (unsigned)(ButtonPressMask|ButtonReleaseMask),
3297 // GrabModeAsync, GrabModeAsync);
3299 // XtSetArg(args[0], XtNlabel, _("Drop"));
3300 // dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
3301 // boardWidget, args, 1);
3302 // for (i = 0; i < DROP_MENU_SIZE; i++) {
3303 // String item = dropMenuStrings[i];
3305 // if (strcmp(item, "----") == 0) {
3306 // entry = XtCreateManagedWidget(item, smeLineObjectClass,
3307 // dropMenu, NULL, 0);
3309 // XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3310 // entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3311 // dropMenu, args, 1);
3312 // selection = dropMenuTranslation[i];
3313 // XtAddCallback(entry, XtNcallback,
3314 // (XtCallbackProc) DropMenuSelect,
3315 // (caddr_t) selection);
3320 void SetupDropMenu()
3328 for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
3329 entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
3330 p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
3331 dmEnables[i].piece);
3332 XtSetSensitive(entry, p != NULL || !appData.testLegality
3333 /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
3334 && !appData.icsActive));
3336 while (p && *p++ == dmEnables[i].piece) count++;
3337 snprintf(label, sizeof(label), "%s %d", dmEnables[i].widget, count);
3339 XtSetArg(args[j], XtNlabel, label); j++;
3340 XtSetValues(entry, args, j);
3344 void PieceMenuPopup(w, event, params, num_params)
3348 Cardinal *num_params;
3351 if (event->type != ButtonPress) return;
3352 if (errorUp) ErrorPopDown();
3356 whichMenu = params[0];
3358 case IcsPlayingWhite:
3359 case IcsPlayingBlack:
3361 case MachinePlaysWhite:
3362 case MachinePlaysBlack:
3363 if (appData.testLegality &&
3364 gameInfo.variant != VariantBughouse &&
3365 gameInfo.variant != VariantCrazyhouse) return;
3367 whichMenu = "menuD";
3373 if (((pmFromX = EventToSquare(event->xbutton.x, BOARD_WIDTH)) < 0) ||
3374 ((pmFromY = EventToSquare(event->xbutton.y, BOARD_HEIGHT)) < 0)) {
3375 pmFromX = pmFromY = -1;
3379 pmFromX = BOARD_WIDTH - 1 - pmFromX;
3381 pmFromY = BOARD_HEIGHT - 1 - pmFromY;
3383 XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
3386 static void PieceMenuSelect(w, piece, junk)
3391 if (pmFromX < 0 || pmFromY < 0) return;
3392 EditPositionMenuEvent(piece, pmFromX, pmFromY);
3395 static void DropMenuSelect(w, piece, junk)
3400 if (pmFromX < 0 || pmFromY < 0) return;
3401 DropMenuEvent(piece, pmFromX, pmFromY);
3404 void WhiteClock(w, event, prms, nprms)
3410 if (gameMode == EditPosition || gameMode == IcsExamining) {
3411 SetWhiteToPlayEvent();
3412 } else if (gameMode == IcsPlayingBlack || gameMode == MachinePlaysWhite) {
3417 void BlackClock(w, event, prms, nprms)
3423 if (gameMode == EditPosition || gameMode == IcsExamining) {
3424 SetBlackToPlayEvent();
3425 } else if (gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) {
3432 * If the user selects on a border boundary, return -1; if off the board,
3433 * return -2. Otherwise map the event coordinate to the square.
3435 int EventToSquare(x, limit)
3443 if ((x % (squareSize + lineGap)) >= squareSize)
3445 x /= (squareSize + lineGap);
3451 static void do_flash_delay(msec)
3457 static void drawHighlight(file, rank, line_type)
3458 int file, rank, line_type;
3463 if (lineGap == 0 || appData.blindfold) return;
3467 x = lineGap/2 + ((BOARD_WIDTH-1)-file) *
3468 (squareSize + lineGap);
3469 y = lineGap/2 + rank * (squareSize + lineGap);
3473 x = lineGap/2 + file * (squareSize + lineGap);
3474 y = lineGap/2 + ((BOARD_HEIGHT-1)-rank) *
3475 (squareSize + lineGap);
3479 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3481 /* draw the highlight */
3482 cairo_move_to (cr, x, y);
3483 cairo_rel_line_to (cr, 0,squareSize+lineGap);
3484 cairo_rel_line_to (cr, squareSize+lineGap,0);
3485 cairo_rel_line_to (cr, 0,-squareSize-lineGap);
3486 cairo_close_path (cr);
3488 cairo_set_line_width (cr, lineGap);
3491 /* TODO: use appdata colors */
3492 case LINE_TYPE_HIGHLIGHT:
3493 cairo_set_source_rgba (cr, 1, 1, 0, 1.0);
3496 cairo_set_source_rgba (cr, 1, 0, 0, 1.0);
3498 case LINE_TYPE_NORMAL:
3500 cairo_set_source_rgba (cr, 0, 1, 0, 1.0);
3511 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
3512 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
3515 SetHighlights(fromX, fromY, toX, toY)
3516 int fromX, fromY, toX, toY;
3518 if (hi1X != fromX || hi1Y != fromY)
3520 if (hi1X >= 0 && hi1Y >= 0)
3522 drawHighlight(hi1X, hi1Y, LINE_TYPE_NORMAL);
3524 if (fromX >= 0 && fromY >= 0)
3526 drawHighlight(fromX, fromY, LINE_TYPE_HIGHLIGHT);
3529 if (hi2X != toX || hi2Y != toY)
3531 if (hi2X >= 0 && hi2Y >= 0)
3533 drawHighlight(hi2X, hi2Y, LINE_TYPE_NORMAL);
3535 if (toX >= 0 && toY >= 0)
3537 drawHighlight(toX, toY, LINE_TYPE_HIGHLIGHT);
3551 SetHighlights(-1, -1, -1, -1);
3556 SetPremoveHighlights(fromX, fromY, toX, toY)
3557 int fromX, fromY, toX, toY;
3559 if (pm1X != fromX || pm1Y != fromY)
3561 if (pm1X >= 0 && pm1Y >= 0)
3563 drawHighlight(pm1X, pm1Y, LINE_TYPE_NORMAL);
3565 if (fromX >= 0 && fromY >= 0)
3567 drawHighlight(fromX, fromY, LINE_TYPE_PRE);
3570 if (pm2X != toX || pm2Y != toY)
3572 if (pm2X >= 0 && pm2Y >= 0)
3574 drawHighlight(pm2X, pm2Y, LINE_TYPE_NORMAL);
3576 if (toX >= 0 && toY >= 0)
3578 drawHighlight(toX, toY, LINE_TYPE_PRE);
3591 ClearPremoveHighlights()
3593 SetPremoveHighlights(-1, -1, -1, -1);
3596 static void BlankSquare(x, y, color, piece, dest)
3609 pb = SVGLightSquare;
3611 case 2: /* neutral */
3613 pb = SVGNeutralSquare;
3616 gdk_draw_pixbuf(GDK_WINDOW(GUI_Board->window),NULL,pb,0,0,x,y,-1,-1, GDK_RGB_DITHER_NORMAL, 0, 0);
3620 static void DrawPiece(piece, square_color, x, y, dest)
3622 int square_color, x, y;
3625 /* redraw background, since piece might be transparent in some areas */
3626 BlankSquare(x,y,square_color,piece,dest);
3629 gdk_draw_pixbuf(GDK_WINDOW(GUI_Board->window),NULL,
3630 GDK_PIXBUF(SVGpieces[piece]),0,0,x,y,-1,-1,
3631 GDK_RGB_DITHER_NORMAL, 0, 0);
3635 /* [HR] determine square color depending on chess variant. */
3636 static int SquareColor(row, column)
3641 if (gameInfo.variant == VariantXiangqi) {
3642 if (column >= 3 && column <= 5 && row >= 0 && row <= 2) {
3644 } else if (column >= 3 && column <= 5 && row >= 7 && row <= 9) {
3646 } else if (row <= 4) {
3652 square_color = ((column + row) % 2) == 1;
3655 /* [hgm] holdings: next line makes all holdings squares light */
3656 if(column < BOARD_LEFT || column >= BOARD_RGHT) square_color = 1;
3658 return square_color;
3661 void DrawSquare(row, column, piece, do_flash)
3662 int row, column, do_flash;
3665 int square_color, x, y;
3670 /* Calculate delay in milliseconds (2-delays per complete flash) */
3671 flash_delay = 500 / appData.flashRate;
3673 /* calculate x and y coordinates from row and column */
3676 x = lineGap + ((BOARD_WIDTH-1)-column) *
3677 (squareSize + lineGap);
3678 y = lineGap + row * (squareSize + lineGap);
3682 x = lineGap + column * (squareSize + lineGap);
3683 y = lineGap + ((BOARD_HEIGHT-1)-row) *
3684 (squareSize + lineGap);
3687 square_color = SquareColor(row, column);
3689 // [HGM] holdings: blank out area between board and holdings
3690 if ( column == BOARD_LEFT-1 || column == BOARD_RGHT
3691 || (column == BOARD_LEFT-2 && row < BOARD_HEIGHT-gameInfo.holdingsSize)
3692 || (column == BOARD_RGHT+1 && row >= gameInfo.holdingsSize) )
3694 BlankSquare(x, y, 2, EmptySquare, xBoardWindow);
3696 // [HGM] print piece counts next to holdings
3697 string[1] = NULLCHAR;
3700 cairo_text_extents_t extents;
3705 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3707 string[0] = '0' + piece;
3709 /* TODO this has to go into the font-selection */
3710 cairo_select_font_face (cr, "Sans",
3711 CAIRO_FONT_SLANT_NORMAL,
3712 CAIRO_FONT_WEIGHT_NORMAL);
3714 cairo_set_font_size (cr, 12.0);
3715 cairo_text_extents (cr, string, &extents);
3717 if (column == (flipView ? BOARD_LEFT-1 : BOARD_RGHT) )
3719 xpos= x + squareSize - extents.width - 2;
3720 ypos= y + extents.y_bearing + 1;
3722 if (column == (flipView ? BOARD_RGHT : BOARD_LEFT-1) && piece > 1)
3725 ypos = y + extents.y_bearing + 1;
3728 /* TODO mono mode? */
3729 cairo_move_to (cr, xpos, ypos);
3730 cairo_text_path (cr, string);
3731 cairo_set_source_rgb (cr, 1.0, 1.0, 1);
3732 cairo_fill_preserve (cr);
3733 cairo_set_source_rgb (cr, 0, 0, 0);
3734 cairo_set_line_width (cr, 0.1);
3743 /* square on the board */
3744 if (piece == EmptySquare || appData.blindfold)
3746 BlankSquare(x, y, square_color, piece, xBoardWindow);
3750 if (do_flash && appData.flashCount > 0)
3752 for (i=0; i<appData.flashCount; ++i)
3755 DrawPiece(piece, square_color, x, y, xBoardWindow);
3756 do_flash_delay(flash_delay);
3758 BlankSquare(x, y, square_color, piece, xBoardWindow);
3759 do_flash_delay(flash_delay);
3762 DrawPiece(piece, square_color, x, y, xBoardWindow);
3766 /* show coordinates if necessary */
3767 if(appData.showCoords)
3769 cairo_text_extents_t extents;
3773 /* TODO this has to go into the font-selection */
3774 cairo_select_font_face (cr, "Sans",
3775 CAIRO_FONT_SLANT_NORMAL,
3776 CAIRO_FONT_WEIGHT_NORMAL);
3777 cairo_set_font_size (cr, 12.0);
3779 string[1] = NULLCHAR;
3782 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3784 if (row == (flipView ? BOARD_HEIGHT-1 : 0) &&
3785 column >= BOARD_LEFT && column < BOARD_RGHT)
3787 string[0] = 'a' + column - BOARD_LEFT;
3788 cairo_text_extents (cr, string, &extents);
3790 xpos = x + squareSize - extents.width - 2;
3791 ypos = y + squareSize - extents.height - extents.y_bearing - 1;
3793 if (appData.monoMode)
3800 cairo_move_to (cr, xpos, ypos);
3801 cairo_text_path (cr, string);
3802 cairo_set_source_rgb (cr, 0.0, 0.0, 0);
3803 cairo_fill_preserve (cr);
3804 cairo_set_source_rgb (cr, 0, 1.0, 0);
3805 cairo_set_line_width (cr, 0.1);
3808 if ( column == (flipView ? BOARD_RGHT-1 : BOARD_LEFT))
3811 string[0] = ONE + row;
3812 cairo_text_extents (cr, string, &extents);
3815 ypos = y + extents.height + 1;
3817 if (appData.monoMode)
3824 cairo_move_to (cr, xpos, ypos);
3825 cairo_text_path (cr, string);
3826 cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
3827 cairo_fill_preserve (cr);
3828 cairo_set_source_rgb (cr, 0, 0, 1.0);
3829 cairo_set_line_width (cr, 0.1);
3841 /* Returns 1 if there are "too many" differences between b1 and b2
3842 (i.e. more than 1 move was made) */
3843 static int too_many_diffs(b1, b2)
3849 for (i=0; i<BOARD_HEIGHT; ++i) {
3850 for (j=0; j<BOARD_WIDTH; ++j) {
3851 if (b1[i][j] != b2[i][j]) {
3852 if (++c > 4) /* Castling causes 4 diffs */
3861 /* Matrix describing castling maneuvers */
3862 /* Row, ColRookFrom, ColKingFrom, ColRookTo, ColKingTo */
3863 static int castling_matrix[4][5] = {
3864 { 0, 0, 4, 3, 2 }, /* 0-0-0, white */
3865 { 0, 7, 4, 5, 6 }, /* 0-0, white */
3866 { 7, 0, 4, 3, 2 }, /* 0-0-0, black */
3867 { 7, 7, 4, 5, 6 } /* 0-0, black */
3870 /* Checks whether castling occurred. If it did, *rrow and *rcol
3871 are set to the destination (row,col) of the rook that moved.
3873 Returns 1 if castling occurred, 0 if not.
3875 Note: Only handles a max of 1 castling move, so be sure
3876 to call too_many_diffs() first.
3878 static int check_castle_draw(newb, oldb, rrow, rcol)
3885 /* For each type of castling... */
3886 for (i=0; i<4; ++i) {
3887 r = castling_matrix[i];
3889 /* Check the 4 squares involved in the castling move */
3891 for (j=1; j<=4; ++j) {
3892 if (newb[r[0]][r[j]] == oldb[r[0]][r[j]]) {
3899 /* All 4 changed, so it must be a castling move */
3908 static int damage[BOARD_SIZE][BOARD_SIZE];
3911 * event handler for redrawing the board
3913 void DrawPosition( repaint, board)
3914 /*Boolean*/int repaint;
3918 static int lastFlipView = 0;
3919 static int lastBoardValid = 0;
3920 static Board lastBoard;
3923 if (board == NULL) {
3924 if (!lastBoardValid) return;
3927 if (!lastBoardValid || lastFlipView != flipView) {
3928 // XtSetArg(args[0], XtNleftBitmap, (flipView ? xMarkPixmap : None));
3929 // XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flip View"),
3934 * It would be simpler to clear the window with XClearWindow()
3935 * but this causes a very distracting flicker.
3938 if (!repaint && lastBoardValid && lastFlipView == flipView)
3940 /* If too much changes (begin observing new game, etc.), don't
3942 do_flash = too_many_diffs(board, lastBoard) ? 0 : 1;
3944 /* Special check for castling so we don't flash both the king
3945 and the rook (just flash the king). */
3948 if (check_castle_draw(board, lastBoard, &rrow, &rcol))
3950 /* Draw rook with NO flashing. King will be drawn flashing later */
3951 DrawSquare(rrow, rcol, board[rrow][rcol], 0);
3952 lastBoard[rrow][rcol] = board[rrow][rcol];
3956 /* First pass -- Draw (newly) empty squares and repair damage.
3957 This prevents you from having a piece show up twice while it
3958 is flashing on its new square */
3959 for (i = 0; i < BOARD_HEIGHT; i++)
3960 for (j = 0; j < BOARD_WIDTH; j++)
3961 if ((board[i][j] != lastBoard[i][j] && board[i][j] == EmptySquare)
3964 DrawSquare(i, j, board[i][j], 0);
3965 damage[i][j] = False;
3968 /* Second pass -- Draw piece(s) in new position and flash them */
3969 for (i = 0; i < BOARD_HEIGHT; i++)
3970 for (j = 0; j < BOARD_WIDTH; j++)
3971 if (board[i][j] != lastBoard[i][j])
3973 DrawSquare(i, j, board[i][j], do_flash);
3985 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3987 cairo_set_line_width (cr, lineGap);
3989 /* TODO: use appdata colors */
3990 cairo_set_source_rgba (cr, 0, 1, 0, 1.0);
3994 for (i = 0; i < BOARD_HEIGHT + 1; i++)
3997 x2 = lineGap + BOARD_WIDTH * (squareSize + lineGap);
3998 y1 = y2 = lineGap / 2 + (i * (squareSize + lineGap));
4000 cairo_move_to (cr, x1, y1);
4001 cairo_rel_line_to (cr, x2,0);
4005 for (j = 0; j < BOARD_WIDTH + 1; j++)
4008 y2 = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
4009 x1 = x2 = lineGap / 2 + (j * (squareSize + lineGap));
4011 cairo_move_to (cr, x1, y1);
4012 cairo_rel_line_to (cr, 0, y2);
4021 for (i = 0; i < BOARD_HEIGHT; i++)
4022 for (j = 0; j < BOARD_WIDTH; j++)
4024 DrawSquare(i, j, board[i][j], 0);
4025 damage[i][j] = False;
4029 CopyBoard(lastBoard, board);
4031 lastFlipView = flipView;
4033 /* Draw highlights */
4034 if (pm1X >= 0 && pm1Y >= 0)
4036 drawHighlight(pm1X, pm1Y, LINE_TYPE_PRE);
4038 if (pm2X >= 0 && pm2Y >= 0)
4040 drawHighlight(pm2X, pm2Y, LINE_TYPE_PRE);
4042 if (hi1X >= 0 && hi1Y >= 0)
4044 drawHighlight(hi1X, hi1Y, LINE_TYPE_HIGHLIGHT);
4046 if (hi2X >= 0 && hi2Y >= 0)
4048 drawHighlight(hi2X, hi2Y, LINE_TYPE_HIGHLIGHT);
4051 /* If piece being dragged around board, must redraw that too */
4058 * event handler for parsing user moves
4060 // [HGM] This routine will need quite some reworking. Although the backend still supports the old
4061 // way of doing things, by calling UserMoveEvent() to test the legality of the move and then perform
4062 // it at the end, and doing all kind of preliminary tests here (e.g. to weed out self-captures), it
4063 // should be made to use the new way, of calling UserMoveTest early to determine the legality of the
4064 // move, (which will weed out the illegal selfcaptures and moves into the holdings, and flag promotions),
4065 // and at the end FinishMove() to perform the move after optional promotion popups.
4066 // For now I patched it to allow self-capture with King, and suppress clicks between board and holdings.
4067 void HandleUserMove(w, event, prms, nprms)
4074 Boolean saveAnimate;
4075 static int second = 0, promotionChoice = 0;
4078 if (w != boardWidget || errorExitStatus != -1) return;
4080 x = EventToSquare(event->xbutton.x, BOARD_WIDTH);
4081 y = EventToSquare(event->xbutton.y, BOARD_HEIGHT);
4082 if (!flipView && y >= 0) {
4083 y = BOARD_HEIGHT - 1 - y;
4085 if (flipView && x >= 0) {
4086 x = BOARD_WIDTH - 1 - x;
4089 if(promotionChoice) { // we are waiting for a click to indicate promotion piece
4090 if(event->type == ButtonRelease) return; // ignore upclick of click-click destination
4091 promotionChoice = FALSE; // only one chance: if click not OK it is interpreted as cancel
4092 if(appData.debugMode) fprintf(debugFP, "promotion click, x=%d, y=%d\n", x, y);
4093 if(gameInfo.holdingsWidth &&
4094 (WhiteOnMove(currentMove)
4095 ? x == BOARD_WIDTH-1 && y < gameInfo.holdingsSize && y > 0
4096 : x == 0 && y >= BOARD_HEIGHT - gameInfo.holdingsSize && y < BOARD_HEIGHT-1) ) {
4097 // click in right holdings, for determining promotion piece
4098 ChessSquare p = boards[currentMove][y][x];
4099 if(appData.debugMode) fprintf(debugFP, "square contains %d\n", (int)p);
4100 if(p != EmptySquare) {
4101 FinishMove(NormalMove, fromX, fromY, toX, toY, ToLower(PieceToChar(p)));
4106 DrawPosition(FALSE, boards[currentMove]);
4109 if (event->type == ButtonPress) ErrorPopDown();
4112 if (event->type == ButtonPress) {
4113 // XtPopdown(promotionShell);
4114 // XtDestroyWidget(promotionShell);
4115 promotionUp = False;
4123 /* [HGM] holdings: next 5 lines: ignore all clicks between board and holdings */
4124 if(event->type == ButtonPress
4125 && ( x == BOARD_LEFT-1 ||
4127 (x == BOARD_LEFT-2 && y < BOARD_HEIGHT-gameInfo.holdingsSize ) ||
4128 (x == BOARD_RGHT+1 && y >= gameInfo.holdingsSize)) )
4132 if (event->type == ButtonPress) {
4133 /* First square, prepare to drag */
4134 if (OKToStartUserMove(x, y)) {
4138 DragPieceBegin(event->xbutton.x, event->xbutton.y);
4139 if (appData.highlightDragging) {
4140 SetHighlights(x, y, -1, -1);
4148 if (event->type == ButtonRelease && x == fromX && y == fromY) {
4149 /* Click on single square in stead of drag-drop */
4150 DragPieceEnd(event->xbutton.x, event->xbutton.y);
4151 if (appData.animateDragging) {
4152 /* Undo animation damage if any */
4153 DrawPosition(FALSE, NULL);
4156 /* Second up/down in same square; just abort move */
4161 ClearPremoveHighlights();
4163 /* First upclick in same square; start click-click mode */
4164 SetHighlights(x, y, -1, -1);
4169 moveType = UserMoveTest(fromX, fromY, x, y, NULLCHAR, event->type == ButtonRelease);
4171 if (moveType == Comment) { // kludge for indicating capture-own on Press
4172 /* Clicked again on same color piece -- changed his mind */
4173 /* note that re-clicking same square always hits same color piece */
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);
4188 if(moveType == AmbiguousMove) { // kludge to indicate edit-position move
4191 DragPieceEnd(event->xbutton.x, event->xbutton.y);
4192 DrawPosition(FALSE, boards[currentMove]);
4196 /* Complete move; (x,y) is now different from (fromX, fromY) on both Press and Release */
4199 saveAnimate = appData.animate;
4200 if (event->type == ButtonPress) {
4201 /* Finish clickclick move */
4202 if (appData.animate || appData.highlightLastMove) {
4203 SetHighlights(fromX, fromY, toX, toY);
4208 /* Finish drag move */
4209 if (appData.highlightLastMove) {
4210 SetHighlights(fromX, fromY, toX, toY);
4214 DragPieceEnd(event->xbutton.x, event->xbutton.y);
4215 /* Don't animate move and drag both */
4216 appData.animate = FALSE;
4218 if (moveType == WhitePromotionKnight || moveType == BlackPromotionKnight ||
4219 (moveType == WhitePromotionQueen || moveType == BlackPromotionQueen) &&
4220 appData.alwaysPromoteToQueen) { // promotion, but no choice
4221 FinishMove(moveType, fromX, fromY, toX, toY, 'q');
4223 if (moveType == WhitePromotionQueen || moveType == BlackPromotionQueen ) {
4224 SetHighlights(fromX, fromY, toX, toY);
4225 if(gameInfo.variant == VariantSuper || gameInfo.variant == VariantGreat) {
4226 // [HGM] super: promotion to captured piece selected from holdings
4227 ChessSquare p = boards[currentMove][fromY][fromX], q = boards[currentMove][toY][toX];
4228 promotionChoice = TRUE;
4229 // kludge follows to temporarily execute move on display, without promoting yet
4230 boards[currentMove][fromY][fromX] = EmptySquare; // move Pawn to 8th rank
4231 boards[currentMove][toY][toX] = p;
4232 DrawPosition(FALSE, boards[currentMove]);
4233 boards[currentMove][fromY][fromX] = p; // take back, but display stays
4234 boards[currentMove][toY][toX] = q;
4235 DisplayMessage("Click in holdings to choose piece", "");
4239 goto skipClearingFrom; // the skipped stuff is done asynchronously by PromotionCallback
4241 if(moveType != ImpossibleMove) { // valid move, but no promotion
4242 FinishMove(moveType, fromX, fromY, toX, toY, NULLCHAR);
4243 } else { // invalid move; could have set premove
4246 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
4247 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
4250 appData.animate = saveAnimate;
4251 if (appData.animate || appData.animateDragging) {
4252 /* Undo animation damage if needed */
4253 DrawPosition(FALSE, NULL);
4257 void AnimateUserMove (Widget w, XEvent * event,
4258 String * params, Cardinal * nParams)
4260 DragPieceMove(event->xmotion.x, event->xmotion.y);
4263 Widget CommentCreate(name, text, mutable, callback, lines)
4265 int /*Boolean*/ mutable;
4266 XtCallbackProc callback;
4270 Widget shell, layout, form, edit, b_ok, b_cancel, b_clear, b_close, b_edit;
4275 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4276 XtGetValues(boardWidget, args, j);
4279 XtSetArg(args[j], XtNresizable, True); j++;
4282 XtCreatePopupShell(name, topLevelShellWidgetClass,
4283 shellWidget, args, j);
4286 XtCreatePopupShell(name, transientShellWidgetClass,
4287 shellWidget, args, j);
4290 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
4291 layoutArgs, XtNumber(layoutArgs));
4293 XtCreateManagedWidget("form", formWidgetClass, layout,
4294 formArgs, XtNumber(formArgs));
4298 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
4299 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
4301 XtSetArg(args[j], XtNstring, text); j++;
4302 XtSetArg(args[j], XtNtop, XtChainTop); j++;
4303 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4304 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4305 XtSetArg(args[j], XtNright, XtChainRight); j++;
4306 XtSetArg(args[j], XtNresizable, True); j++;
4307 XtSetArg(args[j], XtNwidth, bw_width); j++; /*force wider than buttons*/
4308 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
4309 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
4310 XtSetArg(args[j], XtNautoFill, True); j++;
4311 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
4313 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
4317 XtSetArg(args[j], XtNfromVert, edit); j++;
4318 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4319 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4320 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4321 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4323 XtCreateManagedWidget(_("ok"), commandWidgetClass, form, args, j);
4324 XtAddCallback(b_ok, XtNcallback, callback, (XtPointer) 0);
4327 XtSetArg(args[j], XtNfromVert, edit); j++;
4328 XtSetArg(args[j], XtNfromHoriz, b_ok); j++;
4329 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4330 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4331 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4332 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4334 XtCreateManagedWidget(_("cancel"), commandWidgetClass, form, args, j);
4335 XtAddCallback(b_cancel, XtNcallback, callback, (XtPointer) 0);
4338 XtSetArg(args[j], XtNfromVert, edit); j++;
4339 XtSetArg(args[j], XtNfromHoriz, b_cancel); j++;
4340 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4341 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4342 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4343 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4345 XtCreateManagedWidget(_("clear"), commandWidgetClass, form, args, j);
4346 XtAddCallback(b_clear, XtNcallback, callback, (XtPointer) 0);
4349 XtSetArg(args[j], XtNfromVert, edit); j++;
4350 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4351 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4352 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4353 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4355 XtCreateManagedWidget(_("close"), commandWidgetClass, form, args, j);
4356 XtAddCallback(b_close, XtNcallback, callback, (XtPointer) 0);
4359 XtSetArg(args[j], XtNfromVert, edit); j++;
4360 XtSetArg(args[j], XtNfromHoriz, b_close); j++;
4361 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4362 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4363 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4364 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4366 XtCreateManagedWidget(_("edit"), commandWidgetClass, form, args, j);
4367 XtAddCallback(b_edit, XtNcallback, callback, (XtPointer) 0);
4370 XtRealizeWidget(shell);
4372 if (commentX == -1) {
4375 Dimension pw_height;
4376 Dimension ew_height;
4379 XtSetArg(args[j], XtNheight, &ew_height); j++;
4380 XtGetValues(edit, args, j);
4383 XtSetArg(args[j], XtNheight, &pw_height); j++;
4384 XtGetValues(shell, args, j);
4385 commentH = pw_height + (lines - 1) * ew_height;
4386 commentW = bw_width - 16;
4388 XSync(xDisplay, False);
4390 /* This code seems to tickle an X bug if it is executed too soon
4391 after xboard starts up. The coordinates get transformed as if
4392 the main window was positioned at (0, 0).
4394 XtTranslateCoords(shellWidget,
4395 (bw_width - commentW) / 2, 0 - commentH / 2,
4396 &commentX, &commentY);
4398 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
4399 RootWindowOfScreen(XtScreen(shellWidget)),
4400 (bw_width - commentW) / 2, 0 - commentH / 2,
4405 if (commentY < 0) commentY = 0; /*avoid positioning top offscreen*/
4408 XtSetArg(args[j], XtNheight, commentH); j++;
4409 XtSetArg(args[j], XtNwidth, commentW); j++;
4410 XtSetArg(args[j], XtNx, commentX); j++;
4411 XtSetArg(args[j], XtNy, commentY); j++;
4412 XtSetValues(shell, args, j);
4413 XtSetKeyboardFocus(shell, edit);
4418 /* Used for analysis window and ICS input window */
4419 Widget MiscCreate(name, text, mutable, callback, lines)
4421 int /*Boolean*/ mutable;
4422 XtCallbackProc callback;
4426 Widget shell, layout, form, edit;
4428 Dimension bw_width, pw_height, ew_height, w, h;
4434 XtSetArg(args[j], XtNresizable, True); j++;
4437 XtCreatePopupShell(name, topLevelShellWidgetClass,
4438 shellWidget, args, j);
4441 XtCreatePopupShell(name, transientShellWidgetClass,
4442 shellWidget, args, j);
4445 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
4446 layoutArgs, XtNumber(layoutArgs));
4448 XtCreateManagedWidget("form", formWidgetClass, layout,
4449 formArgs, XtNumber(formArgs));
4453 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
4454 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
4456 XtSetArg(args[j], XtNstring, text); j++;
4457 XtSetArg(args[j], XtNtop, XtChainTop); j++;
4458 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4459 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4460 XtSetArg(args[j], XtNright, XtChainRight); j++;
4461 XtSetArg(args[j], XtNresizable, True); j++;
4462 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
4463 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
4464 XtSetArg(args[j], XtNautoFill, True); j++;
4465 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
4467 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
4469 XtRealizeWidget(shell);
4472 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4473 XtGetValues(boardWidget, args, j);
4476 XtSetArg(args[j], XtNheight, &ew_height); j++;
4477 XtGetValues(edit, args, j);
4480 XtSetArg(args[j], XtNheight, &pw_height); j++;
4481 XtGetValues(shell, args, j);
4482 h = pw_height + (lines - 1) * ew_height;
4485 XSync(xDisplay, False);
4487 /* This code seems to tickle an X bug if it is executed too soon
4488 after xboard starts up. The coordinates get transformed as if
4489 the main window was positioned at (0, 0).
4491 XtTranslateCoords(shellWidget, (bw_width - w) / 2, 0 - h / 2, &x, &y);
4493 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
4494 RootWindowOfScreen(XtScreen(shellWidget)),
4495 (bw_width - w) / 2, 0 - h / 2, &xx, &yy, &junk);
4499 if (y < 0) y = 0; /*avoid positioning top offscreen*/
4502 XtSetArg(args[j], XtNheight, h); j++;
4503 XtSetArg(args[j], XtNwidth, w); j++;
4504 XtSetArg(args[j], XtNx, x); j++;
4505 XtSetArg(args[j], XtNy, y); j++;
4506 XtSetValues(shell, args, j);
4512 static int savedIndex; /* gross that this is global */
4514 void EditCommentPopUp(index, title, text)
4523 if (text == NULL) text = "";
4525 if (editShell == NULL) {
4527 CommentCreate(title, text, True, EditCommentCallback, 4);
4528 XtRealizeWidget(editShell);
4529 CatchDeleteWindow(editShell, "EditCommentPopDown");
4531 edit = XtNameToWidget(editShell, "*form.text");
4533 XtSetArg(args[j], XtNstring, text); j++;
4534 XtSetValues(edit, args, j);
4536 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4537 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4538 XtSetValues(editShell, args, j);
4541 XtPopup(editShell, XtGrabNone);
4545 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
4546 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
4550 void EditCommentCallback(w, client_data, call_data)
4552 XtPointer client_data, call_data;
4560 XtSetArg(args[j], XtNlabel, &name); j++;
4561 XtGetValues(w, args, j);
4563 if (strcmp(name, _("ok")) == 0) {
4564 edit = XtNameToWidget(editShell, "*form.text");
4566 XtSetArg(args[j], XtNstring, &val); j++;
4567 XtGetValues(edit, args, j);
4568 ReplaceComment(savedIndex, val);
4569 EditCommentPopDown();
4570 } else if (strcmp(name, _("cancel")) == 0) {
4571 EditCommentPopDown();
4572 } else if (strcmp(name, _("clear")) == 0) {
4573 edit = XtNameToWidget(editShell, "*form.text");
4574 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
4575 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
4579 void EditCommentPopDown()
4584 if (!editUp) return;
4586 XtSetArg(args[j], XtNx, &commentX); j++;
4587 XtSetArg(args[j], XtNy, &commentY); j++;
4588 XtSetArg(args[j], XtNheight, &commentH); j++;
4589 XtSetArg(args[j], XtNwidth, &commentW); j++;
4590 XtGetValues(editShell, args, j);
4591 XtPopdown(editShell);
4594 XtSetArg(args[j], XtNleftBitmap, None); j++;
4595 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
4599 void ICSInputBoxPopUp()
4604 char *title = _("ICS Input");
4607 if (ICSInputShell == NULL) {
4608 ICSInputShell = MiscCreate(title, "", True, NULL, 1);
4609 tr = XtParseTranslationTable(ICSInputTranslations);
4610 edit = XtNameToWidget(ICSInputShell, "*form.text");
4611 XtOverrideTranslations(edit, tr);
4612 XtRealizeWidget(ICSInputShell);
4613 CatchDeleteWindow(ICSInputShell, "ICSInputBoxPopDown");
4616 edit = XtNameToWidget(ICSInputShell, "*form.text");
4618 XtSetArg(args[j], XtNstring, ""); j++;
4619 XtSetValues(edit, args, j);
4621 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4622 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4623 XtSetValues(ICSInputShell, args, j);
4626 XtPopup(ICSInputShell, XtGrabNone);
4627 XtSetKeyboardFocus(ICSInputShell, edit);
4629 ICSInputBoxUp = True;
4631 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
4632 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
4636 void ICSInputSendText()
4643 edit = XtNameToWidget(ICSInputShell, "*form.text");
4645 XtSetArg(args[j], XtNstring, &val); j++;
4646 XtGetValues(edit, args, j);
4647 SendMultiLineToICS(val);
4648 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
4649 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
4652 void ICSInputBoxPopDown()
4657 if (!ICSInputBoxUp) return;
4659 XtPopdown(ICSInputShell);
4660 ICSInputBoxUp = False;
4662 XtSetArg(args[j], XtNleftBitmap, None); j++;
4663 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
4667 void CommentPopUp(title, text)
4674 if (commentShell == NULL) {
4676 CommentCreate(title, text, False, CommentCallback, 4);
4677 XtRealizeWidget(commentShell);
4678 CatchDeleteWindow(commentShell, "CommentPopDown");
4680 edit = XtNameToWidget(commentShell, "*form.text");
4682 XtSetArg(args[j], XtNstring, text); j++;
4683 XtSetValues(edit, args, j);
4685 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4686 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4687 XtSetValues(commentShell, args, j);
4690 XtPopup(commentShell, XtGrabNone);
4691 XSync(xDisplay, False);
4696 void AnalysisPopUp(title, text)
4703 if (analysisShell == NULL) {
4704 analysisShell = MiscCreate(title, text, False, NULL, 4);
4705 XtRealizeWidget(analysisShell);
4706 CatchDeleteWindow(analysisShell, "AnalysisPopDown");
4709 edit = XtNameToWidget(analysisShell, "*form.text");
4711 XtSetArg(args[j], XtNstring, text); j++;
4712 XtSetValues(edit, args, j);
4714 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4715 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4716 XtSetValues(analysisShell, args, j);
4720 XtPopup(analysisShell, XtGrabNone);
4722 XSync(xDisplay, False);
4727 void CommentCallback(w, client_data, call_data)
4729 XtPointer client_data, call_data;
4736 XtSetArg(args[j], XtNlabel, &name); j++;
4737 XtGetValues(w, args, j);
4739 if (strcmp(name, _("close")) == 0) {
4741 } else if (strcmp(name, _("edit")) == 0) {
4748 void CommentPopDown()
4753 if (!commentUp) return;
4755 XtSetArg(args[j], XtNx, &commentX); j++;
4756 XtSetArg(args[j], XtNy, &commentY); j++;
4757 XtSetArg(args[j], XtNwidth, &commentW); j++;
4758 XtSetArg(args[j], XtNheight, &commentH); j++;
4759 XtGetValues(commentShell, args, j);
4760 XtPopdown(commentShell);
4761 XSync(xDisplay, False);
4765 void AnalysisPopDown()
4767 if (!analysisUp) return;
4768 XtPopdown(analysisShell);
4769 XSync(xDisplay, False);
4771 if (appData.icsEngineAnalyze) ExitAnalyzeMode(); /* [DM] icsEngineAnalyze */
4775 void FileNamePopUp(label, def, proc, openMode)
4782 Widget popup, layout, dialog, edit;
4788 fileProc = proc; /* I can't see a way not */
4789 fileOpenMode = openMode; /* to use globals here */
4792 XtSetArg(args[i], XtNresizable, True); i++;
4793 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
4794 XtSetArg(args[i], XtNtitle, XtNewString(_("File name prompt"))); i++;
4795 fileNameShell = popup =
4796 XtCreatePopupShell("File name prompt", transientShellWidgetClass,
4797 shellWidget, args, i);
4800 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
4801 layoutArgs, XtNumber(layoutArgs));
4804 XtSetArg(args[i], XtNlabel, label); i++;
4805 XtSetArg(args[i], XtNvalue, def); i++;
4806 XtSetArg(args[i], XtNborderWidth, 0); i++;
4807 dialog = XtCreateManagedWidget("fileName", dialogWidgetClass,
4810 XawDialogAddButton(dialog, _("ok"), FileNameCallback, (XtPointer) dialog);
4811 XawDialogAddButton(dialog, _("cancel"), FileNameCallback,
4812 (XtPointer) dialog);
4814 XtRealizeWidget(popup);
4815 CatchDeleteWindow(popup, "FileNamePopDown");
4817 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
4818 &x, &y, &win_x, &win_y, &mask);
4820 XtSetArg(args[0], XtNx, x - 10);
4821 XtSetArg(args[1], XtNy, y - 30);
4822 XtSetValues(popup, args, 2);
4824 XtPopup(popup, XtGrabExclusive);
4827 edit = XtNameToWidget(dialog, "*value");
4828 XtSetKeyboardFocus(popup, edit);
4831 void FileNamePopDown()
4833 if (!filenameUp) return;
4834 XtPopdown(fileNameShell);
4835 XtDestroyWidget(fileNameShell);
4840 void FileNameCallback(w, client_data, call_data)
4842 XtPointer client_data, call_data;
4847 XtSetArg(args[0], XtNlabel, &name);
4848 XtGetValues(w, args, 1);
4850 if (strcmp(name, _("cancel")) == 0) {
4855 FileNameAction(w, NULL, NULL, NULL);
4858 void FileNameAction(w, event, prms, nprms)
4870 name = XawDialogGetValueString(w = XtParent(w));
4872 if ((name != NULL) && (*name != NULLCHAR)) {
4874 XtPopdown(w = XtParent(XtParent(w)));
4878 p = strrchr(buf, ' ');
4885 fullname = ExpandPathName(buf);
4887 ErrorPopUp(_("Error"), _("Can't open file"), FALSE);
4890 f = fopen(fullname, fileOpenMode);
4892 DisplayError(_("Failed to open file"), errno);
4894 (void) (*fileProc)(f, index, buf);
4901 XtPopdown(w = XtParent(XtParent(w)));
4907 void PromotionPopUp()
4910 Widget dialog, layout;
4912 Dimension bw_width, pw_width;
4916 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4917 XtGetValues(boardWidget, args, j);
4920 XtSetArg(args[j], XtNresizable, True); j++;
4921 XtSetArg(args[j], XtNtitle, XtNewString(_("Promotion"))); j++;
4923 XtCreatePopupShell("Promotion", transientShellWidgetClass,
4924 shellWidget, args, j);
4926 XtCreateManagedWidget(layoutName, formWidgetClass, promotionShell,
4927 layoutArgs, XtNumber(layoutArgs));
4930 XtSetArg(args[j], XtNlabel, _("Promote to what?")); j++;
4931 XtSetArg(args[j], XtNborderWidth, 0); j++;
4932 dialog = XtCreateManagedWidget("promotion", dialogWidgetClass,
4935 if(gameInfo.variant != VariantShogi) {
4936 XawDialogAddButton(dialog, _("Queen"), PromotionCallback,
4937 (XtPointer) dialog);
4938 XawDialogAddButton(dialog, _("Rook"), PromotionCallback,
4939 (XtPointer) dialog);
4940 XawDialogAddButton(dialog, _("Bishop"), PromotionCallback,
4941 (XtPointer) dialog);
4942 XawDialogAddButton(dialog, _("Knight"), PromotionCallback,
4943 (XtPointer) dialog);
4944 if (!appData.testLegality || gameInfo.variant == VariantSuicide ||
4945 gameInfo.variant == VariantGiveaway) {
4946 XawDialogAddButton(dialog, _("King"), PromotionCallback,
4947 (XtPointer) dialog);
4949 if(gameInfo.variant == VariantCapablanca ||
4950 gameInfo.variant == VariantGothic ||
4951 gameInfo.variant == VariantCapaRandom) {
4952 XawDialogAddButton(dialog, _("Archbishop"), PromotionCallback,
4953 (XtPointer) dialog);
4954 XawDialogAddButton(dialog, _("Chancellor"), PromotionCallback,
4955 (XtPointer) dialog);
4957 } else // [HGM] shogi
4959 XawDialogAddButton(dialog, _("Promote"), PromotionCallback,
4960 (XtPointer) dialog);
4961 XawDialogAddButton(dialog, _("Defer"), PromotionCallback,
4962 (XtPointer) dialog);
4964 XawDialogAddButton(dialog, _("cancel"), PromotionCallback,
4965 (XtPointer) dialog);
4967 XtRealizeWidget(promotionShell);
4968 CatchDeleteWindow(promotionShell, "PromotionPopDown");
4971 XtSetArg(args[j], XtNwidth, &pw_width); j++;
4972 XtGetValues(promotionShell, args, j);
4974 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
4975 lineGap + squareSize/3 +
4976 ((toY == BOARD_HEIGHT-1) ^ (flipView) ?
4977 0 : 6*(squareSize + lineGap)), &x, &y);
4980 XtSetArg(args[j], XtNx, x); j++;
4981 XtSetArg(args[j], XtNy, y); j++;
4982 XtSetValues(promotionShell, args, j);
4984 XtPopup(promotionShell, XtGrabNone);
4989 void PromotionPopDown()
4991 if (!promotionUp) return;
4992 XtPopdown(promotionShell);
4993 XtDestroyWidget(promotionShell);
4994 promotionUp = False;
4997 void PromotionCallback(w, client_data, call_data)
4999 XtPointer client_data, call_data;
5005 XtSetArg(args[0], XtNlabel, &name);
5006 XtGetValues(w, args, 1);
5010 if (fromX == -1) return;
5012 if (strcmp(name, _("cancel")) == 0) {
5016 } else if (strcmp(name, _("Knight")) == 0) {
5018 } else if (strcmp(name, _("Promote")) == 0) {
5020 } else if (strcmp(name, _("Defer")) == 0) {
5023 promoChar = ToLower(name[0]);
5026 FinishMove(NormalMove, fromX, fromY, toX, toY, promoChar);
5028 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
5029 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
5034 void ErrorCallback(w, client_data, call_data)
5036 XtPointer client_data, call_data;
5039 XtPopdown(w = XtParent(XtParent(XtParent(w))));
5041 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5047 if (!errorUp) return;
5051 gtk_widget_destroy(GTK_WIDGET(GUI_Error));
5053 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5058 void ErrorPopUp(title, label, modal)
5059 char *title, *label;
5062 GUI_Error = gtk_message_dialog_new(GTK_WINDOW(GUI_Window),
5063 GTK_DIALOG_DESTROY_WITH_PARENT,
5068 gtk_window_set_title(GTK_WINDOW(GUI_Error),(gchar *) title);
5071 gtk_dialog_run(GTK_DIALOG(GUI_Error));
5072 gtk_widget_destroy(GTK_WIDGET(GUI_Error));
5076 g_signal_connect_swapped (GUI_Error, "response",
5077 G_CALLBACK (ErrorPopDownProc),
5080 gtk_widget_show(GTK_WIDGET(GUI_Error));
5086 /* Disable all user input other than deleting the window */
5087 static int frozen = 0;
5091 /* Grab by a widget that doesn't accept input */
5092 // XtAddGrab(messageWidget, TRUE, FALSE);
5096 /* Undo a FreezeUI */
5099 if (!frozen) return;
5100 // XtRemoveGrab(messageWidget);
5104 char *ModeToWidgetName(mode)
5108 case BeginningOfGame:
5109 if (appData.icsActive)
5110 return "menuMode.ICS Client";
5111 else if (appData.noChessProgram ||
5112 *appData.cmailGameName != NULLCHAR)
5113 return "menuMode.Edit Game";
5115 return "menuMode.Machine Black";
5116 case MachinePlaysBlack:
5117 return "menuMode.Machine Black";
5118 case MachinePlaysWhite:
5119 return "menuMode.Machine White";
5121 return "menuMode.Analysis Mode";
5123 return "menuMode.Analyze File";
5124 case TwoMachinesPlay:
5125 return "menuMode.Two Machines";
5127 return "menuMode.Edit Game";
5128 case PlayFromGameFile:
5129 return "menuFile.Load Game";
5131 return "menuMode.Edit Position";
5133 return "menuMode.Training";
5134 case IcsPlayingWhite:
5135 case IcsPlayingBlack:
5139 return "menuMode.ICS Client";
5146 void ModeHighlight()
5148 static int oldPausing = FALSE;
5149 static GameMode oldmode = (GameMode) -1;
5152 // todo this toggling of the pause button doesn't seem to work?
5153 // e.g. select pause from buttonbar doesn't activate menumode.pause
5155 // if (!boardWidget || !XtIsRealized(boardWidget)) return;
5157 if (pausing != oldPausing) {
5158 oldPausing = pausing;
5159 gtk_button_set_relief(GTK_BUTTON (gtk_builder_get_object (builder, "menuMode.Pause")),pausing?GTK_RELIEF_NORMAL:GTK_RELIEF_NONE);
5160 /* toggle background color in showbuttonbar */
5161 if (appData.showButtonBar) {
5163 gtk_button_pressed(GTK_BUTTON (gtk_builder_get_object (builder, "buttonbar.Pause")));
5165 gtk_button_released(GTK_BUTTON (gtk_builder_get_object (builder, "buttonbar.Pause")));
5170 wname = ModeToWidgetName(oldmode);
5172 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, wname)),True);
5176 /* Maybe all the enables should be handled here, not just this one */
5177 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuMode.Training")),
5178 gameMode == Training || gameMode == PlayFromGameFile);
5183 * Button/menu procedures
5186 int LoadGamePopUp(f, gameNumber, title)
5191 cmailMsgLoaded = FALSE;
5193 if (gameNumber == 0)
5195 int error = GameListBuild(f);
5199 DisplayError(_("Cannot build game list"), error);
5201 else if (!ListEmpty(&gameList)
5202 && ((ListGame *) gameList.tailPred)->number > 1)
5204 GameListPopUp(f, title);
5212 return LoadGame(f, gameNumber, title, FALSE);
5215 void LoadPositionProc(w, event, prms, nprms)
5221 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
5224 FileNamePopUp(_("Load position file name?"), "", LoadPosition, "rb");
5227 void SaveGameProc(w, event, prms, nprms)
5233 FileNamePopUp(_("Save game file name?"),
5234 DefaultFileName(appData.oldSaveStyle ? "game" : "pgn"),
5238 void SavePositionProc(w, event, prms, nprms)
5244 FileNamePopUp(_("Save position file name?"),
5245 DefaultFileName(appData.oldSaveStyle ? "pos" : "fen"),
5249 void ReloadCmailMsgProc(w, event, prms, nprms)
5255 ReloadCmailMsgEvent(FALSE);
5258 void MailMoveProc(w, event, prms, nprms)
5267 /* this variable is shared between CopyPositionProc and SendPositionSelection */
5268 static char *selected_fen_position=NULL;
5271 SendPositionSelection(Widget w, Atom *selection, Atom *target,
5272 Atom *type_return, XtPointer *value_return,
5273 unsigned long *length_return, int *format_return)
5275 char *selection_tmp;
5277 if (!selected_fen_position) return False; /* should never happen */
5278 if (*target == XA_STRING){
5279 /* note: since no XtSelectionDoneProc was registered, Xt will
5280 * automatically call XtFree on the value returned. So have to
5281 * make a copy of it allocated with XtMalloc */
5282 selection_tmp= XtMalloc(strlen(selected_fen_position)+16);
5283 strcpy(selection_tmp, selected_fen_position);
5285 *value_return=selection_tmp;
5286 *length_return=strlen(selection_tmp);
5287 *type_return=XA_STRING;
5288 *format_return = 8; /* bits per byte */
5295 /* note: when called from menu all parameters are NULL, so no clue what the
5296 * Widget which was clicked on was, or what the click event was
5298 void CopyPositionProc(w, event, prms, nprms)
5306 if (selected_fen_position) free(selected_fen_position);
5307 selected_fen_position = (char *)PositionToFEN(currentMove, NULL);
5308 if (!selected_fen_position) return;
5309 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
5311 SendPositionSelection,
5312 NULL/* lose_ownership_proc */ ,
5313 NULL/* transfer_done_proc */);
5315 free(selected_fen_position);
5316 selected_fen_position=NULL;
5320 /* function called when the data to Paste is ready */
5322 PastePositionCB(Widget w, XtPointer client_data, Atom *selection,
5323 Atom *type, XtPointer value, unsigned long *len, int *format)
5326 if (value==NULL || *len==0) return; /* nothing had been selected to copy */
5327 fenstr[*len]='\0'; /* normally this string is terminated, but be safe */
5328 EditPositionPasteFEN(fenstr);
5332 /* called when Paste Position button is pressed,
5333 * all parameters will be NULL */
5334 void PastePositionProc(w, event, prms, nprms)
5340 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
5341 /* (XtSelectionCallbackProc) */ PastePositionCB,
5342 NULL, /* client_data passed to PastePositionCB */
5344 /* better to use the time field from the event that triggered the
5345 * call to this function, but that isn't trivial to get
5353 SendGameSelection(Widget w, Atom *selection, Atom *target,
5354 Atom *type_return, XtPointer *value_return,
5355 unsigned long *length_return, int *format_return)
5357 char *selection_tmp;
5359 if (*target == XA_STRING){
5360 FILE* f = fopen(gameCopyFilename, "r");
5363 if (f == NULL) return False;
5367 selection_tmp = XtMalloc(len + 1);
5368 count = fread(selection_tmp, 1, len, f);
5370 XtFree(selection_tmp);
5373 selection_tmp[len] = NULLCHAR;
5374 *value_return = selection_tmp;
5375 *length_return = len;
5376 *type_return = XA_STRING;
5377 *format_return = 8; /* bits per byte */
5384 /* note: when called from menu all parameters are NULL, so no clue what the
5385 * Widget which was clicked on was, or what the click event was
5387 void CopyGameProc(w, event, prms, nprms)
5395 ret = SaveGameToFile(gameCopyFilename, FALSE);
5398 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
5401 NULL/* lose_ownership_proc */ ,
5402 NULL/* transfer_done_proc */);
5405 /* function called when the data to Paste is ready */
5407 PasteGameCB(Widget w, XtPointer client_data, Atom *selection,
5408 Atom *type, XtPointer value, unsigned long *len, int *format)
5411 if (value == NULL || *len == 0) {
5412 return; /* nothing had been selected to copy */
5414 f = fopen(gamePasteFilename, "w");
5416 DisplayError(_("Can't open temp file"), errno);
5419 fwrite(value, 1, *len, f);
5422 LoadGameFromFile(gamePasteFilename, 0, gamePasteFilename, TRUE);
5425 /* called when Paste Game button is pressed,
5426 * all parameters will be NULL */
5427 void PasteGameProc(w, event, prms, nprms)
5433 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
5434 /* (XtSelectionCallbackProc) */ PasteGameCB,
5435 NULL, /* client_data passed to PasteGameCB */
5437 /* better to use the time field from the event that triggered the
5438 * call to this function, but that isn't trivial to get
5448 SaveGameProc(NULL, NULL, NULL, NULL);
5451 void AnalyzeModeProc(w, event, prms, nprms)
5459 if (!first.analysisSupport) {
5460 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
5461 DisplayError(buf, 0);
5464 /* [DM] icsEngineAnalyze [HGM] This is horrible code; reverse the gameMode and isEngineAnalyze tests! */
5465 if (appData.icsActive) {
5466 if (gameMode != IcsObserving) {
5467 sprintf(buf,_("You are not observing a game"));
5468 DisplayError(buf, 0);
5470 if (appData.icsEngineAnalyze) {
5471 if (appData.debugMode)
5472 fprintf(debugFP, _("Found unexpected active ICS engine analyze \n"));
5478 /* if enable, use want disable icsEngineAnalyze */
5479 if (appData.icsEngineAnalyze) {
5484 appData.icsEngineAnalyze = TRUE;
5485 if (appData.debugMode)
5486 fprintf(debugFP, _("ICS engine analyze starting... \n"));
5488 if (!appData.showThinking)
5489 ShowThinkingProc(NULL,NULL);
5494 void AnalyzeFileProc(w, event, prms, nprms)
5500 if (!first.analysisSupport) {
5502 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
5503 DisplayError(buf, 0);
5508 if (!appData.showThinking)
5509 ShowThinkingProc(NULL,NULL);
5512 FileNamePopUp(_("File to analyze"), "", LoadGamePopUp, "rb");
5513 AnalysisPeriodicEvent(1);
5517 void EditGameProc(w, event, prms, nprms)
5526 void EditPositionProc(w, event, prms, nprms)
5532 EditPositionEvent();
5535 void TrainingProc(w, event, prms, nprms)
5544 void EditCommentProc(w, event, prms, nprms)
5551 EditCommentPopDown();
5557 void IcsInputBoxProc(w, event, prms, nprms)
5563 if (ICSInputBoxUp) {
5564 ICSInputBoxPopDown();
5571 void EnterKeyProc(w, event, prms, nprms)
5577 if (ICSInputBoxUp == True)
5581 void AlwaysQueenProc(w, event, prms, nprms)
5589 appData.alwaysPromoteToQueen = !appData.alwaysPromoteToQueen;
5591 if (appData.alwaysPromoteToQueen) {
5592 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5594 XtSetArg(args[0], XtNleftBitmap, None);
5596 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
5600 void AnimateDraggingProc(w, event, prms, nprms)
5608 appData.animateDragging = !appData.animateDragging;
5610 if (appData.animateDragging) {
5611 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5614 XtSetArg(args[0], XtNleftBitmap, None);
5616 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Dragging"),
5620 void AnimateMovingProc(w, event, prms, nprms)
5628 appData.animate = !appData.animate;
5630 if (appData.animate) {
5631 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5634 XtSetArg(args[0], XtNleftBitmap, None);
5636 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
5640 void AutocommProc(w, event, prms, nprms)
5648 appData.autoComment = !appData.autoComment;
5650 if (appData.autoComment) {
5651 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5653 XtSetArg(args[0], XtNleftBitmap, None);
5655 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
5660 void AutoflagProc(w, event, prms, nprms)
5668 appData.autoCallFlag = !appData.autoCallFlag;
5670 if (appData.autoCallFlag) {
5671 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5673 XtSetArg(args[0], XtNleftBitmap, None);
5675 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
5679 void AutoflipProc(w, event, prms, nprms)
5687 appData.autoFlipView = !appData.autoFlipView;
5689 if (appData.autoFlipView) {
5690 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5692 XtSetArg(args[0], XtNleftBitmap, None);
5694 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flip View"),
5698 void AutobsProc(w, event, prms, nprms)
5706 appData.autoObserve = !appData.autoObserve;
5708 if (appData.autoObserve) {
5709 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5711 XtSetArg(args[0], XtNleftBitmap, None);
5713 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
5717 void AutoraiseProc(w, event, prms, nprms)
5725 appData.autoRaiseBoard = !appData.autoRaiseBoard;
5727 if (appData.autoRaiseBoard) {
5728 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5730 XtSetArg(args[0], XtNleftBitmap, None);
5732 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Raise Board"),
5736 void AutosaveProc(w, event, prms, nprms)
5744 appData.autoSaveGames = !appData.autoSaveGames;
5746 if (appData.autoSaveGames) {
5747 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5749 XtSetArg(args[0], XtNleftBitmap, None);
5751 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
5755 void BlindfoldProc(w, event, prms, nprms)
5763 appData.blindfold = !appData.blindfold;
5765 if (appData.blindfold) {
5766 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5768 XtSetArg(args[0], XtNleftBitmap, None);
5770 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Blindfold"),
5773 DrawPosition(True, NULL);
5776 void TestLegalityProc(w, event, prms, nprms)
5784 appData.testLegality = !appData.testLegality;
5786 if (appData.testLegality) {
5787 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5789 XtSetArg(args[0], XtNleftBitmap, None);
5791 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Test Legality"),
5796 void FlashMovesProc(w, event, prms, nprms)
5804 if (appData.flashCount == 0) {
5805 appData.flashCount = 3;
5807 appData.flashCount = -appData.flashCount;
5810 if (appData.flashCount > 0) {
5811 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5813 XtSetArg(args[0], XtNleftBitmap, None);
5815 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flash Moves"),
5820 void HighlightDraggingProc(w, event, prms, nprms)
5828 appData.highlightDragging = !appData.highlightDragging;
5830 if (appData.highlightDragging) {
5831 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5833 XtSetArg(args[0], XtNleftBitmap, None);
5835 XtSetValues(XtNameToWidget(menuBarWidget,
5836 "menuOptions.Highlight Dragging"), args, 1);
5840 void HighlightLastMoveProc(w, event, prms, nprms)
5848 appData.highlightLastMove = !appData.highlightLastMove;
5850 if (appData.highlightLastMove) {
5851 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5853 XtSetArg(args[0], XtNleftBitmap, None);
5855 XtSetValues(XtNameToWidget(menuBarWidget,
5856 "menuOptions.Highlight Last Move"), args, 1);
5859 void IcsAlarmProc(w, event, prms, nprms)
5867 appData.icsAlarm = !appData.icsAlarm;
5869 if (appData.icsAlarm) {
5870 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5872 XtSetArg(args[0], XtNleftBitmap, None);
5874 XtSetValues(XtNameToWidget(menuBarWidget,
5875 "menuOptions.ICS Alarm"), args, 1);
5878 void MoveSoundProc(w, event, prms, nprms)
5886 appData.ringBellAfterMoves = !appData.ringBellAfterMoves;
5888 if (appData.ringBellAfterMoves) {
5889 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5891 XtSetArg(args[0], XtNleftBitmap, None);
5893 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
5898 void OldSaveStyleProc(w, event, prms, nprms)
5906 appData.oldSaveStyle = !appData.oldSaveStyle;
5908 if (appData.oldSaveStyle) {
5909 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5911 XtSetArg(args[0], XtNleftBitmap, None);
5913 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Old Save Style"),
5917 void PeriodicUpdatesProc(w, event, prms, nprms)
5925 PeriodicUpdatesEvent(!appData.periodicUpdates);
5927 if (appData.periodicUpdates) {
5928 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5930 XtSetArg(args[0], XtNleftBitmap, None);
5932 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Periodic Updates"),
5936 void PonderNextMoveProc(w, event, prms, nprms)
5944 PonderNextMoveEvent(!appData.ponderNextMove);
5946 if (appData.ponderNextMove) {
5947 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5949 XtSetArg(args[0], XtNleftBitmap, None);
5951 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Ponder Next Move"),
5955 void PopupExitMessageProc(w, event, prms, nprms)
5963 appData.popupExitMessage = !appData.popupExitMessage;
5965 if (appData.popupExitMessage) {
5966 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5968 XtSetArg(args[0], XtNleftBitmap, None);
5970 XtSetValues(XtNameToWidget(menuBarWidget,
5971 "menuOptions.Popup Exit Message"), args, 1);
5974 void PopupMoveErrorsProc(w, event, prms, nprms)
5982 appData.popupMoveErrors = !appData.popupMoveErrors;
5984 if (appData.popupMoveErrors) {
5985 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5987 XtSetArg(args[0], XtNleftBitmap, None);
5989 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Popup Move Errors"),
5993 void PremoveProc(w, event, prms, nprms)
6001 appData.premove = !appData.premove;
6003 if (appData.premove) {
6004 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6006 XtSetArg(args[0], XtNleftBitmap, None);
6008 XtSetValues(XtNameToWidget(menuBarWidget,
6009 "menuOptions.Premove"), args, 1);
6012 void QuietPlayProc(w, event, prms, nprms)
6020 appData.quietPlay = !appData.quietPlay;
6022 if (appData.quietPlay) {
6023 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6025 XtSetArg(args[0], XtNleftBitmap, None);
6027 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Quiet Play"),
6031 void DebugProc(w, event, prms, nprms)
6037 appData.debugMode = !appData.debugMode;
6040 void AboutGameProc(w, event, prms, nprms)
6049 void NothingProc(w, event, prms, nprms)
6058 void Iconify(w, event, prms, nprms)
6067 XtSetArg(args[0], XtNiconic, True);
6068 XtSetValues(shellWidget, args, 1);
6071 void DisplayMessage(message, extMessage)
6072 gchar *message, *extMessage;
6079 snprintf(buf, sizeof(buf), "%s %s", message, extMessage);
6082 message = extMessage;
6085 gtk_label_set_text( GTK_LABEL(gtk_builder_get_object (builder, "Messages")),message);
6090 void DisplayTitle(text)
6093 gchar title[MSG_SIZ];
6095 if (text == NULL) text = "";
6097 if (appData.titleInWindow)
6102 if (*text != NULLCHAR)
6104 strcpy(title, text);
6106 else if (appData.icsActive)
6108 snprintf(title, sizeof(title), "%s: %s", programName, appData.icsHost);
6110 else if (appData.cmailGameName[0] != NULLCHAR)
6112 snprintf(title,sizeof(title), "%s: %s", programName, "CMail");
6114 // [HGM] license: This stuff should really be done in back-end, but WinBoard already had a pop-up for it
6116 else if (gameInfo.variant == VariantGothic)
6118 strcpy(title, GOTHIC);
6122 else if (gameInfo.variant == VariantFalcon)
6124 strcpy(title, FALCON);
6127 else if (appData.noChessProgram)
6129 strcpy(title, programName);
6133 snprintf(title,sizeof(title), "%s: %s", programName, first.tidy);
6135 gtk_window_set_title(GTK_WINDOW(GUI_Window),title);
6141 void DisplayError(message, error)
6148 if (appData.debugMode || appData.matchMode) {
6149 fprintf(stderr, "%s: %s\n", programName, message);
6152 if (appData.debugMode || appData.matchMode) {
6153 fprintf(stderr, "%s: %s: %s\n",
6154 programName, message, strerror(error));
6156 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
6159 ErrorPopUp(_("Error"), message, FALSE);
6163 void DisplayMoveError(message)
6168 DrawPosition(FALSE, NULL);
6169 if (appData.debugMode || appData.matchMode) {
6170 fprintf(stderr, "%s: %s\n", programName, message);
6172 if (appData.popupMoveErrors) {
6173 ErrorPopUp(_("Error"), message, FALSE);
6175 DisplayMessage(message, "");
6180 void DisplayFatalError(message, error, status)
6186 errorExitStatus = status;
6188 fprintf(stderr, "%s: %s\n", programName, message);
6190 fprintf(stderr, "%s: %s: %s\n",
6191 programName, message, strerror(error));
6192 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
6195 if (appData.popupExitMessage && boardWidget && XtIsRealized(boardWidget)) {
6196 ErrorPopUp(status ? _("Fatal Error") : _("Exiting"), message, TRUE);
6202 void DisplayInformation(message)
6206 ErrorPopUp(_("Information"), message, TRUE);
6209 void DisplayNote(message)
6213 ErrorPopUp(_("Note"), message, FALSE);
6217 NullXErrorCheck(dpy, error_event)
6219 XErrorEvent *error_event;
6224 void DisplayIcsInteractionTitle(message)
6227 if (oldICSInteractionTitle == NULL) {
6228 /* Magic to find the old window title, adapted from vim */
6229 char *wina = getenv("WINDOWID");
6231 Window win = (Window) atoi(wina);
6232 Window root, parent, *children;
6233 unsigned int nchildren;
6234 int (*oldHandler)() = XSetErrorHandler(NullXErrorCheck);
6236 if (XFetchName(xDisplay, win, &oldICSInteractionTitle)) break;
6237 if (!XQueryTree(xDisplay, win, &root, &parent,
6238 &children, &nchildren)) break;
6239 if (children) XFree((void *)children);
6240 if (parent == root || parent == 0) break;
6243 XSetErrorHandler(oldHandler);
6245 if (oldICSInteractionTitle == NULL) {
6246 oldICSInteractionTitle = "xterm";
6249 printf("\033]0;%s\007", message);
6253 char pendingReplyPrefix[MSG_SIZ];
6254 ProcRef pendingReplyPR;
6256 void AskQuestionProc(w, event, prms, nprms)
6263 fprintf(stderr, _("AskQuestionProc needed 4 parameters, got %d\n"),
6267 AskQuestionEvent(prms[0], prms[1], prms[2], prms[3]);
6270 void AskQuestionPopDown()
6272 if (!askQuestionUp) return;
6273 XtPopdown(askQuestionShell);
6274 XtDestroyWidget(askQuestionShell);
6275 askQuestionUp = False;
6278 void AskQuestionReplyAction(w, event, prms, nprms)
6288 reply = XawDialogGetValueString(w = XtParent(w));
6289 strcpy(buf, pendingReplyPrefix);
6290 if (*buf) strcat(buf, " ");
6293 OutputToProcess(pendingReplyPR, buf, strlen(buf), &err);
6294 AskQuestionPopDown();
6296 if (err) DisplayFatalError(_("Error writing to chess program"), err, 0);
6299 void AskQuestionCallback(w, client_data, call_data)
6301 XtPointer client_data, call_data;
6306 XtSetArg(args[0], XtNlabel, &name);
6307 XtGetValues(w, args, 1);
6309 if (strcmp(name, _("cancel")) == 0) {
6310 AskQuestionPopDown();
6312 AskQuestionReplyAction(w, NULL, NULL, NULL);
6316 void AskQuestion(title, question, replyPrefix, pr)
6317 char *title, *question, *replyPrefix;
6321 Widget popup, layout, dialog, edit;
6327 strcpy(pendingReplyPrefix, replyPrefix);
6328 pendingReplyPR = pr;
6331 XtSetArg(args[i], XtNresizable, True); i++;
6332 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
6333 askQuestionShell = popup =
6334 XtCreatePopupShell(title, transientShellWidgetClass,
6335 shellWidget, args, i);
6338 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
6339 layoutArgs, XtNumber(layoutArgs));
6342 XtSetArg(args[i], XtNlabel, question); i++;
6343 XtSetArg(args[i], XtNvalue, ""); i++;
6344 XtSetArg(args[i], XtNborderWidth, 0); i++;
6345 dialog = XtCreateManagedWidget("question", dialogWidgetClass,
6348 XawDialogAddButton(dialog, _("enter"), AskQuestionCallback,
6349 (XtPointer) dialog);
6350 XawDialogAddButton(dialog, _("cancel"), AskQuestionCallback,
6351 (XtPointer) dialog);
6353 XtRealizeWidget(popup);
6354 CatchDeleteWindow(popup, "AskQuestionPopDown");
6356 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
6357 &x, &y, &win_x, &win_y, &mask);
6359 XtSetArg(args[0], XtNx, x - 10);
6360 XtSetArg(args[1], XtNy, y - 30);
6361 XtSetValues(popup, args, 2);
6363 XtPopup(popup, XtGrabExclusive);
6364 askQuestionUp = True;
6366 edit = XtNameToWidget(dialog, "*value");
6367 XtSetKeyboardFocus(popup, edit);
6375 if (*name == NULLCHAR) {
6377 } else if (strcmp(name, "$") == 0) {
6378 putc(BELLCHAR, stderr);
6381 snprintf(buf, sizeof(buf), "%s '%s' &", appData.soundProgram, name);
6389 PlaySound(appData.soundMove);
6395 PlaySound(appData.soundIcsWin);
6401 PlaySound(appData.soundIcsLoss);
6407 PlaySound(appData.soundIcsDraw);
6411 PlayIcsUnfinishedSound()
6413 PlaySound(appData.soundIcsUnfinished);
6419 PlaySound(appData.soundIcsAlarm);
6425 system("stty echo");
6431 system("stty -echo");
6435 Colorize(cc, continuation)
6440 int count, outCount, error;
6442 if (textColors[(int)cc].bg > 0) {
6443 if (textColors[(int)cc].fg > 0) {
6444 sprintf(buf, "\033[0;%d;%d;%dm", textColors[(int)cc].attr,
6445 textColors[(int)cc].fg, textColors[(int)cc].bg);
6447 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
6448 textColors[(int)cc].bg);
6451 if (textColors[(int)cc].fg > 0) {
6452 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
6453 textColors[(int)cc].fg);
6455 sprintf(buf, "\033[0;%dm", textColors[(int)cc].attr);
6458 count = strlen(buf);
6459 outCount = OutputToProcess(NoProc, buf, count, &error);
6460 if (outCount < count) {
6461 DisplayFatalError(_("Error writing to display"), error, 1);
6464 if (continuation) return;
6467 PlaySound(appData.soundShout);
6470 PlaySound(appData.soundSShout);
6473 PlaySound(appData.soundChannel1);
6476 PlaySound(appData.soundChannel);
6479 PlaySound(appData.soundKibitz);
6482 PlaySound(appData.soundTell);
6484 case ColorChallenge:
6485 PlaySound(appData.soundChallenge);
6488 PlaySound(appData.soundRequest);
6491 PlaySound(appData.soundSeek);
6502 return getpwuid(getuid())->pw_name;
6505 static char *ExpandPathName(path)
6508 static char static_buf[2000];
6509 char *d, *s, buf[2000];
6515 while (*s && isspace(*s))
6524 if (*(s+1) == '/') {
6525 strcpy(d, getpwuid(getuid())->pw_dir);
6530 *strchr(buf, '/') = 0;
6531 pwd = getpwnam(buf);
6534 fprintf(stderr, _("ERROR: Unknown user %s (in path %s)\n"),
6538 strcpy(d, pwd->pw_dir);
6539 strcat(d, strchr(s+1, '/'));
6550 static char host_name[MSG_SIZ];
6552 #if HAVE_GETHOSTNAME
6553 gethostname(host_name, MSG_SIZ);
6555 #else /* not HAVE_GETHOSTNAME */
6556 # if HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H
6557 sysinfo(SI_HOSTNAME, host_name, MSG_SIZ);
6559 # else /* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
6561 # endif/* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
6562 #endif /* not HAVE_GETHOSTNAME */
6565 guint delayedEventTimerTag = 0;
6566 DelayedEventCallback delayedEventCallback = 0;
6569 FireDelayedEvent(data)
6573 g_source_remove(delayedEventTimerTag);
6574 delayedEventTimerTag = 0;
6577 delayedEventCallback();
6583 ScheduleDelayedEvent(cb, millisec)
6584 DelayedEventCallback cb; guint millisec;
6586 if(delayedEventTimerTag && delayedEventCallback == cb)
6587 // [HGM] alive: replace, rather than add or flush identical event
6588 g_source_remove(delayedEventTimerTag);
6589 delayedEventCallback = cb;
6590 delayedEventTimerTag = g_timeout_add(millisec,(GSourceFunc) FireDelayedEvent, NULL);
6594 DelayedEventCallback
6597 if (delayedEventTimerTag)
6599 return delayedEventCallback;
6608 CancelDelayedEvent()
6610 if (delayedEventTimerTag)
6612 g_source_remove(delayedEventTimerTag);
6613 delayedEventTimerTag = 0;
6619 guint loadGameTimerTag = 0;
6621 int LoadGameTimerRunning()
6623 return loadGameTimerTag != 0;
6626 int StopLoadGameTimer()
6628 if (loadGameTimerTag != 0) {
6629 g_source_remove(loadGameTimerTag);
6630 loadGameTimerTag = 0;
6638 LoadGameTimerCallback(data)
6642 g_source_remove(loadGameTimerTag);
6643 loadGameTimerTag = 0;
6650 StartLoadGameTimer(millisec)
6654 g_timeout_add( millisec, (GSourceFunc) LoadGameTimerCallback, NULL);
6658 guint analysisClockTag = 0;
6661 AnalysisClockCallback(data)
6664 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile
6665 || appData.icsEngineAnalyze)
6667 AnalysisPeriodicEvent(0);
6668 return 1; /* keep on going */
6670 return 0; /* stop timer */
6674 StartAnalysisClock()
6677 g_timeout_add( 2000,(GSourceFunc) AnalysisClockCallback, NULL);
6681 guint clockTimerTag = 0;
6683 int ClockTimerRunning()
6685 return clockTimerTag != 0;
6688 int StopClockTimer()
6690 if (clockTimerTag != 0)
6692 g_source_remove(clockTimerTag);
6703 ClockTimerCallback(data)
6707 g_source_remove(clockTimerTag);
6715 StartClockTimer(millisec)
6718 clockTimerTag = g_timeout_add(millisec,(GSourceFunc) ClockTimerCallback,NULL);
6723 DisplayTimerLabel(w, color, timer, highlight)
6732 if (appData.clockMode) {
6733 sprintf(buf, "%s: %s", color, TimeString(timer));
6735 sprintf(buf, "%s ", color);
6737 gtk_label_set_text(GTK_LABEL(w),buf);
6739 /* check for low time warning */
6740 // Pixel foregroundOrWarningColor = timerForegroundPixel;
6743 // appData.lowTimeWarning &&
6744 // (timer / 1000) < appData.icsAlarmTime)
6745 // foregroundOrWarningColor = lowTimeWarningColor;
6747 // if (appData.clockMode) {
6748 // sprintf(buf, "%s: %s", color, TimeString(timer));
6749 // XtSetArg(args[0], XtNlabel, buf);
6751 // sprintf(buf, "%s ", color);
6752 // XtSetArg(args[0], XtNlabel, buf);
6757 // XtSetArg(args[1], XtNbackground, foregroundOrWarningColor);
6758 // XtSetArg(args[2], XtNforeground, timerBackgroundPixel);
6760 // XtSetArg(args[1], XtNbackground, timerBackgroundPixel);
6761 // XtSetArg(args[2], XtNforeground, foregroundOrWarningColor);
6764 // XtSetValues(w, args, 3);
6769 DisplayWhiteClock(timeRemaining, highlight)
6773 if(appData.noGUI) return;
6775 DisplayTimerLabel(GUI_Whiteclock, _("White"), timeRemaining, highlight);
6776 if (highlight && WindowIcon == BlackIcon)
6778 WindowIcon = WhiteIcon;
6779 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
6784 DisplayBlackClock(timeRemaining, highlight)
6788 if(appData.noGUI) return;
6790 DisplayTimerLabel(GUI_Blackclock, _("Black"), timeRemaining, highlight);
6791 if (highlight && WindowIcon == WhiteIcon)
6793 WindowIcon = BlackIcon;
6794 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
6812 int StartChildProcess(cmdLine, dir, pr)
6819 int to_prog[2], from_prog[2];
6823 if (appData.debugMode) {
6824 fprintf(stderr, "StartChildProcess (dir=\"%s\") %s\n",dir, cmdLine);
6827 /* We do NOT feed the cmdLine to the shell; we just
6828 parse it into blank-separated arguments in the
6829 most simple-minded way possible.
6832 strcpy(buf, cmdLine);
6837 if (p == NULL) break;
6842 SetUpChildIO(to_prog, from_prog);
6844 if ((pid = fork()) == 0) {
6846 // [HGM] PSWBTM: made order resistant against case where fd of created pipe was 0 or 1
6847 close(to_prog[1]); // first close the unused pipe ends
6848 close(from_prog[0]);
6849 dup2(to_prog[0], 0); // to_prog was created first, nd is the only one to use 0 or 1
6850 dup2(from_prog[1], 1);
6851 if(to_prog[0] >= 2) close(to_prog[0]); // if 0 or 1, the dup2 already cosed the original
6852 close(from_prog[1]); // and closing again loses one of the pipes!
6853 if(fileno(stderr) >= 2) // better safe than sorry...
6854 dup2(1, fileno(stderr)); /* force stderr to the pipe */
6856 if (dir[0] != NULLCHAR && chdir(dir) != 0) {
6861 nice(appData.niceEngines); // [HGM] nice: adjust priority of engine proc
6863 execvp(argv[0], argv);
6865 /* If we get here, exec failed */
6870 /* Parent process */
6872 close(from_prog[1]);
6874 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
6877 cp->fdFrom = from_prog[0];
6878 cp->fdTo = to_prog[1];
6883 // [HGM] kill: implement the 'hard killing' of AS's Winboard_x
6884 static RETSIGTYPE AlarmCallBack(int n)
6890 DestroyChildProcess(pr, signalType)
6894 ChildProc *cp = (ChildProc *) pr;
6896 if (cp->kind != CPReal) return;
6898 if (signalType == 10) { // [HGM] kill: if it does not terminate in 3 sec, kill
6899 signal(SIGALRM, AlarmCallBack);
6901 if(wait((int *) 0) == -1) { // process does not terminate on its own accord
6902 kill(cp->pid, SIGKILL); // kill it forcefully
6903 wait((int *) 0); // and wait again
6907 kill(cp->pid, signalType == 9 ? SIGKILL : SIGTERM); // [HGM] kill: use hard kill if so requested
6909 /* Process is exiting either because of the kill or because of
6910 a quit command sent by the backend; either way, wait for it to die.
6919 InterruptChildProcess(pr)
6922 ChildProc *cp = (ChildProc *) pr;
6924 if (cp->kind != CPReal) return;
6925 (void) kill(cp->pid, SIGINT); /* stop it thinking */
6928 int OpenTelnet(host, port, pr)
6933 char cmdLine[MSG_SIZ];
6935 if (port[0] == NULLCHAR) {
6936 snprintf(cmdLine, sizeof(cmdLine), "%s %s", appData.telnetProgram, host);
6938 snprintf(cmdLine, sizeof(cmdLine), "%s %s %s", appData.telnetProgram, host, port);
6940 return StartChildProcess(cmdLine, "", pr);
6943 int OpenTCP(host, port, pr)
6949 DisplayFatalError(_("Socket support is not configured in"), 0, 2);
6950 #else /* !OMIT_SOCKETS */
6952 struct sockaddr_in sa;
6954 unsigned short uport;
6957 if ((s = socket(AF_INET, SOCK_STREAM, 6)) < 0) {
6961 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
6962 sa.sin_family = AF_INET;
6963 sa.sin_addr.s_addr = INADDR_ANY;
6964 uport = (unsigned short) 0;
6965 sa.sin_port = htons(uport);
6966 if (bind(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)) < 0) {
6970 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
6971 if (!(hp = gethostbyname(host))) {
6973 if (sscanf(host, "%d.%d.%d.%d", &b0, &b1, &b2, &b3) == 4) {
6974 hp = (struct hostent *) calloc(1, sizeof(struct hostent));
6975 hp->h_addrtype = AF_INET;
6977 hp->h_addr_list = (char **) calloc(2, sizeof(char *));
6978 hp->h_addr_list[0] = (char *) malloc(4);
6979 hp->h_addr_list[0][0] = b0;
6980 hp->h_addr_list[0][1] = b1;
6981 hp->h_addr_list[0][2] = b2;
6982 hp->h_addr_list[0][3] = b3;
6987 sa.sin_family = hp->h_addrtype;
6988 uport = (unsigned short) atoi(port);
6989 sa.sin_port = htons(uport);
6990 memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);
6992 if (connect(s, (struct sockaddr *) &sa,
6993 sizeof(struct sockaddr_in)) < 0) {
6997 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7004 #endif /* !OMIT_SOCKETS */
7009 int OpenCommPort(name, pr)
7016 fd = open(name, 2, 0);
7017 if (fd < 0) return errno;
7019 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7029 int OpenLoopback(pr)
7035 SetUpChildIO(to, from);
7037 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7040 cp->fdFrom = to[0]; /* note not from[0]; we are doing a loopback */
7047 int OpenRcmd(host, user, cmd, pr)
7048 char *host, *user, *cmd;
7051 DisplayFatalError(_("internal rcmd not implemented for Unix"), 0, 1);
7055 #define INPUT_SOURCE_BUF_SIZE 8192
7064 char buf[INPUT_SOURCE_BUF_SIZE];
7069 DoInputCallback(io,cond,data)
7074 /* read input from one of the input source (for example a chess program, ICS, etc).
7075 * and call a function that will handle the input
7078 int count; /* how many bytes did we read */
7082 /* All information (callback function, file descriptor, etc) is
7083 * saved in an InputSource structure
7085 InputSource *is = (InputSource *) data;
7089 count = read(is->fd, is->unused,
7090 INPUT_SOURCE_BUF_SIZE - (is->unused - is->buf));
7094 (is->func)(is, is->closure, is->buf, count, count ? errno : 0);
7097 is->unused += count;
7099 /* break input into lines and call the callback function on each
7102 while (p < is->unused)
7104 q = memchr(p, '\n', is->unused - p);
7105 if (q == NULL) break;
7107 (is->func)(is, is->closure, p, q - p, 0);
7110 /* remember not yet used part of the buffer */
7112 while (p < is->unused)
7120 /* read maximum length of input buffer and send the whole buffer
7121 * to the callback function
7123 count = read(is->fd, is->buf, INPUT_SOURCE_BUF_SIZE);
7128 (is->func)(is, is->closure, is->buf, count, error);
7134 InputSourceRef AddInputSource(pr, lineByLine, func, closure)
7141 GIOChannel *channel;
7142 ChildProc *cp = (ChildProc *) pr;
7144 is = (InputSource *) calloc(1, sizeof(InputSource));
7145 is->lineByLine = lineByLine;
7149 is->fd = fileno(stdin);
7151 is->kind = cp->kind;
7152 is->fd = cp->fdFrom;
7155 is->unused = is->buf;
7159 // is->xid = XtAppAddInput(appContext, is->fd,
7160 // (XtPointer) (XtInputReadMask),
7161 // (XtInputCallbackProc) DoInputCallback,
7165 /* TODO: will this work on windows?*/
7166 printf("DEBUG: fd=%d %d\n",is->fd,is);
7168 channel = g_io_channel_unix_new(is->fd);
7169 g_io_channel_set_close_on_unref (channel, TRUE);
7170 is->sid = g_io_add_watch(channel, G_IO_IN,(GIOFunc) DoInputCallback, is);
7171 is->closure = closure;
7172 return (InputSourceRef) is;
7176 RemoveInputSource(isr)
7179 InputSource *is = (InputSource *) isr;
7181 if (is->sid == 0) return;
7182 g_source_remove(is->sid);
7187 int OutputToProcess(pr, message, count, outError)
7193 ChildProc *cp = (ChildProc *) pr;
7197 outCount = fwrite(message, 1, count, stdout);
7199 outCount = write(cp->fdTo, message, count);
7209 /* Output message to process, with "ms" milliseconds of delay
7210 between each character. This is needed when sending the logon
7211 script to ICC, which for some reason doesn't like the
7212 instantaneous send. */
7213 int OutputToProcessDelayed(pr, message, count, outError, msdelay)
7220 ChildProc *cp = (ChildProc *) pr;
7225 r = write(cp->fdTo, message++, 1);
7238 /**** Animation code by Hugh Fisher, DCS, ANU.
7240 Known problem: if a window overlapping the board is
7241 moved away while a piece is being animated underneath,
7242 the newly exposed area won't be updated properly.
7243 I can live with this.
7245 Known problem: if you look carefully at the animation
7246 of pieces in mono mode, they are being drawn as solid
7247 shapes without interior detail while moving. Fixing
7248 this would be a major complication for minimal return.
7251 /* Masks for XPM pieces. Black and white pieces can have
7252 different shapes, but in the interest of retaining my
7253 sanity pieces must have the same outline on both light
7254 and dark squares, and all pieces must use the same
7255 background square colors/images. */
7257 static int xpmDone = 0;
7260 CreateAnimMasks (pieceDepth)
7267 unsigned long plane;
7270 /* just return for gtk at the moment */
7273 /* Need a bitmap just to get a GC with right depth */
7274 buf = XCreatePixmap(xDisplay, xBoardWindow,
7276 values.foreground = 1;
7277 values.background = 0;
7278 /* Don't use XtGetGC, not read only */
7279 maskGC = XCreateGC(xDisplay, buf,
7280 GCForeground | GCBackground, &values);
7281 XFreePixmap(xDisplay, buf);
7283 buf = XCreatePixmap(xDisplay, xBoardWindow,
7284 squareSize, squareSize, pieceDepth);
7285 values.foreground = XBlackPixel(xDisplay, xScreen);
7286 values.background = XWhitePixel(xDisplay, xScreen);
7287 bufGC = XCreateGC(xDisplay, buf,
7288 GCForeground | GCBackground, &values);
7290 for (piece = WhitePawn; piece <= BlackKing; piece++) {
7291 /* Begin with empty mask */
7292 if(!xpmDone) // [HGM] pieces: keep using existing
7293 xpmMask[piece] = XCreatePixmap(xDisplay, xBoardWindow,
7294 squareSize, squareSize, 1);
7295 XSetFunction(xDisplay, maskGC, GXclear);
7296 XFillRectangle(xDisplay, xpmMask[piece], maskGC,
7297 0, 0, squareSize, squareSize);
7299 /* Take a copy of the piece */
7304 XSetFunction(xDisplay, bufGC, GXcopy);
7305 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn],
7307 0, 0, squareSize, squareSize, 0, 0);
7309 /* XOR the background (light) over the piece */
7310 XSetFunction(xDisplay, bufGC, GXxor);
7312 XCopyArea(xDisplay, xpmLightSquare, buf, bufGC,
7313 0, 0, squareSize, squareSize, 0, 0);
7315 XSetForeground(xDisplay, bufGC, lightSquareColor);
7316 XFillRectangle(xDisplay, buf, bufGC, 0, 0, squareSize, squareSize);
7319 /* We now have an inverted piece image with the background
7320 erased. Construct mask by just selecting all the non-zero
7321 pixels - no need to reconstruct the original image. */
7322 XSetFunction(xDisplay, maskGC, GXor);
7324 /* Might be quicker to download an XImage and create bitmap
7325 data from it rather than this N copies per piece, but it
7326 only takes a fraction of a second and there is a much
7327 longer delay for loading the pieces. */
7328 for (n = 0; n < pieceDepth; n ++) {
7329 XCopyPlane(xDisplay, buf, xpmMask[piece], maskGC,
7330 0, 0, squareSize, squareSize,
7336 XFreePixmap(xDisplay, buf);
7337 XFreeGC(xDisplay, bufGC);
7338 XFreeGC(xDisplay, maskGC);
7342 InitAnimState (anim, info)
7344 XWindowAttributes * info;
7349 /* Each buffer is square size, same depth as window */
7350 // anim->saveBuf = XCreatePixmap(xDisplay, xBoardWindow,
7351 // squareSize, squareSize, info->depth);
7352 // anim->newBuf = XCreatePixmap(xDisplay, xBoardWindow,
7353 // squareSize, squareSize, info->depth);
7355 // /* Create a plain GC for blitting */
7356 // mask = GCForeground | GCBackground | GCFunction |
7357 // GCPlaneMask | GCGraphicsExposures;
7358 // values.foreground = XBlackPixel(xDisplay, xScreen);
7359 // values.background = XWhitePixel(xDisplay, xScreen);
7360 // values.function = GXcopy;
7361 // values.plane_mask = AllPlanes;
7362 // values.graphics_exposures = False;
7363 // anim->blitGC = XCreateGC(xDisplay, xBoardWindow, mask, &values);
7365 // /* Piece will be copied from an existing context at
7366 // the start of each new animation/drag. */
7367 // anim->pieceGC = XCreateGC(xDisplay, xBoardWindow, 0, &values);
7369 // /* Outline will be a read-only copy of an existing */
7370 // anim->outlineGC = None;
7376 static VariantClass old = (VariantClass) -1; // [HGM] pieces: redo every time variant changes
7377 XWindowAttributes info;
7379 /* for gtk at the moment just ... */
7382 if (xpmDone && gameInfo.variant == old) return;
7383 if(xpmDone) old = gameInfo.variant; // first time pieces might not be created yet
7384 // XGetWindowAttributes(xDisplay, xBoardWindow, &info);
7386 // InitAnimState(&game, &info);
7387 // InitAnimState(&player, &info);
7389 /* For XPM pieces, we need bitmaps to use as masks. */
7391 // CreateAnimMasks(info.depth);
7397 static Boolean frameWaiting;
7399 static RETSIGTYPE FrameAlarm (sig)
7402 frameWaiting = False;
7403 /* In case System-V style signals. Needed?? */
7404 signal(SIGALRM, FrameAlarm);
7411 struct itimerval delay;
7413 XSync(xDisplay, False);
7416 frameWaiting = True;
7417 signal(SIGALRM, FrameAlarm);
7418 delay.it_interval.tv_sec =
7419 delay.it_value.tv_sec = time / 1000;
7420 delay.it_interval.tv_usec =
7421 delay.it_value.tv_usec = (time % 1000) * 1000;
7422 setitimer(ITIMER_REAL, &delay, NULL);
7423 while (frameWaiting) pause();
7424 delay.it_interval.tv_sec = delay.it_value.tv_sec = 0;
7425 delay.it_interval.tv_usec = delay.it_value.tv_usec = 0;
7426 setitimer(ITIMER_REAL, &delay, NULL);
7436 // XSync(xDisplay, False);
7438 usleep(time * 1000);
7443 /* Convert board position to corner of screen rect and color */
7446 ScreenSquare(column, row, pt, color)
7447 int column; int row; XPoint * pt; int * color;
7450 pt->x = lineGap + ((BOARD_WIDTH-1)-column) * (squareSize + lineGap);
7451 pt->y = lineGap + row * (squareSize + lineGap);
7453 pt->x = lineGap + column * (squareSize + lineGap);
7454 pt->y = lineGap + ((BOARD_HEIGHT-1)-row) * (squareSize + lineGap);
7456 *color = SquareColor(row, column);
7459 /* Convert window coords to square */
7462 BoardSquare(x, y, column, row)
7463 int x; int y; int * column; int * row;
7465 *column = EventToSquare(x, BOARD_WIDTH);
7466 if (flipView && *column >= 0)
7467 *column = BOARD_WIDTH - 1 - *column;
7468 *row = EventToSquare(y, BOARD_HEIGHT);
7469 if (!flipView && *row >= 0)
7470 *row = BOARD_HEIGHT - 1 - *row;
7475 #undef Max /* just in case */
7477 #define Max(a, b) ((a) > (b) ? (a) : (b))
7478 #define Min(a, b) ((a) < (b) ? (a) : (b))
7481 SetRect(rect, x, y, width, height)
7482 XRectangle * rect; int x; int y; int width; int height;
7486 rect->width = width;
7487 rect->height = height;
7490 /* Test if two frames overlap. If they do, return
7491 intersection rect within old and location of
7492 that rect within new. */
7495 Intersect(old, new, size, area, pt)
7496 XPoint * old; XPoint * new;
7497 int size; XRectangle * area; XPoint * pt;
7499 if (old->x > new->x + size || new->x > old->x + size ||
7500 old->y > new->y + size || new->y > old->y + size) {
7503 SetRect(area, Max(new->x - old->x, 0), Max(new->y - old->y, 0),
7504 size - abs(old->x - new->x), size - abs(old->y - new->y));
7505 pt->x = Max(old->x - new->x, 0);
7506 pt->y = Max(old->y - new->y, 0);
7511 /* For two overlapping frames, return the rect(s)
7512 in the old that do not intersect with the new. */
7515 CalcUpdateRects(old, new, size, update, nUpdates)
7516 XPoint * old; XPoint * new; int size;
7517 XRectangle update[]; int * nUpdates;
7521 /* If old = new (shouldn't happen) then nothing to draw */
7522 if (old->x == new->x && old->y == new->y) {
7526 /* Work out what bits overlap. Since we know the rects
7527 are the same size we don't need a full intersect calc. */
7529 /* Top or bottom edge? */
7530 if (new->y > old->y) {
7531 SetRect(&(update[count]), old->x, old->y, size, new->y - old->y);
7533 } else if (old->y > new->y) {
7534 SetRect(&(update[count]), old->x, old->y + size - (old->y - new->y),
7535 size, old->y - new->y);
7538 /* Left or right edge - don't overlap any update calculated above. */
7539 if (new->x > old->x) {
7540 SetRect(&(update[count]), old->x, Max(new->y, old->y),
7541 new->x - old->x, size - abs(new->y - old->y));
7543 } else if (old->x > new->x) {
7544 SetRect(&(update[count]), new->x + size, Max(new->y, old->y),
7545 old->x - new->x, size - abs(new->y - old->y));
7552 /* Generate a series of frame coords from start->mid->finish.
7553 The movement rate doubles until the half way point is
7554 reached, then halves back down to the final destination,
7555 which gives a nice slow in/out effect. The algorithmn
7556 may seem to generate too many intermediates for short
7557 moves, but remember that the purpose is to attract the
7558 viewers attention to the piece about to be moved and
7559 then to where it ends up. Too few frames would be less
7563 Tween(start, mid, finish, factor, frames, nFrames)
7564 XPoint * start; XPoint * mid;
7565 XPoint * finish; int factor;
7566 XPoint frames[]; int * nFrames;
7568 int fraction, n, count;
7572 /* Slow in, stepping 1/16th, then 1/8th, ... */
7574 for (n = 0; n < factor; n++)
7576 for (n = 0; n < factor; n++) {
7577 frames[count].x = start->x + (mid->x - start->x) / fraction;
7578 frames[count].y = start->y + (mid->y - start->y) / fraction;
7580 fraction = fraction / 2;
7584 frames[count] = *mid;
7587 /* Slow out, stepping 1/2, then 1/4, ... */
7589 for (n = 0; n < factor; n++) {
7590 frames[count].x = finish->x - (finish->x - mid->x) / fraction;
7591 frames[count].y = finish->y - (finish->y - mid->y) / fraction;
7593 fraction = fraction * 2;
7598 /* Draw a piece on the screen without disturbing what's there */
7601 SelectGCMask(piece, clip, outline, mask)
7602 ChessSquare piece; GC * clip; GC * outline; Pixmap * mask;
7606 /* Bitmap for piece being moved. */
7607 if (appData.monoMode) {
7608 *mask = *pieceToSolid(piece);
7609 } else if (useImages) {
7611 *mask = xpmMask[piece];
7613 *mask = ximMaskPm[piece];
7616 *mask = *pieceToSolid(piece);
7619 /* GC for piece being moved. Square color doesn't matter, but
7620 since it gets modified we make a copy of the original. */
7622 if (appData.monoMode)
7627 if (appData.monoMode)
7632 // XCopyGC(xDisplay, source, 0xFFFFFFFF, *clip);
7634 /* Outline only used in mono mode and is not modified */
7636 *outline = bwPieceGC;
7638 *outline = wbPieceGC;
7642 OverlayPiece(piece, clip, outline, dest)
7643 ChessSquare piece; GC clip; GC outline; Drawable dest;
7648 /* Draw solid rectangle which will be clipped to shape of piece */
7649 // XFillRectangle(xDisplay, dest, clip,
7650 // 0, 0, squareSize, squareSize)
7652 if (appData.monoMode)
7653 /* Also draw outline in contrasting color for black
7654 on black / white on white cases */
7655 // XCopyPlane(xDisplay, *pieceToOutline(piece), dest, outline,
7656 // 0, 0, squareSize, squareSize, 0, 0, 1)
7659 /* Copy the piece */
7664 // XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
7666 // 0, 0, squareSize, squareSize,
7671 /* Animate the movement of a single piece */
7674 BeginAnimation(anim, piece, startColor, start)
7682 /* The old buffer is initialised with the start square (empty) */
7683 BlankSquare(0, 0, startColor, EmptySquare, anim->saveBuf);
7684 anim->prevFrame = *start;
7686 /* The piece will be drawn using its own bitmap as a matte */
7687 // SelectGCMask(piece, &anim->pieceGC, &anim->outlineGC, &mask);
7688 // XSetClipMask(xDisplay, anim->pieceGC, mask);
7692 AnimationFrame(anim, frame, piece)
7697 XRectangle updates[4];
7702 /* Save what we are about to draw into the new buffer */
7703 // XCopyArea(xDisplay, xBoardWindow, anim->newBuf, anim->blitGC,
7704 // frame->x, frame->y, squareSize, squareSize,
7707 /* Erase bits of the previous frame */
7708 if (Intersect(&anim->prevFrame, frame, squareSize, &overlap, &pt)) {
7709 /* Where the new frame overlapped the previous,
7710 the contents in newBuf are wrong. */
7711 // XCopyArea(xDisplay, anim->saveBuf, anim->newBuf, anim->blitGC,
7712 // overlap.x, overlap.y,
7713 // overlap.width, overlap.height,
7715 /* Repaint the areas in the old that don't overlap new */
7716 CalcUpdateRects(&anim->prevFrame, frame, squareSize, updates, &count);
7717 for (i = 0; i < count; i++)
7718 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
7719 // updates[i].x - anim->prevFrame.x,
7720 // updates[i].y - anim->prevFrame.y,
7721 // updates[i].width, updates[i].height,
7722 // updates[i].x, updates[i].y)
7725 /* Easy when no overlap */
7726 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
7727 // 0, 0, squareSize, squareSize,
7728 // anim->prevFrame.x, anim->prevFrame.y);
7731 /* Save this frame for next time round */
7732 // XCopyArea(xDisplay, anim->newBuf, anim->saveBuf, anim->blitGC,
7733 // 0, 0, squareSize, squareSize,
7735 anim->prevFrame = *frame;
7737 /* Draw piece over original screen contents, not current,
7738 and copy entire rect. Wipes out overlapping piece images. */
7739 OverlayPiece(piece, anim->pieceGC, anim->outlineGC, anim->newBuf);
7740 // XCopyArea(xDisplay, anim->newBuf, xBoardWindow, anim->blitGC,
7741 // 0, 0, squareSize, squareSize,
7742 // frame->x, frame->y);
7746 EndAnimation (anim, finish)
7750 XRectangle updates[4];
7755 /* The main code will redraw the final square, so we
7756 only need to erase the bits that don't overlap. */
7757 if (Intersect(&anim->prevFrame, finish, squareSize, &overlap, &pt)) {
7758 CalcUpdateRects(&anim->prevFrame, finish, squareSize, updates, &count);
7759 for (i = 0; i < count; i++)
7760 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
7761 // updates[i].x - anim->prevFrame.x,
7762 // updates[i].y - anim->prevFrame.y,
7763 // updates[i].width, updates[i].height,
7764 // updates[i].x, updates[i].y)
7767 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
7768 // 0, 0, squareSize, squareSize,
7769 // anim->prevFrame.x, anim->prevFrame.y);
7774 FrameSequence(anim, piece, startColor, start, finish, frames, nFrames)
7776 ChessSquare piece; int startColor;
7777 XPoint * start; XPoint * finish;
7778 XPoint frames[]; int nFrames;
7782 BeginAnimation(anim, piece, startColor, start);
7783 for (n = 0; n < nFrames; n++) {
7784 AnimationFrame(anim, &(frames[n]), piece);
7785 FrameDelay(appData.animSpeed);
7787 EndAnimation(anim, finish);
7790 /* Main control logic for deciding what to animate and how */
7793 AnimateMove(board, fromX, fromY, toX, toY)
7802 XPoint start, finish, mid;
7803 XPoint frames[kFactor * 2 + 1];
7804 int nFrames, startColor, endColor;
7806 /* Are we animating? */
7807 if (!appData.animate || appData.blindfold)
7810 if(board[toY][toX] == WhiteRook && board[fromY][fromX] == WhiteKing ||
7811 board[toY][toX] == BlackRook && board[fromY][fromX] == BlackKing)
7812 return; // [HGM] FRC: no animtion of FRC castlings, as to-square is not true to-square
7814 if (fromY < 0 || fromX < 0 || toX < 0 || toY < 0) return;
7815 piece = board[fromY][fromX];
7816 if (piece >= EmptySquare) return;
7821 hop = (piece == WhiteKnight || piece == BlackKnight);
7824 if (appData.debugMode) {
7825 fprintf(debugFP, hop ? _("AnimateMove: piece %d hops from %d,%d to %d,%d \n") :
7826 _("AnimateMove: piece %d slides from %d,%d to %d,%d \n"),
7827 piece, fromX, fromY, toX, toY); }
7829 ScreenSquare(fromX, fromY, &start, &startColor);
7830 ScreenSquare(toX, toY, &finish, &endColor);
7833 /* Knight: make diagonal movement then straight */
7834 if (abs(toY - fromY) < abs(toX - fromX)) {
7835 mid.x = start.x + (finish.x - start.x) / 2;
7839 mid.y = start.y + (finish.y - start.y) / 2;
7842 mid.x = start.x + (finish.x - start.x) / 2;
7843 mid.y = start.y + (finish.y - start.y) / 2;
7846 /* Don't use as many frames for very short moves */
7847 if (abs(toY - fromY) + abs(toX - fromX) <= 2)
7848 Tween(&start, &mid, &finish, kFactor - 1, frames, &nFrames);
7850 Tween(&start, &mid, &finish, kFactor, frames, &nFrames);
7851 FrameSequence(&game, piece, startColor, &start, &finish, frames, nFrames);
7853 /* Be sure end square is redrawn */
7854 damage[toY][toX] = True;
7858 DragPieceBegin(x, y)
7861 int boardX, boardY, color;
7864 /* Are we animating? */
7865 if (!appData.animateDragging || appData.blindfold)
7868 /* Figure out which square we start in and the
7869 mouse position relative to top left corner. */
7870 BoardSquare(x, y, &boardX, &boardY);
7871 player.startBoardX = boardX;
7872 player.startBoardY = boardY;
7873 ScreenSquare(boardX, boardY, &corner, &color);
7874 player.startSquare = corner;
7875 player.startColor = color;
7876 /* As soon as we start dragging, the piece will jump slightly to
7877 be centered over the mouse pointer. */
7878 player.mouseDelta.x = squareSize/2;
7879 player.mouseDelta.y = squareSize/2;
7880 /* Initialise animation */
7881 player.dragPiece = PieceForSquare(boardX, boardY);
7883 if (player.dragPiece >= 0 && player.dragPiece < EmptySquare) {
7884 player.dragActive = True;
7885 BeginAnimation(&player, player.dragPiece, color, &corner);
7886 /* Mark this square as needing to be redrawn. Note that
7887 we don't remove the piece though, since logically (ie
7888 as seen by opponent) the move hasn't been made yet. */
7889 if(boardX == BOARD_RGHT+1 && PieceForSquare(boardX-1, boardY) > 1 ||
7890 boardX == BOARD_LEFT-2 && PieceForSquare(boardX+1, boardY) > 1)
7891 // XCopyArea(xDisplay, xBoardWindow, player.saveBuf, player.blitGC,
7892 // corner.x, corner.y, squareSize, squareSize,
7893 // 0, 0); // [HGM] zh: unstack in stead of grab
7894 damage[boardY][boardX] = True;
7896 player.dragActive = False;
7906 /* Are we animating? */
7907 if (!appData.animateDragging || appData.blindfold)
7911 if (! player.dragActive)
7913 /* Move piece, maintaining same relative position
7914 of mouse within square */
7915 corner.x = x - player.mouseDelta.x;
7916 corner.y = y - player.mouseDelta.y;
7917 AnimationFrame(&player, &corner, player.dragPiece);
7919 if (appData.highlightDragging) {
7921 BoardSquare(x, y, &boardX, &boardY);
7922 SetHighlights(fromX, fromY, boardX, boardY);
7931 int boardX, boardY, color;
7934 /* Are we animating? */
7935 if (!appData.animateDragging || appData.blindfold)
7939 if (! player.dragActive)
7941 /* Last frame in sequence is square piece is
7942 placed on, which may not match mouse exactly. */
7943 BoardSquare(x, y, &boardX, &boardY);
7944 ScreenSquare(boardX, boardY, &corner, &color);
7945 EndAnimation(&player, &corner);
7947 /* Be sure end square is redrawn */
7948 damage[boardY][boardX] = True;
7950 /* This prevents weird things happening with fast successive
7951 clicks which on my Sun at least can cause motion events
7952 without corresponding press/release. */
7953 player.dragActive = False;
7956 /* Handle expose event while piece being dragged */
7961 if (!player.dragActive || appData.blindfold)
7964 /* What we're doing: logically, the move hasn't been made yet,
7965 so the piece is still in it's original square. But visually
7966 it's being dragged around the board. So we erase the square
7967 that the piece is on and draw it at the last known drag point. */
7968 BlankSquare(player.startSquare.x, player.startSquare.y,
7969 player.startColor, EmptySquare, xBoardWindow);
7970 AnimationFrame(&player, &player.prevFrame, player.dragPiece);
7971 damage[player.startBoardY][player.startBoardX] = TRUE;
7975 SetProgramStats( FrontEndProgramStats * stats )
7978 // [HGM] done, but perhaps backend should call this directly?
7979 EngineOutputUpdate( stats );