2 * xboard.c -- X front end for XBoard
4 * Copyright 1991 by Digital Equipment Corporation, Maynard,
7 * Enhancements Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006,
8 * 2007, 2008, 2009 Free Software Foundation, Inc.
10 * The following terms apply to Digital Equipment Corporation's copyright
12 * ------------------------------------------------------------------------
15 * Permission to use, copy, modify, and distribute this software and its
16 * documentation for any purpose and without fee is hereby granted,
17 * provided that the above copyright notice appear in all copies and that
18 * both that copyright notice and this permission notice appear in
19 * supporting documentation, and that the name of Digital not be
20 * used in advertising or publicity pertaining to distribution of the
21 * software without specific, written prior permission.
23 * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
24 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
25 * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
26 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
27 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
28 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
30 * ------------------------------------------------------------------------
32 * The following terms apply to the enhanced version of XBoard
33 * distributed by the Free Software Foundation:
34 * ------------------------------------------------------------------------
36 * GNU XBoard is free software: you can redistribute it and/or modify
37 * it under the terms of the GNU General Public License as published by
38 * the Free Software Foundation, either version 3 of the License, or (at
39 * your option) any later version.
41 * GNU XBoard is distributed in the hope that it will be useful, but
42 * WITHOUT ANY WARRANTY; without even the implied warranty of
43 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
44 * General Public License for more details.
46 * You should have received a copy of the GNU General Public License
47 * along with this program. If not, see http://www.gnu.org/licenses/. *
49 *------------------------------------------------------------------------
50 ** See the file ChangeLog for a revision history. */
58 #include <sys/types.h>
63 # if HAVE_SYS_SOCKET_H
64 # include <sys/socket.h>
65 # include <netinet/in.h>
67 # else /* not HAVE_SYS_SOCKET_H */
68 # if HAVE_LAN_SOCKET_H
69 # include <lan/socket.h>
71 # include <lan/netdb.h>
72 # else /* not HAVE_LAN_SOCKET_H */
73 # define OMIT_SOCKETS 1
74 # endif /* not HAVE_LAN_SOCKET_H */
75 # endif /* not HAVE_SYS_SOCKET_H */
76 #endif /* !OMIT_SOCKETS */
81 #else /* not STDC_HEADERS */
82 extern char *getenv();
85 # else /* not HAVE_STRING_H */
87 # endif /* not HAVE_STRING_H */
88 #endif /* not STDC_HEADERS */
91 # include <sys/fcntl.h>
92 #else /* not HAVE_SYS_FCNTL_H */
95 # endif /* HAVE_FCNTL_H */
96 #endif /* not HAVE_SYS_FCNTL_H */
98 #if HAVE_SYS_SYSTEMINFO_H
99 # include <sys/systeminfo.h>
100 #endif /* HAVE_SYS_SYSTEMINFO_H */
102 #if TIME_WITH_SYS_TIME
103 # include <sys/time.h>
107 # include <sys/time.h>
118 # include <sys/wait.h>
123 # define NAMLEN(dirent) strlen((dirent)->d_name)
124 # define HAVE_DIR_STRUCT
126 # define dirent direct
127 # define NAMLEN(dirent) (dirent)->d_namlen
129 # include <sys/ndir.h>
130 # define HAVE_DIR_STRUCT
133 # include <sys/dir.h>
134 # define HAVE_DIR_STRUCT
138 # define HAVE_DIR_STRUCT
142 #include <X11/Intrinsic.h>
143 #include <X11/StringDefs.h>
144 #include <X11/Shell.h>
145 #include <X11/cursorfont.h>
146 #include <X11/Xatom.h>
148 #include <X11/Xaw3d/Dialog.h>
149 #include <X11/Xaw3d/Form.h>
150 #include <X11/Xaw3d/List.h>
151 #include <X11/Xaw3d/Label.h>
152 #include <X11/Xaw3d/SimpleMenu.h>
153 #include <X11/Xaw3d/SmeBSB.h>
154 #include <X11/Xaw3d/SmeLine.h>
155 #include <X11/Xaw3d/Box.h>
156 #include <X11/Xaw3d/MenuButton.h>
157 #include <X11/Xaw3d/Text.h>
158 #include <X11/Xaw3d/AsciiText.h>
160 #include <X11/Xaw/Dialog.h>
161 #include <X11/Xaw/Form.h>
162 #include <X11/Xaw/List.h>
163 #include <X11/Xaw/Label.h>
164 #include <X11/Xaw/SimpleMenu.h>
165 #include <X11/Xaw/SmeBSB.h>
166 #include <X11/Xaw/SmeLine.h>
167 #include <X11/Xaw/Box.h>
168 #include <X11/Xaw/MenuButton.h>
169 #include <X11/Xaw/Text.h>
170 #include <X11/Xaw/AsciiText.h>
173 // [HGM] bitmaps: put before incuding the bitmaps / pixmaps, to know how many piece types there are.
178 #include "pixmaps/pixmaps.h"
179 #define IMAGE_EXT "xpm"
181 #define IMAGE_EXT "xim"
182 #include "bitmaps/bitmaps.h"
187 #include <gdk-pixbuf/gdk-pixbuf.h>
189 #include "bitmaps/icon_white.bm"
190 #include "bitmaps/icon_black.bm"
191 #include "bitmaps/checkmark.bm"
193 #include "frontend.h"
198 #include "xgamelist.h"
199 #include "xhistory.h"
200 #include "xedittags.h"
202 #include "callback.h"
203 #include "interface.h"
205 // must be moved to xengineoutput.h
207 void EngineOutputProc P((Widget w, XEvent *event,
208 String *prms, Cardinal *nprms));
210 void EngineOutputPopDown();
217 #define usleep(t) _sleep2(((t)+500)/1000)
221 # define _(s) gettext (s)
222 # define N_(s) gettext_noop (s)
245 int main P((int argc, char **argv));
246 RETSIGTYPE CmailSigHandler P((int sig));
247 RETSIGTYPE IntSigHandler P((int sig));
248 void CreateGCs P((void));
249 void CreateXIMPieces P((void));
250 void CreateXPMPieces P((void));
251 void CreatePieces P((void));
252 void CreatePieceMenus P((void));
253 Widget CreateMenuBar P((Menu *mb));
254 Widget CreateButtonBar P ((MenuItem *mi));
255 char *FindFont P((char *pattern, int targetPxlSize));
256 void PieceMenuPopup P((Widget w, XEvent *event,
257 String *params, Cardinal *num_params));
258 static void PieceMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
259 static void DropMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
260 int EventToSquare P((int x, int limit));
261 void DrawSquare P((int row, int column, ChessSquare piece, int do_flash));
262 void HandleUserMove P((Widget w, XEvent *event,
263 String *prms, Cardinal *nprms));
264 void AnimateUserMove P((Widget w, XEvent * event,
265 String * params, Cardinal * nParams));
266 void WhiteClock P((Widget w, XEvent *event,
267 String *prms, Cardinal *nprms));
268 void BlackClock P((Widget w, XEvent *event,
269 String *prms, Cardinal *nprms));
270 void CommentPopUp P((char *title, char *label));
271 void CommentPopDown P((void));
272 void CommentCallback P((Widget w, XtPointer client_data,
273 XtPointer call_data));
274 void ICSInputBoxPopUp P((void));
275 void ICSInputBoxPopDown P((void));
276 void FileNamePopUp P((char *label, char *def,
277 FileProc proc, char *openMode));
278 void FileNamePopDown P((void));
279 void FileNameCallback P((Widget w, XtPointer client_data,
280 XtPointer call_data));
281 void FileNameAction P((Widget w, XEvent *event,
282 String *prms, Cardinal *nprms));
283 void AskQuestionReplyAction P((Widget w, XEvent *event,
284 String *prms, Cardinal *nprms));
285 void AskQuestionProc P((Widget w, XEvent *event,
286 String *prms, Cardinal *nprms));
287 void AskQuestionPopDown P((void));
288 void PromotionPopUp P((void));
289 void PromotionPopDown P((void));
290 void PromotionCallback P((Widget w, XtPointer client_data,
291 XtPointer call_data));
292 void EditCommentPopDown P((void));
293 void EditCommentCallback P((Widget w, XtPointer client_data,
294 XtPointer call_data));
295 void SelectCommand P((Widget w, XtPointer client_data, XtPointer call_data));
296 void LoadPositionProc P((Widget w, XEvent *event,
297 String *prms, Cardinal *nprms));
298 void LoadNextPositionProc P((Widget w, XEvent *event, String *prms,
300 void LoadPrevPositionProc P((Widget w, XEvent *event, String *prms,
302 void ReloadPositionProc P((Widget w, XEvent *event, String *prms,
304 void CopyPositionProc P((Widget w, XEvent *event, String *prms,
306 void PastePositionProc P((Widget w, XEvent *event, String *prms,
308 void CopyGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
309 void PasteGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
310 void SaveGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
311 void SavePositionProc P((Widget w, XEvent *event,
312 String *prms, Cardinal *nprms));
313 void MailMoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
314 void ReloadCmailMsgProc P((Widget w, XEvent *event, String *prms,
316 void AnalyzeModeProc P((Widget w, XEvent *event,
317 String *prms, Cardinal *nprms));
318 void AnalyzeFileProc P((Widget w, XEvent *event,
319 String *prms, Cardinal *nprms));
320 void EditGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
321 void EditPositionProc P((Widget w, XEvent *event,
322 String *prms, Cardinal *nprms));
323 void TrainingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
324 void EditCommentProc P((Widget w, XEvent *event,
325 String *prms, Cardinal *nprms));
326 void IcsInputBoxProc P((Widget w, XEvent *event,
327 String *prms, Cardinal *nprms));
328 void EnterKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
329 void AlwaysQueenProc P((Widget w, XEvent *event, String *prms,
331 void AnimateDraggingProc P((Widget w, XEvent *event, String *prms,
333 void AnimateMovingProc P((Widget w, XEvent *event, String *prms,
335 void AutocommProc P((Widget w, XEvent *event, String *prms,
337 void AutoflagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
338 void AutoflipProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
339 void AutobsProc P((Widget w, XEvent *event, String *prms,
341 void AutoraiseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
342 void AutosaveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
343 void BlindfoldProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
344 void FlashMovesProc P((Widget w, XEvent *event, String *prms,
346 void FlipViewProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
347 void GetMoveListProc P((Widget w, XEvent *event, String *prms,
349 void HighlightDraggingProc P((Widget w, XEvent *event, String *prms,
351 void HighlightLastMoveProc P((Widget w, XEvent *event, String *prms,
353 void MoveSoundProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
354 void IcsAlarmProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
355 void OldSaveStyleProc P((Widget w, XEvent *event, String *prms,
357 void PeriodicUpdatesProc P((Widget w, XEvent *event, String *prms,
359 void PonderNextMoveProc P((Widget w, XEvent *event, String *prms,
361 void PopupMoveErrorsProc P((Widget w, XEvent *event, String *prms,
363 void PopupExitMessageProc P((Widget w, XEvent *event, String *prms,
365 void PremoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
366 void QuietPlayProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
367 void ShowThinkingProc P((Widget w, XEvent *event, String *prms,
369 void HideThinkingProc P((Widget w, XEvent *event, String *prms,
371 void TestLegalityProc P((Widget w, XEvent *event, String *prms,
373 void InfoProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
374 void ManProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
375 void HintProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
376 void BookProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
377 void AboutGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
378 void DebugProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
379 void NothingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
380 void Iconify P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
381 void DisplayMove P((int moveNumber));
382 void DisplayTitle P((char *title));
383 void ICSInitScript P((void));
384 int LoadGamePopUp P((FILE *f, int gameNumber, char *title));
385 void ErrorPopUp P((char *title, char *text, int modal));
386 void ErrorPopDown P((void));
387 static char *ExpandPathName P((char *path));
388 static void CreateAnimVars P((void));
389 void DragPieceBegin P((int x, int y));
390 static void DragPieceMove P((int x, int y));
391 void DragPieceEnd P((int x, int y));
392 static void DrawDragPiece P((void));
393 char *ModeToWidgetName P((GameMode mode));
394 void EngineOutputUpdate( FrontEndProgramStats * stats );
395 void ShuffleMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
396 void EngineMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
397 void UciMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
398 void TimeControlProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
399 void NewVariantProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
400 void FirstSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
401 void SecondSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
402 void ShufflePopDown P(());
403 void EnginePopDown P(());
404 void UciPopDown P(());
405 void TimeControlPopDown P(());
406 void NewVariantPopDown P(());
407 void SettingsPopDown P(());
408 void SetMenuEnables P((Enables *enab));
411 * XBoard depends on Xt R4 or higher
413 int xtVersion = XtSpecificationRelease;
418 Pixel lightSquareColor, darkSquareColor, whitePieceColor, blackPieceColor,
419 jailSquareColor, highlightSquareColor, premoveHighlightColor;
420 Pixel lowTimeWarningColor;
422 #define LINE_TYPE_NORMAL 0
423 #define LINE_TYPE_HIGHLIGHT 1
424 #define LINE_TYPE_PRE 2
427 GC lightSquareGC, darkSquareGC, jailSquareGC, wdPieceGC, wlPieceGC,
428 bdPieceGC, blPieceGC, wbPieceGC, bwPieceGC, coordGC,
429 wjPieceGC, bjPieceGC;
430 Pixmap iconPixmap, wIconPixmap, bIconPixmap, xMarkPixmap;
431 Widget shellWidget, layoutWidget, formWidget, boardWidget, messageWidget,
432 whiteTimerWidget, blackTimerWidget, titleWidget, widgetList[16],
433 commentShell, promotionShell, whitePieceMenu, blackPieceMenu, dropMenu,
434 menuBarWidget, buttonBarWidget, editShell, errorShell, analysisShell,
435 ICSInputShell, fileNameShell, askQuestionShell;
436 Font clockFontID, coordFontID, countFontID;
437 XFontStruct *clockFontStruct, *coordFontStruct, *countFontStruct;
438 XtAppContext appContext;
440 char *oldICSInteractionTitle;
444 char installDir[] = "."; // [HGM] UCI: needed for UCI; probably needs run-time initializtion
446 Position commentX = -1, commentY = -1;
447 Dimension commentW, commentH;
449 int squareSize, smallLayout = 0, tinyLayout = 0,
450 marginW, marginH, // [HGM] for run-time resizing
451 fromX = -1, fromY = -1, toX, toY, commentUp = False, analysisUp = False,
452 ICSInputBoxUp = False, askQuestionUp = False,
453 filenameUp = False, promotionUp = False, pmFromX = -1, pmFromY = -1,
454 editUp = False, errorUp = False, errorExitStatus = -1, lineGap;
455 Pixel timerForegroundPixel, timerBackgroundPixel;
456 Pixel buttonForegroundPixel, buttonBackgroundPixel;
457 char *chessDir, *programName, *programVersion,
458 *gameCopyFilename, *gamePasteFilename;
462 Pixmap pieceBitmap[2][(int)BlackPawn];
463 Pixmap pieceBitmap2[2][(int)BlackPawn+4]; /* [HGM] pieces */
464 Pixmap xpmPieceBitmap[4][(int)BlackPawn]; /* LL, LD, DL, DD actually used*/
465 Pixmap xpmPieceBitmap2[4][(int)BlackPawn+4]; /* LL, LD, DL, DD set to select from */
466 Pixmap xpmLightSquare, xpmDarkSquare, xpmJailSquare;
467 int useImages=0, useImageSqs;
468 XImage *ximPieceBitmap[4][(int)BlackPawn+4]; /* LL, LD, DL, DD */
469 Pixmap ximMaskPm[(int)BlackPawn]; /* clipmasks, used for XIM pieces */
470 Pixmap ximMaskPm2[(int)BlackPawn+4]; /* clipmasks, used for XIM pieces */
471 XImage *ximLightSquare, *ximDarkSquare;
474 #define pieceToSolid(piece) &pieceBitmap[SOLID][(piece) % (int)BlackPawn]
475 #define pieceToOutline(piece) &pieceBitmap[OUTLINE][(piece) % (int)BlackPawn]
477 #define White(piece) ((int)(piece) < (int)BlackPawn)
479 /* Variables for doing smooth animation. This whole thing
480 would be much easier if the board was double-buffered,
481 but that would require a fairly major rewrite. */
486 GC blitGC, pieceGC, outlineGC;
487 XPoint startSquare, prevFrame, mouseDelta;
491 int startBoardX, startBoardY;
494 /* There can be two pieces being animated at once: a player
495 can begin dragging a piece before the remote opponent has moved. */
497 static AnimState game, player;
499 /* Bitmaps for use as masks when drawing XPM pieces.
500 Need one for each black and white piece. */
501 static Pixmap xpmMask[BlackKing + 1];
503 /* This magic number is the number of intermediate frames used
504 in each half of the animation. For short moves it's reduced
505 by 1. The total number of frames will be factor * 2 + 1. */
508 SizeDefaults sizeDefaults[] = SIZE_DEFAULTS;
510 Enables icsEnables[] = {
511 { "menuFile.Mail Move", False },
512 { "menuFile.Reload CMail Message", False },
513 { "menuMode.Machine Black", False },
514 { "menuMode.Machine White", False },
515 { "menuMode.Analysis Mode", False },
516 { "menuMode.Analyze File", False },
517 { "menuMode.Two Machines", False },
519 { "menuHelp.Hint", False },
520 { "menuHelp.Book", False },
521 { "menuStep.Move Now", False },
522 { "menuOptions.Periodic Updates", False },
523 { "menuOptions.Hide Thinking", False },
524 { "menuOptions.Ponder Next Move", False },
529 Enables ncpEnables[] = {
530 { "menuFile.Mail Move", False },
531 { "menuFile.Reload CMail Message", False },
532 { "menuMode.Machine White", False },
533 { "menuMode.Machine Black", False },
534 { "menuMode.Analysis Mode", False },
535 { "menuMode.Analyze File", False },
536 { "menuMode.Two Machines", False },
537 { "menuMode.ICS Client", False },
538 { "menuMode.ICS Input Box", False },
540 { "menuStep.Revert", False },
541 { "menuStep.Move Now", False },
542 { "menuStep.Retract Move", False },
543 { "menuOptions.Auto Comment", False },
544 { "menuOptions.Auto Flag", False },
545 { "menuOptions.Auto Flip View", False },
546 { "menuOptions.Auto Observe", False },
547 { "menuOptions.Auto Raise Board", False },
548 { "menuOptions.Get Move List", False },
549 { "menuOptions.ICS Alarm", False },
550 { "menuOptions.Move Sound", False },
551 { "menuOptions.Quiet Play", False },
552 { "menuOptions.Hide Thinking", False },
553 { "menuOptions.Periodic Updates", False },
554 { "menuOptions.Ponder Next Move", False },
555 { "menuHelp.Hint", False },
556 { "menuHelp.Book", False },
560 Enables gnuEnables[] = {
561 { "menuMode.ICS Client", False },
562 { "menuMode.ICS Input Box", False },
563 { "menuAction.Accept", False },
564 { "menuAction.Decline", False },
565 { "menuAction.Rematch", False },
566 { "menuAction.Adjourn", False },
567 { "menuAction.Stop Examining", False },
568 { "menuAction.Stop Observing", False },
569 { "menuStep.Revert", False },
570 { "menuOptions.Auto Comment", False },
571 { "menuOptions.Auto Observe", False },
572 { "menuOptions.Auto Raise Board", False },
573 { "menuOptions.Get Move List", False },
574 { "menuOptions.Premove", False },
575 { "menuOptions.Quiet Play", False },
577 /* The next two options rely on SetCmailMode being called *after* */
578 /* SetGNUMode so that when GNU is being used to give hints these */
579 /* menu options are still available */
581 { "menuFile.Mail Move", False },
582 { "menuFile.Reload CMail Message", False },
586 Enables cmailEnables[] = {
588 { "menuAction.Call Flag", False },
589 { "menuAction.Draw", True },
590 { "menuAction.Adjourn", False },
591 { "menuAction.Abort", False },
592 { "menuAction.Stop Observing", False },
593 { "menuAction.Stop Examining", False },
594 { "menuFile.Mail Move", True },
595 { "menuFile.Reload CMail Message", True },
599 Enables trainingOnEnables[] = {
600 { "menuMode.Edit Comment", False },
601 { "menuMode.Pause", False },
602 { "menuStep.Forward", False },
603 { "menuStep.Backward", False },
604 { "menuStep.Forward to End", False },
605 { "menuStep.Back to Start", False },
606 { "menuStep.Move Now", False },
607 { "menuStep.Truncate Game", False },
611 Enables trainingOffEnables[] = {
612 { "menuMode.Edit Comment", True },
613 { "menuMode.Pause", True },
614 { "menuStep.Forward", True },
615 { "menuStep.Backward", True },
616 { "menuStep.Forward to End", True },
617 { "menuStep.Back to Start", True },
618 { "menuStep.Move Now", True },
619 { "menuStep.Truncate Game", True },
623 Enables machineThinkingEnables[] = {
624 { "menuFile.Load Game", False },
625 { "menuFile.Load Next Game", False },
626 { "menuFile.Load Previous Game", False },
627 { "menuFile.Reload Same Game", False },
628 { "menuFile.Paste Game", False },
629 { "menuFile.Load Position", False },
630 { "menuFile.Load Next Position", False },
631 { "menuFile.Load Previous Position", False },
632 { "menuFile.Reload Same Position", False },
633 { "menuFile.Paste Position", False },
634 { "menuMode.Machine White", False },
635 { "menuMode.Machine Black", False },
636 { "menuMode.Two Machines", False },
637 { "menuStep.Retract Move", False },
641 Enables userThinkingEnables[] = {
642 { "menuFile.Load Game", True },
643 { "menuFile.Load Next Game", True },
644 { "menuFile.Load Previous Game", True },
645 { "menuFile.Reload Same Game", True },
646 { "menuFile.Paste Game", True },
647 { "menuFile.Load Position", True },
648 { "menuFile.Load Next Position", True },
649 { "menuFile.Load Previous Position", True },
650 { "menuFile.Reload Same Position", True },
651 { "menuFile.Paste Position", True },
652 { "menuMode.Machine White", True },
653 { "menuMode.Machine Black", True },
654 { "menuMode.Two Machines", True },
655 { "menuStep.Retract Move", True },
661 MenuItem fileMenu[] = {
662 {N_("New Shuffle Game ..."), ShuffleMenuProc},
663 {N_("New Variant ..."), NewVariantProc}, // [HGM] variant: not functional yet
664 {"----", NothingProc},
665 {N_("Save Game"), SaveGameProc},
666 {"----", NothingProc},
667 {N_("Copy Game"), CopyGameProc},
668 {N_("Paste Game"), PasteGameProc},
669 {"----", NothingProc},
670 {N_("Load Position"), LoadPositionProc},
671 {N_("Load Next Position"), LoadNextPositionProc},
672 {N_("Load Previous Position"), LoadPrevPositionProc},
673 {N_("Reload Same Position"), ReloadPositionProc},
674 {N_("Save Position"), SavePositionProc},
675 {"----", NothingProc},
676 {N_("Copy Position"), CopyPositionProc},
677 {N_("Paste Position"), PastePositionProc},
678 {"----", NothingProc},
679 {N_("Mail Move"), MailMoveProc},
680 {N_("Reload CMail Message"), ReloadCmailMsgProc},
681 {"----", NothingProc},
685 MenuItem modeMenu[] = {
686 // {N_("Machine White"), MachineWhiteProc},
687 // {N_("Machine Black"), MachineBlackProc},
688 // {N_("Two Machines"), TwoMachinesProc},
689 {N_("Analysis Mode"), AnalyzeModeProc},
690 {N_("Analyze File"), AnalyzeFileProc },
691 // {N_("ICS Client"), IcsClientProc},
692 {N_("Edit Game"), EditGameProc},
693 {N_("Edit Position"), EditPositionProc},
694 {N_("Training"), TrainingProc},
695 {"----", NothingProc},
696 {N_("Show Engine Output"), EngineOutputProc},
697 {N_("Show Evaluation Graph"), NothingProc}, // [HGM] evalgr: not functional yet
698 {N_("Show Game List"), ShowGameListProc},
699 {"Show Move History", HistoryShowProc}, // [HGM] hist: activate 4.2.7 code
700 {"----", NothingProc},
701 {N_("Edit Tags"), EditTagsProc},
702 {N_("Edit Comment"), EditCommentProc},
703 {N_("ICS Input Box"), IcsInputBoxProc},
707 MenuItem optionsMenu[] = {
708 {N_("Flip View"), FlipViewProc},
709 {"----", NothingProc},
710 {N_("Adjudications ..."), EngineMenuProc},
711 {N_("General Settings ..."), UciMenuProc},
712 {N_("Engine #1 Settings ..."), FirstSettingsProc},
713 {N_("Engine #2 Settings ..."), SecondSettingsProc},
714 {N_("Time Control ..."), TimeControlProc},
715 {"----", NothingProc},
716 {N_("Always Queen"), AlwaysQueenProc},
717 {N_("Animate Dragging"), AnimateDraggingProc},
718 {N_("Animate Moving"), AnimateMovingProc},
719 {N_("Auto Comment"), AutocommProc},
720 {N_("Auto Flag"), AutoflagProc},
721 {N_("Auto Flip View"), AutoflipProc},
722 {N_("Auto Observe"), AutobsProc},
723 {N_("Auto Raise Board"), AutoraiseProc},
724 {N_("Auto Save"), AutosaveProc},
725 {N_("Blindfold"), BlindfoldProc},
726 {N_("Flash Moves"), FlashMovesProc},
727 {N_("Get Move List"), GetMoveListProc},
729 {N_("Highlight Dragging"), HighlightDraggingProc},
731 {N_("Highlight Last Move"), HighlightLastMoveProc},
732 {N_("Move Sound"), MoveSoundProc},
733 {N_("ICS Alarm"), IcsAlarmProc},
734 {N_("Old Save Style"), OldSaveStyleProc},
735 {N_("Periodic Updates"), PeriodicUpdatesProc},
736 {N_("Ponder Next Move"), PonderNextMoveProc},
737 {N_("Popup Exit Message"), PopupExitMessageProc},
738 {N_("Popup Move Errors"), PopupMoveErrorsProc},
739 {N_("Premove"), PremoveProc},
740 {N_("Quiet Play"), QuietPlayProc},
741 {N_("Hide Thinking"), HideThinkingProc},
742 {N_("Test Legality"), TestLegalityProc},
746 MenuItem helpMenu[] = {
747 {N_("Info XBoard"), InfoProc},
748 {N_("Man XBoard"), ManProc},
749 {"----", NothingProc},
750 {N_("Hint"), HintProc},
751 {N_("Book"), BookProc},
752 {"----", NothingProc},
757 {N_("File"), fileMenu},
758 {N_("Mode"), modeMenu},
759 {N_("Options"), optionsMenu},
760 {N_("Help"), helpMenu},
764 #define PAUSE_BUTTON N_("P")
765 MenuItem buttonBar[] = {
766 // {"<<", ToStartProc},
767 // {"<", BackwardProc},
768 // {PAUSE_BUTTON, PauseProc},
769 // {">", ForwardProc},
770 // {">>", ToEndProc},
774 #define PIECE_MENU_SIZE 18
775 String pieceMenuStrings[2][PIECE_MENU_SIZE] = {
776 { N_("White"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
777 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
778 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
779 N_("Empty square"), N_("Clear board") },
780 { N_("Black"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
781 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
782 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
783 N_("Empty square"), N_("Clear board") }
785 /* must be in same order as PieceMenuStrings! */
786 ChessSquare pieceMenuTranslation[2][PIECE_MENU_SIZE] = {
787 { WhitePlay, (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
788 WhiteRook, WhiteQueen, WhiteKing, (ChessSquare) 0, WhiteAlfil,
789 WhiteCannon, WhiteAngel, WhiteMarshall, (ChessSquare) 0,
790 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
791 { BlackPlay, (ChessSquare) 0, BlackPawn, BlackKnight, BlackBishop,
792 BlackRook, BlackQueen, BlackKing, (ChessSquare) 0, BlackAlfil,
793 BlackCannon, BlackAngel, BlackMarshall, (ChessSquare) 0,
794 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
797 #define DROP_MENU_SIZE 6
798 String dropMenuStrings[DROP_MENU_SIZE] = {
799 "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"), N_("Queen")
801 /* must be in same order as PieceMenuStrings! */
802 ChessSquare dropMenuTranslation[DROP_MENU_SIZE] = {
803 (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
804 WhiteRook, WhiteQueen
812 DropMenuEnables dmEnables[] = {
821 { XtNborderWidth, 0 },
822 { XtNdefaultDistance, 0 },
826 { XtNborderWidth, 0 },
827 { XtNresizable, (XtArgVal) True },
831 { XtNborderWidth, 0 },
836 XtResource clientResources[] = {
837 { "whitePieceColor", "whitePieceColor", XtRString, sizeof(String),
838 XtOffset(AppDataPtr, whitePieceColor), XtRString,
840 { "blackPieceColor", "blackPieceColor", XtRString, sizeof(String),
841 XtOffset(AppDataPtr, blackPieceColor), XtRString,
843 { "lightSquareColor", "lightSquareColor", XtRString,
844 sizeof(String), XtOffset(AppDataPtr, lightSquareColor),
845 XtRString, LIGHT_SQUARE_COLOR },
846 { "darkSquareColor", "darkSquareColor", XtRString, sizeof(String),
847 XtOffset(AppDataPtr, darkSquareColor), XtRString,
849 { "highlightSquareColor", "highlightSquareColor", XtRString,
850 sizeof(String), XtOffset(AppDataPtr, highlightSquareColor),
851 XtRString, HIGHLIGHT_SQUARE_COLOR },
852 { "premoveHighlightColor", "premoveHighlightColor", XtRString,
853 sizeof(String), XtOffset(AppDataPtr, premoveHighlightColor),
854 XtRString, PREMOVE_HIGHLIGHT_COLOR },
855 { "movesPerSession", "movesPerSession", XtRInt, sizeof(int),
856 XtOffset(AppDataPtr, movesPerSession), XtRImmediate,
857 (XtPointer) MOVES_PER_SESSION },
858 { "timeIncrement", "timeIncrement", XtRInt, sizeof(int),
859 XtOffset(AppDataPtr, timeIncrement), XtRImmediate,
860 (XtPointer) TIME_INCREMENT },
861 { "initString", "initString", XtRString, sizeof(String),
862 XtOffset(AppDataPtr, initString), XtRString, INIT_STRING },
863 { "secondInitString", "secondInitString", XtRString, sizeof(String),
864 XtOffset(AppDataPtr, secondInitString), XtRString, INIT_STRING },
865 { "firstComputerString", "firstComputerString", XtRString,
866 sizeof(String), XtOffset(AppDataPtr, firstComputerString), XtRString,
868 { "secondComputerString", "secondComputerString", XtRString,
869 sizeof(String), XtOffset(AppDataPtr, secondComputerString), XtRString,
871 { "firstChessProgram", "firstChessProgram", XtRString,
872 sizeof(String), XtOffset(AppDataPtr, firstChessProgram),
873 XtRString, FIRST_CHESS_PROGRAM },
874 { "secondChessProgram", "secondChessProgram", XtRString,
875 sizeof(String), XtOffset(AppDataPtr, secondChessProgram),
876 XtRString, SECOND_CHESS_PROGRAM },
877 { "firstPlaysBlack", "firstPlaysBlack", XtRBoolean,
878 sizeof(Boolean), XtOffset(AppDataPtr, firstPlaysBlack),
879 XtRImmediate, (XtPointer) False },
880 { "noChessProgram", "noChessProgram", XtRBoolean,
881 sizeof(Boolean), XtOffset(AppDataPtr, noChessProgram),
882 XtRImmediate, (XtPointer) False },
883 { "firstHost", "firstHost", XtRString, sizeof(String),
884 XtOffset(AppDataPtr, firstHost), XtRString, FIRST_HOST },
885 { "secondHost", "secondHost", XtRString, sizeof(String),
886 XtOffset(AppDataPtr, secondHost), XtRString, SECOND_HOST },
887 { "firstDirectory", "firstDirectory", XtRString, sizeof(String),
888 XtOffset(AppDataPtr, firstDirectory), XtRString, "." },
889 { "secondDirectory", "secondDirectory", XtRString, sizeof(String),
890 XtOffset(AppDataPtr, secondDirectory), XtRString, "." },
891 { "bitmapDirectory", "bitmapDirectory", XtRString,
892 sizeof(String), XtOffset(AppDataPtr, bitmapDirectory),
894 { "remoteShell", "remoteShell", XtRString, sizeof(String),
895 XtOffset(AppDataPtr, remoteShell), XtRString, REMOTE_SHELL },
896 { "remoteUser", "remoteUser", XtRString, sizeof(String),
897 XtOffset(AppDataPtr, remoteUser), XtRString, "" },
898 { "timeDelay", "timeDelay", XtRFloat, sizeof(float),
899 XtOffset(AppDataPtr, timeDelay), XtRString,
900 (XtPointer) TIME_DELAY_QUOTE },
901 { "timeControl", "timeControl", XtRString, sizeof(String),
902 XtOffset(AppDataPtr, timeControl), XtRString,
903 (XtPointer) TIME_CONTROL },
904 { "internetChessServerMode", "internetChessServerMode",
905 XtRBoolean, sizeof(Boolean),
906 XtOffset(AppDataPtr, icsActive), XtRImmediate,
908 { "internetChessServerHost", "internetChessServerHost",
909 XtRString, sizeof(String),
910 XtOffset(AppDataPtr, icsHost),
911 XtRString, (XtPointer) ICS_HOST },
912 { "internetChessServerPort", "internetChessServerPort",
913 XtRString, sizeof(String),
914 XtOffset(AppDataPtr, icsPort), XtRString,
915 (XtPointer) ICS_PORT },
916 { "internetChessServerCommPort", "internetChessServerCommPort",
917 XtRString, sizeof(String),
918 XtOffset(AppDataPtr, icsCommPort), XtRString,
920 { "internetChessServerLogonScript", "internetChessServerLogonScript",
921 XtRString, sizeof(String),
922 XtOffset(AppDataPtr, icsLogon), XtRString,
924 { "internetChessServerHelper", "internetChessServerHelper",
925 XtRString, sizeof(String),
926 XtOffset(AppDataPtr, icsHelper), XtRString, "" },
927 { "internetChessServerInputBox", "internetChessServerInputBox",
928 XtRBoolean, sizeof(Boolean),
929 XtOffset(AppDataPtr, icsInputBox), XtRImmediate,
931 { "icsAlarm", "icsAlarm",
932 XtRBoolean, sizeof(Boolean),
933 XtOffset(AppDataPtr, icsAlarm), XtRImmediate,
935 { "icsAlarmTime", "icsAlarmTime",
937 XtOffset(AppDataPtr, icsAlarmTime), XtRImmediate,
939 { "useTelnet", "useTelnet", XtRBoolean, sizeof(Boolean),
940 XtOffset(AppDataPtr, useTelnet), XtRImmediate,
942 { "telnetProgram", "telnetProgram", XtRString, sizeof(String),
943 XtOffset(AppDataPtr, telnetProgram), XtRString, TELNET_PROGRAM },
944 { "gateway", "gateway", XtRString, sizeof(String),
945 XtOffset(AppDataPtr, gateway), XtRString, "" },
946 { "loadGameFile", "loadGameFile", XtRString, sizeof(String),
947 XtOffset(AppDataPtr, loadGameFile), XtRString, "" },
948 { "loadGameIndex", "loadGameIndex",
950 XtOffset(AppDataPtr, loadGameIndex), XtRImmediate,
952 { "saveGameFile", "saveGameFile", XtRString, sizeof(String),
953 XtOffset(AppDataPtr, saveGameFile), XtRString, "" },
954 { "autoRaiseBoard", "autoRaiseBoard", XtRBoolean,
955 sizeof(Boolean), XtOffset(AppDataPtr, autoRaiseBoard),
956 XtRImmediate, (XtPointer) True },
957 { "autoSaveGames", "autoSaveGames", XtRBoolean,
958 sizeof(Boolean), XtOffset(AppDataPtr, autoSaveGames),
959 XtRImmediate, (XtPointer) False },
960 { "blindfold", "blindfold", XtRBoolean,
961 sizeof(Boolean), XtOffset(AppDataPtr, blindfold),
962 XtRImmediate, (XtPointer) False },
963 { "loadPositionFile", "loadPositionFile", XtRString,
964 sizeof(String), XtOffset(AppDataPtr, loadPositionFile),
966 { "loadPositionIndex", "loadPositionIndex",
968 XtOffset(AppDataPtr, loadPositionIndex), XtRImmediate,
970 { "savePositionFile", "savePositionFile", XtRString,
971 sizeof(String), XtOffset(AppDataPtr, savePositionFile),
973 { "matchMode", "matchMode", XtRBoolean, sizeof(Boolean),
974 XtOffset(AppDataPtr, matchMode), XtRImmediate, (XtPointer) False },
975 { "matchGames", "matchGames", XtRInt, sizeof(int),
976 XtOffset(AppDataPtr, matchGames), XtRImmediate,
978 { "monoMode", "monoMode", XtRBoolean, sizeof(Boolean),
979 XtOffset(AppDataPtr, monoMode), XtRImmediate,
981 { "debugMode", "debugMode", XtRBoolean, sizeof(Boolean),
982 XtOffset(AppDataPtr, debugMode), XtRImmediate,
984 { "clockMode", "clockMode", XtRBoolean, sizeof(Boolean),
985 XtOffset(AppDataPtr, clockMode), XtRImmediate,
987 { "boardSize", "boardSize", XtRString, sizeof(String),
988 XtOffset(AppDataPtr, boardSize), XtRString, "" },
989 { "searchTime", "searchTime", XtRString, sizeof(String),
990 XtOffset(AppDataPtr, searchTime), XtRString,
992 { "searchDepth", "searchDepth", XtRInt, sizeof(int),
993 XtOffset(AppDataPtr, searchDepth), XtRImmediate,
995 { "showCoords", "showCoords", XtRBoolean, sizeof(Boolean),
996 XtOffset(AppDataPtr, showCoords), XtRImmediate,
998 { "showJail", "showJail", XtRInt, sizeof(int),
999 XtOffset(AppDataPtr, showJail), XtRImmediate,
1001 { "showThinking", "showThinking", XtRBoolean, sizeof(Boolean),
1002 XtOffset(AppDataPtr, showThinking), XtRImmediate,
1004 { "ponderNextMove", "ponderNextMove", XtRBoolean, sizeof(Boolean),
1005 XtOffset(AppDataPtr, ponderNextMove), XtRImmediate,
1007 { "periodicUpdates", "periodicUpdates", XtRBoolean, sizeof(Boolean),
1008 XtOffset(AppDataPtr, periodicUpdates), XtRImmediate,
1010 { "clockFont", "clockFont", XtRString, sizeof(String),
1011 XtOffset(AppDataPtr, clockFont), XtRString, CLOCK_FONT },
1012 { "coordFont", "coordFont", XtRString, sizeof(String),
1013 XtOffset(AppDataPtr, coordFont), XtRString, COORD_FONT },
1014 { "font", "font", XtRString, sizeof(String),
1015 XtOffset(AppDataPtr, font), XtRString, DEFAULT_FONT },
1016 { "ringBellAfterMoves", "ringBellAfterMoves",
1017 XtRBoolean, sizeof(Boolean),
1018 XtOffset(AppDataPtr, ringBellAfterMoves),
1019 XtRImmediate, (XtPointer) False },
1020 { "autoCallFlag", "autoCallFlag", XtRBoolean,
1021 sizeof(Boolean), XtOffset(AppDataPtr, autoCallFlag),
1022 XtRImmediate, (XtPointer) False },
1023 { "autoFlipView", "autoFlipView", XtRBoolean,
1024 sizeof(Boolean), XtOffset(AppDataPtr, autoFlipView),
1025 XtRImmediate, (XtPointer) True },
1026 { "autoObserve", "autoObserve", XtRBoolean,
1027 sizeof(Boolean), XtOffset(AppDataPtr, autoObserve),
1028 XtRImmediate, (XtPointer) False },
1029 { "autoComment", "autoComment", XtRBoolean,
1030 sizeof(Boolean), XtOffset(AppDataPtr, autoComment),
1031 XtRImmediate, (XtPointer) False },
1032 { "getMoveList", "getMoveList", XtRBoolean,
1033 sizeof(Boolean), XtOffset(AppDataPtr, getMoveList),
1034 XtRImmediate, (XtPointer) True },
1036 { "highlightDragging", "highlightDragging", XtRBoolean,
1037 sizeof(Boolean), XtOffset(AppDataPtr, highlightDragging),
1038 XtRImmediate, (XtPointer) False },
1040 { "highlightLastMove", "highlightLastMove", XtRBoolean,
1041 sizeof(Boolean), XtOffset(AppDataPtr, highlightLastMove),
1042 XtRImmediate, (XtPointer) False },
1043 { "premove", "premove", XtRBoolean,
1044 sizeof(Boolean), XtOffset(AppDataPtr, premove),
1045 XtRImmediate, (XtPointer) True },
1046 { "testLegality", "testLegality", XtRBoolean,
1047 sizeof(Boolean), XtOffset(AppDataPtr, testLegality),
1048 XtRImmediate, (XtPointer) True },
1049 { "flipView", "flipView", XtRBoolean,
1050 sizeof(Boolean), XtOffset(AppDataPtr, flipView),
1051 XtRImmediate, (XtPointer) False },
1052 { "cmail", "cmailGameName", XtRString, sizeof(String),
1053 XtOffset(AppDataPtr, cmailGameName), XtRString, "" },
1054 { "alwaysPromoteToQueen", "alwaysPromoteToQueen", XtRBoolean,
1055 sizeof(Boolean), XtOffset(AppDataPtr, alwaysPromoteToQueen),
1056 XtRImmediate, (XtPointer) False },
1057 { "oldSaveStyle", "oldSaveStyle", XtRBoolean,
1058 sizeof(Boolean), XtOffset(AppDataPtr, oldSaveStyle),
1059 XtRImmediate, (XtPointer) False },
1060 { "quietPlay", "quietPlay", XtRBoolean,
1061 sizeof(Boolean), XtOffset(AppDataPtr, quietPlay),
1062 XtRImmediate, (XtPointer) False },
1063 { "titleInWindow", "titleInWindow", XtRBoolean,
1064 sizeof(Boolean), XtOffset(AppDataPtr, titleInWindow),
1065 XtRImmediate, (XtPointer) False },
1066 { "localLineEditing", "localLineEditing", XtRBoolean,
1067 sizeof(Boolean), XtOffset(AppDataPtr, localLineEditing),
1068 XtRImmediate, (XtPointer) True }, /* not implemented, must be True */
1070 { "zippyTalk", "zippyTalk", XtRBoolean,
1071 sizeof(Boolean), XtOffset(AppDataPtr, zippyTalk),
1072 XtRImmediate, (XtPointer) ZIPPY_TALK },
1073 { "zippyPlay", "zippyPlay", XtRBoolean,
1074 sizeof(Boolean), XtOffset(AppDataPtr, zippyPlay),
1075 XtRImmediate, (XtPointer) ZIPPY_PLAY },
1076 { "zippyLines", "zippyLines", XtRString, sizeof(String),
1077 XtOffset(AppDataPtr, zippyLines), XtRString, ZIPPY_LINES },
1078 { "zippyPinhead", "zippyPinhead", XtRString, sizeof(String),
1079 XtOffset(AppDataPtr, zippyPinhead), XtRString, ZIPPY_PINHEAD },
1080 { "zippyPassword", "zippyPassword", XtRString, sizeof(String),
1081 XtOffset(AppDataPtr, zippyPassword), XtRString, ZIPPY_PASSWORD },
1082 { "zippyPassword2", "zippyPassword2", XtRString, sizeof(String),
1083 XtOffset(AppDataPtr, zippyPassword2), XtRString, ZIPPY_PASSWORD2 },
1084 { "zippyWrongPassword", "zippyWrongPassword", XtRString, sizeof(String),
1085 XtOffset(AppDataPtr, zippyWrongPassword), XtRString,
1086 ZIPPY_WRONG_PASSWORD },
1087 { "zippyAcceptOnly", "zippyAcceptOnly", XtRString, sizeof(String),
1088 XtOffset(AppDataPtr, zippyAcceptOnly), XtRString, ZIPPY_ACCEPT_ONLY },
1089 { "zippyUseI", "zippyUseI", XtRBoolean,
1090 sizeof(Boolean), XtOffset(AppDataPtr, zippyUseI),
1091 XtRImmediate, (XtPointer) ZIPPY_USE_I },
1092 { "zippyBughouse", "zippyBughouse", XtRInt,
1093 sizeof(int), XtOffset(AppDataPtr, zippyBughouse),
1094 XtRImmediate, (XtPointer) ZIPPY_BUGHOUSE },
1095 { "zippyNoplayCrafty", "zippyNoplayCrafty", XtRBoolean,
1096 sizeof(Boolean), XtOffset(AppDataPtr, zippyNoplayCrafty),
1097 XtRImmediate, (XtPointer) ZIPPY_NOPLAY_CRAFTY },
1098 { "zippyGameEnd", "zippyGameEnd", XtRString, sizeof(String),
1099 XtOffset(AppDataPtr, zippyGameEnd), XtRString, ZIPPY_GAME_END },
1100 { "zippyGameStart", "zippyGameStart", XtRString, sizeof(String),
1101 XtOffset(AppDataPtr, zippyGameStart), XtRString, ZIPPY_GAME_START },
1102 { "zippyAdjourn", "zippyAdjourn", XtRBoolean,
1103 sizeof(Boolean), XtOffset(AppDataPtr, zippyAdjourn),
1104 XtRImmediate, (XtPointer) ZIPPY_ADJOURN },
1105 { "zippyAbort", "zippyAbort", XtRBoolean,
1106 sizeof(Boolean), XtOffset(AppDataPtr, zippyAbort),
1107 XtRImmediate, (XtPointer) ZIPPY_ABORT },
1108 { "zippyVariants", "zippyVariants", XtRString, sizeof(String),
1109 XtOffset(AppDataPtr, zippyVariants), XtRString, ZIPPY_VARIANTS },
1110 { "zippyMaxGames", "zippyMaxGames", XtRInt, sizeof(int),
1111 XtOffset(AppDataPtr, zippyMaxGames), XtRImmediate,
1112 (XtPointer) ZIPPY_MAX_GAMES },
1113 { "zippyReplayTimeout", "zippyReplayTimeout", XtRInt, sizeof(int),
1114 XtOffset(AppDataPtr, zippyReplayTimeout), XtRImmediate,
1115 (XtPointer) ZIPPY_REPLAY_TIMEOUT },
1116 { "zippyShortGame", "zippyShortGame", XtRInt, sizeof(int),
1117 XtOffset(AppDataPtr, zippyShortGame), XtRImmediate,
1120 { "flashCount", "flashCount", XtRInt, sizeof(int),
1121 XtOffset(AppDataPtr, flashCount), XtRImmediate,
1122 (XtPointer) FLASH_COUNT },
1123 { "flashRate", "flashRate", XtRInt, sizeof(int),
1124 XtOffset(AppDataPtr, flashRate), XtRImmediate,
1125 (XtPointer) FLASH_RATE },
1126 { "pixmapDirectory", "pixmapDirectory", XtRString,
1127 sizeof(String), XtOffset(AppDataPtr, pixmapDirectory),
1129 { "msLoginDelay", "msLoginDelay", XtRInt, sizeof(int),
1130 XtOffset(AppDataPtr, msLoginDelay), XtRImmediate,
1131 (XtPointer) MS_LOGIN_DELAY },
1132 { "colorizeMessages", "colorizeMessages", XtRBoolean,
1133 sizeof(Boolean), XtOffset(AppDataPtr, colorize),
1134 XtRImmediate, (XtPointer) False },
1135 { "colorShout", "colorShout", XtRString,
1136 sizeof(String), XtOffset(AppDataPtr, colorShout),
1137 XtRString, COLOR_SHOUT },
1138 { "colorSShout", "colorSShout", XtRString,
1139 sizeof(String), XtOffset(AppDataPtr, colorSShout),
1140 XtRString, COLOR_SSHOUT },
1141 { "colorChannel1", "colorChannel1", XtRString,
1142 sizeof(String), XtOffset(AppDataPtr, colorChannel1),
1143 XtRString, COLOR_CHANNEL1 },
1144 { "colorChannel", "colorChannel", XtRString,
1145 sizeof(String), XtOffset(AppDataPtr, colorChannel),
1146 XtRString, COLOR_CHANNEL },
1147 { "colorKibitz", "colorKibitz", XtRString,
1148 sizeof(String), XtOffset(AppDataPtr, colorKibitz),
1149 XtRString, COLOR_KIBITZ },
1150 { "colorTell", "colorTell", XtRString,
1151 sizeof(String), XtOffset(AppDataPtr, colorTell),
1152 XtRString, COLOR_TELL },
1153 { "colorChallenge", "colorChallenge", XtRString,
1154 sizeof(String), XtOffset(AppDataPtr, colorChallenge),
1155 XtRString, COLOR_CHALLENGE },
1156 { "colorRequest", "colorRequest", XtRString,
1157 sizeof(String), XtOffset(AppDataPtr, colorRequest),
1158 XtRString, COLOR_REQUEST },
1159 { "colorSeek", "colorSeek", XtRString,
1160 sizeof(String), XtOffset(AppDataPtr, colorSeek),
1161 XtRString, COLOR_SEEK },
1162 { "colorNormal", "colorNormal", XtRString,
1163 sizeof(String), XtOffset(AppDataPtr, colorNormal),
1164 XtRString, COLOR_NORMAL },
1165 { "soundProgram", "soundProgram", XtRString,
1166 sizeof(String), XtOffset(AppDataPtr, soundProgram),
1167 XtRString, "play" },
1168 { "soundShout", "soundShout", XtRString,
1169 sizeof(String), XtOffset(AppDataPtr, soundShout),
1171 { "soundSShout", "soundSShout", XtRString,
1172 sizeof(String), XtOffset(AppDataPtr, soundSShout),
1174 { "soundChannel1", "soundChannel1", XtRString,
1175 sizeof(String), XtOffset(AppDataPtr, soundChannel1),
1177 { "soundChannel", "soundChannel", XtRString,
1178 sizeof(String), XtOffset(AppDataPtr, soundChannel),
1180 { "soundKibitz", "soundKibitz", XtRString,
1181 sizeof(String), XtOffset(AppDataPtr, soundKibitz),
1183 { "soundTell", "soundTell", XtRString,
1184 sizeof(String), XtOffset(AppDataPtr, soundTell),
1186 { "soundChallenge", "soundChallenge", XtRString,
1187 sizeof(String), XtOffset(AppDataPtr, soundChallenge),
1189 { "soundRequest", "soundRequest", XtRString,
1190 sizeof(String), XtOffset(AppDataPtr, soundRequest),
1192 { "soundSeek", "soundSeek", XtRString,
1193 sizeof(String), XtOffset(AppDataPtr, soundSeek),
1195 { "soundMove", "soundMove", XtRString,
1196 sizeof(String), XtOffset(AppDataPtr, soundMove),
1198 { "soundIcsWin", "soundIcsWin", XtRString,
1199 sizeof(String), XtOffset(AppDataPtr, soundIcsWin),
1201 { "soundIcsLoss", "soundIcsLoss", XtRString,
1202 sizeof(String), XtOffset(AppDataPtr, soundIcsLoss),
1204 { "soundIcsDraw", "soundIcsDraw", XtRString,
1205 sizeof(String), XtOffset(AppDataPtr, soundIcsDraw),
1207 { "soundIcsUnfinished", "soundIcsUnfinished", XtRString,
1208 sizeof(String), XtOffset(AppDataPtr, soundIcsUnfinished),
1210 { "soundIcsAlarm", "soundIcsAlarm", XtRString,
1211 sizeof(String), XtOffset(AppDataPtr, soundIcsAlarm),
1213 { "reuseFirst", "reuseFirst", XtRBoolean,
1214 sizeof(Boolean), XtOffset(AppDataPtr, reuseFirst),
1215 XtRImmediate, (XtPointer) True },
1216 { "reuseSecond", "reuseSecond", XtRBoolean,
1217 sizeof(Boolean), XtOffset(AppDataPtr, reuseSecond),
1218 XtRImmediate, (XtPointer) True },
1219 { "animateDragging", "animateDragging", XtRBoolean,
1220 sizeof(Boolean), XtOffset(AppDataPtr, animateDragging),
1221 XtRImmediate, (XtPointer) True },
1222 { "animateMoving", "animateMoving", XtRBoolean,
1223 sizeof(Boolean), XtOffset(AppDataPtr, animate),
1224 XtRImmediate, (XtPointer) True },
1225 { "animateSpeed", "animateSpeed", XtRInt,
1226 sizeof(int), XtOffset(AppDataPtr, animSpeed),
1227 XtRImmediate, (XtPointer)10 },
1228 { "popupExitMessage", "popupExitMessage", XtRBoolean,
1229 sizeof(Boolean), XtOffset(AppDataPtr, popupExitMessage),
1230 XtRImmediate, (XtPointer) True },
1231 { "popupMoveErrors", "popupMoveErrors", XtRBoolean,
1232 sizeof(Boolean), XtOffset(AppDataPtr, popupMoveErrors),
1233 XtRImmediate, (XtPointer) False },
1234 { "fontSizeTolerance", "fontSizeTolerance", XtRInt,
1235 sizeof(int), XtOffset(AppDataPtr, fontSizeTolerance),
1236 XtRImmediate, (XtPointer)4 },
1237 { "initialMode", "initialMode", XtRString,
1238 sizeof(String), XtOffset(AppDataPtr, initialMode),
1239 XtRImmediate, (XtPointer) "" },
1240 { "variant", "variant", XtRString,
1241 sizeof(String), XtOffset(AppDataPtr, variant),
1242 XtRImmediate, (XtPointer) "normal" },
1243 { "firstProtocolVersion", "firstProtocolVersion", XtRInt,
1244 sizeof(int), XtOffset(AppDataPtr, firstProtocolVersion),
1245 XtRImmediate, (XtPointer)PROTOVER },
1246 { "secondProtocolVersion", "secondProtocolVersion", XtRInt,
1247 sizeof(int), XtOffset(AppDataPtr, secondProtocolVersion),
1248 XtRImmediate, (XtPointer)PROTOVER },
1249 { "showButtonBar", "showButtonBar", XtRBoolean,
1250 sizeof(Boolean), XtOffset(AppDataPtr, showButtonBar),
1251 XtRImmediate, (XtPointer) True },
1252 { "lowTimeWarningColor", "lowTimeWarningColor", XtRString,
1253 sizeof(String), XtOffset(AppDataPtr, lowTimeWarningColor),
1254 XtRString, COLOR_LOWTIMEWARNING },
1255 { "lowTimeWarning", "lowTimeWarning", XtRBoolean,
1256 sizeof(Boolean), XtOffset(AppDataPtr, lowTimeWarning),
1257 XtRImmediate, (XtPointer) False },
1258 {"icsEngineAnalyze", "icsEngineAnalyze", XtRBoolean, /* [DM] icsEngineAnalyze */
1259 sizeof(Boolean), XtOffset(AppDataPtr, icsEngineAnalyze),
1260 XtRImmediate, (XtPointer) False },
1261 { "firstScoreAbs", "firstScoreAbs", XtRBoolean,
1262 sizeof(Boolean), XtOffset(AppDataPtr, firstScoreIsAbsolute),
1263 XtRImmediate, (XtPointer) False },
1264 { "secondScoreAbs", "secondScoreAbs", XtRBoolean,
1265 sizeof(Boolean), XtOffset(AppDataPtr, secondScoreIsAbsolute),
1266 XtRImmediate, (XtPointer) False },
1267 { "pgnExtendedInfo", "pgnExtendedInfo", XtRBoolean,
1268 sizeof(Boolean), XtOffset(AppDataPtr, saveExtendedInfoInPGN),
1269 XtRImmediate, (XtPointer) False },
1270 { "hideThinkingFromHuman", "hideThinkingFromHuman", XtRBoolean,
1271 sizeof(Boolean), XtOffset(AppDataPtr, hideThinkingFromHuman),
1272 XtRImmediate, (XtPointer) True },
1273 { "adjudicateLossThreshold", "adjudicateLossThreshold", XtRInt,
1274 sizeof(int), XtOffset(AppDataPtr, adjudicateLossThreshold),
1275 XtRImmediate, (XtPointer) 0},
1276 { "pgnEventHeader", "pgnEventHeader", XtRString,
1277 sizeof(String), XtOffset(AppDataPtr, pgnEventHeader),
1278 XtRImmediate, (XtPointer) "Computer Chess Game" },
1279 { "defaultFrcPosition", "defaultFrcPositon", XtRInt,
1280 sizeof(int), XtOffset(AppDataPtr, defaultFrcPosition),
1281 XtRImmediate, (XtPointer) -1},
1282 { "gameListTags", "gameListTags", XtRString,
1283 sizeof(String), XtOffset(AppDataPtr, gameListTags),
1284 XtRImmediate, (XtPointer) GLT_DEFAULT_TAGS },
1286 // [HGM] 4.3.xx options
1287 { "boardWidth", "boardWidth", XtRInt,
1288 sizeof(int), XtOffset(AppDataPtr, NrFiles),
1289 XtRImmediate, (XtPointer) -1},
1290 { "boardHeight", "boardHeight", XtRInt,
1291 sizeof(int), XtOffset(AppDataPtr, NrRanks),
1292 XtRImmediate, (XtPointer) -1},
1293 { "matchPause", "matchPause", XtRInt,
1294 sizeof(int), XtOffset(AppDataPtr, matchPause),
1295 XtRImmediate, (XtPointer) 10000},
1296 { "holdingsSize", "holdingsSize", XtRInt,
1297 sizeof(int), XtOffset(AppDataPtr, holdingsSize),
1298 XtRImmediate, (XtPointer) -1},
1299 { "flipBlack", "flipBlack", XtRBoolean,
1300 sizeof(Boolean), XtOffset(AppDataPtr, upsideDown),
1301 XtRImmediate, (XtPointer) False},
1302 { "allWhite", "allWhite", XtRBoolean,
1303 sizeof(Boolean), XtOffset(AppDataPtr, allWhite),
1304 XtRImmediate, (XtPointer) False},
1305 { "pieceToCharTable", "pieceToCharTable", XtRString,
1306 sizeof(String), XtOffset(AppDataPtr, pieceToCharTable),
1307 XtRImmediate, (XtPointer) 0},
1308 { "alphaRank", "alphaRank", XtRBoolean,
1309 sizeof(Boolean), XtOffset(AppDataPtr, alphaRank),
1310 XtRImmediate, (XtPointer) False},
1311 { "testClaims", "testClaims", XtRBoolean,
1312 sizeof(Boolean), XtOffset(AppDataPtr, testClaims),
1313 XtRImmediate, (XtPointer) True},
1314 { "checkMates", "checkMates", XtRBoolean,
1315 sizeof(Boolean), XtOffset(AppDataPtr, checkMates),
1316 XtRImmediate, (XtPointer) True},
1317 { "materialDraws", "materialDraws", XtRBoolean,
1318 sizeof(Boolean), XtOffset(AppDataPtr, materialDraws),
1319 XtRImmediate, (XtPointer) True},
1320 { "trivialDraws", "trivialDraws", XtRBoolean,
1321 sizeof(Boolean), XtOffset(AppDataPtr, trivialDraws),
1322 XtRImmediate, (XtPointer) False},
1323 { "ruleMoves", "ruleMoves", XtRInt,
1324 sizeof(int), XtOffset(AppDataPtr, ruleMoves),
1325 XtRImmediate, (XtPointer) 51},
1326 { "repeatsToDraw", "repeatsToDraw", XtRInt,
1327 sizeof(int), XtOffset(AppDataPtr, drawRepeats),
1328 XtRImmediate, (XtPointer) 6},
1329 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1330 sizeof(int), XtOffset(AppDataPtr, engineComments),
1331 XtRImmediate, (XtPointer) 1},
1332 { "userName", "userName", XtRString,
1333 sizeof(int), XtOffset(AppDataPtr, userName),
1334 XtRImmediate, (XtPointer) 0},
1335 { "autoKibitz", "autoKibitz", XtRBoolean,
1336 sizeof(Boolean), XtOffset(AppDataPtr, autoKibitz),
1337 XtRImmediate, (XtPointer) False},
1338 { "firstTimeOdds", "firstTimeOdds", XtRInt,
1339 sizeof(int), XtOffset(AppDataPtr, firstTimeOdds),
1340 XtRImmediate, (XtPointer) 1},
1341 { "secondTimeOdds", "secondTimeOdds", XtRInt,
1342 sizeof(int), XtOffset(AppDataPtr, secondTimeOdds),
1343 XtRImmediate, (XtPointer) 1},
1344 { "timeOddsMode", "timeOddsMode", XtRInt,
1345 sizeof(int), XtOffset(AppDataPtr, timeOddsMode),
1346 XtRImmediate, (XtPointer) 0},
1347 { "firstAccumulateTC", "firstAccumulateTC", XtRInt,
1348 sizeof(int), XtOffset(AppDataPtr, firstAccumulateTC),
1349 XtRImmediate, (XtPointer) 1},
1350 { "secondAccumulateTC", "secondAccumulateTC", XtRInt,
1351 sizeof(int), XtOffset(AppDataPtr, secondAccumulateTC),
1352 XtRImmediate, (XtPointer) 1},
1353 { "firstNPS", "firstNPS", XtRInt,
1354 sizeof(int), XtOffset(AppDataPtr, firstNPS),
1355 XtRImmediate, (XtPointer) -1},
1356 { "secondNPS", "secondNPS", XtRInt,
1357 sizeof(int), XtOffset(AppDataPtr, secondNPS),
1358 XtRImmediate, (XtPointer) -1},
1359 { "serverMoves", "serverMoves", XtRString,
1360 sizeof(String), XtOffset(AppDataPtr, serverMovesName),
1361 XtRImmediate, (XtPointer) 0},
1362 { "serverPause", "serverPause", XtRInt,
1363 sizeof(int), XtOffset(AppDataPtr, serverPause),
1364 XtRImmediate, (XtPointer) 0},
1365 { "suppressLoadMoves", "suppressLoadMoves", XtRBoolean,
1366 sizeof(Boolean), XtOffset(AppDataPtr, suppressLoadMoves),
1367 XtRImmediate, (XtPointer) False},
1368 { "userName", "userName", XtRString,
1369 sizeof(String), XtOffset(AppDataPtr, userName),
1370 XtRImmediate, (XtPointer) 0},
1371 { "egtFormats", "egtFormats", XtRString,
1372 sizeof(String), XtOffset(AppDataPtr, egtFormats),
1373 XtRImmediate, (XtPointer) 0},
1374 { "rewindIndex", "rewindIndex", XtRInt,
1375 sizeof(int), XtOffset(AppDataPtr, rewindIndex),
1376 XtRImmediate, (XtPointer) 0},
1377 { "sameColorGames", "sameColorGames", XtRInt,
1378 sizeof(int), XtOffset(AppDataPtr, sameColorGames),
1379 XtRImmediate, (XtPointer) 0},
1380 { "smpCores", "smpCores", XtRInt,
1381 sizeof(int), XtOffset(AppDataPtr, smpCores),
1382 XtRImmediate, (XtPointer) 1},
1383 { "niceEngines", "niceEngines", XtRInt,
1384 sizeof(int), XtOffset(AppDataPtr, niceEngines),
1385 XtRImmediate, (XtPointer) 0},
1386 { "nameOfDebugFile", "nameOfDebugFile", XtRString,
1387 sizeof(String), XtOffset(AppDataPtr, nameOfDebugFile),
1388 XtRImmediate, (XtPointer) "xboard.debug"},
1389 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1390 sizeof(int), XtOffset(AppDataPtr, engineComments),
1391 XtRImmediate, (XtPointer) 0},
1392 { "noGUI", "noGUI", XtRBoolean,
1393 sizeof(Boolean), XtOffset(AppDataPtr, noGUI),
1394 XtRImmediate, (XtPointer) 0},
1395 { "firstOptions", "firstOptions", XtRString,
1396 sizeof(String), XtOffset(AppDataPtr, firstOptions),
1397 XtRImmediate, (XtPointer) "" },
1398 { "secondOptions", "secondOptions", XtRString,
1399 sizeof(String), XtOffset(AppDataPtr, secondOptions),
1400 XtRImmediate, (XtPointer) "" },
1401 { "firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XtRString,
1402 sizeof(String), XtOffset(AppDataPtr, fenOverride1),
1403 XtRImmediate, (XtPointer) 0 },
1404 { "secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XtRString,
1405 sizeof(String), XtOffset(AppDataPtr, fenOverride2),
1406 XtRImmediate, (XtPointer) 0 },
1408 // [HGM] Winboard_x UCI options
1409 { "firstIsUCI", "firstIsUCI", XtRBoolean,
1410 sizeof(Boolean), XtOffset(AppDataPtr, firstIsUCI),
1411 XtRImmediate, (XtPointer) False},
1412 { "secondIsUCI", "secondIsUCI", XtRBoolean,
1413 sizeof(Boolean), XtOffset(AppDataPtr, secondIsUCI),
1414 XtRImmediate, (XtPointer) False},
1415 { "firstHasOwnBookUCI", "firstHasOwnBookUCI", XtRBoolean,
1416 sizeof(Boolean), XtOffset(AppDataPtr, firstHasOwnBookUCI),
1417 XtRImmediate, (XtPointer) True},
1418 { "secondHasOwnBookUCI", "secondHasOwnBookUCI", XtRBoolean,
1419 sizeof(Boolean), XtOffset(AppDataPtr, secondHasOwnBookUCI),
1420 XtRImmediate, (XtPointer) True},
1421 { "usePolyglotBook", "usePolyglotBook", XtRBoolean,
1422 sizeof(Boolean), XtOffset(AppDataPtr, usePolyglotBook),
1423 XtRImmediate, (XtPointer) False},
1424 { "defaultHashSize", "defaultHashSize", XtRInt,
1425 sizeof(int), XtOffset(AppDataPtr, defaultHashSize),
1426 XtRImmediate, (XtPointer) 64},
1427 { "defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XtRInt,
1428 sizeof(int), XtOffset(AppDataPtr, defaultCacheSizeEGTB),
1429 XtRImmediate, (XtPointer) 4},
1430 { "polyglotDir", "polyglotDir", XtRString,
1431 sizeof(String), XtOffset(AppDataPtr, polyglotDir),
1432 XtRImmediate, (XtPointer) "." },
1433 { "polyglotBook", "polyglotBook", XtRString,
1434 sizeof(String), XtOffset(AppDataPtr, polyglotBook),
1435 XtRImmediate, (XtPointer) "" },
1436 { "defaultPathEGTB", "defaultPathEGTB", XtRString,
1437 sizeof(String), XtOffset(AppDataPtr, defaultPathEGTB),
1438 XtRImmediate, (XtPointer) "/usr/local/share/egtb"},
1439 { "delayBeforeQuit", "delayBeforeQuit", XtRInt,
1440 sizeof(int), XtOffset(AppDataPtr, delayBeforeQuit),
1441 XtRImmediate, (XtPointer) 0},
1442 { "delayAfterQuit", "delayAfterQuit", XtRInt,
1443 sizeof(int), XtOffset(AppDataPtr, delayAfterQuit),
1444 XtRImmediate, (XtPointer) 0},
1447 XrmOptionDescRec shellOptions[] = {
1448 { "-whitePieceColor", "whitePieceColor", XrmoptionSepArg, NULL },
1449 { "-blackPieceColor", "blackPieceColor", XrmoptionSepArg, NULL },
1450 { "-lightSquareColor", "lightSquareColor", XrmoptionSepArg, NULL },
1451 { "-darkSquareColor", "darkSquareColor", XrmoptionSepArg, NULL },
1452 { "-highlightSquareColor", "highlightSquareColor", XrmoptionSepArg, NULL },
1453 { "-premoveHighlightColor", "premoveHighlightColor", XrmoptionSepArg,NULL},
1454 { "-movesPerSession", "movesPerSession", XrmoptionSepArg, NULL },
1455 { "-mps", "movesPerSession", XrmoptionSepArg, NULL },
1456 { "-timeIncrement", "timeIncrement", XrmoptionSepArg, NULL },
1457 { "-inc", "timeIncrement", XrmoptionSepArg, NULL },
1458 { "-initString", "initString", XrmoptionSepArg, NULL },
1459 { "-firstInitString", "initString", XrmoptionSepArg, NULL },
1460 { "-secondInitString", "secondInitString", XrmoptionSepArg, NULL },
1461 { "-firstComputerString", "firstComputerString", XrmoptionSepArg, NULL },
1462 { "-secondComputerString", "secondComputerString", XrmoptionSepArg, NULL },
1463 { "-firstChessProgram", "firstChessProgram", XrmoptionSepArg, NULL },
1464 { "-fcp", "firstChessProgram", XrmoptionSepArg, NULL },
1465 { "-secondChessProgram", "secondChessProgram", XrmoptionSepArg, NULL },
1466 { "-scp", "secondChessProgram", XrmoptionSepArg, NULL },
1467 { "-firstPlaysBlack", "firstPlaysBlack", XrmoptionSepArg, NULL },
1468 { "-fb", "firstPlaysBlack", XrmoptionNoArg, "True" },
1469 { "-xfb", "firstPlaysBlack", XrmoptionNoArg, "False" },
1470 { "-noChessProgram", "noChessProgram", XrmoptionSepArg, NULL },
1471 { "-ncp", "noChessProgram", XrmoptionNoArg, "True" },
1472 { "-xncp", "noChessProgram", XrmoptionNoArg, "False" },
1473 { "-firstHost", "firstHost", XrmoptionSepArg, NULL },
1474 { "-fh", "firstHost", XrmoptionSepArg, NULL },
1475 { "-secondHost", "secondHost", XrmoptionSepArg, NULL },
1476 { "-sh", "secondHost", XrmoptionSepArg, NULL },
1477 { "-firstDirectory", "firstDirectory", XrmoptionSepArg, NULL },
1478 { "-fd", "firstDirectory", XrmoptionSepArg, NULL },
1479 { "-secondDirectory", "secondDirectory", XrmoptionSepArg, NULL },
1480 { "-sd", "secondDirectory", XrmoptionSepArg, NULL },
1481 { "-bitmapDirectory", "bitmapDirectory", XrmoptionSepArg, NULL },
1482 { "-bm", "bitmapDirectory", XrmoptionSepArg, NULL },
1483 { "-remoteShell", "remoteShell", XrmoptionSepArg, NULL },
1484 { "-rsh", "remoteShell", XrmoptionSepArg, NULL },
1485 { "-remoteUser", "remoteUser", XrmoptionSepArg, NULL },
1486 { "-ruser", "remoteUser", XrmoptionSepArg, NULL },
1487 { "-timeDelay", "timeDelay", XrmoptionSepArg, NULL },
1488 { "-td", "timeDelay", XrmoptionSepArg, NULL },
1489 { "-timeControl", "timeControl", XrmoptionSepArg, NULL },
1490 { "-tc", "timeControl", XrmoptionSepArg, NULL },
1491 { "-internetChessServerMode", "internetChessServerMode",
1492 XrmoptionSepArg, NULL },
1493 { "-ics", "internetChessServerMode", XrmoptionNoArg, "True" },
1494 { "-xics", "internetChessServerMode", XrmoptionNoArg, "False" },
1495 { "-internetChessServerHost", "internetChessServerHost",
1496 XrmoptionSepArg, NULL },
1497 { "-icshost", "internetChessServerHost", XrmoptionSepArg, NULL },
1498 { "-internetChessServerPort", "internetChessServerPort",
1499 XrmoptionSepArg, NULL },
1500 { "-icsport", "internetChessServerPort", XrmoptionSepArg, NULL },
1501 { "-internetChessServerCommPort", "internetChessServerCommPort",
1502 XrmoptionSepArg, NULL },
1503 { "-icscomm", "internetChessServerCommPort", XrmoptionSepArg, NULL },
1504 { "-internetChessServerLogonScript", "internetChessServerLogonScript",
1505 XrmoptionSepArg, NULL },
1506 { "-icslogon", "internetChessServerLogonScript", XrmoptionSepArg, NULL },
1507 { "-internetChessServerHelper", "internetChessServerHelper",
1508 XrmoptionSepArg, NULL },
1509 { "-icshelper", "internetChessServerHelper", XrmoptionSepArg, NULL },
1510 { "-internetChessServerInputBox", "internetChessServerInputBox",
1511 XrmoptionSepArg, NULL },
1512 { "-icsinput", "internetChessServerInputBox", XrmoptionNoArg, "True" },
1513 { "-xicsinput", "internetChessServerInputBox", XrmoptionNoArg, "False" },
1514 { "-icsAlarm", "icsAlarm", XrmoptionSepArg, NULL },
1515 { "-alarm", "icsAlarm", XrmoptionNoArg, "True" },
1516 { "-xalarm", "icsAlarm", XrmoptionNoArg, "False" },
1517 { "-icsAlarmTime", "icsAlarmTime", XrmoptionSepArg, NULL },
1518 { "-useTelnet", "useTelnet", XrmoptionSepArg, NULL },
1519 { "-telnet", "useTelnet", XrmoptionNoArg, "True" },
1520 { "-xtelnet", "useTelnet", XrmoptionNoArg, "False" },
1521 { "-telnetProgram", "telnetProgram", XrmoptionSepArg, NULL },
1522 { "-gateway", "gateway", XrmoptionSepArg, NULL },
1523 { "-loadGameFile", "loadGameFile", XrmoptionSepArg, NULL },
1524 { "-lgf", "loadGameFile", XrmoptionSepArg, NULL },
1525 { "-loadGameIndex", "loadGameIndex", XrmoptionSepArg, NULL },
1526 { "-lgi", "loadGameIndex", XrmoptionSepArg, NULL },
1527 { "-saveGameFile", "saveGameFile", XrmoptionSepArg, NULL },
1528 { "-sgf", "saveGameFile", XrmoptionSepArg, NULL },
1529 { "-autoSaveGames", "autoSaveGames", XrmoptionSepArg, NULL },
1530 { "-autosave", "autoSaveGames", XrmoptionNoArg, "True" },
1531 { "-xautosave", "autoSaveGames", XrmoptionNoArg, "False" },
1532 { "-autoRaiseBoard", "autoRaiseBoard", XrmoptionSepArg, NULL },
1533 { "-autoraise", "autoRaiseBoard", XrmoptionNoArg, "True" },
1534 { "-xautoraise", "autoRaiseBoard", XrmoptionNoArg, "False" },
1535 { "-blindfold", "blindfold", XrmoptionSepArg, NULL },
1536 { "-blind", "blindfold", XrmoptionNoArg, "True" },
1537 { "-xblind", "blindfold", XrmoptionNoArg, "False" },
1538 { "-loadPositionFile", "loadPositionFile", XrmoptionSepArg, NULL },
1539 { "-lpf", "loadPositionFile", XrmoptionSepArg, NULL },
1540 { "-loadPositionIndex", "loadPositionIndex", XrmoptionSepArg, NULL },
1541 { "-lpi", "loadPositionIndex", XrmoptionSepArg, NULL },
1542 { "-savePositionFile", "savePositionFile", XrmoptionSepArg, NULL },
1543 { "-spf", "savePositionFile", XrmoptionSepArg, NULL },
1544 { "-matchMode", "matchMode", XrmoptionSepArg, NULL },
1545 { "-mm", "matchMode", XrmoptionNoArg, "True" },
1546 { "-xmm", "matchMode", XrmoptionNoArg, "False" },
1547 { "-matchGames", "matchGames", XrmoptionSepArg, NULL },
1548 { "-mg", "matchGames", XrmoptionSepArg, NULL },
1549 { "-monoMode", "monoMode", XrmoptionSepArg, NULL },
1550 { "-mono", "monoMode", XrmoptionNoArg, "True" },
1551 { "-xmono", "monoMode", XrmoptionNoArg, "False" },
1552 { "-debugMode", "debugMode", XrmoptionSepArg, NULL },
1553 { "-debug", "debugMode", XrmoptionNoArg, "True" },
1554 { "-xdebug", "debugMode", XrmoptionNoArg, "False" },
1555 { "-clockMode", "clockMode", XrmoptionSepArg, NULL },
1556 { "-clock", "clockMode", XrmoptionNoArg, "True" },
1557 { "-xclock", "clockMode", XrmoptionNoArg, "False" },
1558 { "-boardSize", "boardSize", XrmoptionSepArg, NULL },
1559 { "-size", "boardSize", XrmoptionSepArg, NULL },
1560 { "-searchTime", "searchTime", XrmoptionSepArg, NULL },
1561 { "-st", "searchTime", XrmoptionSepArg, NULL },
1562 { "-searchDepth", "searchDepth", XrmoptionSepArg, NULL },
1563 { "-depth", "searchDepth", XrmoptionSepArg, NULL },
1564 { "-showCoords", "showCoords", XrmoptionSepArg, NULL },
1565 { "-coords", "showCoords", XrmoptionNoArg, "True" },
1566 { "-xcoords", "showCoords", XrmoptionNoArg, "False" },
1568 { "-showJail", "showJail", XrmoptionSepArg, NULL },
1569 { "-jail", "showJail", XrmoptionNoArg, "1" },
1570 { "-sidejail", "showJail", XrmoptionNoArg, "2" },
1571 { "-xjail", "showJail", XrmoptionNoArg, "0" },
1573 { "-showThinking", "showThinking", XrmoptionSepArg, NULL },
1574 { "-thinking", "showThinking", XrmoptionNoArg, "True" },
1575 { "-xthinking", "showThinking", XrmoptionNoArg, "False" },
1576 { "-ponderNextMove", "ponderNextMove", XrmoptionSepArg, NULL },
1577 { "-ponder", "ponderNextMove", XrmoptionNoArg, "True" },
1578 { "-xponder", "ponderNextMove", XrmoptionNoArg, "False" },
1579 { "-periodicUpdates", "periodicUpdates", XrmoptionSepArg, NULL },
1580 { "-periodic", "periodicUpdates", XrmoptionNoArg, "True" },
1581 { "-xperiodic", "periodicUpdates", XrmoptionNoArg, "False" },
1582 { "-clockFont", "clockFont", XrmoptionSepArg, NULL },
1583 { "-coordFont", "coordFont", XrmoptionSepArg, NULL },
1584 { "-font", "font", XrmoptionSepArg, NULL },
1585 { "-ringBellAfterMoves", "ringBellAfterMoves", XrmoptionSepArg, NULL },
1586 { "-bell", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1587 { "-xbell", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1588 { "-movesound", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1589 { "-xmovesound", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1590 { "-autoCallFlag", "autoCallFlag", XrmoptionSepArg, NULL },
1591 { "-autoflag", "autoCallFlag", XrmoptionNoArg, "True" },
1592 { "-xautoflag", "autoCallFlag", XrmoptionNoArg, "False" },
1593 { "-autoFlipView", "autoFlipView", XrmoptionSepArg, NULL },
1594 { "-autoflip", "autoFlipView", XrmoptionNoArg, "True" },
1595 { "-xautoflip", "autoFlipView", XrmoptionNoArg, "False" },
1596 { "-autoObserve", "autoObserve", XrmoptionSepArg, NULL },
1597 { "-autobs", "autoObserve", XrmoptionNoArg, "True" },
1598 { "-xautobs", "autoObserve", XrmoptionNoArg, "False" },
1599 { "-autoComment", "autoComment", XrmoptionSepArg, NULL },
1600 { "-autocomm", "autoComment", XrmoptionNoArg, "True" },
1601 { "-xautocomm", "autoComment", XrmoptionNoArg, "False" },
1602 { "-getMoveList", "getMoveList", XrmoptionSepArg, NULL },
1603 { "-moves", "getMoveList", XrmoptionNoArg, "True" },
1604 { "-xmoves", "getMoveList", XrmoptionNoArg, "False" },
1606 { "-highlightDragging", "highlightDragging", XrmoptionSepArg, NULL },
1607 { "-highdrag", "highlightDragging", XrmoptionNoArg, "True" },
1608 { "-xhighdrag", "highlightDragging", XrmoptionNoArg, "False" },
1610 { "-highlightLastMove", "highlightLastMove", XrmoptionSepArg, NULL },
1611 { "-highlight", "highlightLastMove", XrmoptionNoArg, "True" },
1612 { "-xhighlight", "highlightLastMove", XrmoptionNoArg, "False" },
1613 { "-premove", "premove", XrmoptionSepArg, NULL },
1614 { "-pre", "premove", XrmoptionNoArg, "True" },
1615 { "-xpre", "premove", XrmoptionNoArg, "False" },
1616 { "-testLegality", "testLegality", XrmoptionSepArg, NULL },
1617 { "-legal", "testLegality", XrmoptionNoArg, "True" },
1618 { "-xlegal", "testLegality", XrmoptionNoArg, "False" },
1619 { "-flipView", "flipView", XrmoptionSepArg, NULL },
1620 { "-flip", "flipView", XrmoptionNoArg, "True" },
1621 { "-xflip", "flipView", XrmoptionNoArg, "False" },
1622 { "-cmail", "cmailGameName", XrmoptionSepArg, NULL },
1623 { "-alwaysPromoteToQueen", "alwaysPromoteToQueen",
1624 XrmoptionSepArg, NULL },
1625 { "-queen", "alwaysPromoteToQueen", XrmoptionNoArg, "True" },
1626 { "-xqueen", "alwaysPromoteToQueen", XrmoptionNoArg, "False" },
1627 { "-oldSaveStyle", "oldSaveStyle", XrmoptionSepArg, NULL },
1628 { "-oldsave", "oldSaveStyle", XrmoptionNoArg, "True" },
1629 { "-xoldsave", "oldSaveStyle", XrmoptionNoArg, "False" },
1630 { "-quietPlay", "quietPlay", XrmoptionSepArg, NULL },
1631 { "-quiet", "quietPlay", XrmoptionNoArg, "True" },
1632 { "-xquiet", "quietPlay", XrmoptionNoArg, "False" },
1633 { "-titleInWindow", "titleInWindow", XrmoptionSepArg, NULL },
1634 { "-title", "titleInWindow", XrmoptionNoArg, "True" },
1635 { "-xtitle", "titleInWindow", XrmoptionNoArg, "False" },
1637 { "-zippyTalk", "zippyTalk", XrmoptionSepArg, NULL },
1638 { "-zt", "zippyTalk", XrmoptionNoArg, "True" },
1639 { "-xzt", "zippyTalk", XrmoptionNoArg, "False" },
1640 { "-zippyPlay", "zippyPlay", XrmoptionSepArg, NULL },
1641 { "-zp", "zippyPlay", XrmoptionNoArg, "True" },
1642 { "-xzp", "zippyPlay", XrmoptionNoArg, "False" },
1643 { "-zippyLines", "zippyLines", XrmoptionSepArg, NULL },
1644 { "-zippyPinhead", "zippyPinhead", XrmoptionSepArg, NULL },
1645 { "-zippyPassword", "zippyPassword", XrmoptionSepArg, NULL },
1646 { "-zippyPassword2", "zippyPassword2", XrmoptionSepArg, NULL },
1647 { "-zippyWrongPassword", "zippyWrongPassword", XrmoptionSepArg, NULL },
1648 { "-zippyAcceptOnly", "zippyAcceptOnly", XrmoptionSepArg, NULL },
1649 { "-zippyUseI", "zippyUseI", XrmoptionSepArg, NULL },
1650 { "-zui", "zippyUseI", XrmoptionNoArg, "True" },
1651 { "-xzui", "zippyUseI", XrmoptionNoArg, "False" },
1652 { "-zippyBughouse", "zippyBughouse", XrmoptionSepArg, NULL },
1653 { "-zippyNoplayCrafty", "zippyNoplayCrafty", XrmoptionSepArg, NULL },
1654 { "-znc", "zippyNoplayCrafty", XrmoptionNoArg, "True" },
1655 { "-xznc", "zippyNoplayCrafty", XrmoptionNoArg, "False" },
1656 { "-zippyGameEnd", "zippyGameEnd", XrmoptionSepArg, NULL },
1657 { "-zippyGameStart", "zippyGameStart", XrmoptionSepArg, NULL },
1658 { "-zippyAdjourn", "zippyAdjourn", XrmoptionSepArg, NULL },
1659 { "-zadj", "zippyAdjourn", XrmoptionNoArg, "True" },
1660 { "-xzadj", "zippyAdjourn", XrmoptionNoArg, "False" },
1661 { "-zippyAbort", "zippyAbort", XrmoptionSepArg, NULL },
1662 { "-zab", "zippyAbort", XrmoptionNoArg, "True" },
1663 { "-xzab", "zippyAbort", XrmoptionNoArg, "False" },
1664 { "-zippyVariants", "zippyVariants", XrmoptionSepArg, NULL },
1665 { "-zippyMaxGames", "zippyMaxGames", XrmoptionSepArg, NULL },
1666 { "-zippyReplayTimeout", "zippyReplayTimeout", XrmoptionSepArg, NULL },
1667 { "-zippyShortGame", "zippyShortGame", XrmoptionSepArg, NULL },
1669 { "-flashCount", "flashCount", XrmoptionSepArg, NULL },
1670 { "-flash", "flashCount", XrmoptionNoArg, "3" },
1671 { "-xflash", "flashCount", XrmoptionNoArg, "0" },
1672 { "-flashRate", "flashRate", XrmoptionSepArg, NULL },
1673 { "-pixmapDirectory", "pixmapDirectory", XrmoptionSepArg, NULL },
1674 { "-msLoginDelay", "msLoginDelay", XrmoptionSepArg, NULL },
1675 { "-pixmap", "pixmapDirectory", XrmoptionSepArg, NULL },
1676 { "-colorizeMessages", "colorizeMessages", XrmoptionSepArg, NULL },
1677 { "-colorize", "colorizeMessages", XrmoptionNoArg, "True" },
1678 { "-xcolorize", "colorizeMessages", XrmoptionNoArg, "False" },
1679 { "-colorShout", "colorShout", XrmoptionSepArg, NULL },
1680 { "-colorSShout", "colorSShout", XrmoptionSepArg, NULL },
1681 { "-colorCShout", "colorSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1682 { "-colorChannel1", "colorChannel1", XrmoptionSepArg, NULL },
1683 { "-colorChannel", "colorChannel", XrmoptionSepArg, NULL },
1684 { "-colorKibitz", "colorKibitz", XrmoptionSepArg, NULL },
1685 { "-colorTell", "colorTell", XrmoptionSepArg, NULL },
1686 { "-colorChallenge", "colorChallenge", XrmoptionSepArg, NULL },
1687 { "-colorRequest", "colorRequest", XrmoptionSepArg, NULL },
1688 { "-colorSeek", "colorSeek", XrmoptionSepArg, NULL },
1689 { "-colorNormal", "colorNormal", XrmoptionSepArg, NULL },
1690 { "-soundProgram", "soundProgram", XrmoptionSepArg, NULL },
1691 { "-soundShout", "soundShout", XrmoptionSepArg, NULL },
1692 { "-soundSShout", "soundSShout", XrmoptionSepArg, NULL },
1693 { "-soundCShout", "soundSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1694 { "-soundChannel1", "soundChannel1", XrmoptionSepArg, NULL },
1695 { "-soundChannel", "soundChannel", XrmoptionSepArg, NULL },
1696 { "-soundKibitz", "soundKibitz", XrmoptionSepArg, NULL },
1697 { "-soundTell", "soundTell", XrmoptionSepArg, NULL },
1698 { "-soundChallenge", "soundChallenge", XrmoptionSepArg, NULL },
1699 { "-soundRequest", "soundRequest", XrmoptionSepArg, NULL },
1700 { "-soundSeek", "soundSeek", XrmoptionSepArg, NULL },
1701 { "-soundMove", "soundMove", XrmoptionSepArg, NULL },
1702 { "-soundIcsWin", "soundIcsWin", XrmoptionSepArg, NULL },
1703 { "-soundIcsLoss", "soundIcsLoss", XrmoptionSepArg, NULL },
1704 { "-soundIcsDraw", "soundIcsDraw", XrmoptionSepArg, NULL },
1705 { "-soundIcsUnfinished", "soundIcsUnfinished", XrmoptionSepArg, NULL },
1706 { "-soundIcsAlarm", "soundIcsAlarm", XrmoptionSepArg, NULL },
1707 { "-reuseFirst", "reuseFirst", XrmoptionSepArg, NULL },
1708 { "-reuseChessPrograms", "reuseFirst", XrmoptionSepArg, NULL }, /*compat*/
1709 { "-reuse", "reuseFirst", XrmoptionNoArg, "True" },
1710 { "-xreuse", "reuseFirst", XrmoptionNoArg, "False" },
1711 { "-reuseSecond", "reuseSecond", XrmoptionSepArg, NULL },
1712 { "-reuse2", "reuseSecond", XrmoptionNoArg, "True" },
1713 { "-xreuse2", "reuseSecond", XrmoptionNoArg, "False" },
1714 { "-animateMoving", "animateMoving", XrmoptionSepArg, NULL },
1715 { "-animate", "animateMoving", XrmoptionNoArg, "True" },
1716 { "-xanimate", "animateMoving", XrmoptionNoArg, "False" },
1717 { "-animateDragging", "animateDragging", XrmoptionSepArg, NULL },
1718 { "-drag", "animateDragging", XrmoptionNoArg, "True" },
1719 { "-xdrag", "animateDragging", XrmoptionNoArg, "False" },
1720 { "-animateSpeed", "animateSpeed", XrmoptionSepArg, NULL },
1721 { "-popupExitMessage", "popupExitMessage", XrmoptionSepArg, NULL },
1722 { "-exit", "popupExitMessage", XrmoptionNoArg, "True" },
1723 { "-xexit", "popupExitMessage", XrmoptionNoArg, "False" },
1724 { "-popupMoveErrors", "popupMoveErrors", XrmoptionSepArg, NULL },
1725 { "-popup", "popupMoveErrors", XrmoptionNoArg, "True" },
1726 { "-xpopup", "popupMoveErrors", XrmoptionNoArg, "False" },
1727 { "-fontSizeTolerance", "fontSizeTolerance", XrmoptionSepArg, NULL },
1728 { "-initialMode", "initialMode", XrmoptionSepArg, NULL },
1729 { "-mode", "initialMode", XrmoptionSepArg, NULL },
1730 { "-variant", "variant", XrmoptionSepArg, NULL },
1731 { "-firstProtocolVersion", "firstProtocolVersion", XrmoptionSepArg, NULL },
1732 { "-secondProtocolVersion","secondProtocolVersion",XrmoptionSepArg, NULL },
1733 { "-showButtonBar", "showButtonBar", XrmoptionSepArg, NULL },
1734 { "-buttons", "showButtonBar", XrmoptionNoArg, "True" },
1735 { "-xbuttons", "showButtonBar", XrmoptionNoArg, "False" },
1736 { "-lowTimeWarningColor", "lowTimeWarningColor", XrmoptionSepArg, NULL },
1737 { "-lowTimeWarning", "lowTimeWarning", XrmoptionSepArg, NULL },
1738 /* [AS,HR] New features */
1739 { "-firstScoreAbs", "firstScoreAbs", XrmoptionSepArg, NULL },
1740 { "-secondScoreAbs", "secondScoreAbs", XrmoptionSepArg, NULL },
1741 { "-pgnExtendedInfo", "pgnExtendedInfo", XrmoptionSepArg, NULL },
1742 { "-hideThinkingFromHuman", "hideThinkingFromHuman", XrmoptionSepArg, NULL },
1743 { "-adjudicateLossThreshold", "adjudicateLossThreshold", XrmoptionSepArg, NULL },
1744 { "-pgnEventHeader", "pgnEventHeader", XrmoptionSepArg, NULL },
1745 { "-firstIsUCI", "firstIsUCI", XrmoptionSepArg, NULL },
1746 { "-secondIsUCI", "secondIsUCI", XrmoptionSepArg, NULL },
1747 { "-fUCI", "firstIsUCI", XrmoptionNoArg, "True" },
1748 { "-sUCI", "secondIsUCI", XrmoptionNoArg, "True" },
1749 { "-firstHasOwnBookUCI", "firstHasOwnBookUCI", XrmoptionSepArg, NULL },
1750 { "-secondHasOwnBookUCI", "secondHasOwnBookUCI", XrmoptionSepArg, NULL },
1751 { "-fNoOwnBookUCI", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1752 { "-sNoOwnBookUCI", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1753 { "-firstXBook", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1754 { "-secondXBook", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1755 { "-polyglotDir", "polyglotDir", XrmoptionSepArg, NULL },
1756 { "-usePolyglotBook", "usePolyglotBook", XrmoptionSepArg, NULL },
1757 { "-polyglotBook", "polyglotBook", XrmoptionSepArg, NULL },
1758 { "-defaultHashSize", "defaultHashSize", XrmoptionSepArg, NULL },
1759 { "-defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XrmoptionSepArg, NULL },
1760 { "-defaultPathEGTB", "defaultPathEGTB", XrmoptionSepArg, NULL },
1761 { "-defaultFrcPosition", "defaultFrcPosition", XrmoptionSepArg, NULL },
1762 { "-gameListTags", "gameListTags", XrmoptionSepArg, NULL },
1763 // [HGM] I am sure AS added many more options, but we have to fish them out, from the list in winboard.c
1765 /* [HGM,HR] User-selectable board size */
1766 { "-boardWidth", "boardWidth", XrmoptionSepArg, NULL },
1767 { "-boardHeight", "boardHeight", XrmoptionSepArg, NULL },
1768 { "-matchPause", "matchPause", XrmoptionSepArg, NULL },
1770 /* [HGM] new arguments of 4.3.xx. All except first three are back-end options, which should work immediately */
1771 { "-holdingsSize", "holdingsSize", XrmoptionSepArg, NULL }, // requires extensive front-end changes to work
1772 { "-flipBlack", "flipBlack", XrmoptionSepArg, NULL }, // requires front-end changes to work
1773 { "-allWhite", "allWhite", XrmoptionSepArg, NULL }, // requires front-end changes to work
1774 { "-pieceToCharTable", "pieceToCharTable", XrmoptionSepArg, NULL },
1775 { "-alphaRank", "alphaRank", XrmoptionSepArg, NULL },
1776 { "-testClaims", "testClaims", XrmoptionSepArg, NULL },
1777 { "-checkMates", "checkMates", XrmoptionSepArg, NULL },
1778 { "-materialDraws", "materialDraws", XrmoptionSepArg, NULL },
1779 { "-trivialDraws", "trivialDraws", XrmoptionSepArg, NULL },
1780 { "-ruleMoves", "ruleMoves", XrmoptionSepArg, NULL },
1781 { "-repeatsToDraw", "repeatsToDraw", XrmoptionSepArg, NULL },
1782 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1783 { "-userName", "userName", XrmoptionSepArg, NULL },
1784 { "-autoKibitz", "autoKibitz", XrmoptionNoArg, "True" },
1785 { "-firstTimeOdds", "firstTimeOdds", XrmoptionSepArg, NULL },
1786 { "-secondTimeOdds", "secondTimeOdds", XrmoptionSepArg, NULL },
1787 { "-timeOddsMode", "timeOddsMode", XrmoptionSepArg, NULL },
1788 { "-firstAccumulateTC", "firstAccumulateTC", XrmoptionSepArg, NULL },
1789 { "-secondAccumulateTC", "secondAccumulateTC", XrmoptionSepArg, NULL },
1790 { "-firstNPS", "firstNPS", XrmoptionSepArg, NULL },
1791 { "-secondNPS", "secondNPS", XrmoptionSepArg, NULL },
1792 { "-serverMoves", "serverMoves", XrmoptionSepArg, NULL },
1793 { "-serverPause", "serverPause", XrmoptionSepArg, NULL },
1794 { "-suppressLoadMoves", "suppressLoadMoves", XrmoptionSepArg, NULL },
1795 { "-egtFormats", "egtFormats", XrmoptionSepArg, NULL },
1796 { "-userName", "userName", XrmoptionSepArg, NULL },
1797 { "-smpCores", "smpCores", XrmoptionSepArg, NULL },
1798 { "-sameColorGames", "sameColorGames", XrmoptionSepArg, NULL },
1799 { "-rewindIndex", "rewindIndex", XrmoptionSepArg, NULL },
1800 { "-niceEngines", "niceEngines", XrmoptionSepArg, NULL },
1801 { "-delayBeforeQuit", "delayBeforeQuit", XrmoptionSepArg, NULL },
1802 { "-delayAfterQuit", "delayAfterQuit", XrmoptionSepArg, NULL },
1803 { "-nameOfDebugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1804 { "-debugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1805 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1806 { "-noGUI", "noGUI", XrmoptionNoArg, "True" },
1807 { "-firstOptions", "firstOptions", XrmoptionSepArg, NULL },
1808 { "-secondOptions", "secondOptions", XrmoptionSepArg, NULL },
1809 { "-firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1810 { "-secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1814 XtActionsRec boardActions[] = {
1815 { "HandleUserMove", HandleUserMove },
1816 { "AnimateUserMove", AnimateUserMove },
1817 { "FileNameAction", FileNameAction },
1818 { "AskQuestionProc", AskQuestionProc },
1819 { "AskQuestionReplyAction", AskQuestionReplyAction },
1820 { "PieceMenuPopup", PieceMenuPopup },
1821 { "WhiteClock", WhiteClock },
1822 { "BlackClock", BlackClock },
1823 { "Iconify", Iconify },
1824 { "LoadSelectedProc", LoadSelectedProc },
1825 { "LoadPositionProc", LoadPositionProc },
1826 { "LoadNextPositionProc", LoadNextPositionProc },
1827 { "LoadPrevPositionProc", LoadPrevPositionProc },
1828 { "ReloadPositionProc", ReloadPositionProc },
1829 { "CopyPositionProc", CopyPositionProc },
1830 { "PastePositionProc", PastePositionProc },
1831 { "CopyGameProc", CopyGameProc },
1832 { "PasteGameProc", PasteGameProc },
1833 { "SaveGameProc", SaveGameProc },
1834 { "SavePositionProc", SavePositionProc },
1835 { "MailMoveProc", MailMoveProc },
1836 { "ReloadCmailMsgProc", ReloadCmailMsgProc },
1837 // { "MachineWhiteProc", MachineWhiteProc },
1838 // { "MachineBlackProc", MachineBlackProc },
1839 { "AnalysisModeProc", AnalyzeModeProc },
1840 { "AnalyzeFileProc", AnalyzeFileProc },
1841 // { "TwoMachinesProc", TwoMachinesProc },
1842 // { "IcsClientProc", IcsClientProc },
1843 { "EditGameProc", EditGameProc },
1844 { "EditPositionProc", EditPositionProc },
1845 { "TrainingProc", EditPositionProc },
1846 { "EngineOutputProc", EngineOutputProc}, // [HGM] Winboard_x engine-output window
1847 { "ShowGameListProc", ShowGameListProc },
1848 { "ShowMoveListProc", HistoryShowProc},
1849 { "EditTagsProc", EditCommentProc },
1850 { "EditCommentProc", EditCommentProc },
1851 { "IcsAlarmProc", IcsAlarmProc },
1852 { "IcsInputBoxProc", IcsInputBoxProc },
1853 // { "AcceptProc", AcceptProc },
1854 // { "DeclineProc", DeclineProc },
1855 // { "RematchProc", RematchProc },
1856 // { "CallFlagProc", CallFlagProc },
1857 // { "DrawProc", DrawProc },
1858 // { "AdjournProc", AdjournProc },
1859 // { "AbortProc", AbortProc },
1860 // { "ResignProc", ResignProc },
1861 // { "AdjuWhiteProc", AdjuWhiteProc },
1862 // { "AdjuBlackProc", AdjuBlackProc },
1863 // { "AdjuDrawProc", AdjuDrawProc },
1864 { "EnterKeyProc", EnterKeyProc },
1865 // { "StopObservingProc", StopObservingProc },
1866 // { "StopExaminingProc", StopExaminingProc },
1867 // { "BackwardProc", BackwardProc },
1868 // { "ForwardProc", ForwardProc },
1869 // { "ToStartProc", ToStartProc },
1870 // { "ToEndProc", ToEndProc },
1871 // { "RevertProc", RevertProc },
1872 // { "TruncateGameProc", TruncateGameProc },
1873 // { "MoveNowProc", MoveNowProc },
1874 // { "RetractMoveProc", RetractMoveProc },
1875 { "AlwaysQueenProc", AlwaysQueenProc },
1876 { "AnimateDraggingProc", AnimateDraggingProc },
1877 { "AnimateMovingProc", AnimateMovingProc },
1878 { "AutoflagProc", AutoflagProc },
1879 { "AutoflipProc", AutoflipProc },
1880 { "AutobsProc", AutobsProc },
1881 { "AutoraiseProc", AutoraiseProc },
1882 { "AutosaveProc", AutosaveProc },
1883 { "BlindfoldProc", BlindfoldProc },
1884 { "FlashMovesProc", FlashMovesProc },
1885 { "FlipViewProc", FlipViewProc },
1886 { "GetMoveListProc", GetMoveListProc },
1888 { "HighlightDraggingProc", HighlightDraggingProc },
1890 { "HighlightLastMoveProc", HighlightLastMoveProc },
1891 { "IcsAlarmProc", IcsAlarmProc },
1892 { "MoveSoundProc", MoveSoundProc },
1893 { "OldSaveStyleProc", OldSaveStyleProc },
1894 { "PeriodicUpdatesProc", PeriodicUpdatesProc },
1895 { "PonderNextMoveProc", PonderNextMoveProc },
1896 { "PopupExitMessageProc", PopupExitMessageProc },
1897 { "PopupMoveErrorsProc", PopupMoveErrorsProc },
1898 { "PremoveProc", PremoveProc },
1899 { "QuietPlayProc", QuietPlayProc },
1900 { "ShowThinkingProc", ShowThinkingProc },
1901 { "HideThinkingProc", HideThinkingProc },
1902 { "TestLegalityProc", TestLegalityProc },
1903 { "InfoProc", InfoProc },
1904 { "ManProc", ManProc },
1905 { "HintProc", HintProc },
1906 { "BookProc", BookProc },
1907 { "AboutGameProc", AboutGameProc },
1908 { "DebugProc", DebugProc },
1909 { "NothingProc", NothingProc },
1910 { "CommentPopDown", (XtActionProc) CommentPopDown },
1911 { "EditCommentPopDown", (XtActionProc) EditCommentPopDown },
1912 { "TagsPopDown", (XtActionProc) TagsPopDown },
1913 { "ErrorPopDown", (XtActionProc) ErrorPopDown },
1914 { "ICSInputBoxPopDown", (XtActionProc) ICSInputBoxPopDown },
1915 { "AnalysisPopDown", (XtActionProc) AnalysisPopDown },
1916 { "FileNamePopDown", (XtActionProc) FileNamePopDown },
1917 { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown },
1918 { "GameListPopDown", (XtActionProc) GameListPopDown },
1919 { "PromotionPopDown", (XtActionProc) PromotionPopDown },
1920 { "HistoryPopDown", (XtActionProc) HistoryPopDown },
1921 { "EngineOutputPopDown", (XtActionProc) EngineOutputPopDown },
1922 { "ShufflePopDown", (XtActionProc) ShufflePopDown },
1923 { "EnginePopDown", (XtActionProc) EnginePopDown },
1924 { "UciPopDown", (XtActionProc) UciPopDown },
1925 { "TimeControlPopDown", (XtActionProc) TimeControlPopDown },
1926 { "NewVariantPopDown", (XtActionProc) NewVariantPopDown },
1927 { "SettingsPopDown", (XtActionProc) SettingsPopDown },
1931 char ICSInputTranslations[] =
1932 "<Key>Return: EnterKeyProc() \n";
1934 String xboardResources[] = {
1935 "*fileName*value.translations: #override\\n <Key>Return: FileNameAction()",
1936 "*question*value.translations: #override\\n <Key>Return: AskQuestionReplyAction()",
1937 "*errorpopup*translations: #override\\n <Key>Return: ErrorPopDown()",
1941 static char *cnames[9] = { "black", "red", "green", "yellow", "blue",
1942 "magenta", "cyan", "white" };
1946 TextColors textColors[(int)NColorClasses];
1948 /* String is: "fg, bg, attr". Which is 0, 1, 2 */
1950 parse_color(str, which)
1954 char *p, buf[100], *d;
1957 if (strlen(str) > 99) /* watch bounds on buf */
1962 for (i=0; i<which; ++i) {
1969 /* Could be looking at something like:
1971 .. in which case we want to stop on a comma also */
1972 while (*p && *p != ',' && !isalpha(*p) && !isdigit(*p))
1976 return -1; /* Use default for empty field */
1979 if (which == 2 || isdigit(*p))
1982 while (*p && isalpha(*p))
1987 for (i=0; i<8; ++i) {
1988 if (!StrCaseCmp(buf, cnames[i]))
1989 return which? (i+40) : (i+30);
1991 if (!StrCaseCmp(buf, "default")) return -1;
1993 fprintf(stderr, _("%s: unrecognized color %s\n"), programName, buf);
1998 parse_cpair(cc, str)
2002 if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {
2003 fprintf(stderr, _("%s: can't parse foreground color in `%s'\n"),
2008 /* bg and attr are optional */
2009 textColors[(int)cc].bg = parse_color(str, 1);
2010 if ((textColors[(int)cc].attr = parse_color(str, 2)) < 0) {
2011 textColors[(int)cc].attr = 0;
2017 /* Arrange to catch delete-window events */
2018 Atom wm_delete_window;
2020 CatchDeleteWindow(Widget w, String procname)
2023 XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
2024 snprintf(buf, sizeof(buf), "<Message>WM_PROTOCOLS: %s() \n", procname);
2025 XtAugmentTranslations(w, XtParseTranslationTable(buf));
2031 /* this should raise the board to the top */
2032 gtk_window_present(GTK_WINDOW(GUI_Window));
2037 // eventually, all layout determining code should go into a subroutine, but until then IDSIZE remains undefined
2039 #define BoardSize int
2040 void InitDrawingSizes(BoardSize boardSize, int flags)
2041 { // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
2042 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2044 XtGeometryResult gres;
2047 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2048 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2050 timerWidth = (boardWidth - sep) / 2;
2052 if (appData.titleInWindow)
2057 w = boardWidth - 2*bor;
2061 w = boardWidth - w - sep - 2*bor - 2; // WIDTH_FUDGE
2065 if(!formWidget) return;
2068 * Inhibit shell resizing.
2071 // [HGM] pieces: tailor piece bitmaps to needs of specific variant
2074 for(i=0; i<4; i++) {
2076 for(p=0; p<=(int)WhiteKing; p++)
2077 xpmPieceBitmap[i][p] = xpmPieceBitmap2[i][p]; // defaults
2078 if(gameInfo.variant == VariantShogi) {
2079 xpmPieceBitmap[i][(int)WhiteCannon] = xpmPieceBitmap2[i][(int)WhiteKing+1];
2080 xpmPieceBitmap[i][(int)WhiteNightrider] = xpmPieceBitmap2[i][(int)WhiteKing+2];
2081 xpmPieceBitmap[i][(int)WhiteSilver] = xpmPieceBitmap2[i][(int)WhiteKing+3];
2082 xpmPieceBitmap[i][(int)WhiteGrasshopper] = xpmPieceBitmap2[i][(int)WhiteKing+4];
2083 xpmPieceBitmap[i][(int)WhiteQueen] = xpmPieceBitmap2[i][(int)WhiteLance];
2086 if(gameInfo.variant == VariantGothic) {
2087 xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteSilver];
2091 // [HGM] why are thee ximMasks used at all? the ximPieceBitmaps seem to be never used!
2092 for(p=0; p<=(int)WhiteKing; p++)
2093 ximMaskPm[p] = ximMaskPm2[p]; // defaults
2094 if(gameInfo.variant == VariantShogi) {
2095 ximMaskPm[(int)WhiteCannon] = ximMaskPm2[(int)WhiteKing+1];
2096 ximMaskPm[(int)WhiteNightrider] = ximMaskPm2[(int)WhiteKing+2];
2097 ximMaskPm[(int)WhiteSilver] = ximMaskPm2[(int)WhiteKing+3];
2098 ximMaskPm[(int)WhiteGrasshopper] = ximMaskPm2[(int)WhiteKing+4];
2099 ximMaskPm[(int)WhiteQueen] = ximMaskPm2[(int)WhiteLance];
2102 if(gameInfo.variant == VariantGothic) {
2103 ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[i][(int)WhiteSilver];
2109 for(i=0; i<2; i++) {
2111 for(p=0; p<=(int)WhiteKing; p++)
2112 pieceBitmap[i][p] = pieceBitmap2[i][p]; // defaults
2113 if(gameInfo.variant == VariantShogi) {
2114 pieceBitmap[i][(int)WhiteCannon] = pieceBitmap2[i][(int)WhiteKing+1];
2115 pieceBitmap[i][(int)WhiteNightrider] = pieceBitmap2[i][(int)WhiteKing+2];
2116 pieceBitmap[i][(int)WhiteSilver] = pieceBitmap2[i][(int)WhiteKing+3];
2117 pieceBitmap[i][(int)WhiteGrasshopper] = pieceBitmap2[i][(int)WhiteKing+4];
2118 pieceBitmap[i][(int)WhiteQueen] = pieceBitmap2[i][(int)WhiteLance];
2121 if(gameInfo.variant == VariantGothic) {
2122 pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteSilver];
2138 int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
2139 XSetWindowAttributes window_attributes;
2141 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2142 XrmValue vFrom, vTo;
2143 XtGeometryResult gres;
2146 int forceMono = False;
2150 // [HGM] before anything else, expand any indirection files amongst options
2151 char *argvCopy[1000]; // 1000 seems enough
2152 char newArgs[10000]; // holds actual characters
2155 srandom(time(0)); // [HGM] book: make random truly random
2158 for(i=0; i<argc; i++) {
2159 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2160 //fprintf(stderr, "arg %s\n", argv[i]);
2161 if(argv[i][0] != '@') argvCopy[j++] = argv[i]; else {
2163 FILE *f = fopen(argv[i]+1, "rb");
2164 if(f == NULL) { fprintf(stderr, _("ignore %s\n"), argv[i]); continue; } // do not expand non-existing
2165 argvCopy[j++] = newArgs + k; // get ready for first argument from file
2166 while((c = fgetc(f)) != EOF) { // each line of file inserts 1 argument in the list
2168 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2169 newArgs[k++] = 0; // terminate current arg
2170 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2171 argvCopy[j++] = newArgs + k; // get ready for next
2173 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2186 if(appData.debugMode,1) { // OK, appData is not initialized here yet...
2187 for(i=0; i<argc; i++) fprintf(stderr, "argv[%2d] = '%s'\n", i, argv[i]);
2193 setbuf(stdout, NULL);
2194 setbuf(stderr, NULL);
2197 programName = strrchr(argv[0], '/');
2198 if (programName == NULL)
2199 programName = argv[0];
2204 XtSetLanguageProc(NULL, NULL, NULL);
2205 bindtextdomain(PACKAGE, LOCALEDIR);
2206 textdomain(PACKAGE);
2210 XtAppInitialize(&appContext, "XBoard", shellOptions,
2211 XtNumber(shellOptions),
2212 &argc, argv, xboardResources, NULL, 0);
2216 gtk_init (&argc, &argv);
2218 /* parse glade file to build widgets */
2220 builder = gtk_builder_new ();
2221 gtk_builder_add_from_file (builder, "gtk-interface.xml", NULL);
2223 /* test if everything worked ok */
2225 GUI_Window = GTK_WIDGET (gtk_builder_get_object (builder, "MainWindow"));
2226 if(!GUI_Window) printf("Error: gtk_builder didn't work!\n");
2227 GUI_Board = GTK_WIDGET (gtk_builder_get_object (builder, "Board"));
2228 if(!GUI_Board) printf("Error: gtk_builder didn't work!\n");
2229 GUI_Whiteclock = GTK_WIDGET (gtk_builder_get_object (builder, "WhiteClock"));
2230 if(!GUI_Whiteclock) printf("Error: gtk_builder didn't work!\n");
2231 GUI_Blackclock = GTK_WIDGET (gtk_builder_get_object (builder, "BlackClock"));
2232 if(!GUI_Blackclock) printf("Error: gtk_builder didn't work!\n");
2234 gtk_builder_connect_signals (builder, NULL);
2236 // don't unref the builder, since we use it to get references to widgets
2237 // g_object_unref (G_OBJECT (builder));
2239 /* end parse glade file */
2243 fprintf(stderr, _("%s: unrecognized argument %s\n"),
2244 programName, argv[1]);
2245 fprintf(stderr, "Recognized options:\n");
2246 for(i = 0; i < XtNumber(shellOptions); i++)
2248 j = fprintf(stderr, " %s%s", shellOptions[i].option,
2249 (shellOptions[i].argKind == XrmoptionSepArg
2251 if (i++ < XtNumber(shellOptions))
2253 fprintf(stderr, "%*c%s%s\n", 40 - j, ' ',
2254 shellOptions[i].option,
2255 (shellOptions[i].argKind == XrmoptionSepArg
2260 fprintf(stderr, "\n");
2266 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL)
2272 if (chdir(chessDir) != 0)
2274 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
2281 if (p == NULL) p = "/tmp";
2282 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
2283 gameCopyFilename = (char*) malloc(i);
2284 gamePasteFilename = (char*) malloc(i);
2285 snprintf(gameCopyFilename,i, "%s/.xboard%05uc.pgn", p, getpid());
2286 snprintf(gamePasteFilename,i, "%s/.xboard%05up.pgn", p, getpid());
2288 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
2289 clientResources, XtNumber(clientResources),
2292 if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) {
2293 /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */
2294 if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL) {
2295 printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile);
2298 setbuf(debugFP, NULL);
2301 /* [HGM,HR] make sure board size is acceptable */
2302 if(appData.NrFiles > BOARD_SIZE ||
2303 appData.NrRanks > BOARD_SIZE )
2304 DisplayFatalError(_("Recompile with BOARD_SIZE > 12, to support this size"), 0, 2);
2307 /* This feature does not work; animation needs a rewrite */
2308 appData.highlightDragging = FALSE;
2312 xDisplay = XtDisplay(shellWidget);
2313 xScreen = DefaultScreen(xDisplay);
2314 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
2316 gameInfo.variant = StringToVariant(appData.variant);
2317 InitPosition(FALSE);
2321 * Determine boardSize
2323 gameInfo.boardWidth = gameInfo.boardHeight = 8; // [HGM] boardsize: make sure we start as 8x8
2326 // [HGM] as long as we have not created the possibility to change size while running, start with requested size
2327 gameInfo.boardWidth = appData.NrFiles > 0 ? appData.NrFiles : 8;
2328 gameInfo.boardHeight = appData.NrRanks > 0 ? appData.NrRanks : 8;
2329 gameInfo.holdingsWidth = appData.holdingsSize > 0 ? 2 : 0;
2334 InitDrawingSizes(-1, 0); // [HGM] initsize: make this into a subroutine
2336 if (isdigit(appData.boardSize[0])) {
2337 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
2338 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
2339 &fontPxlSize, &smallLayout, &tinyLayout);
2341 fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
2342 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) {
2351 if (abs(szd->squareSize - squareSize) < distance) {
2353 distance = abs(szd->squareSize - squareSize);
2354 if (distance == 0) break;
2358 if (i < 2) lineGap = nearest->lineGap;
2359 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
2360 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
2361 if (i < 5) fontPxlSize = nearest->fontPxlSize;
2362 if (i < 6) smallLayout = nearest->smallLayout;
2363 if (i < 7) tinyLayout = nearest->tinyLayout;
2366 SizeDefaults *szd = sizeDefaults;
2367 if (*appData.boardSize == NULLCHAR) {
2368 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize ||
2369 DisplayHeight(xDisplay, xScreen) < szd->minScreenSize) {
2372 if (szd->name == NULL) szd--;
2374 while (szd->name != NULL &&
2375 StrCaseCmp(szd->name, appData.boardSize) != 0) szd++;
2376 if (szd->name == NULL) {
2377 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
2378 programName, appData.boardSize);
2382 squareSize = szd->squareSize;
2383 lineGap = szd->lineGap;
2384 clockFontPxlSize = szd->clockFontPxlSize;
2385 coordFontPxlSize = szd->coordFontPxlSize;
2386 fontPxlSize = szd->fontPxlSize;
2387 smallLayout = szd->smallLayout;
2388 tinyLayout = szd->tinyLayout;
2391 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2392 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2393 if (appData.showJail == 1) {
2394 /* Jail on top and bottom */
2395 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2396 XtSetArg(boardArgs[2], XtNheight,
2397 boardHeight + 2*(lineGap + squareSize));
2398 } else if (appData.showJail == 2) {
2400 XtSetArg(boardArgs[1], XtNwidth,
2401 boardWidth + 2*(lineGap + squareSize));
2402 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2405 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2406 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2410 * Determine what fonts to use.
2412 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
2413 clockFontID = XLoadFont(xDisplay, appData.clockFont);
2414 clockFontStruct = XQueryFont(xDisplay, clockFontID);
2415 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
2416 coordFontID = XLoadFont(xDisplay, appData.coordFont);
2417 coordFontStruct = XQueryFont(xDisplay, coordFontID);
2418 appData.font = FindFont(appData.font, fontPxlSize);
2419 countFontID = XLoadFont(xDisplay, appData.coordFont); // [HGM] holdings
2420 countFontStruct = XQueryFont(xDisplay, countFontID);
2421 // appData.font = FindFont(appData.font, fontPxlSize);
2423 xdb = XtDatabase(xDisplay);
2424 XrmPutStringResource(&xdb, "*font", appData.font);
2427 * Detect if there are not enough colors available and adapt.
2429 if (DefaultDepth(xDisplay, xScreen) <= 2) {
2430 appData.monoMode = True;
2433 if (!appData.monoMode) {
2434 vFrom.addr = (caddr_t) appData.lightSquareColor;
2435 vFrom.size = strlen(appData.lightSquareColor);
2436 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2437 if (vTo.addr == NULL) {
2438 appData.monoMode = True;
2441 lightSquareColor = *(Pixel *) vTo.addr;
2444 if (!appData.monoMode) {
2445 vFrom.addr = (caddr_t) appData.darkSquareColor;
2446 vFrom.size = strlen(appData.darkSquareColor);
2447 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2448 if (vTo.addr == NULL) {
2449 appData.monoMode = True;
2452 darkSquareColor = *(Pixel *) vTo.addr;
2455 if (!appData.monoMode) {
2456 vFrom.addr = (caddr_t) appData.whitePieceColor;
2457 vFrom.size = strlen(appData.whitePieceColor);
2458 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2459 if (vTo.addr == NULL) {
2460 appData.monoMode = True;
2463 whitePieceColor = *(Pixel *) vTo.addr;
2466 if (!appData.monoMode) {
2467 vFrom.addr = (caddr_t) appData.blackPieceColor;
2468 vFrom.size = strlen(appData.blackPieceColor);
2469 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2470 if (vTo.addr == NULL) {
2471 appData.monoMode = True;
2474 blackPieceColor = *(Pixel *) vTo.addr;
2478 if (!appData.monoMode) {
2479 vFrom.addr = (caddr_t) appData.highlightSquareColor;
2480 vFrom.size = strlen(appData.highlightSquareColor);
2481 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2482 if (vTo.addr == NULL) {
2483 appData.monoMode = True;
2486 highlightSquareColor = *(Pixel *) vTo.addr;
2490 if (!appData.monoMode) {
2491 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
2492 vFrom.size = strlen(appData.premoveHighlightColor);
2493 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2494 if (vTo.addr == NULL) {
2495 appData.monoMode = True;
2498 premoveHighlightColor = *(Pixel *) vTo.addr;
2503 fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2506 if (appData.bitmapDirectory == NULL ||
2507 appData.bitmapDirectory[0] == NULLCHAR)
2508 appData.bitmapDirectory = DEF_BITMAP_DIR;
2511 if (appData.lowTimeWarning && !appData.monoMode) {
2512 vFrom.addr = (caddr_t) appData.lowTimeWarningColor;
2513 vFrom.size = strlen(appData.lowTimeWarningColor);
2514 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2515 if (vTo.addr == NULL)
2516 appData.monoMode = True;
2518 lowTimeWarningColor = *(Pixel *) vTo.addr;
2521 if (appData.monoMode && appData.debugMode) {
2522 fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2523 (unsigned long) XWhitePixel(xDisplay, xScreen),
2524 (unsigned long) XBlackPixel(xDisplay, xScreen));
2527 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
2528 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
2529 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
2530 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
2531 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
2532 parse_cpair(ColorTell, appData.colorTell) < 0 ||
2533 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
2534 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
2535 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
2536 parse_cpair(ColorNormal, appData.colorNormal) < 0)
2538 if (appData.colorize) {
2540 _("%s: can't parse color names; disabling colorization\n"),
2543 appData.colorize = FALSE;
2545 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2546 textColors[ColorNone].attr = 0;
2548 // XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2554 layoutName = "tinyLayout";
2555 } else if (smallLayout) {
2556 layoutName = "smallLayout";
2558 layoutName = "normalLayout";
2561 if (appData.titleInWindow) {
2562 /* todo check what this appdata does */
2565 if (appData.showButtonBar) {
2566 /* TODO hide button bar if requested */
2570 * gtk set properties of widgets
2573 /* set board size */
2574 gtk_widget_set_size_request(GTK_WIDGET(GUI_Board),
2575 boardWidth,boardHeight);
2577 /* end gtk set properties of widgets */
2579 if (appData.titleInWindow)
2584 if (appData.showButtonBar)
2591 if (appData.showButtonBar)
2600 // [HGM] it seems the layout code ends here, but perhaps the color stuff is size independent and would
2601 // not need to go into InitDrawingSizes().
2604 /* set some checkboxes in the menu according to appData */
2606 if (appData.alwaysPromoteToQueen)
2607 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Always Queen")),TRUE);
2609 if (appData.animateDragging)
2610 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Animate Dragging")),TRUE);
2612 if (appData.animate)
2613 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Animate Moving")),TRUE);
2615 if (appData.autoComment)
2616 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Comment")),TRUE);
2618 if (appData.autoCallFlag)
2619 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Flag")),TRUE);
2621 if (appData.autoFlipView)
2622 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Flip View")),TRUE);
2624 if (appData.autoObserve)
2625 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Observe")),TRUE);
2627 if (appData.autoRaiseBoard)
2628 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Raise Board")),TRUE);
2630 if (appData.autoSaveGames)
2631 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Save")),TRUE);
2633 if (appData.saveGameFile[0] != NULLCHAR)
2635 /* Can't turn this off from menu */
2636 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Save")),TRUE);
2637 gtk_action_set_sensitive(GTK_ACTION (gtk_builder_get_object (builder, "menuOptions.Auto Save")),FALSE);
2640 if (appData.blindfold)
2641 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Blindfold")),TRUE);
2643 if (appData.flashCount > 0)
2644 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Flash Moves")),TRUE);
2646 if (appData.getMoveList)
2647 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Get Move List")),TRUE);
2650 if (appData.highlightDragging)
2651 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Highlight Dragging")),TRUE);
2654 if (appData.highlightLastMove)
2655 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Highlight Last Move")),TRUE);
2657 if (appData.icsAlarm)
2658 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.ICS Alarm")),TRUE);
2660 if (appData.ringBellAfterMoves)
2661 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Move Sound")),TRUE);
2663 if (appData.oldSaveStyle)
2664 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Old Save Style")),TRUE);
2666 if (appData.periodicUpdates)
2667 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Periodic Updates")),TRUE);
2669 if (appData.ponderNextMove)
2670 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Ponder Next Move")),TRUE);
2672 if (appData.popupExitMessage)
2673 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Popup Exit Message")),TRUE);
2675 if (appData.popupMoveErrors)
2676 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Popup Move Errors")),TRUE);
2678 if (appData.premove)
2679 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Premove")),TRUE);
2681 if (appData.quietPlay)
2682 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Quit Play")),TRUE);
2684 if (appData.showCoords)
2685 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Show Coords")),TRUE);
2687 if (appData.showThinking)
2688 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Show Thinking")),TRUE);
2690 if (appData.testLegality)
2691 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Test Legality")),TRUE);
2693 /* end setting check boxes */
2696 /* load square colors */
2697 SVGLightSquare = load_pixbuf("svg/LightSquare.svg",squareSize);
2698 SVGDarkSquare = load_pixbuf("svg/DarkSquare.svg",squareSize);
2699 SVGNeutralSquare = load_pixbuf("svg/NeutralSquare.svg",squareSize);
2701 /* use two icons to indicate if it is white's or black's turn */
2702 WhiteIcon = load_pixbuf("svg/icon_white.svg",0);
2703 BlackIcon = load_pixbuf("svg/icon_black.svg",0);
2704 WindowIcon = WhiteIcon;
2705 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
2707 /* do resizing to a fixed aspect ratio */
2712 GUI_SetAspectRatio(0.7);
2714 /* realize window */
2715 gtk_widget_show (GUI_Window);
2721 if (appData.animate || appData.animateDragging)
2726 if (errorExitStatus == -1) {
2727 if (appData.icsActive) {
2728 /* We now wait until we see "login:" from the ICS before
2729 sending the logon script (problems with timestamp otherwise) */
2730 /*ICSInitScript();*/
2731 if (appData.icsInputBox) ICSInputBoxPopUp();
2734 signal(SIGINT, IntSigHandler);
2735 signal(SIGTERM, IntSigHandler);
2736 if (*appData.cmailGameName != NULLCHAR) {
2737 signal(SIGUSR1, CmailSigHandler);
2740 gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes()
2744 * Create a cursor for the board widget.
2745 * (This needs to be called after the window has been created to have access to board-window)
2748 BoardCursor = gdk_cursor_new(GDK_HAND2);
2749 gdk_window_set_cursor(GUI_Board->window, BoardCursor);
2750 gdk_cursor_destroy(BoardCursor);
2755 if (appData.debugMode) fclose(debugFP); // [DM] debug
2762 if (appData.icsActive && oldICSInteractionTitle != NULL) {
2763 DisplayIcsInteractionTitle(oldICSInteractionTitle);
2765 unlink(gameCopyFilename);
2766 unlink(gamePasteFilename);
2777 CmailSigHandler(sig)
2783 signal(SIGUSR1, SIG_IGN); /* suspend handler */
2785 /* Activate call-back function CmailSigHandlerCallBack() */
2786 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
2788 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
2792 CmailSigHandlerCallBack(isr, closure, message, count, error)
2800 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
2802 /**** end signal code ****/
2812 f = fopen(appData.icsLogon, "r");
2818 strcat(buf, appData.icsLogon);
2819 f = fopen(buf, "r");
2823 ProcessICSInitScript(f);
2830 EditCommentPopDown();
2836 SetMenuEnables(enab)
2841 if (!builder) return;
2842 while (enab->name != NULL) {
2843 o = gtk_builder_get_object(builder, enab->name);
2844 if(GTK_IS_WIDGET(o))
2845 gtk_widget_set_sensitive(GTK_WIDGET (o),enab->value);
2848 if(GTK_IS_ACTION(o))
2849 gtk_action_set_sensitive(GTK_ACTION (o),enab->value);
2851 DisplayError(enab->name, 0);
2859 SetMenuEnables(icsEnables);
2862 if (appData.zippyPlay && !appData.noChessProgram) /* [DM] icsEngineAnalyze */
2863 {}; // XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
2870 SetMenuEnables(ncpEnables);
2876 SetMenuEnables(gnuEnables);
2882 SetMenuEnables(cmailEnables);
2888 SetMenuEnables(trainingOnEnables);
2889 if (appData.showButtonBar) {
2890 // XtSetSensitive(buttonBarWidget, False);
2896 SetTrainingModeOff()
2898 SetMenuEnables(trainingOffEnables);
2899 if (appData.showButtonBar) {
2900 // XtSetSensitive(buttonBarWidget, True);
2905 SetUserThinkingEnables()
2907 if (appData.noChessProgram) return;
2908 SetMenuEnables(userThinkingEnables);
2912 SetMachineThinkingEnables()
2914 if (appData.noChessProgram) return;
2915 SetMenuEnables(machineThinkingEnables);
2917 case MachinePlaysBlack:
2918 case MachinePlaysWhite:
2919 case TwoMachinesPlay:
2920 // XtSetSensitive(XtNameToWidget(menuBarWidget,
2921 // ModeToWidgetName(gameMode)), True);
2928 #define Abs(n) ((n)<0 ? -(n) : (n))
2931 * Find a font that matches "pattern" that is as close as
2932 * possible to the targetPxlSize. Prefer fonts that are k
2933 * pixels smaller to fonts that are k pixels larger. The
2934 * pattern must be in the X Consortium standard format,
2935 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
2936 * The return value should be freed with XtFree when no
2939 char *FindFont(pattern, targetPxlSize)
2943 char **fonts, *p, *best, *scalable, *scalableTail;
2944 int i, j, nfonts, minerr, err, pxlSize;
2947 char **missing_list;
2949 char *def_string, *base_fnt_lst, strInt[3];
2951 XFontStruct **fnt_list;
2953 base_fnt_lst = calloc(1, strlen(pattern) + 3);
2954 sprintf(strInt, "%d", targetPxlSize);
2955 p = strstr(pattern, "--");
2956 strncpy(base_fnt_lst, pattern, p - pattern + 2);
2957 strcat(base_fnt_lst, strInt);
2958 strcat(base_fnt_lst, strchr(p + 2, '-'));
2960 if ((fntSet = XCreateFontSet(xDisplay,
2964 &def_string)) == NULL) {
2966 fprintf(stderr, _("Unable to create font set.\n"));
2970 nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
2972 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
2974 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
2975 programName, pattern);
2983 for (i=0; i<nfonts; i++) {
2986 if (*p != '-') continue;
2988 if (*p == NULLCHAR) break;
2989 if (*p++ == '-') j++;
2991 if (j < 7) continue;
2994 scalable = fonts[i];
2997 err = pxlSize - targetPxlSize;
2998 if (Abs(err) < Abs(minerr) ||
2999 (minerr > 0 && err < 0 && -err == minerr)) {
3005 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
3006 /* If the error is too big and there is a scalable font,
3007 use the scalable font. */
3008 int headlen = scalableTail - scalable;
3009 p = (char *) XtMalloc(strlen(scalable) + 10);
3010 while (isdigit(*scalableTail)) scalableTail++;
3011 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
3013 p = (char *) XtMalloc(strlen(best) + 1);
3016 if (appData.debugMode) {
3017 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
3018 pattern, targetPxlSize, p);
3021 if (missing_count > 0)
3022 XFreeStringList(missing_list);
3023 XFreeFontSet(xDisplay, fntSet);
3025 XFreeFontNames(fonts);
3032 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
3033 | GCBackground | GCFunction | GCPlaneMask;
3034 XGCValues gc_values;
3037 gc_values.plane_mask = AllPlanes;
3038 gc_values.line_width = lineGap;
3039 gc_values.line_style = LineSolid;
3040 gc_values.function = GXcopy;
3042 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3043 gc_values.background = XWhitePixel(xDisplay, xScreen);
3044 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
3045 XSetFont(xDisplay, coordGC, coordFontID);
3047 if (appData.monoMode) {
3048 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3049 gc_values.background = XBlackPixel(xDisplay, xScreen);
3050 lightSquareGC = wbPieceGC
3051 = XtGetGC(shellWidget, value_mask, &gc_values);
3053 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3054 gc_values.background = XWhitePixel(xDisplay, xScreen);
3055 darkSquareGC = bwPieceGC
3056 = XtGetGC(shellWidget, value_mask, &gc_values);
3058 if (DefaultDepth(xDisplay, xScreen) == 1) {
3059 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3060 gc_values.function = GXcopyInverted;
3061 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3062 gc_values.function = GXcopy;
3063 if (XBlackPixel(xDisplay, xScreen) == 1) {
3064 bwPieceGC = darkSquareGC;
3065 wbPieceGC = copyInvertedGC;
3067 bwPieceGC = copyInvertedGC;
3068 wbPieceGC = lightSquareGC;
3072 gc_values.foreground = lightSquareColor;
3073 gc_values.background = darkSquareColor;
3074 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3076 gc_values.foreground = darkSquareColor;
3077 gc_values.background = lightSquareColor;
3078 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3080 gc_values.foreground = jailSquareColor;
3081 gc_values.background = jailSquareColor;
3082 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3084 gc_values.foreground = whitePieceColor;
3085 gc_values.background = darkSquareColor;
3086 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3088 gc_values.foreground = whitePieceColor;
3089 gc_values.background = lightSquareColor;
3090 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3092 gc_values.foreground = whitePieceColor;
3093 gc_values.background = jailSquareColor;
3094 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3096 gc_values.foreground = blackPieceColor;
3097 gc_values.background = darkSquareColor;
3098 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3100 gc_values.foreground = blackPieceColor;
3101 gc_values.background = lightSquareColor;
3102 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3104 gc_values.foreground = blackPieceColor;
3105 gc_values.background = jailSquareColor;
3106 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3113 WhitePawn, WhiteKnight, WhiteBishop, WhiteRook, WhiteQueen, WhiteKing,
3114 BlackPawn, BlackKnight, BlackBishop, BlackRook, BlackQueen, BlackKing,
3118 /* get some defaults going */
3119 for(i=WhitePawn; i<DemotePiece+1; i++)
3120 SVGpieces[i] = load_pixbuf("svg/NeutralSquare.svg",squareSize);
3123 SVGpieces[WhitePawn] = load_pixbuf("svg/WhitePawn.svg",squareSize);
3124 SVGpieces[WhiteKnight] = load_pixbuf("svg/WhiteKnight.svg",squareSize);
3125 SVGpieces[WhiteBishop] = load_pixbuf("svg/WhiteBishop.svg",squareSize);
3126 SVGpieces[WhiteRook] = load_pixbuf("svg/WhiteRook.svg",squareSize);
3127 SVGpieces[WhiteQueen] = load_pixbuf("svg/WhiteQueen.svg",squareSize);
3128 SVGpieces[WhiteKing] = load_pixbuf("svg/WhiteKing.svg",squareSize);
3130 SVGpieces[BlackPawn] = load_pixbuf("svg/BlackPawn.svg",squareSize);
3131 SVGpieces[BlackKnight] = load_pixbuf("svg/BlackKnight.svg",squareSize);
3132 SVGpieces[BlackBishop] = load_pixbuf("svg/BlackBishop.svg",squareSize);
3133 SVGpieces[BlackRook] = load_pixbuf("svg/BlackRook.svg",squareSize);
3134 SVGpieces[BlackQueen] = load_pixbuf("svg/BlackQueen.svg",squareSize);
3135 SVGpieces[BlackKing] = load_pixbuf("svg/BlackKing.svg",squareSize);
3141 static void MenuBarSelect(w, addr, index)
3146 XtActionProc proc = (XtActionProc) addr;
3148 (proc)(NULL, NULL, NULL, NULL);
3151 void CreateMenuBarPopup(parent, name, mb)
3161 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3164 XtSetArg(args[j], XtNleftMargin, 20); j++;
3165 XtSetArg(args[j], XtNrightMargin, 20); j++;
3167 while (mi->string != NULL) {
3168 if (strcmp(mi->string, "----") == 0) {
3169 entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
3172 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string)));
3173 entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass,
3175 XtAddCallback(entry, XtNcallback,
3176 (XtCallbackProc) MenuBarSelect,
3177 (caddr_t) mi->proc);
3183 Widget CreateMenuBar(mb)
3187 Widget anchor, menuBar;
3189 char menuName[MSG_SIZ];
3192 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3193 XtSetArg(args[j], XtNvSpace, 0); j++;
3194 XtSetArg(args[j], XtNborderWidth, 0); j++;
3195 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
3196 formWidget, args, j);
3198 while (mb->name != NULL) {
3199 strcpy(menuName, "menu");
3200 strcat(menuName, mb->name);
3202 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
3205 shortName[0] = _(mb->name)[0];
3206 shortName[1] = NULLCHAR;
3207 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
3210 XtSetArg(args[j], XtNlabel, XtNewString(_(mb->name))); j++;
3213 XtSetArg(args[j], XtNborderWidth, 0); j++;
3214 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
3216 CreateMenuBarPopup(menuBar, menuName, mb);
3222 Widget CreateButtonBar(mi)
3226 Widget button, buttonBar;
3230 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3232 XtSetArg(args[j], XtNhSpace, 0); j++;
3234 XtSetArg(args[j], XtNborderWidth, 0); j++;
3235 XtSetArg(args[j], XtNvSpace, 0); j++;
3236 buttonBar = XtCreateWidget("buttonBar", boxWidgetClass,
3237 formWidget, args, j);
3239 while (mi->string != NULL) {
3242 XtSetArg(args[j], XtNinternalWidth, 2); j++;
3243 XtSetArg(args[j], XtNborderWidth, 0); j++;
3245 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string))); j++;
3246 button = XtCreateManagedWidget(mi->string, commandWidgetClass,
3247 buttonBar, args, j);
3248 XtAddCallback(button, XtNcallback,
3249 (XtCallbackProc) MenuBarSelect,
3250 (caddr_t) mi->proc);
3257 CreatePieceMenu(name, color)
3264 ChessSquare selection;
3266 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3267 boardWidget, args, 0);
3269 for (i = 0; i < PIECE_MENU_SIZE; i++) {
3270 String item = pieceMenuStrings[color][i];
3272 if (strcmp(item, "----") == 0) {
3273 entry = XtCreateManagedWidget(item, smeLineObjectClass,
3276 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3277 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3279 selection = pieceMenuTranslation[color][i];
3280 XtAddCallback(entry, XtNcallback,
3281 (XtCallbackProc) PieceMenuSelect,
3282 (caddr_t) selection);
3283 if (selection == WhitePawn || selection == BlackPawn) {
3284 XtSetArg(args[0], XtNpopupOnEntry, entry);
3285 XtSetValues(menu, args, 1);
3298 ChessSquare selection;
3300 // whitePieceMenu = CreatePieceMenu("menuW", 0);
3301 // blackPieceMenu = CreatePieceMenu("menuB", 1);
3303 // XtRegisterGrabAction(PieceMenuPopup, True,
3304 // (unsigned)(ButtonPressMask|ButtonReleaseMask),
3305 // GrabModeAsync, GrabModeAsync);
3307 // XtSetArg(args[0], XtNlabel, _("Drop"));
3308 // dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
3309 // boardWidget, args, 1);
3310 // for (i = 0; i < DROP_MENU_SIZE; i++) {
3311 // String item = dropMenuStrings[i];
3313 // if (strcmp(item, "----") == 0) {
3314 // entry = XtCreateManagedWidget(item, smeLineObjectClass,
3315 // dropMenu, NULL, 0);
3317 // XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3318 // entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3319 // dropMenu, args, 1);
3320 // selection = dropMenuTranslation[i];
3321 // XtAddCallback(entry, XtNcallback,
3322 // (XtCallbackProc) DropMenuSelect,
3323 // (caddr_t) selection);
3328 void SetupDropMenu()
3336 for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
3337 entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
3338 p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
3339 dmEnables[i].piece);
3340 XtSetSensitive(entry, p != NULL || !appData.testLegality
3341 /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
3342 && !appData.icsActive));
3344 while (p && *p++ == dmEnables[i].piece) count++;
3345 snprintf(label, sizeof(label), "%s %d", dmEnables[i].widget, count);
3347 XtSetArg(args[j], XtNlabel, label); j++;
3348 XtSetValues(entry, args, j);
3352 void PieceMenuPopup(w, event, params, num_params)
3356 Cardinal *num_params;
3359 if (event->type != ButtonPress) return;
3360 if (errorUp) ErrorPopDown();
3364 whichMenu = params[0];
3366 case IcsPlayingWhite:
3367 case IcsPlayingBlack:
3369 case MachinePlaysWhite:
3370 case MachinePlaysBlack:
3371 if (appData.testLegality &&
3372 gameInfo.variant != VariantBughouse &&
3373 gameInfo.variant != VariantCrazyhouse) return;
3375 whichMenu = "menuD";
3381 if (((pmFromX = EventToSquare(event->xbutton.x, BOARD_WIDTH)) < 0) ||
3382 ((pmFromY = EventToSquare(event->xbutton.y, BOARD_HEIGHT)) < 0)) {
3383 pmFromX = pmFromY = -1;
3387 pmFromX = BOARD_WIDTH - 1 - pmFromX;
3389 pmFromY = BOARD_HEIGHT - 1 - pmFromY;
3391 XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
3394 static void PieceMenuSelect(w, piece, junk)
3399 if (pmFromX < 0 || pmFromY < 0) return;
3400 EditPositionMenuEvent(piece, pmFromX, pmFromY);
3403 static void DropMenuSelect(w, piece, junk)
3408 if (pmFromX < 0 || pmFromY < 0) return;
3409 DropMenuEvent(piece, pmFromX, pmFromY);
3412 void WhiteClock(w, event, prms, nprms)
3418 if (gameMode == EditPosition || gameMode == IcsExamining) {
3419 SetWhiteToPlayEvent();
3420 } else if (gameMode == IcsPlayingBlack || gameMode == MachinePlaysWhite) {
3425 void BlackClock(w, event, prms, nprms)
3431 if (gameMode == EditPosition || gameMode == IcsExamining) {
3432 SetBlackToPlayEvent();
3433 } else if (gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) {
3440 * If the user selects on a border boundary, return -1; if off the board,
3441 * return -2. Otherwise map the event coordinate to the square.
3443 int EventToSquare(x, limit)
3451 if ((x % (squareSize + lineGap)) >= squareSize)
3453 x /= (squareSize + lineGap);
3459 static void do_flash_delay(msec)
3465 static void drawHighlight(file, rank, line_type)
3466 int file, rank, line_type;
3471 if (lineGap == 0 || appData.blindfold) return;
3475 x = lineGap/2 + ((BOARD_WIDTH-1)-file) *
3476 (squareSize + lineGap);
3477 y = lineGap/2 + rank * (squareSize + lineGap);
3481 x = lineGap/2 + file * (squareSize + lineGap);
3482 y = lineGap/2 + ((BOARD_HEIGHT-1)-rank) *
3483 (squareSize + lineGap);
3487 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3489 /* draw the highlight */
3490 cairo_move_to (cr, x, y);
3491 cairo_rel_line_to (cr, 0,squareSize+lineGap);
3492 cairo_rel_line_to (cr, squareSize+lineGap,0);
3493 cairo_rel_line_to (cr, 0,-squareSize-lineGap);
3494 cairo_close_path (cr);
3496 cairo_set_line_width (cr, lineGap);
3499 /* TODO: use appdata colors */
3500 case LINE_TYPE_HIGHLIGHT:
3501 cairo_set_source_rgba (cr, 1, 1, 0, 1.0);
3504 cairo_set_source_rgba (cr, 1, 0, 0, 1.0);
3506 case LINE_TYPE_NORMAL:
3508 cairo_set_source_rgba (cr, 0, 1, 0, 1.0);
3519 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
3520 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
3523 SetHighlights(fromX, fromY, toX, toY)
3524 int fromX, fromY, toX, toY;
3526 if (hi1X != fromX || hi1Y != fromY)
3528 if (hi1X >= 0 && hi1Y >= 0)
3530 drawHighlight(hi1X, hi1Y, LINE_TYPE_NORMAL);
3532 if (fromX >= 0 && fromY >= 0)
3534 drawHighlight(fromX, fromY, LINE_TYPE_HIGHLIGHT);
3537 if (hi2X != toX || hi2Y != toY)
3539 if (hi2X >= 0 && hi2Y >= 0)
3541 drawHighlight(hi2X, hi2Y, LINE_TYPE_NORMAL);
3543 if (toX >= 0 && toY >= 0)
3545 drawHighlight(toX, toY, LINE_TYPE_HIGHLIGHT);
3559 SetHighlights(-1, -1, -1, -1);
3564 SetPremoveHighlights(fromX, fromY, toX, toY)
3565 int fromX, fromY, toX, toY;
3567 if (pm1X != fromX || pm1Y != fromY)
3569 if (pm1X >= 0 && pm1Y >= 0)
3571 drawHighlight(pm1X, pm1Y, LINE_TYPE_NORMAL);
3573 if (fromX >= 0 && fromY >= 0)
3575 drawHighlight(fromX, fromY, LINE_TYPE_PRE);
3578 if (pm2X != toX || pm2Y != toY)
3580 if (pm2X >= 0 && pm2Y >= 0)
3582 drawHighlight(pm2X, pm2Y, LINE_TYPE_NORMAL);
3584 if (toX >= 0 && toY >= 0)
3586 drawHighlight(toX, toY, LINE_TYPE_PRE);
3599 ClearPremoveHighlights()
3601 SetPremoveHighlights(-1, -1, -1, -1);
3604 static void BlankSquare(x, y, color, piece, dest)
3617 pb = SVGLightSquare;
3619 case 2: /* neutral */
3621 pb = SVGNeutralSquare;
3624 gdk_draw_pixbuf(GDK_WINDOW(GUI_Board->window),NULL,pb,0,0,x,y,-1,-1, GDK_RGB_DITHER_NORMAL, 0, 0);
3628 static void DrawPiece(piece, square_color, x, y, dest)
3630 int square_color, x, y;
3633 /* redraw background, since piece might be transparent in some areas */
3634 BlankSquare(x,y,square_color,piece,dest);
3637 gdk_draw_pixbuf(GDK_WINDOW(GUI_Board->window),NULL,
3638 GDK_PIXBUF(SVGpieces[piece]),0,0,x,y,-1,-1,
3639 GDK_RGB_DITHER_NORMAL, 0, 0);
3643 /* [HR] determine square color depending on chess variant. */
3644 static int SquareColor(row, column)
3649 if (gameInfo.variant == VariantXiangqi) {
3650 if (column >= 3 && column <= 5 && row >= 0 && row <= 2) {
3652 } else if (column >= 3 && column <= 5 && row >= 7 && row <= 9) {
3654 } else if (row <= 4) {
3660 square_color = ((column + row) % 2) == 1;
3663 /* [hgm] holdings: next line makes all holdings squares light */
3664 if(column < BOARD_LEFT || column >= BOARD_RGHT) square_color = 1;
3666 return square_color;
3669 void DrawSquare(row, column, piece, do_flash)
3670 int row, column, do_flash;
3673 int square_color, x, y;
3678 /* Calculate delay in milliseconds (2-delays per complete flash) */
3679 flash_delay = 500 / appData.flashRate;
3681 /* calculate x and y coordinates from row and column */
3684 x = lineGap + ((BOARD_WIDTH-1)-column) *
3685 (squareSize + lineGap);
3686 y = lineGap + row * (squareSize + lineGap);
3690 x = lineGap + column * (squareSize + lineGap);
3691 y = lineGap + ((BOARD_HEIGHT-1)-row) *
3692 (squareSize + lineGap);
3695 square_color = SquareColor(row, column);
3697 // [HGM] holdings: blank out area between board and holdings
3698 if ( column == BOARD_LEFT-1 || column == BOARD_RGHT
3699 || (column == BOARD_LEFT-2 && row < BOARD_HEIGHT-gameInfo.holdingsSize)
3700 || (column == BOARD_RGHT+1 && row >= gameInfo.holdingsSize) )
3702 BlankSquare(x, y, 2, EmptySquare, xBoardWindow);
3704 // [HGM] print piece counts next to holdings
3705 string[1] = NULLCHAR;
3708 cairo_text_extents_t extents;
3713 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3715 string[0] = '0' + piece;
3717 /* TODO this has to go into the font-selection */
3718 cairo_select_font_face (cr, "Sans",
3719 CAIRO_FONT_SLANT_NORMAL,
3720 CAIRO_FONT_WEIGHT_NORMAL);
3722 cairo_set_font_size (cr, 12.0);
3723 cairo_text_extents (cr, string, &extents);
3725 if (column == (flipView ? BOARD_LEFT-1 : BOARD_RGHT) )
3727 xpos= x + squareSize - extents.width - 2;
3728 ypos= y + extents.y_bearing + 1;
3730 if (column == (flipView ? BOARD_RGHT : BOARD_LEFT-1) && piece > 1)
3733 ypos = y + extents.y_bearing + 1;
3736 /* TODO mono mode? */
3737 cairo_move_to (cr, xpos, ypos);
3738 cairo_text_path (cr, string);
3739 cairo_set_source_rgb (cr, 1.0, 1.0, 1);
3740 cairo_fill_preserve (cr);
3741 cairo_set_source_rgb (cr, 0, 0, 0);
3742 cairo_set_line_width (cr, 0.1);
3751 /* square on the board */
3752 if (piece == EmptySquare || appData.blindfold)
3754 BlankSquare(x, y, square_color, piece, xBoardWindow);
3758 if (do_flash && appData.flashCount > 0)
3760 for (i=0; i<appData.flashCount; ++i)
3763 DrawPiece(piece, square_color, x, y, xBoardWindow);
3764 do_flash_delay(flash_delay);
3766 BlankSquare(x, y, square_color, piece, xBoardWindow);
3767 do_flash_delay(flash_delay);
3770 DrawPiece(piece, square_color, x, y, xBoardWindow);
3774 /* show coordinates if necessary */
3775 if(appData.showCoords)
3777 cairo_text_extents_t extents;
3781 /* TODO this has to go into the font-selection */
3782 cairo_select_font_face (cr, "Sans",
3783 CAIRO_FONT_SLANT_NORMAL,
3784 CAIRO_FONT_WEIGHT_NORMAL);
3785 cairo_set_font_size (cr, 12.0);
3787 string[1] = NULLCHAR;
3790 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3792 if (row == (flipView ? BOARD_HEIGHT-1 : 0) &&
3793 column >= BOARD_LEFT && column < BOARD_RGHT)
3795 string[0] = 'a' + column - BOARD_LEFT;
3796 cairo_text_extents (cr, string, &extents);
3798 xpos = x + squareSize - extents.width - 2;
3799 ypos = y + squareSize - extents.height - extents.y_bearing - 1;
3801 if (appData.monoMode)
3808 cairo_move_to (cr, xpos, ypos);
3809 cairo_text_path (cr, string);
3810 cairo_set_source_rgb (cr, 0.0, 0.0, 0);
3811 cairo_fill_preserve (cr);
3812 cairo_set_source_rgb (cr, 0, 1.0, 0);
3813 cairo_set_line_width (cr, 0.1);
3816 if ( column == (flipView ? BOARD_RGHT-1 : BOARD_LEFT))
3819 string[0] = ONE + row;
3820 cairo_text_extents (cr, string, &extents);
3823 ypos = y + extents.height + 1;
3825 if (appData.monoMode)
3832 cairo_move_to (cr, xpos, ypos);
3833 cairo_text_path (cr, string);
3834 cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
3835 cairo_fill_preserve (cr);
3836 cairo_set_source_rgb (cr, 0, 0, 1.0);
3837 cairo_set_line_width (cr, 0.1);
3849 /* Returns 1 if there are "too many" differences between b1 and b2
3850 (i.e. more than 1 move was made) */
3851 static int too_many_diffs(b1, b2)
3857 for (i=0; i<BOARD_HEIGHT; ++i) {
3858 for (j=0; j<BOARD_WIDTH; ++j) {
3859 if (b1[i][j] != b2[i][j]) {
3860 if (++c > 4) /* Castling causes 4 diffs */
3869 /* Matrix describing castling maneuvers */
3870 /* Row, ColRookFrom, ColKingFrom, ColRookTo, ColKingTo */
3871 static int castling_matrix[4][5] = {
3872 { 0, 0, 4, 3, 2 }, /* 0-0-0, white */
3873 { 0, 7, 4, 5, 6 }, /* 0-0, white */
3874 { 7, 0, 4, 3, 2 }, /* 0-0-0, black */
3875 { 7, 7, 4, 5, 6 } /* 0-0, black */
3878 /* Checks whether castling occurred. If it did, *rrow and *rcol
3879 are set to the destination (row,col) of the rook that moved.
3881 Returns 1 if castling occurred, 0 if not.
3883 Note: Only handles a max of 1 castling move, so be sure
3884 to call too_many_diffs() first.
3886 static int check_castle_draw(newb, oldb, rrow, rcol)
3893 /* For each type of castling... */
3894 for (i=0; i<4; ++i) {
3895 r = castling_matrix[i];
3897 /* Check the 4 squares involved in the castling move */
3899 for (j=1; j<=4; ++j) {
3900 if (newb[r[0]][r[j]] == oldb[r[0]][r[j]]) {
3907 /* All 4 changed, so it must be a castling move */
3916 static int damage[BOARD_SIZE][BOARD_SIZE];
3919 * event handler for redrawing the board
3921 void DrawPosition( repaint, board)
3922 /*Boolean*/int repaint;
3926 static int lastFlipView = 0;
3927 static int lastBoardValid = 0;
3928 static Board lastBoard;
3931 if (board == NULL) {
3932 if (!lastBoardValid) return;
3935 if (!lastBoardValid || lastFlipView != flipView) {
3936 // XtSetArg(args[0], XtNleftBitmap, (flipView ? xMarkPixmap : None));
3937 // XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flip View"),
3942 * It would be simpler to clear the window with XClearWindow()
3943 * but this causes a very distracting flicker.
3946 if (!repaint && lastBoardValid && lastFlipView == flipView)
3948 /* If too much changes (begin observing new game, etc.), don't
3950 do_flash = too_many_diffs(board, lastBoard) ? 0 : 1;
3952 /* Special check for castling so we don't flash both the king
3953 and the rook (just flash the king). */
3956 if (check_castle_draw(board, lastBoard, &rrow, &rcol))
3958 /* Draw rook with NO flashing. King will be drawn flashing later */
3959 DrawSquare(rrow, rcol, board[rrow][rcol], 0);
3960 lastBoard[rrow][rcol] = board[rrow][rcol];
3964 /* First pass -- Draw (newly) empty squares and repair damage.
3965 This prevents you from having a piece show up twice while it
3966 is flashing on its new square */
3967 for (i = 0; i < BOARD_HEIGHT; i++)
3968 for (j = 0; j < BOARD_WIDTH; j++)
3969 if ((board[i][j] != lastBoard[i][j] && board[i][j] == EmptySquare)
3972 DrawSquare(i, j, board[i][j], 0);
3973 damage[i][j] = False;
3976 /* Second pass -- Draw piece(s) in new position and flash them */
3977 for (i = 0; i < BOARD_HEIGHT; i++)
3978 for (j = 0; j < BOARD_WIDTH; j++)
3979 if (board[i][j] != lastBoard[i][j])
3981 DrawSquare(i, j, board[i][j], do_flash);
3993 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3995 cairo_set_line_width (cr, lineGap);
3997 /* TODO: use appdata colors */
3998 cairo_set_source_rgba (cr, 0, 1, 0, 1.0);
4002 for (i = 0; i < BOARD_HEIGHT + 1; i++)
4005 x2 = lineGap + BOARD_WIDTH * (squareSize + lineGap);
4006 y1 = y2 = lineGap / 2 + (i * (squareSize + lineGap));
4008 cairo_move_to (cr, x1, y1);
4009 cairo_rel_line_to (cr, x2,0);
4013 for (j = 0; j < BOARD_WIDTH + 1; j++)
4016 y2 = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
4017 x1 = x2 = lineGap / 2 + (j * (squareSize + lineGap));
4019 cairo_move_to (cr, x1, y1);
4020 cairo_rel_line_to (cr, 0, y2);
4029 for (i = 0; i < BOARD_HEIGHT; i++)
4030 for (j = 0; j < BOARD_WIDTH; j++)
4032 DrawSquare(i, j, board[i][j], 0);
4033 damage[i][j] = False;
4037 CopyBoard(lastBoard, board);
4039 lastFlipView = flipView;
4041 /* Draw highlights */
4042 if (pm1X >= 0 && pm1Y >= 0)
4044 drawHighlight(pm1X, pm1Y, LINE_TYPE_PRE);
4046 if (pm2X >= 0 && pm2Y >= 0)
4048 drawHighlight(pm2X, pm2Y, LINE_TYPE_PRE);
4050 if (hi1X >= 0 && hi1Y >= 0)
4052 drawHighlight(hi1X, hi1Y, LINE_TYPE_HIGHLIGHT);
4054 if (hi2X >= 0 && hi2Y >= 0)
4056 drawHighlight(hi2X, hi2Y, LINE_TYPE_HIGHLIGHT);
4059 /* If piece being dragged around board, must redraw that too */
4066 * event handler for parsing user moves
4068 // [HGM] This routine will need quite some reworking. Although the backend still supports the old
4069 // way of doing things, by calling UserMoveEvent() to test the legality of the move and then perform
4070 // it at the end, and doing all kind of preliminary tests here (e.g. to weed out self-captures), it
4071 // should be made to use the new way, of calling UserMoveTest early to determine the legality of the
4072 // move, (which will weed out the illegal selfcaptures and moves into the holdings, and flag promotions),
4073 // and at the end FinishMove() to perform the move after optional promotion popups.
4074 // For now I patched it to allow self-capture with King, and suppress clicks between board and holdings.
4075 void HandleUserMove(w, event, prms, nprms)
4082 Boolean saveAnimate;
4083 static int second = 0;
4085 if (w != boardWidget || errorExitStatus != -1) return;
4087 if (event->type == ButtonPress) ErrorPopDown();
4090 if (event->type == ButtonPress) {
4091 // XtPopdown(promotionShell);
4092 // XtDestroyWidget(promotionShell);
4093 promotionUp = False;
4101 x = EventToSquare(event->xbutton.x, BOARD_WIDTH);
4102 y = EventToSquare(event->xbutton.y, BOARD_HEIGHT);
4103 if (!flipView && y >= 0) {
4104 y = BOARD_HEIGHT - 1 - y;
4106 if (flipView && x >= 0) {
4107 x = BOARD_WIDTH - 1 - x;
4110 /* [HGM] holdings: next 5 lines: ignore all clicks between board and holdings */
4111 if(event->type == ButtonPress
4112 && ( x == BOARD_LEFT-1 ||
4114 (x == BOARD_LEFT-2 && y < BOARD_HEIGHT-gameInfo.holdingsSize ) ||
4115 (x == BOARD_RGHT+1 && y >= gameInfo.holdingsSize)) )
4119 if (event->type == ButtonPress) {
4121 if (OKToStartUserMove(x, y)) {
4125 DragPieceBegin(event->xbutton.x, event->xbutton.y);
4126 if (appData.highlightDragging) {
4127 SetHighlights(x, y, -1, -1);
4135 if (event->type == ButtonPress && gameMode != EditPosition &&
4140 /* Check if clicking again on the same color piece */
4141 fromP = boards[currentMove][fromY][fromX];
4142 toP = boards[currentMove][y][x];
4143 if ((WhitePawn <= fromP && fromP < WhiteKing && // [HGM] this test should go, as UserMoveTest now does it.
4144 WhitePawn <= toP && toP <= WhiteKing) || // For now I made it less critical by exempting King
4145 (BlackPawn <= fromP && fromP < BlackKing && // moves, to not interfere with FRC castlings.
4146 BlackPawn <= toP && toP <= BlackKing)) {
4147 /* Clicked again on same color piece -- changed his mind */
4148 second = (x == fromX && y == fromY);
4149 if (appData.highlightDragging) {
4150 SetHighlights(x, y, -1, -1);
4154 if (OKToStartUserMove(x, y)) {
4157 DragPieceBegin(event->xbutton.x, event->xbutton.y);
4163 if (event->type == ButtonRelease && x == fromX && y == fromY) {
4164 DragPieceEnd(event->xbutton.x, event->xbutton.y);
4165 if (appData.animateDragging) {
4166 /* Undo animation damage if any */
4167 DrawPosition(FALSE, NULL);
4170 /* Second up/down in same square; just abort move */
4175 ClearPremoveHighlights();
4177 /* First upclick in same square; start click-click mode */
4178 SetHighlights(x, y, -1, -1);
4183 /* Completed move */
4186 saveAnimate = appData.animate;
4187 if (event->type == ButtonPress) {
4188 /* Finish clickclick move */
4189 if (appData.animate || appData.highlightLastMove) {
4190 SetHighlights(fromX, fromY, toX, toY);
4195 /* Finish drag move */
4196 if (appData.highlightLastMove) {
4197 SetHighlights(fromX, fromY, toX, toY);
4201 DragPieceEnd(event->xbutton.x, event->xbutton.y);
4202 /* Don't animate move and drag both */
4203 appData.animate = FALSE;
4205 if (IsPromotion(fromX, fromY, toX, toY)) {
4206 if (appData.alwaysPromoteToQueen) {
4207 UserMoveEvent(fromX, fromY, toX, toY, 'q');
4208 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
4209 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
4212 SetHighlights(fromX, fromY, toX, toY);
4216 UserMoveEvent(fromX, fromY, toX, toY, NULLCHAR);
4217 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
4218 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
4221 appData.animate = saveAnimate;
4222 if (appData.animate || appData.animateDragging) {
4223 /* Undo animation damage if needed */
4224 DrawPosition(FALSE, NULL);
4228 void AnimateUserMove (Widget w, XEvent * event,
4229 String * params, Cardinal * nParams)
4231 DragPieceMove(event->xmotion.x, event->xmotion.y);
4234 Widget CommentCreate(name, text, mutable, callback, lines)
4236 int /*Boolean*/ mutable;
4237 XtCallbackProc callback;
4241 Widget shell, layout, form, edit, b_ok, b_cancel, b_clear, b_close, b_edit;
4246 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4247 XtGetValues(boardWidget, args, j);
4250 XtSetArg(args[j], XtNresizable, True); j++;
4253 XtCreatePopupShell(name, topLevelShellWidgetClass,
4254 shellWidget, args, j);
4257 XtCreatePopupShell(name, transientShellWidgetClass,
4258 shellWidget, args, j);
4261 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
4262 layoutArgs, XtNumber(layoutArgs));
4264 XtCreateManagedWidget("form", formWidgetClass, layout,
4265 formArgs, XtNumber(formArgs));
4269 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
4270 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
4272 XtSetArg(args[j], XtNstring, text); j++;
4273 XtSetArg(args[j], XtNtop, XtChainTop); j++;
4274 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4275 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4276 XtSetArg(args[j], XtNright, XtChainRight); j++;
4277 XtSetArg(args[j], XtNresizable, True); j++;
4278 XtSetArg(args[j], XtNwidth, bw_width); j++; /*force wider than buttons*/
4280 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
4282 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
4283 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
4285 XtSetArg(args[j], XtNautoFill, True); j++;
4286 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
4288 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
4292 XtSetArg(args[j], XtNfromVert, edit); j++;
4293 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4294 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4295 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4296 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4298 XtCreateManagedWidget(_("ok"), commandWidgetClass, form, args, j);
4299 XtAddCallback(b_ok, XtNcallback, callback, (XtPointer) 0);
4302 XtSetArg(args[j], XtNfromVert, edit); j++;
4303 XtSetArg(args[j], XtNfromHoriz, b_ok); j++;
4304 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4305 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4306 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4307 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4309 XtCreateManagedWidget(_("cancel"), commandWidgetClass, form, args, j);
4310 XtAddCallback(b_cancel, XtNcallback, callback, (XtPointer) 0);
4313 XtSetArg(args[j], XtNfromVert, edit); j++;
4314 XtSetArg(args[j], XtNfromHoriz, b_cancel); j++;
4315 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4316 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4317 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4318 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4320 XtCreateManagedWidget(_("clear"), commandWidgetClass, form, args, j);
4321 XtAddCallback(b_clear, XtNcallback, callback, (XtPointer) 0);
4324 XtSetArg(args[j], XtNfromVert, edit); j++;
4325 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4326 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4327 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4328 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4330 XtCreateManagedWidget(_("close"), commandWidgetClass, form, args, j);
4331 XtAddCallback(b_close, XtNcallback, callback, (XtPointer) 0);
4334 XtSetArg(args[j], XtNfromVert, edit); j++;
4335 XtSetArg(args[j], XtNfromHoriz, b_close); j++;
4336 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4337 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4338 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4339 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4341 XtCreateManagedWidget(_("edit"), commandWidgetClass, form, args, j);
4342 XtAddCallback(b_edit, XtNcallback, callback, (XtPointer) 0);
4345 XtRealizeWidget(shell);
4347 if (commentX == -1) {
4350 Dimension pw_height;
4351 Dimension ew_height;
4354 XtSetArg(args[j], XtNheight, &ew_height); j++;
4355 XtGetValues(edit, args, j);
4358 XtSetArg(args[j], XtNheight, &pw_height); j++;
4359 XtGetValues(shell, args, j);
4360 commentH = pw_height + (lines - 1) * ew_height;
4361 commentW = bw_width - 16;
4363 XSync(xDisplay, False);
4365 /* This code seems to tickle an X bug if it is executed too soon
4366 after xboard starts up. The coordinates get transformed as if
4367 the main window was positioned at (0, 0).
4369 XtTranslateCoords(shellWidget,
4370 (bw_width - commentW) / 2, 0 - commentH / 2,
4371 &commentX, &commentY);
4373 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
4374 RootWindowOfScreen(XtScreen(shellWidget)),
4375 (bw_width - commentW) / 2, 0 - commentH / 2,
4380 if (commentY < 0) commentY = 0; /*avoid positioning top offscreen*/
4383 XtSetArg(args[j], XtNheight, commentH); j++;
4384 XtSetArg(args[j], XtNwidth, commentW); j++;
4385 XtSetArg(args[j], XtNx, commentX); j++;
4386 XtSetArg(args[j], XtNy, commentY); j++;
4387 XtSetValues(shell, args, j);
4388 XtSetKeyboardFocus(shell, edit);
4393 /* Used for analysis window and ICS input window */
4394 Widget MiscCreate(name, text, mutable, callback, lines)
4396 int /*Boolean*/ mutable;
4397 XtCallbackProc callback;
4401 Widget shell, layout, form, edit;
4403 Dimension bw_width, pw_height, ew_height, w, h;
4409 XtSetArg(args[j], XtNresizable, True); j++;
4412 XtCreatePopupShell(name, topLevelShellWidgetClass,
4413 shellWidget, args, j);
4416 XtCreatePopupShell(name, transientShellWidgetClass,
4417 shellWidget, args, j);
4420 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
4421 layoutArgs, XtNumber(layoutArgs));
4423 XtCreateManagedWidget("form", formWidgetClass, layout,
4424 formArgs, XtNumber(formArgs));
4428 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
4429 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
4431 XtSetArg(args[j], XtNstring, text); j++;
4432 XtSetArg(args[j], XtNtop, XtChainTop); j++;
4433 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4434 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4435 XtSetArg(args[j], XtNright, XtChainRight); j++;
4436 XtSetArg(args[j], XtNresizable, True); j++;
4438 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
4440 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
4441 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
4443 XtSetArg(args[j], XtNautoFill, True); j++;
4444 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
4446 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
4448 XtRealizeWidget(shell);
4451 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4452 XtGetValues(boardWidget, args, j);
4455 XtSetArg(args[j], XtNheight, &ew_height); j++;
4456 XtGetValues(edit, args, j);
4459 XtSetArg(args[j], XtNheight, &pw_height); j++;
4460 XtGetValues(shell, args, j);
4461 h = pw_height + (lines - 1) * ew_height;
4464 XSync(xDisplay, False);
4466 /* This code seems to tickle an X bug if it is executed too soon
4467 after xboard starts up. The coordinates get transformed as if
4468 the main window was positioned at (0, 0).
4470 XtTranslateCoords(shellWidget, (bw_width - w) / 2, 0 - h / 2, &x, &y);
4472 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
4473 RootWindowOfScreen(XtScreen(shellWidget)),
4474 (bw_width - w) / 2, 0 - h / 2, &xx, &yy, &junk);
4478 if (y < 0) y = 0; /*avoid positioning top offscreen*/
4481 XtSetArg(args[j], XtNheight, h); j++;
4482 XtSetArg(args[j], XtNwidth, w); j++;
4483 XtSetArg(args[j], XtNx, x); j++;
4484 XtSetArg(args[j], XtNy, y); j++;
4485 XtSetValues(shell, args, j);
4491 static int savedIndex; /* gross that this is global */
4493 void EditCommentPopUp(index, title, text)
4502 if (text == NULL) text = "";
4504 if (editShell == NULL) {
4506 CommentCreate(title, text, True, EditCommentCallback, 4);
4507 XtRealizeWidget(editShell);
4508 CatchDeleteWindow(editShell, "EditCommentPopDown");
4510 edit = XtNameToWidget(editShell, "*form.text");
4512 XtSetArg(args[j], XtNstring, text); j++;
4513 XtSetValues(edit, args, j);
4515 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4516 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4517 XtSetValues(editShell, args, j);
4520 XtPopup(editShell, XtGrabNone);
4524 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
4525 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
4529 void EditCommentCallback(w, client_data, call_data)
4531 XtPointer client_data, call_data;
4539 XtSetArg(args[j], XtNlabel, &name); j++;
4540 XtGetValues(w, args, j);
4542 if (strcmp(name, _("ok")) == 0) {
4543 edit = XtNameToWidget(editShell, "*form.text");
4545 XtSetArg(args[j], XtNstring, &val); j++;
4546 XtGetValues(edit, args, j);
4547 ReplaceComment(savedIndex, val);
4548 EditCommentPopDown();
4549 } else if (strcmp(name, _("cancel")) == 0) {
4550 EditCommentPopDown();
4551 } else if (strcmp(name, _("clear")) == 0) {
4552 edit = XtNameToWidget(editShell, "*form.text");
4553 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
4554 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
4558 void EditCommentPopDown()
4563 if (!editUp) return;
4565 XtSetArg(args[j], XtNx, &commentX); j++;
4566 XtSetArg(args[j], XtNy, &commentY); j++;
4567 XtSetArg(args[j], XtNheight, &commentH); j++;
4568 XtSetArg(args[j], XtNwidth, &commentW); j++;
4569 XtGetValues(editShell, args, j);
4570 XtPopdown(editShell);
4573 XtSetArg(args[j], XtNleftBitmap, None); j++;
4574 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
4578 void ICSInputBoxPopUp()
4583 char *title = _("ICS Input");
4586 if (ICSInputShell == NULL) {
4587 ICSInputShell = MiscCreate(title, "", True, NULL, 1);
4588 tr = XtParseTranslationTable(ICSInputTranslations);
4589 edit = XtNameToWidget(ICSInputShell, "*form.text");
4590 XtOverrideTranslations(edit, tr);
4591 XtRealizeWidget(ICSInputShell);
4592 CatchDeleteWindow(ICSInputShell, "ICSInputBoxPopDown");
4595 edit = XtNameToWidget(ICSInputShell, "*form.text");
4597 XtSetArg(args[j], XtNstring, ""); j++;
4598 XtSetValues(edit, args, j);
4600 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4601 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4602 XtSetValues(ICSInputShell, args, j);
4605 XtPopup(ICSInputShell, XtGrabNone);
4606 XtSetKeyboardFocus(ICSInputShell, edit);
4608 ICSInputBoxUp = True;
4610 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
4611 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
4615 void ICSInputSendText()
4622 edit = XtNameToWidget(ICSInputShell, "*form.text");
4624 XtSetArg(args[j], XtNstring, &val); j++;
4625 XtGetValues(edit, args, j);
4626 SendMultiLineToICS(val);
4627 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
4628 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
4631 void ICSInputBoxPopDown()
4636 if (!ICSInputBoxUp) return;
4638 XtPopdown(ICSInputShell);
4639 ICSInputBoxUp = False;
4641 XtSetArg(args[j], XtNleftBitmap, None); j++;
4642 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
4646 void CommentPopUp(title, text)
4653 if (commentShell == NULL) {
4655 CommentCreate(title, text, False, CommentCallback, 4);
4656 XtRealizeWidget(commentShell);
4657 CatchDeleteWindow(commentShell, "CommentPopDown");
4659 edit = XtNameToWidget(commentShell, "*form.text");
4661 XtSetArg(args[j], XtNstring, text); j++;
4662 XtSetValues(edit, args, j);
4664 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4665 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4666 XtSetValues(commentShell, args, j);
4669 XtPopup(commentShell, XtGrabNone);
4670 XSync(xDisplay, False);
4675 void AnalysisPopUp(title, text)
4682 if (analysisShell == NULL) {
4683 analysisShell = MiscCreate(title, text, False, NULL, 4);
4684 XtRealizeWidget(analysisShell);
4685 CatchDeleteWindow(analysisShell, "AnalysisPopDown");
4688 edit = XtNameToWidget(analysisShell, "*form.text");
4690 XtSetArg(args[j], XtNstring, text); j++;
4691 XtSetValues(edit, args, j);
4693 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4694 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4695 XtSetValues(analysisShell, args, j);
4699 XtPopup(analysisShell, XtGrabNone);
4701 XSync(xDisplay, False);
4706 void CommentCallback(w, client_data, call_data)
4708 XtPointer client_data, call_data;
4715 XtSetArg(args[j], XtNlabel, &name); j++;
4716 XtGetValues(w, args, j);
4718 if (strcmp(name, _("close")) == 0) {
4720 } else if (strcmp(name, _("edit")) == 0) {
4727 void CommentPopDown()
4732 if (!commentUp) return;
4734 XtSetArg(args[j], XtNx, &commentX); j++;
4735 XtSetArg(args[j], XtNy, &commentY); j++;
4736 XtSetArg(args[j], XtNwidth, &commentW); j++;
4737 XtSetArg(args[j], XtNheight, &commentH); j++;
4738 XtGetValues(commentShell, args, j);
4739 XtPopdown(commentShell);
4740 XSync(xDisplay, False);
4744 void AnalysisPopDown()
4746 if (!analysisUp) return;
4747 XtPopdown(analysisShell);
4748 XSync(xDisplay, False);
4750 if (appData.icsEngineAnalyze) ExitAnalyzeMode(); /* [DM] icsEngineAnalyze */
4754 void FileNamePopUp(label, def, proc, openMode)
4761 Widget popup, layout, dialog, edit;
4767 fileProc = proc; /* I can't see a way not */
4768 fileOpenMode = openMode; /* to use globals here */
4771 XtSetArg(args[i], XtNresizable, True); i++;
4772 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
4773 XtSetArg(args[i], XtNtitle, XtNewString(_("File name prompt"))); i++;
4774 fileNameShell = popup =
4775 XtCreatePopupShell("File name prompt", transientShellWidgetClass,
4776 shellWidget, args, i);
4779 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
4780 layoutArgs, XtNumber(layoutArgs));
4783 XtSetArg(args[i], XtNlabel, label); i++;
4784 XtSetArg(args[i], XtNvalue, def); i++;
4785 XtSetArg(args[i], XtNborderWidth, 0); i++;
4786 dialog = XtCreateManagedWidget("fileName", dialogWidgetClass,
4789 XawDialogAddButton(dialog, _("ok"), FileNameCallback, (XtPointer) dialog);
4790 XawDialogAddButton(dialog, _("cancel"), FileNameCallback,
4791 (XtPointer) dialog);
4793 XtRealizeWidget(popup);
4794 CatchDeleteWindow(popup, "FileNamePopDown");
4796 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
4797 &x, &y, &win_x, &win_y, &mask);
4799 XtSetArg(args[0], XtNx, x - 10);
4800 XtSetArg(args[1], XtNy, y - 30);
4801 XtSetValues(popup, args, 2);
4803 XtPopup(popup, XtGrabExclusive);
4806 edit = XtNameToWidget(dialog, "*value");
4807 XtSetKeyboardFocus(popup, edit);
4810 void FileNamePopDown()
4812 if (!filenameUp) return;
4813 XtPopdown(fileNameShell);
4814 XtDestroyWidget(fileNameShell);
4819 void FileNameCallback(w, client_data, call_data)
4821 XtPointer client_data, call_data;
4826 XtSetArg(args[0], XtNlabel, &name);
4827 XtGetValues(w, args, 1);
4829 if (strcmp(name, _("cancel")) == 0) {
4834 FileNameAction(w, NULL, NULL, NULL);
4837 void FileNameAction(w, event, prms, nprms)
4849 name = XawDialogGetValueString(w = XtParent(w));
4851 if ((name != NULL) && (*name != NULLCHAR)) {
4853 XtPopdown(w = XtParent(XtParent(w)));
4857 p = strrchr(buf, ' ');
4864 fullname = ExpandPathName(buf);
4866 ErrorPopUp(_("Error"), _("Can't open file"), FALSE);
4869 f = fopen(fullname, fileOpenMode);
4871 DisplayError(_("Failed to open file"), errno);
4873 (void) (*fileProc)(f, index, buf);
4880 XtPopdown(w = XtParent(XtParent(w)));
4886 void PromotionPopUp()
4889 Widget dialog, layout;
4891 Dimension bw_width, pw_width;
4895 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4896 XtGetValues(boardWidget, args, j);
4899 XtSetArg(args[j], XtNresizable, True); j++;
4900 XtSetArg(args[j], XtNtitle, XtNewString(_("Promotion"))); j++;
4902 XtCreatePopupShell("Promotion", transientShellWidgetClass,
4903 shellWidget, args, j);
4905 XtCreateManagedWidget(layoutName, formWidgetClass, promotionShell,
4906 layoutArgs, XtNumber(layoutArgs));
4909 XtSetArg(args[j], XtNlabel, _("Promote to what?")); j++;
4910 XtSetArg(args[j], XtNborderWidth, 0); j++;
4911 dialog = XtCreateManagedWidget("promotion", dialogWidgetClass,
4914 if(gameInfo.variant != VariantShogi) {
4915 XawDialogAddButton(dialog, _("Queen"), PromotionCallback,
4916 (XtPointer) dialog);
4917 XawDialogAddButton(dialog, _("Rook"), PromotionCallback,
4918 (XtPointer) dialog);
4919 XawDialogAddButton(dialog, _("Bishop"), PromotionCallback,
4920 (XtPointer) dialog);
4921 XawDialogAddButton(dialog, _("Knight"), PromotionCallback,
4922 (XtPointer) dialog);
4923 if (!appData.testLegality || gameInfo.variant == VariantSuicide ||
4924 gameInfo.variant == VariantGiveaway) {
4925 XawDialogAddButton(dialog, _("King"), PromotionCallback,
4926 (XtPointer) dialog);
4928 if(gameInfo.variant == VariantCapablanca ||
4929 gameInfo.variant == VariantGothic ||
4930 gameInfo.variant == VariantCapaRandom) {
4931 XawDialogAddButton(dialog, _("Archbishop"), PromotionCallback,
4932 (XtPointer) dialog);
4933 XawDialogAddButton(dialog, _("Chancellor"), PromotionCallback,
4934 (XtPointer) dialog);
4936 } else // [HGM] shogi
4938 XawDialogAddButton(dialog, _("Promote"), PromotionCallback,
4939 (XtPointer) dialog);
4940 XawDialogAddButton(dialog, _("Defer"), PromotionCallback,
4941 (XtPointer) dialog);
4943 XawDialogAddButton(dialog, _("cancel"), PromotionCallback,
4944 (XtPointer) dialog);
4946 XtRealizeWidget(promotionShell);
4947 CatchDeleteWindow(promotionShell, "PromotionPopDown");
4950 XtSetArg(args[j], XtNwidth, &pw_width); j++;
4951 XtGetValues(promotionShell, args, j);
4953 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
4954 lineGap + squareSize/3 +
4955 ((toY == BOARD_HEIGHT-1) ^ (flipView) ?
4956 0 : 6*(squareSize + lineGap)), &x, &y);
4959 XtSetArg(args[j], XtNx, x); j++;
4960 XtSetArg(args[j], XtNy, y); j++;
4961 XtSetValues(promotionShell, args, j);
4963 XtPopup(promotionShell, XtGrabNone);
4968 void PromotionPopDown()
4970 if (!promotionUp) return;
4971 XtPopdown(promotionShell);
4972 XtDestroyWidget(promotionShell);
4973 promotionUp = False;
4976 void PromotionCallback(w, client_data, call_data)
4978 XtPointer client_data, call_data;
4984 XtSetArg(args[0], XtNlabel, &name);
4985 XtGetValues(w, args, 1);
4989 if (fromX == -1) return;
4991 if (strcmp(name, _("cancel")) == 0) {
4995 } else if (strcmp(name, _("Knight")) == 0) {
4997 } else if (strcmp(name, _("Promote")) == 0) {
4999 } else if (strcmp(name, _("Defer")) == 0) {
5002 promoChar = ToLower(name[0]);
5005 UserMoveEvent(fromX, fromY, toX, toY, promoChar);
5007 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
5008 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
5013 void ErrorCallback(w, client_data, call_data)
5015 XtPointer client_data, call_data;
5018 XtPopdown(w = XtParent(XtParent(XtParent(w))));
5020 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5026 if (!errorUp) return;
5030 gtk_widget_destroy(GTK_WIDGET(GUI_Error));
5032 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5037 void ErrorPopUp(title, label, modal)
5038 char *title, *label;
5041 GUI_Error = gtk_message_dialog_new(GTK_WINDOW(GUI_Window),
5042 GTK_DIALOG_DESTROY_WITH_PARENT,
5047 gtk_window_set_title(GTK_WINDOW(GUI_Error),(gchar *) title);
5050 gtk_dialog_run(GTK_DIALOG(GUI_Error));
5051 gtk_widget_destroy(GTK_WIDGET(GUI_Error));
5055 g_signal_connect_swapped (GUI_Error, "response",
5056 G_CALLBACK (ErrorPopDownProc),
5059 gtk_widget_show(GTK_WIDGET(GUI_Error));
5065 /* Disable all user input other than deleting the window */
5066 static int frozen = 0;
5070 /* Grab by a widget that doesn't accept input */
5071 // XtAddGrab(messageWidget, TRUE, FALSE);
5075 /* Undo a FreezeUI */
5078 if (!frozen) return;
5079 // XtRemoveGrab(messageWidget);
5083 char *ModeToWidgetName(mode)
5087 case BeginningOfGame:
5088 if (appData.icsActive)
5089 return "menuMode.ICS Client";
5090 else if (appData.noChessProgram ||
5091 *appData.cmailGameName != NULLCHAR)
5092 return "menuMode.Edit Game";
5094 return "menuMode.Machine Black";
5095 case MachinePlaysBlack:
5096 return "menuMode.Machine Black";
5097 case MachinePlaysWhite:
5098 return "menuMode.Machine White";
5100 return "menuMode.Analysis Mode";
5102 return "menuMode.Analyze File";
5103 case TwoMachinesPlay:
5104 return "menuMode.Two Machines";
5106 return "menuMode.Edit Game";
5107 case PlayFromGameFile:
5108 return "menuFile.Load Game";
5110 return "menuMode.Edit Position";
5112 return "menuMode.Training";
5113 case IcsPlayingWhite:
5114 case IcsPlayingBlack:
5118 return "menuMode.ICS Client";
5125 void ModeHighlight()
5127 static int oldPausing = FALSE;
5128 static GameMode oldmode = (GameMode) -1;
5131 // todo this toggling of the pause button doesn't seem to work?
5132 // e.g. select pause from buttonbar doesn't activate menumode.pause
5134 // if (!boardWidget || !XtIsRealized(boardWidget)) return;
5136 if (pausing != oldPausing) {
5137 oldPausing = pausing;
5138 gtk_button_set_relief(GTK_BUTTON (gtk_builder_get_object (builder, "menuMode.Pause")),pausing?GTK_RELIEF_NORMAL:GTK_RELIEF_NONE);
5139 /* toggle background color in showbuttonbar */
5140 if (appData.showButtonBar) {
5142 gtk_button_pressed(GTK_BUTTON (gtk_builder_get_object (builder, "buttonbar.Pause")));
5144 gtk_button_released(GTK_BUTTON (gtk_builder_get_object (builder, "buttonbar.Pause")));
5149 wname = ModeToWidgetName(oldmode);
5151 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, wname)),True);
5155 /* Maybe all the enables should be handled here, not just this one */
5156 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuMode.Training")),
5157 gameMode == Training || gameMode == PlayFromGameFile);
5162 * Button/menu procedures
5165 int LoadGamePopUp(f, gameNumber, title)
5170 cmailMsgLoaded = FALSE;
5171 if (gameNumber == 0) {
5172 int error = GameListBuild(f);
5174 DisplayError(_("Cannot build game list"), error);
5175 } else if (!ListEmpty(&gameList) &&
5176 ((ListGame *) gameList.tailPred)->number > 1) {
5177 GameListPopUp(f, title);
5183 return LoadGame(f, gameNumber, title, FALSE);
5187 void LoadNextPositionProc(w, event, prms, nprms)
5196 void LoadPrevPositionProc(w, event, prms, nprms)
5205 void ReloadPositionProc(w, event, prms, nprms)
5214 void LoadPositionProc(w, event, prms, nprms)
5220 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
5223 FileNamePopUp(_("Load position file name?"), "", LoadPosition, "rb");
5226 void SaveGameProc(w, event, prms, nprms)
5232 FileNamePopUp(_("Save game file name?"),
5233 DefaultFileName(appData.oldSaveStyle ? "game" : "pgn"),
5237 void SavePositionProc(w, event, prms, nprms)
5243 FileNamePopUp(_("Save position file name?"),
5244 DefaultFileName(appData.oldSaveStyle ? "pos" : "fen"),
5248 void ReloadCmailMsgProc(w, event, prms, nprms)
5254 ReloadCmailMsgEvent(FALSE);
5257 void MailMoveProc(w, event, prms, nprms)
5266 /* this variable is shared between CopyPositionProc and SendPositionSelection */
5267 static char *selected_fen_position=NULL;
5270 SendPositionSelection(Widget w, Atom *selection, Atom *target,
5271 Atom *type_return, XtPointer *value_return,
5272 unsigned long *length_return, int *format_return)
5274 char *selection_tmp;
5276 if (!selected_fen_position) return False; /* should never happen */
5277 if (*target == XA_STRING){
5278 /* note: since no XtSelectionDoneProc was registered, Xt will
5279 * automatically call XtFree on the value returned. So have to
5280 * make a copy of it allocated with XtMalloc */
5281 selection_tmp= XtMalloc(strlen(selected_fen_position)+16);
5282 strcpy(selection_tmp, selected_fen_position);
5284 *value_return=selection_tmp;
5285 *length_return=strlen(selection_tmp);
5286 *type_return=XA_STRING;
5287 *format_return = 8; /* bits per byte */
5294 /* note: when called from menu all parameters are NULL, so no clue what the
5295 * Widget which was clicked on was, or what the click event was
5297 void CopyPositionProc(w, event, prms, nprms)
5305 if (selected_fen_position) free(selected_fen_position);
5306 selected_fen_position = (char *)PositionToFEN(currentMove, NULL);
5307 if (!selected_fen_position) return;
5308 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
5310 SendPositionSelection,
5311 NULL/* lose_ownership_proc */ ,
5312 NULL/* transfer_done_proc */);
5314 free(selected_fen_position);
5315 selected_fen_position=NULL;
5319 /* function called when the data to Paste is ready */
5321 PastePositionCB(Widget w, XtPointer client_data, Atom *selection,
5322 Atom *type, XtPointer value, unsigned long *len, int *format)
5325 if (value==NULL || *len==0) return; /* nothing had been selected to copy */
5326 fenstr[*len]='\0'; /* normally this string is terminated, but be safe */
5327 EditPositionPasteFEN(fenstr);
5331 /* called when Paste Position button is pressed,
5332 * all parameters will be NULL */
5333 void PastePositionProc(w, event, prms, nprms)
5339 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
5340 /* (XtSelectionCallbackProc) */ PastePositionCB,
5341 NULL, /* client_data passed to PastePositionCB */
5343 /* better to use the time field from the event that triggered the
5344 * call to this function, but that isn't trivial to get
5352 SendGameSelection(Widget w, Atom *selection, Atom *target,
5353 Atom *type_return, XtPointer *value_return,
5354 unsigned long *length_return, int *format_return)
5356 char *selection_tmp;
5358 if (*target == XA_STRING){
5359 FILE* f = fopen(gameCopyFilename, "r");
5362 if (f == NULL) return False;
5366 selection_tmp = XtMalloc(len + 1);
5367 count = fread(selection_tmp, 1, len, f);
5369 XtFree(selection_tmp);
5372 selection_tmp[len] = NULLCHAR;
5373 *value_return = selection_tmp;
5374 *length_return = len;
5375 *type_return = XA_STRING;
5376 *format_return = 8; /* bits per byte */
5383 /* note: when called from menu all parameters are NULL, so no clue what the
5384 * Widget which was clicked on was, or what the click event was
5386 void CopyGameProc(w, event, prms, nprms)
5394 ret = SaveGameToFile(gameCopyFilename, FALSE);
5397 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
5400 NULL/* lose_ownership_proc */ ,
5401 NULL/* transfer_done_proc */);
5404 /* function called when the data to Paste is ready */
5406 PasteGameCB(Widget w, XtPointer client_data, Atom *selection,
5407 Atom *type, XtPointer value, unsigned long *len, int *format)
5410 if (value == NULL || *len == 0) {
5411 return; /* nothing had been selected to copy */
5413 f = fopen(gamePasteFilename, "w");
5415 DisplayError(_("Can't open temp file"), errno);
5418 fwrite(value, 1, *len, f);
5421 LoadGameFromFile(gamePasteFilename, 0, gamePasteFilename, TRUE);
5424 /* called when Paste Game button is pressed,
5425 * all parameters will be NULL */
5426 void PasteGameProc(w, event, prms, nprms)
5432 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
5433 /* (XtSelectionCallbackProc) */ PasteGameCB,
5434 NULL, /* client_data passed to PasteGameCB */
5436 /* better to use the time field from the event that triggered the
5437 * call to this function, but that isn't trivial to get
5447 SaveGameProc(NULL, NULL, NULL, NULL);
5450 void AnalyzeModeProc(w, event, prms, nprms)
5458 if (!first.analysisSupport) {
5459 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
5460 DisplayError(buf, 0);
5463 /* [DM] icsEngineAnalyze [HGM] This is horrible code; reverse the gameMode and isEngineAnalyze tests! */
5464 if (appData.icsActive) {
5465 if (gameMode != IcsObserving) {
5466 sprintf(buf,_("You are not observing a game"));
5467 DisplayError(buf, 0);
5469 if (appData.icsEngineAnalyze) {
5470 if (appData.debugMode)
5471 fprintf(debugFP, _("Found unexpected active ICS engine analyze \n"));
5477 /* if enable, use want disable icsEngineAnalyze */
5478 if (appData.icsEngineAnalyze) {
5483 appData.icsEngineAnalyze = TRUE;
5484 if (appData.debugMode)
5485 fprintf(debugFP, _("ICS engine analyze starting... \n"));
5487 if (!appData.showThinking)
5488 ShowThinkingProc(w,event,prms,nprms);
5493 void AnalyzeFileProc(w, event, prms, nprms)
5499 if (!first.analysisSupport) {
5501 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
5502 DisplayError(buf, 0);
5507 if (!appData.showThinking)
5508 ShowThinkingProc(w,event,prms,nprms);
5511 FileNamePopUp(_("File to analyze"), "", LoadGamePopUp, "rb");
5512 AnalysisPeriodicEvent(1);
5516 void EditGameProc(w, event, prms, nprms)
5525 void EditPositionProc(w, event, prms, nprms)
5531 EditPositionEvent();
5534 void TrainingProc(w, event, prms, nprms)
5543 void EditCommentProc(w, event, prms, nprms)
5550 EditCommentPopDown();
5556 void IcsInputBoxProc(w, event, prms, nprms)
5562 if (ICSInputBoxUp) {
5563 ICSInputBoxPopDown();
5570 void EnterKeyProc(w, event, prms, nprms)
5576 if (ICSInputBoxUp == True)
5580 void AlwaysQueenProc(w, event, prms, nprms)
5588 appData.alwaysPromoteToQueen = !appData.alwaysPromoteToQueen;
5590 if (appData.alwaysPromoteToQueen) {
5591 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5593 XtSetArg(args[0], XtNleftBitmap, None);
5595 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
5599 void AnimateDraggingProc(w, event, prms, nprms)
5607 appData.animateDragging = !appData.animateDragging;
5609 if (appData.animateDragging) {
5610 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5613 XtSetArg(args[0], XtNleftBitmap, None);
5615 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Dragging"),
5619 void AnimateMovingProc(w, event, prms, nprms)
5627 appData.animate = !appData.animate;
5629 if (appData.animate) {
5630 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5633 XtSetArg(args[0], XtNleftBitmap, None);
5635 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
5639 void AutocommProc(w, event, prms, nprms)
5647 appData.autoComment = !appData.autoComment;
5649 if (appData.autoComment) {
5650 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5652 XtSetArg(args[0], XtNleftBitmap, None);
5654 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
5659 void AutoflagProc(w, event, prms, nprms)
5667 appData.autoCallFlag = !appData.autoCallFlag;
5669 if (appData.autoCallFlag) {
5670 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5672 XtSetArg(args[0], XtNleftBitmap, None);
5674 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
5678 void AutoflipProc(w, event, prms, nprms)
5686 appData.autoFlipView = !appData.autoFlipView;
5688 if (appData.autoFlipView) {
5689 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5691 XtSetArg(args[0], XtNleftBitmap, None);
5693 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flip View"),
5697 void AutobsProc(w, event, prms, nprms)
5705 appData.autoObserve = !appData.autoObserve;
5707 if (appData.autoObserve) {
5708 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5710 XtSetArg(args[0], XtNleftBitmap, None);
5712 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
5716 void AutoraiseProc(w, event, prms, nprms)
5724 appData.autoRaiseBoard = !appData.autoRaiseBoard;
5726 if (appData.autoRaiseBoard) {
5727 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5729 XtSetArg(args[0], XtNleftBitmap, None);
5731 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Raise Board"),
5735 void AutosaveProc(w, event, prms, nprms)
5743 appData.autoSaveGames = !appData.autoSaveGames;
5745 if (appData.autoSaveGames) {
5746 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5748 XtSetArg(args[0], XtNleftBitmap, None);
5750 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
5754 void BlindfoldProc(w, event, prms, nprms)
5762 appData.blindfold = !appData.blindfold;
5764 if (appData.blindfold) {
5765 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5767 XtSetArg(args[0], XtNleftBitmap, None);
5769 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Blindfold"),
5772 DrawPosition(True, NULL);
5775 void TestLegalityProc(w, event, prms, nprms)
5783 appData.testLegality = !appData.testLegality;
5785 if (appData.testLegality) {
5786 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5788 XtSetArg(args[0], XtNleftBitmap, None);
5790 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Test Legality"),
5795 void FlashMovesProc(w, event, prms, nprms)
5803 if (appData.flashCount == 0) {
5804 appData.flashCount = 3;
5806 appData.flashCount = -appData.flashCount;
5809 if (appData.flashCount > 0) {
5810 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5812 XtSetArg(args[0], XtNleftBitmap, None);
5814 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flash Moves"),
5818 void FlipViewProc(w, event, prms, nprms)
5824 flipView = !flipView;
5825 DrawPosition(True, NULL);
5828 void GetMoveListProc(w, event, prms, nprms)
5836 appData.getMoveList = !appData.getMoveList;
5838 if (appData.getMoveList) {
5839 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5842 XtSetArg(args[0], XtNleftBitmap, None);
5844 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
5849 void HighlightDraggingProc(w, event, prms, nprms)
5857 appData.highlightDragging = !appData.highlightDragging;
5859 if (appData.highlightDragging) {
5860 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5862 XtSetArg(args[0], XtNleftBitmap, None);
5864 XtSetValues(XtNameToWidget(menuBarWidget,
5865 "menuOptions.Highlight Dragging"), args, 1);
5869 void HighlightLastMoveProc(w, event, prms, nprms)
5877 appData.highlightLastMove = !appData.highlightLastMove;
5879 if (appData.highlightLastMove) {
5880 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5882 XtSetArg(args[0], XtNleftBitmap, None);
5884 XtSetValues(XtNameToWidget(menuBarWidget,
5885 "menuOptions.Highlight Last Move"), args, 1);
5888 void IcsAlarmProc(w, event, prms, nprms)
5896 appData.icsAlarm = !appData.icsAlarm;
5898 if (appData.icsAlarm) {
5899 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5901 XtSetArg(args[0], XtNleftBitmap, None);
5903 XtSetValues(XtNameToWidget(menuBarWidget,
5904 "menuOptions.ICS Alarm"), args, 1);
5907 void MoveSoundProc(w, event, prms, nprms)
5915 appData.ringBellAfterMoves = !appData.ringBellAfterMoves;
5917 if (appData.ringBellAfterMoves) {
5918 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5920 XtSetArg(args[0], XtNleftBitmap, None);
5922 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
5927 void OldSaveStyleProc(w, event, prms, nprms)
5935 appData.oldSaveStyle = !appData.oldSaveStyle;
5937 if (appData.oldSaveStyle) {
5938 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5940 XtSetArg(args[0], XtNleftBitmap, None);
5942 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Old Save Style"),
5946 void PeriodicUpdatesProc(w, event, prms, nprms)
5954 PeriodicUpdatesEvent(!appData.periodicUpdates);
5956 if (appData.periodicUpdates) {
5957 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5959 XtSetArg(args[0], XtNleftBitmap, None);
5961 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Periodic Updates"),
5965 void PonderNextMoveProc(w, event, prms, nprms)
5973 PonderNextMoveEvent(!appData.ponderNextMove);
5975 if (appData.ponderNextMove) {
5976 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5978 XtSetArg(args[0], XtNleftBitmap, None);
5980 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Ponder Next Move"),
5984 void PopupExitMessageProc(w, event, prms, nprms)
5992 appData.popupExitMessage = !appData.popupExitMessage;
5994 if (appData.popupExitMessage) {
5995 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5997 XtSetArg(args[0], XtNleftBitmap, None);
5999 XtSetValues(XtNameToWidget(menuBarWidget,
6000 "menuOptions.Popup Exit Message"), args, 1);
6003 void PopupMoveErrorsProc(w, event, prms, nprms)
6011 appData.popupMoveErrors = !appData.popupMoveErrors;
6013 if (appData.popupMoveErrors) {
6014 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6016 XtSetArg(args[0], XtNleftBitmap, None);
6018 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Popup Move Errors"),
6022 void PremoveProc(w, event, prms, nprms)
6030 appData.premove = !appData.premove;
6032 if (appData.premove) {
6033 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6035 XtSetArg(args[0], XtNleftBitmap, None);
6037 XtSetValues(XtNameToWidget(menuBarWidget,
6038 "menuOptions.Premove"), args, 1);
6041 void QuietPlayProc(w, event, prms, nprms)
6049 appData.quietPlay = !appData.quietPlay;
6051 if (appData.quietPlay) {
6052 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6054 XtSetArg(args[0], XtNleftBitmap, None);
6056 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Quiet Play"),
6060 void ShowThinkingProc(w, event, prms, nprms)
6068 appData.showThinking = !appData.showThinking; // [HGM] thinking: tken out of ShowThinkingEvent
6069 ShowThinkingEvent();
6071 // [HGM] thinking: currently no suc menu item; replaced by Hide Thinking (From Human)
6072 if (appData.showThinking) {
6073 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6075 XtSetArg(args[0], XtNleftBitmap, None);
6077 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Thinking"),
6082 void HideThinkingProc(w, event, prms, nprms)
6090 appData.hideThinkingFromHuman = !appData.hideThinkingFromHuman; // [HGM] thinking: tken out of ShowThinkingEvent
6091 ShowThinkingEvent();
6093 if (appData.hideThinkingFromHuman) {
6094 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6096 XtSetArg(args[0], XtNleftBitmap, None);
6098 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
6102 void InfoProc(w, event, prms, nprms)
6109 snprintf(buf, sizeof(buf), "xterm -e info --directory %s --directory . -f %s &",
6114 void ManProc(w, event, prms, nprms)
6122 if (nprms && *nprms > 0)
6126 snprintf(buf, sizeof(buf), "xterm -e man %s &", name);
6130 void HintProc(w, event, prms, nprms)
6139 void BookProc(w, event, prms, nprms)
6148 void DebugProc(w, event, prms, nprms)
6154 appData.debugMode = !appData.debugMode;
6157 void AboutGameProc(w, event, prms, nprms)
6166 void NothingProc(w, event, prms, nprms)
6175 void Iconify(w, event, prms, nprms)
6184 XtSetArg(args[0], XtNiconic, True);
6185 XtSetValues(shellWidget, args, 1);
6188 void DisplayMessage(message, extMessage)
6189 gchar *message, *extMessage;
6196 snprintf(buf, sizeof(buf), "%s %s", message, extMessage);
6199 message = extMessage;
6202 gtk_label_set_text( GTK_LABEL(gtk_builder_get_object (builder, "Messages")),message);
6207 void DisplayTitle(text)
6210 gchar title[MSG_SIZ];
6212 if (text == NULL) text = "";
6214 if (appData.titleInWindow)
6219 if (*text != NULLCHAR)
6221 strcpy(title, text);
6223 else if (appData.icsActive)
6225 snprintf(title, sizeof(title), "%s: %s", programName, appData.icsHost);
6227 else if (appData.cmailGameName[0] != NULLCHAR)
6229 snprintf(title,sizeof(title), "%s: %s", programName, "CMail");
6231 // [HGM] license: This stuff should really be done in back-end, but WinBoard already had a pop-up for it
6233 else if (gameInfo.variant == VariantGothic)
6235 strcpy(title, GOTHIC);
6239 else if (gameInfo.variant == VariantFalcon)
6241 strcpy(title, FALCON);
6244 else if (appData.noChessProgram)
6246 strcpy(title, programName);
6250 snprintf(title,sizeof(title), "%s: %s", programName, first.tidy);
6252 gtk_window_set_title(GTK_WINDOW(GUI_Window),title);
6258 void DisplayError(message, error)
6265 if (appData.debugMode || appData.matchMode) {
6266 fprintf(stderr, "%s: %s\n", programName, message);
6269 if (appData.debugMode || appData.matchMode) {
6270 fprintf(stderr, "%s: %s: %s\n",
6271 programName, message, strerror(error));
6273 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
6276 ErrorPopUp(_("Error"), message, FALSE);
6280 void DisplayMoveError(message)
6285 DrawPosition(FALSE, NULL);
6286 if (appData.debugMode || appData.matchMode) {
6287 fprintf(stderr, "%s: %s\n", programName, message);
6289 if (appData.popupMoveErrors) {
6290 ErrorPopUp(_("Error"), message, FALSE);
6292 DisplayMessage(message, "");
6297 void DisplayFatalError(message, error, status)
6303 errorExitStatus = status;
6305 fprintf(stderr, "%s: %s\n", programName, message);
6307 fprintf(stderr, "%s: %s: %s\n",
6308 programName, message, strerror(error));
6309 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
6312 if (appData.popupExitMessage && boardWidget && XtIsRealized(boardWidget)) {
6313 ErrorPopUp(status ? _("Fatal Error") : _("Exiting"), message, TRUE);
6319 void DisplayInformation(message)
6323 ErrorPopUp(_("Information"), message, TRUE);
6326 void DisplayNote(message)
6330 ErrorPopUp(_("Note"), message, FALSE);
6334 NullXErrorCheck(dpy, error_event)
6336 XErrorEvent *error_event;
6341 void DisplayIcsInteractionTitle(message)
6344 if (oldICSInteractionTitle == NULL) {
6345 /* Magic to find the old window title, adapted from vim */
6346 char *wina = getenv("WINDOWID");
6348 Window win = (Window) atoi(wina);
6349 Window root, parent, *children;
6350 unsigned int nchildren;
6351 int (*oldHandler)() = XSetErrorHandler(NullXErrorCheck);
6353 if (XFetchName(xDisplay, win, &oldICSInteractionTitle)) break;
6354 if (!XQueryTree(xDisplay, win, &root, &parent,
6355 &children, &nchildren)) break;
6356 if (children) XFree((void *)children);
6357 if (parent == root || parent == 0) break;
6360 XSetErrorHandler(oldHandler);
6362 if (oldICSInteractionTitle == NULL) {
6363 oldICSInteractionTitle = "xterm";
6366 printf("\033]0;%s\007", message);
6370 char pendingReplyPrefix[MSG_SIZ];
6371 ProcRef pendingReplyPR;
6373 void AskQuestionProc(w, event, prms, nprms)
6380 fprintf(stderr, _("AskQuestionProc needed 4 parameters, got %d\n"),
6384 AskQuestionEvent(prms[0], prms[1], prms[2], prms[3]);
6387 void AskQuestionPopDown()
6389 if (!askQuestionUp) return;
6390 XtPopdown(askQuestionShell);
6391 XtDestroyWidget(askQuestionShell);
6392 askQuestionUp = False;
6395 void AskQuestionReplyAction(w, event, prms, nprms)
6405 reply = XawDialogGetValueString(w = XtParent(w));
6406 strcpy(buf, pendingReplyPrefix);
6407 if (*buf) strcat(buf, " ");
6410 OutputToProcess(pendingReplyPR, buf, strlen(buf), &err);
6411 AskQuestionPopDown();
6413 if (err) DisplayFatalError(_("Error writing to chess program"), err, 0);
6416 void AskQuestionCallback(w, client_data, call_data)
6418 XtPointer client_data, call_data;
6423 XtSetArg(args[0], XtNlabel, &name);
6424 XtGetValues(w, args, 1);
6426 if (strcmp(name, _("cancel")) == 0) {
6427 AskQuestionPopDown();
6429 AskQuestionReplyAction(w, NULL, NULL, NULL);
6433 void AskQuestion(title, question, replyPrefix, pr)
6434 char *title, *question, *replyPrefix;
6438 Widget popup, layout, dialog, edit;
6444 strcpy(pendingReplyPrefix, replyPrefix);
6445 pendingReplyPR = pr;
6448 XtSetArg(args[i], XtNresizable, True); i++;
6449 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
6450 askQuestionShell = popup =
6451 XtCreatePopupShell(title, transientShellWidgetClass,
6452 shellWidget, args, i);
6455 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
6456 layoutArgs, XtNumber(layoutArgs));
6459 XtSetArg(args[i], XtNlabel, question); i++;
6460 XtSetArg(args[i], XtNvalue, ""); i++;
6461 XtSetArg(args[i], XtNborderWidth, 0); i++;
6462 dialog = XtCreateManagedWidget("question", dialogWidgetClass,
6465 XawDialogAddButton(dialog, _("enter"), AskQuestionCallback,
6466 (XtPointer) dialog);
6467 XawDialogAddButton(dialog, _("cancel"), AskQuestionCallback,
6468 (XtPointer) dialog);
6470 XtRealizeWidget(popup);
6471 CatchDeleteWindow(popup, "AskQuestionPopDown");
6473 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
6474 &x, &y, &win_x, &win_y, &mask);
6476 XtSetArg(args[0], XtNx, x - 10);
6477 XtSetArg(args[1], XtNy, y - 30);
6478 XtSetValues(popup, args, 2);
6480 XtPopup(popup, XtGrabExclusive);
6481 askQuestionUp = True;
6483 edit = XtNameToWidget(dialog, "*value");
6484 XtSetKeyboardFocus(popup, edit);
6492 if (*name == NULLCHAR) {
6494 } else if (strcmp(name, "$") == 0) {
6495 putc(BELLCHAR, stderr);
6498 snprintf(buf, sizeof(buf), "%s '%s' &", appData.soundProgram, name);
6506 PlaySound(appData.soundMove);
6512 PlaySound(appData.soundIcsWin);
6518 PlaySound(appData.soundIcsLoss);
6524 PlaySound(appData.soundIcsDraw);
6528 PlayIcsUnfinishedSound()
6530 PlaySound(appData.soundIcsUnfinished);
6536 PlaySound(appData.soundIcsAlarm);
6542 system("stty echo");
6548 system("stty -echo");
6552 Colorize(cc, continuation)
6557 int count, outCount, error;
6559 if (textColors[(int)cc].bg > 0) {
6560 if (textColors[(int)cc].fg > 0) {
6561 sprintf(buf, "\033[0;%d;%d;%dm", textColors[(int)cc].attr,
6562 textColors[(int)cc].fg, textColors[(int)cc].bg);
6564 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
6565 textColors[(int)cc].bg);
6568 if (textColors[(int)cc].fg > 0) {
6569 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
6570 textColors[(int)cc].fg);
6572 sprintf(buf, "\033[0;%dm", textColors[(int)cc].attr);
6575 count = strlen(buf);
6576 outCount = OutputToProcess(NoProc, buf, count, &error);
6577 if (outCount < count) {
6578 DisplayFatalError(_("Error writing to display"), error, 1);
6581 if (continuation) return;
6584 PlaySound(appData.soundShout);
6587 PlaySound(appData.soundSShout);
6590 PlaySound(appData.soundChannel1);
6593 PlaySound(appData.soundChannel);
6596 PlaySound(appData.soundKibitz);
6599 PlaySound(appData.soundTell);
6601 case ColorChallenge:
6602 PlaySound(appData.soundChallenge);
6605 PlaySound(appData.soundRequest);
6608 PlaySound(appData.soundSeek);
6619 return getpwuid(getuid())->pw_name;
6622 static char *ExpandPathName(path)
6625 static char static_buf[2000];
6626 char *d, *s, buf[2000];
6632 while (*s && isspace(*s))
6641 if (*(s+1) == '/') {
6642 strcpy(d, getpwuid(getuid())->pw_dir);
6647 *strchr(buf, '/') = 0;
6648 pwd = getpwnam(buf);
6651 fprintf(stderr, _("ERROR: Unknown user %s (in path %s)\n"),
6655 strcpy(d, pwd->pw_dir);
6656 strcat(d, strchr(s+1, '/'));
6667 static char host_name[MSG_SIZ];
6669 #if HAVE_GETHOSTNAME
6670 gethostname(host_name, MSG_SIZ);
6672 #else /* not HAVE_GETHOSTNAME */
6673 # if HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H
6674 sysinfo(SI_HOSTNAME, host_name, MSG_SIZ);
6676 # else /* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
6678 # endif/* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
6679 #endif /* not HAVE_GETHOSTNAME */
6682 gint delayedEventTimerTag = 0;
6683 DelayedEventCallback delayedEventCallback = 0;
6686 FireDelayedEvent(data)
6689 delayedEventTimerTag = 0;
6690 delayedEventCallback();
6694 ScheduleDelayedEvent(cb, millisec)
6695 DelayedEventCallback cb; long millisec;
6697 delayedEventCallback = cb;
6698 delayedEventTimerTag = gtk_timeout_add(millisec,(GtkFunction) FireDelayedEvent, NULL);
6701 DelayedEventCallback
6704 if (delayedEventTimerTag)
6706 return delayedEventCallback;
6715 CancelDelayedEvent()
6717 if (delayedEventTimerTag)
6719 gtk_timeout_remove(delayedEventTimerTag);
6720 delayedEventTimerTag = 0;
6726 gint loadGameTimerTag = 0;
6728 int LoadGameTimerRunning()
6730 return loadGameTimerTag != 0;
6733 int StopLoadGameTimer()
6735 if (loadGameTimerTag != 0) {
6736 gtk_timeout_remove(loadGameTimerTag);
6737 loadGameTimerTag = 0;
6745 LoadGameTimerCallback(data)
6748 loadGameTimerTag = 0;
6753 StartLoadGameTimer(millisec)
6757 gtk_timeout_add( millisec, (GtkFunction) LoadGameTimerCallback, NULL);
6760 gint analysisClockTag = 0;
6763 AnalysisClockCallback(data)
6766 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile
6767 || appData.icsEngineAnalyze)
6769 AnalysisPeriodicEvent(0);
6770 StartAnalysisClock();
6775 StartAnalysisClock()
6778 gtk_timeout_add( 2000,(GtkFunction) AnalysisClockCallback, NULL);
6781 gint clockTimerTag = 0;
6783 int ClockTimerRunning()
6785 return clockTimerTag != 0;
6788 int StopClockTimer()
6790 if (clockTimerTag != 0)
6792 gtk_timeout_remove(clockTimerTag);
6803 ClockTimerCallback(data)
6812 StartClockTimer(millisec)
6815 clockTimerTag = gtk_timeout_add(millisec,(GtkFunction) ClockTimerCallback,NULL);
6820 DisplayTimerLabel(w, color, timer, highlight)
6829 if (appData.clockMode) {
6830 sprintf(buf, "%s: %s", color, TimeString(timer));
6832 sprintf(buf, "%s ", color);
6834 gtk_label_set_text(GTK_LABEL(w),buf);
6836 /* check for low time warning */
6837 // Pixel foregroundOrWarningColor = timerForegroundPixel;
6840 // appData.lowTimeWarning &&
6841 // (timer / 1000) < appData.icsAlarmTime)
6842 // foregroundOrWarningColor = lowTimeWarningColor;
6844 // if (appData.clockMode) {
6845 // sprintf(buf, "%s: %s", color, TimeString(timer));
6846 // XtSetArg(args[0], XtNlabel, buf);
6848 // sprintf(buf, "%s ", color);
6849 // XtSetArg(args[0], XtNlabel, buf);
6854 // XtSetArg(args[1], XtNbackground, foregroundOrWarningColor);
6855 // XtSetArg(args[2], XtNforeground, timerBackgroundPixel);
6857 // XtSetArg(args[1], XtNbackground, timerBackgroundPixel);
6858 // XtSetArg(args[2], XtNforeground, foregroundOrWarningColor);
6861 // XtSetValues(w, args, 3);
6866 DisplayWhiteClock(timeRemaining, highlight)
6870 if(appData.noGUI) return;
6872 DisplayTimerLabel(GUI_Whiteclock, _("White"), timeRemaining, highlight);
6873 if (highlight && WindowIcon == BlackIcon)
6875 WindowIcon = WhiteIcon;
6876 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
6881 DisplayBlackClock(timeRemaining, highlight)
6885 if(appData.noGUI) return;
6887 DisplayTimerLabel(GUI_Blackclock, _("Black"), timeRemaining, highlight);
6888 if (highlight && WindowIcon == WhiteIcon)
6890 WindowIcon = BlackIcon;
6891 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
6909 int StartChildProcess(cmdLine, dir, pr)
6916 int to_prog[2], from_prog[2];
6920 if (appData.debugMode) {
6921 fprintf(stderr, "StartChildProcess (dir=\"%s\") %s\n",dir, cmdLine);
6924 /* We do NOT feed the cmdLine to the shell; we just
6925 parse it into blank-separated arguments in the
6926 most simple-minded way possible.
6929 strcpy(buf, cmdLine);
6934 if (p == NULL) break;
6939 SetUpChildIO(to_prog, from_prog);
6941 if ((pid = fork()) == 0) {
6943 // [HGM] PSWBTM: made order resistant against case where fd of created pipe was 0 or 1
6944 close(to_prog[1]); // first close the unused pipe ends
6945 close(from_prog[0]);
6946 dup2(to_prog[0], 0); // to_prog was created first, nd is the only one to use 0 or 1
6947 dup2(from_prog[1], 1);
6948 if(to_prog[0] >= 2) close(to_prog[0]); // if 0 or 1, the dup2 already cosed the original
6949 close(from_prog[1]); // and closing again loses one of the pipes!
6950 if(fileno(stderr) >= 2) // better safe than sorry...
6951 dup2(1, fileno(stderr)); /* force stderr to the pipe */
6953 if (dir[0] != NULLCHAR && chdir(dir) != 0) {
6958 nice(appData.niceEngines); // [HGM] nice: adjust priority of engine proc
6960 execvp(argv[0], argv);
6962 /* If we get here, exec failed */
6967 /* Parent process */
6969 close(from_prog[1]);
6971 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
6974 cp->fdFrom = from_prog[0];
6975 cp->fdTo = to_prog[1];
6980 // [HGM] kill: implement the 'hard killing' of AS's Winboard_x
6981 static RETSIGTYPE AlarmCallBack(int n)
6987 DestroyChildProcess(pr, signalType)
6991 ChildProc *cp = (ChildProc *) pr;
6993 if (cp->kind != CPReal) return;
6995 if (signalType == 10) { // [HGM] kill: if it does not terminate in 3 sec, kill
6996 signal(SIGALRM, AlarmCallBack);
6998 if(wait((int *) 0) == -1) { // process does not terminate on its own accord
6999 kill(cp->pid, SIGKILL); // kill it forcefully
7000 wait((int *) 0); // and wait again
7004 kill(cp->pid, signalType == 9 ? SIGKILL : SIGTERM); // [HGM] kill: use hard kill if so requested
7006 /* Process is exiting either because of the kill or because of
7007 a quit command sent by the backend; either way, wait for it to die.
7016 InterruptChildProcess(pr)
7019 ChildProc *cp = (ChildProc *) pr;
7021 if (cp->kind != CPReal) return;
7022 (void) kill(cp->pid, SIGINT); /* stop it thinking */
7025 int OpenTelnet(host, port, pr)
7030 char cmdLine[MSG_SIZ];
7032 if (port[0] == NULLCHAR) {
7033 snprintf(cmdLine, sizeof(cmdLine), "%s %s", appData.telnetProgram, host);
7035 snprintf(cmdLine, sizeof(cmdLine), "%s %s %s", appData.telnetProgram, host, port);
7037 return StartChildProcess(cmdLine, "", pr);
7040 int OpenTCP(host, port, pr)
7046 DisplayFatalError(_("Socket support is not configured in"), 0, 2);
7047 #else /* !OMIT_SOCKETS */
7049 struct sockaddr_in sa;
7051 unsigned short uport;
7054 if ((s = socket(AF_INET, SOCK_STREAM, 6)) < 0) {
7058 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
7059 sa.sin_family = AF_INET;
7060 sa.sin_addr.s_addr = INADDR_ANY;
7061 uport = (unsigned short) 0;
7062 sa.sin_port = htons(uport);
7063 if (bind(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)) < 0) {
7067 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
7068 if (!(hp = gethostbyname(host))) {
7070 if (sscanf(host, "%d.%d.%d.%d", &b0, &b1, &b2, &b3) == 4) {
7071 hp = (struct hostent *) calloc(1, sizeof(struct hostent));
7072 hp->h_addrtype = AF_INET;
7074 hp->h_addr_list = (char **) calloc(2, sizeof(char *));
7075 hp->h_addr_list[0] = (char *) malloc(4);
7076 hp->h_addr_list[0][0] = b0;
7077 hp->h_addr_list[0][1] = b1;
7078 hp->h_addr_list[0][2] = b2;
7079 hp->h_addr_list[0][3] = b3;
7084 sa.sin_family = hp->h_addrtype;
7085 uport = (unsigned short) atoi(port);
7086 sa.sin_port = htons(uport);
7087 memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);
7089 if (connect(s, (struct sockaddr *) &sa,
7090 sizeof(struct sockaddr_in)) < 0) {
7094 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7101 #endif /* !OMIT_SOCKETS */
7106 int OpenCommPort(name, pr)
7113 fd = open(name, 2, 0);
7114 if (fd < 0) return errno;
7116 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7126 int OpenLoopback(pr)
7132 SetUpChildIO(to, from);
7134 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7137 cp->fdFrom = to[0]; /* note not from[0]; we are doing a loopback */
7144 int OpenRcmd(host, user, cmd, pr)
7145 char *host, *user, *cmd;
7148 DisplayFatalError(_("internal rcmd not implemented for Unix"), 0, 1);
7152 #define INPUT_SOURCE_BUF_SIZE 8192
7161 char buf[INPUT_SOURCE_BUF_SIZE];
7166 DoInputCallback(closure, source, xid)
7171 InputSource *is = (InputSource *) closure;
7176 if (is->lineByLine) {
7177 count = read(is->fd, is->unused,
7178 INPUT_SOURCE_BUF_SIZE - (is->unused - is->buf));
7180 (is->func)(is, is->closure, is->buf, count, count ? errno : 0);
7183 is->unused += count;
7185 while (p < is->unused) {
7186 q = memchr(p, '\n', is->unused - p);
7187 if (q == NULL) break;
7189 (is->func)(is, is->closure, p, q - p, 0);
7193 while (p < is->unused) {
7198 count = read(is->fd, is->buf, INPUT_SOURCE_BUF_SIZE);
7203 (is->func)(is, is->closure, is->buf, count, error);
7207 InputSourceRef AddInputSource(pr, lineByLine, func, closure)
7214 ChildProc *cp = (ChildProc *) pr;
7216 is = (InputSource *) calloc(1, sizeof(InputSource));
7217 is->lineByLine = lineByLine;
7221 is->fd = fileno(stdin);
7223 is->kind = cp->kind;
7224 is->fd = cp->fdFrom;
7227 is->unused = is->buf;
7230 is->xid = XtAppAddInput(appContext, is->fd,
7231 (XtPointer) (XtInputReadMask),
7232 (XtInputCallbackProc) DoInputCallback,
7234 is->closure = closure;
7235 return (InputSourceRef) is;
7239 RemoveInputSource(isr)
7242 InputSource *is = (InputSource *) isr;
7244 if (is->xid == 0) return;
7245 XtRemoveInput(is->xid);
7249 int OutputToProcess(pr, message, count, outError)
7255 ChildProc *cp = (ChildProc *) pr;
7259 outCount = fwrite(message, 1, count, stdout);
7261 outCount = write(cp->fdTo, message, count);
7271 /* Output message to process, with "ms" milliseconds of delay
7272 between each character. This is needed when sending the logon
7273 script to ICC, which for some reason doesn't like the
7274 instantaneous send. */
7275 int OutputToProcessDelayed(pr, message, count, outError, msdelay)
7282 ChildProc *cp = (ChildProc *) pr;
7287 r = write(cp->fdTo, message++, 1);
7300 /**** Animation code by Hugh Fisher, DCS, ANU.
7302 Known problem: if a window overlapping the board is
7303 moved away while a piece is being animated underneath,
7304 the newly exposed area won't be updated properly.
7305 I can live with this.
7307 Known problem: if you look carefully at the animation
7308 of pieces in mono mode, they are being drawn as solid
7309 shapes without interior detail while moving. Fixing
7310 this would be a major complication for minimal return.
7313 /* Masks for XPM pieces. Black and white pieces can have
7314 different shapes, but in the interest of retaining my
7315 sanity pieces must have the same outline on both light
7316 and dark squares, and all pieces must use the same
7317 background square colors/images. */
7319 static int xpmDone = 0;
7322 CreateAnimMasks (pieceDepth)
7329 unsigned long plane;
7332 /* just return for gtk at the moment */
7335 /* Need a bitmap just to get a GC with right depth */
7336 buf = XCreatePixmap(xDisplay, xBoardWindow,
7338 values.foreground = 1;
7339 values.background = 0;
7340 /* Don't use XtGetGC, not read only */
7341 maskGC = XCreateGC(xDisplay, buf,
7342 GCForeground | GCBackground, &values);
7343 XFreePixmap(xDisplay, buf);
7345 buf = XCreatePixmap(xDisplay, xBoardWindow,
7346 squareSize, squareSize, pieceDepth);
7347 values.foreground = XBlackPixel(xDisplay, xScreen);
7348 values.background = XWhitePixel(xDisplay, xScreen);
7349 bufGC = XCreateGC(xDisplay, buf,
7350 GCForeground | GCBackground, &values);
7352 for (piece = WhitePawn; piece <= BlackKing; piece++) {
7353 /* Begin with empty mask */
7354 if(!xpmDone) // [HGM] pieces: keep using existing
7355 xpmMask[piece] = XCreatePixmap(xDisplay, xBoardWindow,
7356 squareSize, squareSize, 1);
7357 XSetFunction(xDisplay, maskGC, GXclear);
7358 XFillRectangle(xDisplay, xpmMask[piece], maskGC,
7359 0, 0, squareSize, squareSize);
7361 /* Take a copy of the piece */
7366 XSetFunction(xDisplay, bufGC, GXcopy);
7367 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn],
7369 0, 0, squareSize, squareSize, 0, 0);
7371 /* XOR the background (light) over the piece */
7372 XSetFunction(xDisplay, bufGC, GXxor);
7374 XCopyArea(xDisplay, xpmLightSquare, buf, bufGC,
7375 0, 0, squareSize, squareSize, 0, 0);
7377 XSetForeground(xDisplay, bufGC, lightSquareColor);
7378 XFillRectangle(xDisplay, buf, bufGC, 0, 0, squareSize, squareSize);
7381 /* We now have an inverted piece image with the background
7382 erased. Construct mask by just selecting all the non-zero
7383 pixels - no need to reconstruct the original image. */
7384 XSetFunction(xDisplay, maskGC, GXor);
7386 /* Might be quicker to download an XImage and create bitmap
7387 data from it rather than this N copies per piece, but it
7388 only takes a fraction of a second and there is a much
7389 longer delay for loading the pieces. */
7390 for (n = 0; n < pieceDepth; n ++) {
7391 XCopyPlane(xDisplay, buf, xpmMask[piece], maskGC,
7392 0, 0, squareSize, squareSize,
7398 XFreePixmap(xDisplay, buf);
7399 XFreeGC(xDisplay, bufGC);
7400 XFreeGC(xDisplay, maskGC);
7404 InitAnimState (anim, info)
7406 XWindowAttributes * info;
7411 /* Each buffer is square size, same depth as window */
7412 // anim->saveBuf = XCreatePixmap(xDisplay, xBoardWindow,
7413 // squareSize, squareSize, info->depth);
7414 // anim->newBuf = XCreatePixmap(xDisplay, xBoardWindow,
7415 // squareSize, squareSize, info->depth);
7417 // /* Create a plain GC for blitting */
7418 // mask = GCForeground | GCBackground | GCFunction |
7419 // GCPlaneMask | GCGraphicsExposures;
7420 // values.foreground = XBlackPixel(xDisplay, xScreen);
7421 // values.background = XWhitePixel(xDisplay, xScreen);
7422 // values.function = GXcopy;
7423 // values.plane_mask = AllPlanes;
7424 // values.graphics_exposures = False;
7425 // anim->blitGC = XCreateGC(xDisplay, xBoardWindow, mask, &values);
7427 // /* Piece will be copied from an existing context at
7428 // the start of each new animation/drag. */
7429 // anim->pieceGC = XCreateGC(xDisplay, xBoardWindow, 0, &values);
7431 // /* Outline will be a read-only copy of an existing */
7432 // anim->outlineGC = None;
7438 static VariantClass old = (VariantClass) -1; // [HGM] pieces: redo every time variant changes
7439 XWindowAttributes info;
7441 /* for gtk at the moment just ... */
7444 if (xpmDone && gameInfo.variant == old) return;
7445 if(xpmDone) old = gameInfo.variant; // first time pieces might not be created yet
7446 // XGetWindowAttributes(xDisplay, xBoardWindow, &info);
7448 // InitAnimState(&game, &info);
7449 // InitAnimState(&player, &info);
7451 /* For XPM pieces, we need bitmaps to use as masks. */
7453 // CreateAnimMasks(info.depth);
7459 static Boolean frameWaiting;
7461 static RETSIGTYPE FrameAlarm (sig)
7464 frameWaiting = False;
7465 /* In case System-V style signals. Needed?? */
7466 signal(SIGALRM, FrameAlarm);
7473 struct itimerval delay;
7475 XSync(xDisplay, False);
7478 frameWaiting = True;
7479 signal(SIGALRM, FrameAlarm);
7480 delay.it_interval.tv_sec =
7481 delay.it_value.tv_sec = time / 1000;
7482 delay.it_interval.tv_usec =
7483 delay.it_value.tv_usec = (time % 1000) * 1000;
7484 setitimer(ITIMER_REAL, &delay, NULL);
7486 /* Ugh -- busy-wait! --tpm */
7487 while (frameWaiting);
7489 while (frameWaiting) pause();
7491 delay.it_interval.tv_sec = delay.it_value.tv_sec = 0;
7492 delay.it_interval.tv_usec = delay.it_value.tv_usec = 0;
7493 setitimer(ITIMER_REAL, &delay, NULL);
7503 // XSync(xDisplay, False);
7505 usleep(time * 1000);
7510 /* Convert board position to corner of screen rect and color */
7513 ScreenSquare(column, row, pt, color)
7514 int column; int row; XPoint * pt; int * color;
7517 pt->x = lineGap + ((BOARD_WIDTH-1)-column) * (squareSize + lineGap);
7518 pt->y = lineGap + row * (squareSize + lineGap);
7520 pt->x = lineGap + column * (squareSize + lineGap);
7521 pt->y = lineGap + ((BOARD_HEIGHT-1)-row) * (squareSize + lineGap);
7523 *color = SquareColor(row, column);
7526 /* Convert window coords to square */
7529 BoardSquare(x, y, column, row)
7530 int x; int y; int * column; int * row;
7532 *column = EventToSquare(x, BOARD_WIDTH);
7533 if (flipView && *column >= 0)
7534 *column = BOARD_WIDTH - 1 - *column;
7535 *row = EventToSquare(y, BOARD_HEIGHT);
7536 if (!flipView && *row >= 0)
7537 *row = BOARD_HEIGHT - 1 - *row;
7542 #undef Max /* just in case */
7544 #define Max(a, b) ((a) > (b) ? (a) : (b))
7545 #define Min(a, b) ((a) < (b) ? (a) : (b))
7548 SetRect(rect, x, y, width, height)
7549 XRectangle * rect; int x; int y; int width; int height;
7553 rect->width = width;
7554 rect->height = height;
7557 /* Test if two frames overlap. If they do, return
7558 intersection rect within old and location of
7559 that rect within new. */
7562 Intersect(old, new, size, area, pt)
7563 XPoint * old; XPoint * new;
7564 int size; XRectangle * area; XPoint * pt;
7566 if (old->x > new->x + size || new->x > old->x + size ||
7567 old->y > new->y + size || new->y > old->y + size) {
7570 SetRect(area, Max(new->x - old->x, 0), Max(new->y - old->y, 0),
7571 size - abs(old->x - new->x), size - abs(old->y - new->y));
7572 pt->x = Max(old->x - new->x, 0);
7573 pt->y = Max(old->y - new->y, 0);
7578 /* For two overlapping frames, return the rect(s)
7579 in the old that do not intersect with the new. */
7582 CalcUpdateRects(old, new, size, update, nUpdates)
7583 XPoint * old; XPoint * new; int size;
7584 XRectangle update[]; int * nUpdates;
7588 /* If old = new (shouldn't happen) then nothing to draw */
7589 if (old->x == new->x && old->y == new->y) {
7593 /* Work out what bits overlap. Since we know the rects
7594 are the same size we don't need a full intersect calc. */
7596 /* Top or bottom edge? */
7597 if (new->y > old->y) {
7598 SetRect(&(update[count]), old->x, old->y, size, new->y - old->y);
7600 } else if (old->y > new->y) {
7601 SetRect(&(update[count]), old->x, old->y + size - (old->y - new->y),
7602 size, old->y - new->y);
7605 /* Left or right edge - don't overlap any update calculated above. */
7606 if (new->x > old->x) {
7607 SetRect(&(update[count]), old->x, Max(new->y, old->y),
7608 new->x - old->x, size - abs(new->y - old->y));
7610 } else if (old->x > new->x) {
7611 SetRect(&(update[count]), new->x + size, Max(new->y, old->y),
7612 old->x - new->x, size - abs(new->y - old->y));
7619 /* Generate a series of frame coords from start->mid->finish.
7620 The movement rate doubles until the half way point is
7621 reached, then halves back down to the final destination,
7622 which gives a nice slow in/out effect. The algorithmn
7623 may seem to generate too many intermediates for short
7624 moves, but remember that the purpose is to attract the
7625 viewers attention to the piece about to be moved and
7626 then to where it ends up. Too few frames would be less
7630 Tween(start, mid, finish, factor, frames, nFrames)
7631 XPoint * start; XPoint * mid;
7632 XPoint * finish; int factor;
7633 XPoint frames[]; int * nFrames;
7635 int fraction, n, count;
7639 /* Slow in, stepping 1/16th, then 1/8th, ... */
7641 for (n = 0; n < factor; n++)
7643 for (n = 0; n < factor; n++) {
7644 frames[count].x = start->x + (mid->x - start->x) / fraction;
7645 frames[count].y = start->y + (mid->y - start->y) / fraction;
7647 fraction = fraction / 2;
7651 frames[count] = *mid;
7654 /* Slow out, stepping 1/2, then 1/4, ... */
7656 for (n = 0; n < factor; n++) {
7657 frames[count].x = finish->x - (finish->x - mid->x) / fraction;
7658 frames[count].y = finish->y - (finish->y - mid->y) / fraction;
7660 fraction = fraction * 2;
7665 /* Draw a piece on the screen without disturbing what's there */
7668 SelectGCMask(piece, clip, outline, mask)
7669 ChessSquare piece; GC * clip; GC * outline; Pixmap * mask;
7673 /* Bitmap for piece being moved. */
7674 if (appData.monoMode) {
7675 *mask = *pieceToSolid(piece);
7676 } else if (useImages) {
7678 *mask = xpmMask[piece];
7680 *mask = ximMaskPm[piece];
7683 *mask = *pieceToSolid(piece);
7686 /* GC for piece being moved. Square color doesn't matter, but
7687 since it gets modified we make a copy of the original. */
7689 if (appData.monoMode)
7694 if (appData.monoMode)
7699 // XCopyGC(xDisplay, source, 0xFFFFFFFF, *clip);
7701 /* Outline only used in mono mode and is not modified */
7703 *outline = bwPieceGC;
7705 *outline = wbPieceGC;
7709 OverlayPiece(piece, clip, outline, dest)
7710 ChessSquare piece; GC clip; GC outline; Drawable dest;
7715 /* Draw solid rectangle which will be clipped to shape of piece */
7716 // XFillRectangle(xDisplay, dest, clip,
7717 // 0, 0, squareSize, squareSize)
7719 if (appData.monoMode)
7720 /* Also draw outline in contrasting color for black
7721 on black / white on white cases */
7722 // XCopyPlane(xDisplay, *pieceToOutline(piece), dest, outline,
7723 // 0, 0, squareSize, squareSize, 0, 0, 1)
7726 /* Copy the piece */
7731 // XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
7733 // 0, 0, squareSize, squareSize,
7738 /* Animate the movement of a single piece */
7741 BeginAnimation(anim, piece, startColor, start)
7749 /* The old buffer is initialised with the start square (empty) */
7750 BlankSquare(0, 0, startColor, EmptySquare, anim->saveBuf);
7751 anim->prevFrame = *start;
7753 /* The piece will be drawn using its own bitmap as a matte */
7754 // SelectGCMask(piece, &anim->pieceGC, &anim->outlineGC, &mask);
7755 // XSetClipMask(xDisplay, anim->pieceGC, mask);
7759 AnimationFrame(anim, frame, piece)
7764 XRectangle updates[4];
7769 /* Save what we are about to draw into the new buffer */
7770 // XCopyArea(xDisplay, xBoardWindow, anim->newBuf, anim->blitGC,
7771 // frame->x, frame->y, squareSize, squareSize,
7774 /* Erase bits of the previous frame */
7775 if (Intersect(&anim->prevFrame, frame, squareSize, &overlap, &pt)) {
7776 /* Where the new frame overlapped the previous,
7777 the contents in newBuf are wrong. */
7778 // XCopyArea(xDisplay, anim->saveBuf, anim->newBuf, anim->blitGC,
7779 // overlap.x, overlap.y,
7780 // overlap.width, overlap.height,
7782 /* Repaint the areas in the old that don't overlap new */
7783 CalcUpdateRects(&anim->prevFrame, frame, squareSize, updates, &count);
7784 for (i = 0; i < count; i++)
7785 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
7786 // updates[i].x - anim->prevFrame.x,
7787 // updates[i].y - anim->prevFrame.y,
7788 // updates[i].width, updates[i].height,
7789 // updates[i].x, updates[i].y)
7792 /* Easy when no overlap */
7793 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
7794 // 0, 0, squareSize, squareSize,
7795 // anim->prevFrame.x, anim->prevFrame.y);
7798 /* Save this frame for next time round */
7799 // XCopyArea(xDisplay, anim->newBuf, anim->saveBuf, anim->blitGC,
7800 // 0, 0, squareSize, squareSize,
7802 anim->prevFrame = *frame;
7804 /* Draw piece over original screen contents, not current,
7805 and copy entire rect. Wipes out overlapping piece images. */
7806 OverlayPiece(piece, anim->pieceGC, anim->outlineGC, anim->newBuf);
7807 // XCopyArea(xDisplay, anim->newBuf, xBoardWindow, anim->blitGC,
7808 // 0, 0, squareSize, squareSize,
7809 // frame->x, frame->y);
7813 EndAnimation (anim, finish)
7817 XRectangle updates[4];
7822 /* The main code will redraw the final square, so we
7823 only need to erase the bits that don't overlap. */
7824 if (Intersect(&anim->prevFrame, finish, squareSize, &overlap, &pt)) {
7825 CalcUpdateRects(&anim->prevFrame, finish, squareSize, updates, &count);
7826 for (i = 0; i < count; i++)
7827 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
7828 // updates[i].x - anim->prevFrame.x,
7829 // updates[i].y - anim->prevFrame.y,
7830 // updates[i].width, updates[i].height,
7831 // updates[i].x, updates[i].y)
7834 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
7835 // 0, 0, squareSize, squareSize,
7836 // anim->prevFrame.x, anim->prevFrame.y);
7841 FrameSequence(anim, piece, startColor, start, finish, frames, nFrames)
7843 ChessSquare piece; int startColor;
7844 XPoint * start; XPoint * finish;
7845 XPoint frames[]; int nFrames;
7849 BeginAnimation(anim, piece, startColor, start);
7850 for (n = 0; n < nFrames; n++) {
7851 AnimationFrame(anim, &(frames[n]), piece);
7852 FrameDelay(appData.animSpeed);
7854 EndAnimation(anim, finish);
7857 /* Main control logic for deciding what to animate and how */
7860 AnimateMove(board, fromX, fromY, toX, toY)
7869 XPoint start, finish, mid;
7870 XPoint frames[kFactor * 2 + 1];
7871 int nFrames, startColor, endColor;
7873 /* Are we animating? */
7874 if (!appData.animate || appData.blindfold)
7877 if(board[toY][toX] == WhiteRook && board[fromY][fromX] == WhiteKing ||
7878 board[toY][toX] == BlackRook && board[fromY][fromX] == BlackKing)
7879 return; // [HGM] FRC: no animtion of FRC castlings, as to-square is not true to-square
7881 if (fromY < 0 || fromX < 0 || toX < 0 || toY < 0) return;
7882 piece = board[fromY][fromX];
7883 if (piece >= EmptySquare) return;
7888 hop = (piece == WhiteKnight || piece == BlackKnight);
7891 if (appData.debugMode) {
7892 fprintf(debugFP, hop ? _("AnimateMove: piece %d hops from %d,%d to %d,%d \n") :
7893 _("AnimateMove: piece %d slides from %d,%d to %d,%d \n"),
7894 piece, fromX, fromY, toX, toY); }
7896 ScreenSquare(fromX, fromY, &start, &startColor);
7897 ScreenSquare(toX, toY, &finish, &endColor);
7900 /* Knight: make diagonal movement then straight */
7901 if (abs(toY - fromY) < abs(toX - fromX)) {
7902 mid.x = start.x + (finish.x - start.x) / 2;
7906 mid.y = start.y + (finish.y - start.y) / 2;
7909 mid.x = start.x + (finish.x - start.x) / 2;
7910 mid.y = start.y + (finish.y - start.y) / 2;
7913 /* Don't use as many frames for very short moves */
7914 if (abs(toY - fromY) + abs(toX - fromX) <= 2)
7915 Tween(&start, &mid, &finish, kFactor - 1, frames, &nFrames);
7917 Tween(&start, &mid, &finish, kFactor, frames, &nFrames);
7918 FrameSequence(&game, piece, startColor, &start, &finish, frames, nFrames);
7920 /* Be sure end square is redrawn */
7921 damage[toY][toX] = True;
7925 DragPieceBegin(x, y)
7928 int boardX, boardY, color;
7931 /* Are we animating? */
7932 if (!appData.animateDragging || appData.blindfold)
7935 /* Figure out which square we start in and the
7936 mouse position relative to top left corner. */
7937 BoardSquare(x, y, &boardX, &boardY);
7938 player.startBoardX = boardX;
7939 player.startBoardY = boardY;
7940 ScreenSquare(boardX, boardY, &corner, &color);
7941 player.startSquare = corner;
7942 player.startColor = color;
7944 /* Start from exactly where the piece is. This can be confusing
7945 if you start dragging far from the center of the square; most
7946 or all of the piece can be over a different square from the one
7947 the mouse pointer is in. */
7948 player.mouseDelta.x = x - corner.x;
7949 player.mouseDelta.y = y - corner.y;
7951 /* As soon as we start dragging, the piece will jump slightly to
7952 be centered over the mouse pointer. */
7953 player.mouseDelta.x = squareSize/2;
7954 player.mouseDelta.y = squareSize/2;
7956 /* Initialise animation */
7957 player.dragPiece = PieceForSquare(boardX, boardY);
7959 if (player.dragPiece >= 0 && player.dragPiece < EmptySquare) {
7960 player.dragActive = True;
7961 BeginAnimation(&player, player.dragPiece, color, &corner);
7962 /* Mark this square as needing to be redrawn. Note that
7963 we don't remove the piece though, since logically (ie
7964 as seen by opponent) the move hasn't been made yet. */
7965 if(boardX == BOARD_RGHT+1 && PieceForSquare(boardX-1, boardY) > 1 ||
7966 boardX == BOARD_LEFT-2 && PieceForSquare(boardX+1, boardY) > 1)
7967 // XCopyArea(xDisplay, xBoardWindow, player.saveBuf, player.blitGC,
7968 // corner.x, corner.y, squareSize, squareSize,
7969 // 0, 0); // [HGM] zh: unstack in stead of grab
7970 damage[boardY][boardX] = True;
7972 player.dragActive = False;
7982 /* Are we animating? */
7983 if (!appData.animateDragging || appData.blindfold)
7987 if (! player.dragActive)
7989 /* Move piece, maintaining same relative position
7990 of mouse within square */
7991 corner.x = x - player.mouseDelta.x;
7992 corner.y = y - player.mouseDelta.y;
7993 AnimationFrame(&player, &corner, player.dragPiece);
7995 if (appData.highlightDragging) {
7997 BoardSquare(x, y, &boardX, &boardY);
7998 SetHighlights(fromX, fromY, boardX, boardY);
8007 int boardX, boardY, color;
8010 /* Are we animating? */
8011 if (!appData.animateDragging || appData.blindfold)
8015 if (! player.dragActive)
8017 /* Last frame in sequence is square piece is
8018 placed on, which may not match mouse exactly. */
8019 BoardSquare(x, y, &boardX, &boardY);
8020 ScreenSquare(boardX, boardY, &corner, &color);
8021 EndAnimation(&player, &corner);
8023 /* Be sure end square is redrawn */
8024 damage[boardY][boardX] = True;
8026 /* This prevents weird things happening with fast successive
8027 clicks which on my Sun at least can cause motion events
8028 without corresponding press/release. */
8029 player.dragActive = False;
8032 /* Handle expose event while piece being dragged */
8037 if (!player.dragActive || appData.blindfold)
8040 /* What we're doing: logically, the move hasn't been made yet,
8041 so the piece is still in it's original square. But visually
8042 it's being dragged around the board. So we erase the square
8043 that the piece is on and draw it at the last known drag point. */
8044 BlankSquare(player.startSquare.x, player.startSquare.y,
8045 player.startColor, EmptySquare, xBoardWindow);
8046 AnimationFrame(&player, &player.prevFrame, player.dragPiece);
8047 damage[player.startBoardY][player.startBoardX] = TRUE;
8051 SetProgramStats( FrontEndProgramStats * stats )
8054 // [HGM] done, but perhaps backend should call this directly?
8055 EngineOutputUpdate( stats );