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 IcsClientProc P((Widget w, XEvent *event, String *prms,
322 void EditGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
323 void EditPositionProc P((Widget w, XEvent *event,
324 String *prms, Cardinal *nprms));
325 void TrainingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
326 void EditCommentProc P((Widget w, XEvent *event,
327 String *prms, Cardinal *nprms));
328 void IcsInputBoxProc P((Widget w, XEvent *event,
329 String *prms, Cardinal *nprms));
330 void EnterKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
331 void BackwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
332 void ForwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
333 void ToStartProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
334 void ToEndProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
335 void RevertProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
336 void TruncateGameProc P((Widget w, XEvent *event, String *prms,
338 void RetractMoveProc P((Widget w, XEvent *event, String *prms,
340 void AlwaysQueenProc P((Widget w, XEvent *event, String *prms,
342 void AnimateDraggingProc P((Widget w, XEvent *event, String *prms,
344 void AnimateMovingProc P((Widget w, XEvent *event, String *prms,
346 void AutocommProc P((Widget w, XEvent *event, String *prms,
348 void AutoflagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
349 void AutoflipProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
350 void AutobsProc P((Widget w, XEvent *event, String *prms,
352 void AutoraiseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
353 void AutosaveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
354 void BlindfoldProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
355 void FlashMovesProc P((Widget w, XEvent *event, String *prms,
357 void FlipViewProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
358 void GetMoveListProc P((Widget w, XEvent *event, String *prms,
360 void HighlightDraggingProc P((Widget w, XEvent *event, String *prms,
362 void HighlightLastMoveProc P((Widget w, XEvent *event, String *prms,
364 void MoveSoundProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
365 void IcsAlarmProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
366 void OldSaveStyleProc P((Widget w, XEvent *event, String *prms,
368 void PeriodicUpdatesProc P((Widget w, XEvent *event, String *prms,
370 void PonderNextMoveProc P((Widget w, XEvent *event, String *prms,
372 void PopupMoveErrorsProc P((Widget w, XEvent *event, String *prms,
374 void PopupExitMessageProc P((Widget w, XEvent *event, String *prms,
376 void PremoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
377 void QuietPlayProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
378 void ShowThinkingProc P((Widget w, XEvent *event, String *prms,
380 void HideThinkingProc P((Widget w, XEvent *event, String *prms,
382 void TestLegalityProc P((Widget w, XEvent *event, String *prms,
384 void InfoProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
385 void ManProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
386 void HintProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
387 void BookProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
388 void AboutGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
389 void DebugProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
390 void NothingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
391 void Iconify P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
392 void DisplayMove P((int moveNumber));
393 void DisplayTitle P((char *title));
394 void ICSInitScript P((void));
395 int LoadGamePopUp P((FILE *f, int gameNumber, char *title));
396 void ErrorPopUp P((char *title, char *text, int modal));
397 void ErrorPopDown P((void));
398 static char *ExpandPathName P((char *path));
399 static void CreateAnimVars P((void));
400 void DragPieceBegin P((int x, int y));
401 static void DragPieceMove P((int x, int y));
402 void DragPieceEnd P((int x, int y));
403 static void DrawDragPiece P((void));
404 char *ModeToWidgetName P((GameMode mode));
405 void EngineOutputUpdate( FrontEndProgramStats * stats );
406 void ShuffleMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
407 void EngineMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
408 void UciMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
409 void TimeControlProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
410 void NewVariantProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
411 void FirstSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
412 void SecondSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
413 void ShufflePopDown P(());
414 void EnginePopDown P(());
415 void UciPopDown P(());
416 void TimeControlPopDown P(());
417 void NewVariantPopDown P(());
418 void SettingsPopDown P(());
419 void SetMenuEnables P((Enables *enab));
422 * XBoard depends on Xt R4 or higher
424 int xtVersion = XtSpecificationRelease;
429 Pixel lightSquareColor, darkSquareColor, whitePieceColor, blackPieceColor,
430 jailSquareColor, highlightSquareColor, premoveHighlightColor;
431 Pixel lowTimeWarningColor;
433 #define LINE_TYPE_NORMAL 0
434 #define LINE_TYPE_HIGHLIGHT 1
435 #define LINE_TYPE_PRE 2
438 GC lightSquareGC, darkSquareGC, jailSquareGC, wdPieceGC, wlPieceGC,
439 bdPieceGC, blPieceGC, wbPieceGC, bwPieceGC, coordGC,
440 wjPieceGC, bjPieceGC;
441 Pixmap iconPixmap, wIconPixmap, bIconPixmap, xMarkPixmap;
442 Widget shellWidget, layoutWidget, formWidget, boardWidget, messageWidget,
443 whiteTimerWidget, blackTimerWidget, titleWidget, widgetList[16],
444 commentShell, promotionShell, whitePieceMenu, blackPieceMenu, dropMenu,
445 menuBarWidget, buttonBarWidget, editShell, errorShell, analysisShell,
446 ICSInputShell, fileNameShell, askQuestionShell;
447 Font clockFontID, coordFontID, countFontID;
448 XFontStruct *clockFontStruct, *coordFontStruct, *countFontStruct;
449 XtAppContext appContext;
451 char *oldICSInteractionTitle;
455 char installDir[] = "."; // [HGM] UCI: needed for UCI; probably needs run-time initializtion
457 Position commentX = -1, commentY = -1;
458 Dimension commentW, commentH;
460 int squareSize, smallLayout = 0, tinyLayout = 0,
461 marginW, marginH, // [HGM] for run-time resizing
462 fromX = -1, fromY = -1, toX, toY, commentUp = False, analysisUp = False,
463 ICSInputBoxUp = False, askQuestionUp = False,
464 filenameUp = False, promotionUp = False, pmFromX = -1, pmFromY = -1,
465 editUp = False, errorUp = False, errorExitStatus = -1, lineGap;
466 Pixel timerForegroundPixel, timerBackgroundPixel;
467 Pixel buttonForegroundPixel, buttonBackgroundPixel;
468 char *chessDir, *programName, *programVersion,
469 *gameCopyFilename, *gamePasteFilename;
473 Pixmap pieceBitmap[2][(int)BlackPawn];
474 Pixmap pieceBitmap2[2][(int)BlackPawn+4]; /* [HGM] pieces */
475 Pixmap xpmPieceBitmap[4][(int)BlackPawn]; /* LL, LD, DL, DD actually used*/
476 Pixmap xpmPieceBitmap2[4][(int)BlackPawn+4]; /* LL, LD, DL, DD set to select from */
477 Pixmap xpmLightSquare, xpmDarkSquare, xpmJailSquare;
478 int useImages=0, useImageSqs;
479 XImage *ximPieceBitmap[4][(int)BlackPawn+4]; /* LL, LD, DL, DD */
480 Pixmap ximMaskPm[(int)BlackPawn]; /* clipmasks, used for XIM pieces */
481 Pixmap ximMaskPm2[(int)BlackPawn+4]; /* clipmasks, used for XIM pieces */
482 XImage *ximLightSquare, *ximDarkSquare;
485 #define pieceToSolid(piece) &pieceBitmap[SOLID][(piece) % (int)BlackPawn]
486 #define pieceToOutline(piece) &pieceBitmap[OUTLINE][(piece) % (int)BlackPawn]
488 #define White(piece) ((int)(piece) < (int)BlackPawn)
490 /* Variables for doing smooth animation. This whole thing
491 would be much easier if the board was double-buffered,
492 but that would require a fairly major rewrite. */
497 GC blitGC, pieceGC, outlineGC;
498 XPoint startSquare, prevFrame, mouseDelta;
502 int startBoardX, startBoardY;
505 /* There can be two pieces being animated at once: a player
506 can begin dragging a piece before the remote opponent has moved. */
508 static AnimState game, player;
510 /* Bitmaps for use as masks when drawing XPM pieces.
511 Need one for each black and white piece. */
512 static Pixmap xpmMask[BlackKing + 1];
514 /* This magic number is the number of intermediate frames used
515 in each half of the animation. For short moves it's reduced
516 by 1. The total number of frames will be factor * 2 + 1. */
519 SizeDefaults sizeDefaults[] = SIZE_DEFAULTS;
521 Enables icsEnables[] = {
522 { "menuFile.Mail Move", False },
523 { "menuFile.Reload CMail Message", False },
524 { "menuMode.Machine Black", False },
525 { "menuMode.Machine White", False },
526 { "menuMode.Analysis Mode", False },
527 { "menuMode.Analyze File", False },
528 { "menuMode.Two Machines", False },
530 { "menuHelp.Hint", False },
531 { "menuHelp.Book", False },
532 { "menuStep.Move Now", False },
533 { "menuOptions.Periodic Updates", False },
534 { "menuOptions.Hide Thinking", False },
535 { "menuOptions.Ponder Next Move", False },
540 Enables ncpEnables[] = {
541 { "menuFile.Mail Move", False },
542 { "menuFile.Reload CMail Message", False },
543 { "menuMode.Machine White", False },
544 { "menuMode.Machine Black", False },
545 { "menuMode.Analysis Mode", False },
546 { "menuMode.Analyze File", False },
547 { "menuMode.Two Machines", False },
548 { "menuMode.ICS Client", False },
549 { "menuMode.ICS Input Box", False },
551 { "menuStep.Revert", False },
552 { "menuStep.Move Now", False },
553 { "menuStep.Retract Move", False },
554 { "menuOptions.Auto Comment", False },
555 { "menuOptions.Auto Flag", False },
556 { "menuOptions.Auto Flip View", False },
557 { "menuOptions.Auto Observe", False },
558 { "menuOptions.Auto Raise Board", False },
559 { "menuOptions.Get Move List", False },
560 { "menuOptions.ICS Alarm", False },
561 { "menuOptions.Move Sound", False },
562 { "menuOptions.Quiet Play", False },
563 { "menuOptions.Hide Thinking", False },
564 { "menuOptions.Periodic Updates", False },
565 { "menuOptions.Ponder Next Move", False },
566 { "menuHelp.Hint", False },
567 { "menuHelp.Book", False },
571 Enables gnuEnables[] = {
572 { "menuMode.ICS Client", False },
573 { "menuMode.ICS Input Box", False },
574 { "menuAction.Accept", False },
575 { "menuAction.Decline", False },
576 { "menuAction.Rematch", False },
577 { "menuAction.Adjourn", False },
578 { "menuAction.Stop Examining", False },
579 { "menuAction.Stop Observing", False },
580 { "menuStep.Revert", False },
581 { "menuOptions.Auto Comment", False },
582 { "menuOptions.Auto Observe", False },
583 { "menuOptions.Auto Raise Board", False },
584 { "menuOptions.Get Move List", False },
585 { "menuOptions.Premove", False },
586 { "menuOptions.Quiet Play", False },
588 /* The next two options rely on SetCmailMode being called *after* */
589 /* SetGNUMode so that when GNU is being used to give hints these */
590 /* menu options are still available */
592 { "menuFile.Mail Move", False },
593 { "menuFile.Reload CMail Message", False },
597 Enables cmailEnables[] = {
599 { "menuAction.Call Flag", False },
600 { "menuAction.Draw", True },
601 { "menuAction.Adjourn", False },
602 { "menuAction.Abort", False },
603 { "menuAction.Stop Observing", False },
604 { "menuAction.Stop Examining", False },
605 { "menuFile.Mail Move", True },
606 { "menuFile.Reload CMail Message", True },
610 Enables trainingOnEnables[] = {
611 { "menuMode.Edit Comment", False },
612 { "menuMode.Pause", False },
613 { "menuStep.Forward", False },
614 { "menuStep.Backward", False },
615 { "menuStep.Forward to End", False },
616 { "menuStep.Back to Start", False },
617 { "menuStep.Move Now", False },
618 { "menuStep.Truncate Game", False },
622 Enables trainingOffEnables[] = {
623 { "menuMode.Edit Comment", True },
624 { "menuMode.Pause", True },
625 { "menuStep.Forward", True },
626 { "menuStep.Backward", True },
627 { "menuStep.Forward to End", True },
628 { "menuStep.Back to Start", True },
629 { "menuStep.Move Now", True },
630 { "menuStep.Truncate Game", True },
634 Enables machineThinkingEnables[] = {
635 { "menuFile.Load Game", False },
636 { "menuFile.Load Next Game", False },
637 { "menuFile.Load Previous Game", False },
638 { "menuFile.Reload Same Game", False },
639 { "menuFile.Paste Game", False },
640 { "menuFile.Load Position", False },
641 { "menuFile.Load Next Position", False },
642 { "menuFile.Load Previous Position", False },
643 { "menuFile.Reload Same Position", False },
644 { "menuFile.Paste Position", False },
645 { "menuMode.Machine White", False },
646 { "menuMode.Machine Black", False },
647 { "menuMode.Two Machines", False },
648 { "menuStep.Retract Move", False },
652 Enables userThinkingEnables[] = {
653 { "menuFile.Load Game", True },
654 { "menuFile.Load Next Game", True },
655 { "menuFile.Load Previous Game", True },
656 { "menuFile.Reload Same Game", True },
657 { "menuFile.Paste Game", True },
658 { "menuFile.Load Position", True },
659 { "menuFile.Load Next Position", True },
660 { "menuFile.Load Previous Position", True },
661 { "menuFile.Reload Same Position", True },
662 { "menuFile.Paste Position", True },
663 { "menuMode.Machine White", True },
664 { "menuMode.Machine Black", True },
665 { "menuMode.Two Machines", True },
666 { "menuStep.Retract Move", True },
672 MenuItem fileMenu[] = {
673 {N_("New Shuffle Game ..."), ShuffleMenuProc},
674 {N_("New Variant ..."), NewVariantProc}, // [HGM] variant: not functional yet
675 {"----", NothingProc},
676 {N_("Save Game"), SaveGameProc},
677 {"----", NothingProc},
678 {N_("Copy Game"), CopyGameProc},
679 {N_("Paste Game"), PasteGameProc},
680 {"----", NothingProc},
681 {N_("Load Position"), LoadPositionProc},
682 {N_("Load Next Position"), LoadNextPositionProc},
683 {N_("Load Previous Position"), LoadPrevPositionProc},
684 {N_("Reload Same Position"), ReloadPositionProc},
685 {N_("Save Position"), SavePositionProc},
686 {"----", NothingProc},
687 {N_("Copy Position"), CopyPositionProc},
688 {N_("Paste Position"), PastePositionProc},
689 {"----", NothingProc},
690 {N_("Mail Move"), MailMoveProc},
691 {N_("Reload CMail Message"), ReloadCmailMsgProc},
692 {"----", NothingProc},
696 MenuItem modeMenu[] = {
697 // {N_("Machine White"), MachineWhiteProc},
698 // {N_("Machine Black"), MachineBlackProc},
699 // {N_("Two Machines"), TwoMachinesProc},
700 {N_("Analysis Mode"), AnalyzeModeProc},
701 {N_("Analyze File"), AnalyzeFileProc },
702 {N_("ICS Client"), IcsClientProc},
703 {N_("Edit Game"), EditGameProc},
704 {N_("Edit Position"), EditPositionProc},
705 {N_("Training"), TrainingProc},
706 {"----", NothingProc},
707 {N_("Show Engine Output"), EngineOutputProc},
708 {N_("Show Evaluation Graph"), NothingProc}, // [HGM] evalgr: not functional yet
709 {N_("Show Game List"), ShowGameListProc},
710 {"Show Move History", HistoryShowProc}, // [HGM] hist: activate 4.2.7 code
711 {"----", NothingProc},
712 {N_("Edit Tags"), EditTagsProc},
713 {N_("Edit Comment"), EditCommentProc},
714 {N_("ICS Input Box"), IcsInputBoxProc},
718 MenuItem stepMenu[] = {
719 {N_("Backward"), BackwardProc},
720 {N_("Forward"), ForwardProc},
721 {N_("Back to Start"), ToStartProc},
722 {N_("Forward to End"), ToEndProc},
723 {N_("Revert"), RevertProc},
724 {N_("Truncate Game"), TruncateGameProc},
725 {"----", NothingProc},
726 // {N_("Move Now"), MoveNowProc},
727 {N_("Retract Move"), RetractMoveProc},
731 MenuItem optionsMenu[] = {
732 {N_("Flip View"), FlipViewProc},
733 {"----", NothingProc},
734 {N_("Adjudications ..."), EngineMenuProc},
735 {N_("General Settings ..."), UciMenuProc},
736 {N_("Engine #1 Settings ..."), FirstSettingsProc},
737 {N_("Engine #2 Settings ..."), SecondSettingsProc},
738 {N_("Time Control ..."), TimeControlProc},
739 {"----", NothingProc},
740 {N_("Always Queen"), AlwaysQueenProc},
741 {N_("Animate Dragging"), AnimateDraggingProc},
742 {N_("Animate Moving"), AnimateMovingProc},
743 {N_("Auto Comment"), AutocommProc},
744 {N_("Auto Flag"), AutoflagProc},
745 {N_("Auto Flip View"), AutoflipProc},
746 {N_("Auto Observe"), AutobsProc},
747 {N_("Auto Raise Board"), AutoraiseProc},
748 {N_("Auto Save"), AutosaveProc},
749 {N_("Blindfold"), BlindfoldProc},
750 {N_("Flash Moves"), FlashMovesProc},
751 {N_("Get Move List"), GetMoveListProc},
753 {N_("Highlight Dragging"), HighlightDraggingProc},
755 {N_("Highlight Last Move"), HighlightLastMoveProc},
756 {N_("Move Sound"), MoveSoundProc},
757 {N_("ICS Alarm"), IcsAlarmProc},
758 {N_("Old Save Style"), OldSaveStyleProc},
759 {N_("Periodic Updates"), PeriodicUpdatesProc},
760 {N_("Ponder Next Move"), PonderNextMoveProc},
761 {N_("Popup Exit Message"), PopupExitMessageProc},
762 {N_("Popup Move Errors"), PopupMoveErrorsProc},
763 {N_("Premove"), PremoveProc},
764 {N_("Quiet Play"), QuietPlayProc},
765 {N_("Hide Thinking"), HideThinkingProc},
766 {N_("Test Legality"), TestLegalityProc},
770 MenuItem helpMenu[] = {
771 {N_("Info XBoard"), InfoProc},
772 {N_("Man XBoard"), ManProc},
773 {"----", NothingProc},
774 {N_("Hint"), HintProc},
775 {N_("Book"), BookProc},
776 {"----", NothingProc},
781 {N_("File"), fileMenu},
782 {N_("Mode"), modeMenu},
783 {N_("Step"), stepMenu},
784 {N_("Options"), optionsMenu},
785 {N_("Help"), helpMenu},
789 #define PAUSE_BUTTON N_("P")
790 MenuItem buttonBar[] = {
793 // {PAUSE_BUTTON, PauseProc},
799 #define PIECE_MENU_SIZE 18
800 String pieceMenuStrings[2][PIECE_MENU_SIZE] = {
801 { N_("White"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
802 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
803 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
804 N_("Empty square"), N_("Clear board") },
805 { N_("Black"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
806 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
807 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
808 N_("Empty square"), N_("Clear board") }
810 /* must be in same order as PieceMenuStrings! */
811 ChessSquare pieceMenuTranslation[2][PIECE_MENU_SIZE] = {
812 { WhitePlay, (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
813 WhiteRook, WhiteQueen, WhiteKing, (ChessSquare) 0, WhiteAlfil,
814 WhiteCannon, WhiteAngel, WhiteMarshall, (ChessSquare) 0,
815 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
816 { BlackPlay, (ChessSquare) 0, BlackPawn, BlackKnight, BlackBishop,
817 BlackRook, BlackQueen, BlackKing, (ChessSquare) 0, BlackAlfil,
818 BlackCannon, BlackAngel, BlackMarshall, (ChessSquare) 0,
819 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
822 #define DROP_MENU_SIZE 6
823 String dropMenuStrings[DROP_MENU_SIZE] = {
824 "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"), N_("Queen")
826 /* must be in same order as PieceMenuStrings! */
827 ChessSquare dropMenuTranslation[DROP_MENU_SIZE] = {
828 (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
829 WhiteRook, WhiteQueen
837 DropMenuEnables dmEnables[] = {
846 { XtNborderWidth, 0 },
847 { XtNdefaultDistance, 0 },
851 { XtNborderWidth, 0 },
852 { XtNresizable, (XtArgVal) True },
856 { XtNborderWidth, 0 },
861 XtResource clientResources[] = {
862 { "whitePieceColor", "whitePieceColor", XtRString, sizeof(String),
863 XtOffset(AppDataPtr, whitePieceColor), XtRString,
865 { "blackPieceColor", "blackPieceColor", XtRString, sizeof(String),
866 XtOffset(AppDataPtr, blackPieceColor), XtRString,
868 { "lightSquareColor", "lightSquareColor", XtRString,
869 sizeof(String), XtOffset(AppDataPtr, lightSquareColor),
870 XtRString, LIGHT_SQUARE_COLOR },
871 { "darkSquareColor", "darkSquareColor", XtRString, sizeof(String),
872 XtOffset(AppDataPtr, darkSquareColor), XtRString,
874 { "highlightSquareColor", "highlightSquareColor", XtRString,
875 sizeof(String), XtOffset(AppDataPtr, highlightSquareColor),
876 XtRString, HIGHLIGHT_SQUARE_COLOR },
877 { "premoveHighlightColor", "premoveHighlightColor", XtRString,
878 sizeof(String), XtOffset(AppDataPtr, premoveHighlightColor),
879 XtRString, PREMOVE_HIGHLIGHT_COLOR },
880 { "movesPerSession", "movesPerSession", XtRInt, sizeof(int),
881 XtOffset(AppDataPtr, movesPerSession), XtRImmediate,
882 (XtPointer) MOVES_PER_SESSION },
883 { "timeIncrement", "timeIncrement", XtRInt, sizeof(int),
884 XtOffset(AppDataPtr, timeIncrement), XtRImmediate,
885 (XtPointer) TIME_INCREMENT },
886 { "initString", "initString", XtRString, sizeof(String),
887 XtOffset(AppDataPtr, initString), XtRString, INIT_STRING },
888 { "secondInitString", "secondInitString", XtRString, sizeof(String),
889 XtOffset(AppDataPtr, secondInitString), XtRString, INIT_STRING },
890 { "firstComputerString", "firstComputerString", XtRString,
891 sizeof(String), XtOffset(AppDataPtr, firstComputerString), XtRString,
893 { "secondComputerString", "secondComputerString", XtRString,
894 sizeof(String), XtOffset(AppDataPtr, secondComputerString), XtRString,
896 { "firstChessProgram", "firstChessProgram", XtRString,
897 sizeof(String), XtOffset(AppDataPtr, firstChessProgram),
898 XtRString, FIRST_CHESS_PROGRAM },
899 { "secondChessProgram", "secondChessProgram", XtRString,
900 sizeof(String), XtOffset(AppDataPtr, secondChessProgram),
901 XtRString, SECOND_CHESS_PROGRAM },
902 { "firstPlaysBlack", "firstPlaysBlack", XtRBoolean,
903 sizeof(Boolean), XtOffset(AppDataPtr, firstPlaysBlack),
904 XtRImmediate, (XtPointer) False },
905 { "noChessProgram", "noChessProgram", XtRBoolean,
906 sizeof(Boolean), XtOffset(AppDataPtr, noChessProgram),
907 XtRImmediate, (XtPointer) False },
908 { "firstHost", "firstHost", XtRString, sizeof(String),
909 XtOffset(AppDataPtr, firstHost), XtRString, FIRST_HOST },
910 { "secondHost", "secondHost", XtRString, sizeof(String),
911 XtOffset(AppDataPtr, secondHost), XtRString, SECOND_HOST },
912 { "firstDirectory", "firstDirectory", XtRString, sizeof(String),
913 XtOffset(AppDataPtr, firstDirectory), XtRString, "." },
914 { "secondDirectory", "secondDirectory", XtRString, sizeof(String),
915 XtOffset(AppDataPtr, secondDirectory), XtRString, "." },
916 { "bitmapDirectory", "bitmapDirectory", XtRString,
917 sizeof(String), XtOffset(AppDataPtr, bitmapDirectory),
919 { "remoteShell", "remoteShell", XtRString, sizeof(String),
920 XtOffset(AppDataPtr, remoteShell), XtRString, REMOTE_SHELL },
921 { "remoteUser", "remoteUser", XtRString, sizeof(String),
922 XtOffset(AppDataPtr, remoteUser), XtRString, "" },
923 { "timeDelay", "timeDelay", XtRFloat, sizeof(float),
924 XtOffset(AppDataPtr, timeDelay), XtRString,
925 (XtPointer) TIME_DELAY_QUOTE },
926 { "timeControl", "timeControl", XtRString, sizeof(String),
927 XtOffset(AppDataPtr, timeControl), XtRString,
928 (XtPointer) TIME_CONTROL },
929 { "internetChessServerMode", "internetChessServerMode",
930 XtRBoolean, sizeof(Boolean),
931 XtOffset(AppDataPtr, icsActive), XtRImmediate,
933 { "internetChessServerHost", "internetChessServerHost",
934 XtRString, sizeof(String),
935 XtOffset(AppDataPtr, icsHost),
936 XtRString, (XtPointer) ICS_HOST },
937 { "internetChessServerPort", "internetChessServerPort",
938 XtRString, sizeof(String),
939 XtOffset(AppDataPtr, icsPort), XtRString,
940 (XtPointer) ICS_PORT },
941 { "internetChessServerCommPort", "internetChessServerCommPort",
942 XtRString, sizeof(String),
943 XtOffset(AppDataPtr, icsCommPort), XtRString,
945 { "internetChessServerLogonScript", "internetChessServerLogonScript",
946 XtRString, sizeof(String),
947 XtOffset(AppDataPtr, icsLogon), XtRString,
949 { "internetChessServerHelper", "internetChessServerHelper",
950 XtRString, sizeof(String),
951 XtOffset(AppDataPtr, icsHelper), XtRString, "" },
952 { "internetChessServerInputBox", "internetChessServerInputBox",
953 XtRBoolean, sizeof(Boolean),
954 XtOffset(AppDataPtr, icsInputBox), XtRImmediate,
956 { "icsAlarm", "icsAlarm",
957 XtRBoolean, sizeof(Boolean),
958 XtOffset(AppDataPtr, icsAlarm), XtRImmediate,
960 { "icsAlarmTime", "icsAlarmTime",
962 XtOffset(AppDataPtr, icsAlarmTime), XtRImmediate,
964 { "useTelnet", "useTelnet", XtRBoolean, sizeof(Boolean),
965 XtOffset(AppDataPtr, useTelnet), XtRImmediate,
967 { "telnetProgram", "telnetProgram", XtRString, sizeof(String),
968 XtOffset(AppDataPtr, telnetProgram), XtRString, TELNET_PROGRAM },
969 { "gateway", "gateway", XtRString, sizeof(String),
970 XtOffset(AppDataPtr, gateway), XtRString, "" },
971 { "loadGameFile", "loadGameFile", XtRString, sizeof(String),
972 XtOffset(AppDataPtr, loadGameFile), XtRString, "" },
973 { "loadGameIndex", "loadGameIndex",
975 XtOffset(AppDataPtr, loadGameIndex), XtRImmediate,
977 { "saveGameFile", "saveGameFile", XtRString, sizeof(String),
978 XtOffset(AppDataPtr, saveGameFile), XtRString, "" },
979 { "autoRaiseBoard", "autoRaiseBoard", XtRBoolean,
980 sizeof(Boolean), XtOffset(AppDataPtr, autoRaiseBoard),
981 XtRImmediate, (XtPointer) True },
982 { "autoSaveGames", "autoSaveGames", XtRBoolean,
983 sizeof(Boolean), XtOffset(AppDataPtr, autoSaveGames),
984 XtRImmediate, (XtPointer) False },
985 { "blindfold", "blindfold", XtRBoolean,
986 sizeof(Boolean), XtOffset(AppDataPtr, blindfold),
987 XtRImmediate, (XtPointer) False },
988 { "loadPositionFile", "loadPositionFile", XtRString,
989 sizeof(String), XtOffset(AppDataPtr, loadPositionFile),
991 { "loadPositionIndex", "loadPositionIndex",
993 XtOffset(AppDataPtr, loadPositionIndex), XtRImmediate,
995 { "savePositionFile", "savePositionFile", XtRString,
996 sizeof(String), XtOffset(AppDataPtr, savePositionFile),
998 { "matchMode", "matchMode", XtRBoolean, sizeof(Boolean),
999 XtOffset(AppDataPtr, matchMode), XtRImmediate, (XtPointer) False },
1000 { "matchGames", "matchGames", XtRInt, sizeof(int),
1001 XtOffset(AppDataPtr, matchGames), XtRImmediate,
1003 { "monoMode", "monoMode", XtRBoolean, sizeof(Boolean),
1004 XtOffset(AppDataPtr, monoMode), XtRImmediate,
1005 (XtPointer) False },
1006 { "debugMode", "debugMode", XtRBoolean, sizeof(Boolean),
1007 XtOffset(AppDataPtr, debugMode), XtRImmediate,
1008 (XtPointer) False },
1009 { "clockMode", "clockMode", XtRBoolean, sizeof(Boolean),
1010 XtOffset(AppDataPtr, clockMode), XtRImmediate,
1012 { "boardSize", "boardSize", XtRString, sizeof(String),
1013 XtOffset(AppDataPtr, boardSize), XtRString, "" },
1014 { "searchTime", "searchTime", XtRString, sizeof(String),
1015 XtOffset(AppDataPtr, searchTime), XtRString,
1017 { "searchDepth", "searchDepth", XtRInt, sizeof(int),
1018 XtOffset(AppDataPtr, searchDepth), XtRImmediate,
1020 { "showCoords", "showCoords", XtRBoolean, sizeof(Boolean),
1021 XtOffset(AppDataPtr, showCoords), XtRImmediate,
1022 (XtPointer) False },
1023 { "showJail", "showJail", XtRInt, sizeof(int),
1024 XtOffset(AppDataPtr, showJail), XtRImmediate,
1026 { "showThinking", "showThinking", XtRBoolean, sizeof(Boolean),
1027 XtOffset(AppDataPtr, showThinking), XtRImmediate,
1029 { "ponderNextMove", "ponderNextMove", XtRBoolean, sizeof(Boolean),
1030 XtOffset(AppDataPtr, ponderNextMove), XtRImmediate,
1032 { "periodicUpdates", "periodicUpdates", XtRBoolean, sizeof(Boolean),
1033 XtOffset(AppDataPtr, periodicUpdates), XtRImmediate,
1035 { "clockFont", "clockFont", XtRString, sizeof(String),
1036 XtOffset(AppDataPtr, clockFont), XtRString, CLOCK_FONT },
1037 { "coordFont", "coordFont", XtRString, sizeof(String),
1038 XtOffset(AppDataPtr, coordFont), XtRString, COORD_FONT },
1039 { "font", "font", XtRString, sizeof(String),
1040 XtOffset(AppDataPtr, font), XtRString, DEFAULT_FONT },
1041 { "ringBellAfterMoves", "ringBellAfterMoves",
1042 XtRBoolean, sizeof(Boolean),
1043 XtOffset(AppDataPtr, ringBellAfterMoves),
1044 XtRImmediate, (XtPointer) False },
1045 { "autoCallFlag", "autoCallFlag", XtRBoolean,
1046 sizeof(Boolean), XtOffset(AppDataPtr, autoCallFlag),
1047 XtRImmediate, (XtPointer) False },
1048 { "autoFlipView", "autoFlipView", XtRBoolean,
1049 sizeof(Boolean), XtOffset(AppDataPtr, autoFlipView),
1050 XtRImmediate, (XtPointer) True },
1051 { "autoObserve", "autoObserve", XtRBoolean,
1052 sizeof(Boolean), XtOffset(AppDataPtr, autoObserve),
1053 XtRImmediate, (XtPointer) False },
1054 { "autoComment", "autoComment", XtRBoolean,
1055 sizeof(Boolean), XtOffset(AppDataPtr, autoComment),
1056 XtRImmediate, (XtPointer) False },
1057 { "getMoveList", "getMoveList", XtRBoolean,
1058 sizeof(Boolean), XtOffset(AppDataPtr, getMoveList),
1059 XtRImmediate, (XtPointer) True },
1061 { "highlightDragging", "highlightDragging", XtRBoolean,
1062 sizeof(Boolean), XtOffset(AppDataPtr, highlightDragging),
1063 XtRImmediate, (XtPointer) False },
1065 { "highlightLastMove", "highlightLastMove", XtRBoolean,
1066 sizeof(Boolean), XtOffset(AppDataPtr, highlightLastMove),
1067 XtRImmediate, (XtPointer) False },
1068 { "premove", "premove", XtRBoolean,
1069 sizeof(Boolean), XtOffset(AppDataPtr, premove),
1070 XtRImmediate, (XtPointer) True },
1071 { "testLegality", "testLegality", XtRBoolean,
1072 sizeof(Boolean), XtOffset(AppDataPtr, testLegality),
1073 XtRImmediate, (XtPointer) True },
1074 { "flipView", "flipView", XtRBoolean,
1075 sizeof(Boolean), XtOffset(AppDataPtr, flipView),
1076 XtRImmediate, (XtPointer) False },
1077 { "cmail", "cmailGameName", XtRString, sizeof(String),
1078 XtOffset(AppDataPtr, cmailGameName), XtRString, "" },
1079 { "alwaysPromoteToQueen", "alwaysPromoteToQueen", XtRBoolean,
1080 sizeof(Boolean), XtOffset(AppDataPtr, alwaysPromoteToQueen),
1081 XtRImmediate, (XtPointer) False },
1082 { "oldSaveStyle", "oldSaveStyle", XtRBoolean,
1083 sizeof(Boolean), XtOffset(AppDataPtr, oldSaveStyle),
1084 XtRImmediate, (XtPointer) False },
1085 { "quietPlay", "quietPlay", XtRBoolean,
1086 sizeof(Boolean), XtOffset(AppDataPtr, quietPlay),
1087 XtRImmediate, (XtPointer) False },
1088 { "titleInWindow", "titleInWindow", XtRBoolean,
1089 sizeof(Boolean), XtOffset(AppDataPtr, titleInWindow),
1090 XtRImmediate, (XtPointer) False },
1091 { "localLineEditing", "localLineEditing", XtRBoolean,
1092 sizeof(Boolean), XtOffset(AppDataPtr, localLineEditing),
1093 XtRImmediate, (XtPointer) True }, /* not implemented, must be True */
1095 { "zippyTalk", "zippyTalk", XtRBoolean,
1096 sizeof(Boolean), XtOffset(AppDataPtr, zippyTalk),
1097 XtRImmediate, (XtPointer) ZIPPY_TALK },
1098 { "zippyPlay", "zippyPlay", XtRBoolean,
1099 sizeof(Boolean), XtOffset(AppDataPtr, zippyPlay),
1100 XtRImmediate, (XtPointer) ZIPPY_PLAY },
1101 { "zippyLines", "zippyLines", XtRString, sizeof(String),
1102 XtOffset(AppDataPtr, zippyLines), XtRString, ZIPPY_LINES },
1103 { "zippyPinhead", "zippyPinhead", XtRString, sizeof(String),
1104 XtOffset(AppDataPtr, zippyPinhead), XtRString, ZIPPY_PINHEAD },
1105 { "zippyPassword", "zippyPassword", XtRString, sizeof(String),
1106 XtOffset(AppDataPtr, zippyPassword), XtRString, ZIPPY_PASSWORD },
1107 { "zippyPassword2", "zippyPassword2", XtRString, sizeof(String),
1108 XtOffset(AppDataPtr, zippyPassword2), XtRString, ZIPPY_PASSWORD2 },
1109 { "zippyWrongPassword", "zippyWrongPassword", XtRString, sizeof(String),
1110 XtOffset(AppDataPtr, zippyWrongPassword), XtRString,
1111 ZIPPY_WRONG_PASSWORD },
1112 { "zippyAcceptOnly", "zippyAcceptOnly", XtRString, sizeof(String),
1113 XtOffset(AppDataPtr, zippyAcceptOnly), XtRString, ZIPPY_ACCEPT_ONLY },
1114 { "zippyUseI", "zippyUseI", XtRBoolean,
1115 sizeof(Boolean), XtOffset(AppDataPtr, zippyUseI),
1116 XtRImmediate, (XtPointer) ZIPPY_USE_I },
1117 { "zippyBughouse", "zippyBughouse", XtRInt,
1118 sizeof(int), XtOffset(AppDataPtr, zippyBughouse),
1119 XtRImmediate, (XtPointer) ZIPPY_BUGHOUSE },
1120 { "zippyNoplayCrafty", "zippyNoplayCrafty", XtRBoolean,
1121 sizeof(Boolean), XtOffset(AppDataPtr, zippyNoplayCrafty),
1122 XtRImmediate, (XtPointer) ZIPPY_NOPLAY_CRAFTY },
1123 { "zippyGameEnd", "zippyGameEnd", XtRString, sizeof(String),
1124 XtOffset(AppDataPtr, zippyGameEnd), XtRString, ZIPPY_GAME_END },
1125 { "zippyGameStart", "zippyGameStart", XtRString, sizeof(String),
1126 XtOffset(AppDataPtr, zippyGameStart), XtRString, ZIPPY_GAME_START },
1127 { "zippyAdjourn", "zippyAdjourn", XtRBoolean,
1128 sizeof(Boolean), XtOffset(AppDataPtr, zippyAdjourn),
1129 XtRImmediate, (XtPointer) ZIPPY_ADJOURN },
1130 { "zippyAbort", "zippyAbort", XtRBoolean,
1131 sizeof(Boolean), XtOffset(AppDataPtr, zippyAbort),
1132 XtRImmediate, (XtPointer) ZIPPY_ABORT },
1133 { "zippyVariants", "zippyVariants", XtRString, sizeof(String),
1134 XtOffset(AppDataPtr, zippyVariants), XtRString, ZIPPY_VARIANTS },
1135 { "zippyMaxGames", "zippyMaxGames", XtRInt, sizeof(int),
1136 XtOffset(AppDataPtr, zippyMaxGames), XtRImmediate,
1137 (XtPointer) ZIPPY_MAX_GAMES },
1138 { "zippyReplayTimeout", "zippyReplayTimeout", XtRInt, sizeof(int),
1139 XtOffset(AppDataPtr, zippyReplayTimeout), XtRImmediate,
1140 (XtPointer) ZIPPY_REPLAY_TIMEOUT },
1141 { "zippyShortGame", "zippyShortGame", XtRInt, sizeof(int),
1142 XtOffset(AppDataPtr, zippyShortGame), XtRImmediate,
1145 { "flashCount", "flashCount", XtRInt, sizeof(int),
1146 XtOffset(AppDataPtr, flashCount), XtRImmediate,
1147 (XtPointer) FLASH_COUNT },
1148 { "flashRate", "flashRate", XtRInt, sizeof(int),
1149 XtOffset(AppDataPtr, flashRate), XtRImmediate,
1150 (XtPointer) FLASH_RATE },
1151 { "pixmapDirectory", "pixmapDirectory", XtRString,
1152 sizeof(String), XtOffset(AppDataPtr, pixmapDirectory),
1154 { "msLoginDelay", "msLoginDelay", XtRInt, sizeof(int),
1155 XtOffset(AppDataPtr, msLoginDelay), XtRImmediate,
1156 (XtPointer) MS_LOGIN_DELAY },
1157 { "colorizeMessages", "colorizeMessages", XtRBoolean,
1158 sizeof(Boolean), XtOffset(AppDataPtr, colorize),
1159 XtRImmediate, (XtPointer) False },
1160 { "colorShout", "colorShout", XtRString,
1161 sizeof(String), XtOffset(AppDataPtr, colorShout),
1162 XtRString, COLOR_SHOUT },
1163 { "colorSShout", "colorSShout", XtRString,
1164 sizeof(String), XtOffset(AppDataPtr, colorSShout),
1165 XtRString, COLOR_SSHOUT },
1166 { "colorChannel1", "colorChannel1", XtRString,
1167 sizeof(String), XtOffset(AppDataPtr, colorChannel1),
1168 XtRString, COLOR_CHANNEL1 },
1169 { "colorChannel", "colorChannel", XtRString,
1170 sizeof(String), XtOffset(AppDataPtr, colorChannel),
1171 XtRString, COLOR_CHANNEL },
1172 { "colorKibitz", "colorKibitz", XtRString,
1173 sizeof(String), XtOffset(AppDataPtr, colorKibitz),
1174 XtRString, COLOR_KIBITZ },
1175 { "colorTell", "colorTell", XtRString,
1176 sizeof(String), XtOffset(AppDataPtr, colorTell),
1177 XtRString, COLOR_TELL },
1178 { "colorChallenge", "colorChallenge", XtRString,
1179 sizeof(String), XtOffset(AppDataPtr, colorChallenge),
1180 XtRString, COLOR_CHALLENGE },
1181 { "colorRequest", "colorRequest", XtRString,
1182 sizeof(String), XtOffset(AppDataPtr, colorRequest),
1183 XtRString, COLOR_REQUEST },
1184 { "colorSeek", "colorSeek", XtRString,
1185 sizeof(String), XtOffset(AppDataPtr, colorSeek),
1186 XtRString, COLOR_SEEK },
1187 { "colorNormal", "colorNormal", XtRString,
1188 sizeof(String), XtOffset(AppDataPtr, colorNormal),
1189 XtRString, COLOR_NORMAL },
1190 { "soundProgram", "soundProgram", XtRString,
1191 sizeof(String), XtOffset(AppDataPtr, soundProgram),
1192 XtRString, "play" },
1193 { "soundShout", "soundShout", XtRString,
1194 sizeof(String), XtOffset(AppDataPtr, soundShout),
1196 { "soundSShout", "soundSShout", XtRString,
1197 sizeof(String), XtOffset(AppDataPtr, soundSShout),
1199 { "soundChannel1", "soundChannel1", XtRString,
1200 sizeof(String), XtOffset(AppDataPtr, soundChannel1),
1202 { "soundChannel", "soundChannel", XtRString,
1203 sizeof(String), XtOffset(AppDataPtr, soundChannel),
1205 { "soundKibitz", "soundKibitz", XtRString,
1206 sizeof(String), XtOffset(AppDataPtr, soundKibitz),
1208 { "soundTell", "soundTell", XtRString,
1209 sizeof(String), XtOffset(AppDataPtr, soundTell),
1211 { "soundChallenge", "soundChallenge", XtRString,
1212 sizeof(String), XtOffset(AppDataPtr, soundChallenge),
1214 { "soundRequest", "soundRequest", XtRString,
1215 sizeof(String), XtOffset(AppDataPtr, soundRequest),
1217 { "soundSeek", "soundSeek", XtRString,
1218 sizeof(String), XtOffset(AppDataPtr, soundSeek),
1220 { "soundMove", "soundMove", XtRString,
1221 sizeof(String), XtOffset(AppDataPtr, soundMove),
1223 { "soundIcsWin", "soundIcsWin", XtRString,
1224 sizeof(String), XtOffset(AppDataPtr, soundIcsWin),
1226 { "soundIcsLoss", "soundIcsLoss", XtRString,
1227 sizeof(String), XtOffset(AppDataPtr, soundIcsLoss),
1229 { "soundIcsDraw", "soundIcsDraw", XtRString,
1230 sizeof(String), XtOffset(AppDataPtr, soundIcsDraw),
1232 { "soundIcsUnfinished", "soundIcsUnfinished", XtRString,
1233 sizeof(String), XtOffset(AppDataPtr, soundIcsUnfinished),
1235 { "soundIcsAlarm", "soundIcsAlarm", XtRString,
1236 sizeof(String), XtOffset(AppDataPtr, soundIcsAlarm),
1238 { "reuseFirst", "reuseFirst", XtRBoolean,
1239 sizeof(Boolean), XtOffset(AppDataPtr, reuseFirst),
1240 XtRImmediate, (XtPointer) True },
1241 { "reuseSecond", "reuseSecond", XtRBoolean,
1242 sizeof(Boolean), XtOffset(AppDataPtr, reuseSecond),
1243 XtRImmediate, (XtPointer) True },
1244 { "animateDragging", "animateDragging", XtRBoolean,
1245 sizeof(Boolean), XtOffset(AppDataPtr, animateDragging),
1246 XtRImmediate, (XtPointer) True },
1247 { "animateMoving", "animateMoving", XtRBoolean,
1248 sizeof(Boolean), XtOffset(AppDataPtr, animate),
1249 XtRImmediate, (XtPointer) True },
1250 { "animateSpeed", "animateSpeed", XtRInt,
1251 sizeof(int), XtOffset(AppDataPtr, animSpeed),
1252 XtRImmediate, (XtPointer)10 },
1253 { "popupExitMessage", "popupExitMessage", XtRBoolean,
1254 sizeof(Boolean), XtOffset(AppDataPtr, popupExitMessage),
1255 XtRImmediate, (XtPointer) True },
1256 { "popupMoveErrors", "popupMoveErrors", XtRBoolean,
1257 sizeof(Boolean), XtOffset(AppDataPtr, popupMoveErrors),
1258 XtRImmediate, (XtPointer) False },
1259 { "fontSizeTolerance", "fontSizeTolerance", XtRInt,
1260 sizeof(int), XtOffset(AppDataPtr, fontSizeTolerance),
1261 XtRImmediate, (XtPointer)4 },
1262 { "initialMode", "initialMode", XtRString,
1263 sizeof(String), XtOffset(AppDataPtr, initialMode),
1264 XtRImmediate, (XtPointer) "" },
1265 { "variant", "variant", XtRString,
1266 sizeof(String), XtOffset(AppDataPtr, variant),
1267 XtRImmediate, (XtPointer) "normal" },
1268 { "firstProtocolVersion", "firstProtocolVersion", XtRInt,
1269 sizeof(int), XtOffset(AppDataPtr, firstProtocolVersion),
1270 XtRImmediate, (XtPointer)PROTOVER },
1271 { "secondProtocolVersion", "secondProtocolVersion", XtRInt,
1272 sizeof(int), XtOffset(AppDataPtr, secondProtocolVersion),
1273 XtRImmediate, (XtPointer)PROTOVER },
1274 { "showButtonBar", "showButtonBar", XtRBoolean,
1275 sizeof(Boolean), XtOffset(AppDataPtr, showButtonBar),
1276 XtRImmediate, (XtPointer) True },
1277 { "lowTimeWarningColor", "lowTimeWarningColor", XtRString,
1278 sizeof(String), XtOffset(AppDataPtr, lowTimeWarningColor),
1279 XtRString, COLOR_LOWTIMEWARNING },
1280 { "lowTimeWarning", "lowTimeWarning", XtRBoolean,
1281 sizeof(Boolean), XtOffset(AppDataPtr, lowTimeWarning),
1282 XtRImmediate, (XtPointer) False },
1283 {"icsEngineAnalyze", "icsEngineAnalyze", XtRBoolean, /* [DM] icsEngineAnalyze */
1284 sizeof(Boolean), XtOffset(AppDataPtr, icsEngineAnalyze),
1285 XtRImmediate, (XtPointer) False },
1286 { "firstScoreAbs", "firstScoreAbs", XtRBoolean,
1287 sizeof(Boolean), XtOffset(AppDataPtr, firstScoreIsAbsolute),
1288 XtRImmediate, (XtPointer) False },
1289 { "secondScoreAbs", "secondScoreAbs", XtRBoolean,
1290 sizeof(Boolean), XtOffset(AppDataPtr, secondScoreIsAbsolute),
1291 XtRImmediate, (XtPointer) False },
1292 { "pgnExtendedInfo", "pgnExtendedInfo", XtRBoolean,
1293 sizeof(Boolean), XtOffset(AppDataPtr, saveExtendedInfoInPGN),
1294 XtRImmediate, (XtPointer) False },
1295 { "hideThinkingFromHuman", "hideThinkingFromHuman", XtRBoolean,
1296 sizeof(Boolean), XtOffset(AppDataPtr, hideThinkingFromHuman),
1297 XtRImmediate, (XtPointer) True },
1298 { "adjudicateLossThreshold", "adjudicateLossThreshold", XtRInt,
1299 sizeof(int), XtOffset(AppDataPtr, adjudicateLossThreshold),
1300 XtRImmediate, (XtPointer) 0},
1301 { "pgnEventHeader", "pgnEventHeader", XtRString,
1302 sizeof(String), XtOffset(AppDataPtr, pgnEventHeader),
1303 XtRImmediate, (XtPointer) "Computer Chess Game" },
1304 { "defaultFrcPosition", "defaultFrcPositon", XtRInt,
1305 sizeof(int), XtOffset(AppDataPtr, defaultFrcPosition),
1306 XtRImmediate, (XtPointer) -1},
1307 { "gameListTags", "gameListTags", XtRString,
1308 sizeof(String), XtOffset(AppDataPtr, gameListTags),
1309 XtRImmediate, (XtPointer) GLT_DEFAULT_TAGS },
1311 // [HGM] 4.3.xx options
1312 { "boardWidth", "boardWidth", XtRInt,
1313 sizeof(int), XtOffset(AppDataPtr, NrFiles),
1314 XtRImmediate, (XtPointer) -1},
1315 { "boardHeight", "boardHeight", XtRInt,
1316 sizeof(int), XtOffset(AppDataPtr, NrRanks),
1317 XtRImmediate, (XtPointer) -1},
1318 { "matchPause", "matchPause", XtRInt,
1319 sizeof(int), XtOffset(AppDataPtr, matchPause),
1320 XtRImmediate, (XtPointer) 10000},
1321 { "holdingsSize", "holdingsSize", XtRInt,
1322 sizeof(int), XtOffset(AppDataPtr, holdingsSize),
1323 XtRImmediate, (XtPointer) -1},
1324 { "flipBlack", "flipBlack", XtRBoolean,
1325 sizeof(Boolean), XtOffset(AppDataPtr, upsideDown),
1326 XtRImmediate, (XtPointer) False},
1327 { "allWhite", "allWhite", XtRBoolean,
1328 sizeof(Boolean), XtOffset(AppDataPtr, allWhite),
1329 XtRImmediate, (XtPointer) False},
1330 { "pieceToCharTable", "pieceToCharTable", XtRString,
1331 sizeof(String), XtOffset(AppDataPtr, pieceToCharTable),
1332 XtRImmediate, (XtPointer) 0},
1333 { "alphaRank", "alphaRank", XtRBoolean,
1334 sizeof(Boolean), XtOffset(AppDataPtr, alphaRank),
1335 XtRImmediate, (XtPointer) False},
1336 { "testClaims", "testClaims", XtRBoolean,
1337 sizeof(Boolean), XtOffset(AppDataPtr, testClaims),
1338 XtRImmediate, (XtPointer) True},
1339 { "checkMates", "checkMates", XtRBoolean,
1340 sizeof(Boolean), XtOffset(AppDataPtr, checkMates),
1341 XtRImmediate, (XtPointer) True},
1342 { "materialDraws", "materialDraws", XtRBoolean,
1343 sizeof(Boolean), XtOffset(AppDataPtr, materialDraws),
1344 XtRImmediate, (XtPointer) True},
1345 { "trivialDraws", "trivialDraws", XtRBoolean,
1346 sizeof(Boolean), XtOffset(AppDataPtr, trivialDraws),
1347 XtRImmediate, (XtPointer) False},
1348 { "ruleMoves", "ruleMoves", XtRInt,
1349 sizeof(int), XtOffset(AppDataPtr, ruleMoves),
1350 XtRImmediate, (XtPointer) 51},
1351 { "repeatsToDraw", "repeatsToDraw", XtRInt,
1352 sizeof(int), XtOffset(AppDataPtr, drawRepeats),
1353 XtRImmediate, (XtPointer) 6},
1354 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1355 sizeof(int), XtOffset(AppDataPtr, engineComments),
1356 XtRImmediate, (XtPointer) 1},
1357 { "userName", "userName", XtRString,
1358 sizeof(int), XtOffset(AppDataPtr, userName),
1359 XtRImmediate, (XtPointer) 0},
1360 { "autoKibitz", "autoKibitz", XtRBoolean,
1361 sizeof(Boolean), XtOffset(AppDataPtr, autoKibitz),
1362 XtRImmediate, (XtPointer) False},
1363 { "firstTimeOdds", "firstTimeOdds", XtRInt,
1364 sizeof(int), XtOffset(AppDataPtr, firstTimeOdds),
1365 XtRImmediate, (XtPointer) 1},
1366 { "secondTimeOdds", "secondTimeOdds", XtRInt,
1367 sizeof(int), XtOffset(AppDataPtr, secondTimeOdds),
1368 XtRImmediate, (XtPointer) 1},
1369 { "timeOddsMode", "timeOddsMode", XtRInt,
1370 sizeof(int), XtOffset(AppDataPtr, timeOddsMode),
1371 XtRImmediate, (XtPointer) 0},
1372 { "firstAccumulateTC", "firstAccumulateTC", XtRInt,
1373 sizeof(int), XtOffset(AppDataPtr, firstAccumulateTC),
1374 XtRImmediate, (XtPointer) 1},
1375 { "secondAccumulateTC", "secondAccumulateTC", XtRInt,
1376 sizeof(int), XtOffset(AppDataPtr, secondAccumulateTC),
1377 XtRImmediate, (XtPointer) 1},
1378 { "firstNPS", "firstNPS", XtRInt,
1379 sizeof(int), XtOffset(AppDataPtr, firstNPS),
1380 XtRImmediate, (XtPointer) -1},
1381 { "secondNPS", "secondNPS", XtRInt,
1382 sizeof(int), XtOffset(AppDataPtr, secondNPS),
1383 XtRImmediate, (XtPointer) -1},
1384 { "serverMoves", "serverMoves", XtRString,
1385 sizeof(String), XtOffset(AppDataPtr, serverMovesName),
1386 XtRImmediate, (XtPointer) 0},
1387 { "serverPause", "serverPause", XtRInt,
1388 sizeof(int), XtOffset(AppDataPtr, serverPause),
1389 XtRImmediate, (XtPointer) 0},
1390 { "suppressLoadMoves", "suppressLoadMoves", XtRBoolean,
1391 sizeof(Boolean), XtOffset(AppDataPtr, suppressLoadMoves),
1392 XtRImmediate, (XtPointer) False},
1393 { "userName", "userName", XtRString,
1394 sizeof(String), XtOffset(AppDataPtr, userName),
1395 XtRImmediate, (XtPointer) 0},
1396 { "egtFormats", "egtFormats", XtRString,
1397 sizeof(String), XtOffset(AppDataPtr, egtFormats),
1398 XtRImmediate, (XtPointer) 0},
1399 { "rewindIndex", "rewindIndex", XtRInt,
1400 sizeof(int), XtOffset(AppDataPtr, rewindIndex),
1401 XtRImmediate, (XtPointer) 0},
1402 { "sameColorGames", "sameColorGames", XtRInt,
1403 sizeof(int), XtOffset(AppDataPtr, sameColorGames),
1404 XtRImmediate, (XtPointer) 0},
1405 { "smpCores", "smpCores", XtRInt,
1406 sizeof(int), XtOffset(AppDataPtr, smpCores),
1407 XtRImmediate, (XtPointer) 1},
1408 { "niceEngines", "niceEngines", XtRInt,
1409 sizeof(int), XtOffset(AppDataPtr, niceEngines),
1410 XtRImmediate, (XtPointer) 0},
1411 { "nameOfDebugFile", "nameOfDebugFile", XtRString,
1412 sizeof(String), XtOffset(AppDataPtr, nameOfDebugFile),
1413 XtRImmediate, (XtPointer) "xboard.debug"},
1414 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1415 sizeof(int), XtOffset(AppDataPtr, engineComments),
1416 XtRImmediate, (XtPointer) 0},
1417 { "noGUI", "noGUI", XtRBoolean,
1418 sizeof(Boolean), XtOffset(AppDataPtr, noGUI),
1419 XtRImmediate, (XtPointer) 0},
1420 { "firstOptions", "firstOptions", XtRString,
1421 sizeof(String), XtOffset(AppDataPtr, firstOptions),
1422 XtRImmediate, (XtPointer) "" },
1423 { "secondOptions", "secondOptions", XtRString,
1424 sizeof(String), XtOffset(AppDataPtr, secondOptions),
1425 XtRImmediate, (XtPointer) "" },
1426 { "firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XtRString,
1427 sizeof(String), XtOffset(AppDataPtr, fenOverride1),
1428 XtRImmediate, (XtPointer) 0 },
1429 { "secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XtRString,
1430 sizeof(String), XtOffset(AppDataPtr, fenOverride2),
1431 XtRImmediate, (XtPointer) 0 },
1433 // [HGM] Winboard_x UCI options
1434 { "firstIsUCI", "firstIsUCI", XtRBoolean,
1435 sizeof(Boolean), XtOffset(AppDataPtr, firstIsUCI),
1436 XtRImmediate, (XtPointer) False},
1437 { "secondIsUCI", "secondIsUCI", XtRBoolean,
1438 sizeof(Boolean), XtOffset(AppDataPtr, secondIsUCI),
1439 XtRImmediate, (XtPointer) False},
1440 { "firstHasOwnBookUCI", "firstHasOwnBookUCI", XtRBoolean,
1441 sizeof(Boolean), XtOffset(AppDataPtr, firstHasOwnBookUCI),
1442 XtRImmediate, (XtPointer) True},
1443 { "secondHasOwnBookUCI", "secondHasOwnBookUCI", XtRBoolean,
1444 sizeof(Boolean), XtOffset(AppDataPtr, secondHasOwnBookUCI),
1445 XtRImmediate, (XtPointer) True},
1446 { "usePolyglotBook", "usePolyglotBook", XtRBoolean,
1447 sizeof(Boolean), XtOffset(AppDataPtr, usePolyglotBook),
1448 XtRImmediate, (XtPointer) False},
1449 { "defaultHashSize", "defaultHashSize", XtRInt,
1450 sizeof(int), XtOffset(AppDataPtr, defaultHashSize),
1451 XtRImmediate, (XtPointer) 64},
1452 { "defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XtRInt,
1453 sizeof(int), XtOffset(AppDataPtr, defaultCacheSizeEGTB),
1454 XtRImmediate, (XtPointer) 4},
1455 { "polyglotDir", "polyglotDir", XtRString,
1456 sizeof(String), XtOffset(AppDataPtr, polyglotDir),
1457 XtRImmediate, (XtPointer) "." },
1458 { "polyglotBook", "polyglotBook", XtRString,
1459 sizeof(String), XtOffset(AppDataPtr, polyglotBook),
1460 XtRImmediate, (XtPointer) "" },
1461 { "defaultPathEGTB", "defaultPathEGTB", XtRString,
1462 sizeof(String), XtOffset(AppDataPtr, defaultPathEGTB),
1463 XtRImmediate, (XtPointer) "/usr/local/share/egtb"},
1464 { "delayBeforeQuit", "delayBeforeQuit", XtRInt,
1465 sizeof(int), XtOffset(AppDataPtr, delayBeforeQuit),
1466 XtRImmediate, (XtPointer) 0},
1467 { "delayAfterQuit", "delayAfterQuit", XtRInt,
1468 sizeof(int), XtOffset(AppDataPtr, delayAfterQuit),
1469 XtRImmediate, (XtPointer) 0},
1472 XrmOptionDescRec shellOptions[] = {
1473 { "-whitePieceColor", "whitePieceColor", XrmoptionSepArg, NULL },
1474 { "-blackPieceColor", "blackPieceColor", XrmoptionSepArg, NULL },
1475 { "-lightSquareColor", "lightSquareColor", XrmoptionSepArg, NULL },
1476 { "-darkSquareColor", "darkSquareColor", XrmoptionSepArg, NULL },
1477 { "-highlightSquareColor", "highlightSquareColor", XrmoptionSepArg, NULL },
1478 { "-premoveHighlightColor", "premoveHighlightColor", XrmoptionSepArg,NULL},
1479 { "-movesPerSession", "movesPerSession", XrmoptionSepArg, NULL },
1480 { "-mps", "movesPerSession", XrmoptionSepArg, NULL },
1481 { "-timeIncrement", "timeIncrement", XrmoptionSepArg, NULL },
1482 { "-inc", "timeIncrement", XrmoptionSepArg, NULL },
1483 { "-initString", "initString", XrmoptionSepArg, NULL },
1484 { "-firstInitString", "initString", XrmoptionSepArg, NULL },
1485 { "-secondInitString", "secondInitString", XrmoptionSepArg, NULL },
1486 { "-firstComputerString", "firstComputerString", XrmoptionSepArg, NULL },
1487 { "-secondComputerString", "secondComputerString", XrmoptionSepArg, NULL },
1488 { "-firstChessProgram", "firstChessProgram", XrmoptionSepArg, NULL },
1489 { "-fcp", "firstChessProgram", XrmoptionSepArg, NULL },
1490 { "-secondChessProgram", "secondChessProgram", XrmoptionSepArg, NULL },
1491 { "-scp", "secondChessProgram", XrmoptionSepArg, NULL },
1492 { "-firstPlaysBlack", "firstPlaysBlack", XrmoptionSepArg, NULL },
1493 { "-fb", "firstPlaysBlack", XrmoptionNoArg, "True" },
1494 { "-xfb", "firstPlaysBlack", XrmoptionNoArg, "False" },
1495 { "-noChessProgram", "noChessProgram", XrmoptionSepArg, NULL },
1496 { "-ncp", "noChessProgram", XrmoptionNoArg, "True" },
1497 { "-xncp", "noChessProgram", XrmoptionNoArg, "False" },
1498 { "-firstHost", "firstHost", XrmoptionSepArg, NULL },
1499 { "-fh", "firstHost", XrmoptionSepArg, NULL },
1500 { "-secondHost", "secondHost", XrmoptionSepArg, NULL },
1501 { "-sh", "secondHost", XrmoptionSepArg, NULL },
1502 { "-firstDirectory", "firstDirectory", XrmoptionSepArg, NULL },
1503 { "-fd", "firstDirectory", XrmoptionSepArg, NULL },
1504 { "-secondDirectory", "secondDirectory", XrmoptionSepArg, NULL },
1505 { "-sd", "secondDirectory", XrmoptionSepArg, NULL },
1506 { "-bitmapDirectory", "bitmapDirectory", XrmoptionSepArg, NULL },
1507 { "-bm", "bitmapDirectory", XrmoptionSepArg, NULL },
1508 { "-remoteShell", "remoteShell", XrmoptionSepArg, NULL },
1509 { "-rsh", "remoteShell", XrmoptionSepArg, NULL },
1510 { "-remoteUser", "remoteUser", XrmoptionSepArg, NULL },
1511 { "-ruser", "remoteUser", XrmoptionSepArg, NULL },
1512 { "-timeDelay", "timeDelay", XrmoptionSepArg, NULL },
1513 { "-td", "timeDelay", XrmoptionSepArg, NULL },
1514 { "-timeControl", "timeControl", XrmoptionSepArg, NULL },
1515 { "-tc", "timeControl", XrmoptionSepArg, NULL },
1516 { "-internetChessServerMode", "internetChessServerMode",
1517 XrmoptionSepArg, NULL },
1518 { "-ics", "internetChessServerMode", XrmoptionNoArg, "True" },
1519 { "-xics", "internetChessServerMode", XrmoptionNoArg, "False" },
1520 { "-internetChessServerHost", "internetChessServerHost",
1521 XrmoptionSepArg, NULL },
1522 { "-icshost", "internetChessServerHost", XrmoptionSepArg, NULL },
1523 { "-internetChessServerPort", "internetChessServerPort",
1524 XrmoptionSepArg, NULL },
1525 { "-icsport", "internetChessServerPort", XrmoptionSepArg, NULL },
1526 { "-internetChessServerCommPort", "internetChessServerCommPort",
1527 XrmoptionSepArg, NULL },
1528 { "-icscomm", "internetChessServerCommPort", XrmoptionSepArg, NULL },
1529 { "-internetChessServerLogonScript", "internetChessServerLogonScript",
1530 XrmoptionSepArg, NULL },
1531 { "-icslogon", "internetChessServerLogonScript", XrmoptionSepArg, NULL },
1532 { "-internetChessServerHelper", "internetChessServerHelper",
1533 XrmoptionSepArg, NULL },
1534 { "-icshelper", "internetChessServerHelper", XrmoptionSepArg, NULL },
1535 { "-internetChessServerInputBox", "internetChessServerInputBox",
1536 XrmoptionSepArg, NULL },
1537 { "-icsinput", "internetChessServerInputBox", XrmoptionNoArg, "True" },
1538 { "-xicsinput", "internetChessServerInputBox", XrmoptionNoArg, "False" },
1539 { "-icsAlarm", "icsAlarm", XrmoptionSepArg, NULL },
1540 { "-alarm", "icsAlarm", XrmoptionNoArg, "True" },
1541 { "-xalarm", "icsAlarm", XrmoptionNoArg, "False" },
1542 { "-icsAlarmTime", "icsAlarmTime", XrmoptionSepArg, NULL },
1543 { "-useTelnet", "useTelnet", XrmoptionSepArg, NULL },
1544 { "-telnet", "useTelnet", XrmoptionNoArg, "True" },
1545 { "-xtelnet", "useTelnet", XrmoptionNoArg, "False" },
1546 { "-telnetProgram", "telnetProgram", XrmoptionSepArg, NULL },
1547 { "-gateway", "gateway", XrmoptionSepArg, NULL },
1548 { "-loadGameFile", "loadGameFile", XrmoptionSepArg, NULL },
1549 { "-lgf", "loadGameFile", XrmoptionSepArg, NULL },
1550 { "-loadGameIndex", "loadGameIndex", XrmoptionSepArg, NULL },
1551 { "-lgi", "loadGameIndex", XrmoptionSepArg, NULL },
1552 { "-saveGameFile", "saveGameFile", XrmoptionSepArg, NULL },
1553 { "-sgf", "saveGameFile", XrmoptionSepArg, NULL },
1554 { "-autoSaveGames", "autoSaveGames", XrmoptionSepArg, NULL },
1555 { "-autosave", "autoSaveGames", XrmoptionNoArg, "True" },
1556 { "-xautosave", "autoSaveGames", XrmoptionNoArg, "False" },
1557 { "-autoRaiseBoard", "autoRaiseBoard", XrmoptionSepArg, NULL },
1558 { "-autoraise", "autoRaiseBoard", XrmoptionNoArg, "True" },
1559 { "-xautoraise", "autoRaiseBoard", XrmoptionNoArg, "False" },
1560 { "-blindfold", "blindfold", XrmoptionSepArg, NULL },
1561 { "-blind", "blindfold", XrmoptionNoArg, "True" },
1562 { "-xblind", "blindfold", XrmoptionNoArg, "False" },
1563 { "-loadPositionFile", "loadPositionFile", XrmoptionSepArg, NULL },
1564 { "-lpf", "loadPositionFile", XrmoptionSepArg, NULL },
1565 { "-loadPositionIndex", "loadPositionIndex", XrmoptionSepArg, NULL },
1566 { "-lpi", "loadPositionIndex", XrmoptionSepArg, NULL },
1567 { "-savePositionFile", "savePositionFile", XrmoptionSepArg, NULL },
1568 { "-spf", "savePositionFile", XrmoptionSepArg, NULL },
1569 { "-matchMode", "matchMode", XrmoptionSepArg, NULL },
1570 { "-mm", "matchMode", XrmoptionNoArg, "True" },
1571 { "-xmm", "matchMode", XrmoptionNoArg, "False" },
1572 { "-matchGames", "matchGames", XrmoptionSepArg, NULL },
1573 { "-mg", "matchGames", XrmoptionSepArg, NULL },
1574 { "-monoMode", "monoMode", XrmoptionSepArg, NULL },
1575 { "-mono", "monoMode", XrmoptionNoArg, "True" },
1576 { "-xmono", "monoMode", XrmoptionNoArg, "False" },
1577 { "-debugMode", "debugMode", XrmoptionSepArg, NULL },
1578 { "-debug", "debugMode", XrmoptionNoArg, "True" },
1579 { "-xdebug", "debugMode", XrmoptionNoArg, "False" },
1580 { "-clockMode", "clockMode", XrmoptionSepArg, NULL },
1581 { "-clock", "clockMode", XrmoptionNoArg, "True" },
1582 { "-xclock", "clockMode", XrmoptionNoArg, "False" },
1583 { "-boardSize", "boardSize", XrmoptionSepArg, NULL },
1584 { "-size", "boardSize", XrmoptionSepArg, NULL },
1585 { "-searchTime", "searchTime", XrmoptionSepArg, NULL },
1586 { "-st", "searchTime", XrmoptionSepArg, NULL },
1587 { "-searchDepth", "searchDepth", XrmoptionSepArg, NULL },
1588 { "-depth", "searchDepth", XrmoptionSepArg, NULL },
1589 { "-showCoords", "showCoords", XrmoptionSepArg, NULL },
1590 { "-coords", "showCoords", XrmoptionNoArg, "True" },
1591 { "-xcoords", "showCoords", XrmoptionNoArg, "False" },
1593 { "-showJail", "showJail", XrmoptionSepArg, NULL },
1594 { "-jail", "showJail", XrmoptionNoArg, "1" },
1595 { "-sidejail", "showJail", XrmoptionNoArg, "2" },
1596 { "-xjail", "showJail", XrmoptionNoArg, "0" },
1598 { "-showThinking", "showThinking", XrmoptionSepArg, NULL },
1599 { "-thinking", "showThinking", XrmoptionNoArg, "True" },
1600 { "-xthinking", "showThinking", XrmoptionNoArg, "False" },
1601 { "-ponderNextMove", "ponderNextMove", XrmoptionSepArg, NULL },
1602 { "-ponder", "ponderNextMove", XrmoptionNoArg, "True" },
1603 { "-xponder", "ponderNextMove", XrmoptionNoArg, "False" },
1604 { "-periodicUpdates", "periodicUpdates", XrmoptionSepArg, NULL },
1605 { "-periodic", "periodicUpdates", XrmoptionNoArg, "True" },
1606 { "-xperiodic", "periodicUpdates", XrmoptionNoArg, "False" },
1607 { "-clockFont", "clockFont", XrmoptionSepArg, NULL },
1608 { "-coordFont", "coordFont", XrmoptionSepArg, NULL },
1609 { "-font", "font", XrmoptionSepArg, NULL },
1610 { "-ringBellAfterMoves", "ringBellAfterMoves", XrmoptionSepArg, NULL },
1611 { "-bell", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1612 { "-xbell", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1613 { "-movesound", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1614 { "-xmovesound", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1615 { "-autoCallFlag", "autoCallFlag", XrmoptionSepArg, NULL },
1616 { "-autoflag", "autoCallFlag", XrmoptionNoArg, "True" },
1617 { "-xautoflag", "autoCallFlag", XrmoptionNoArg, "False" },
1618 { "-autoFlipView", "autoFlipView", XrmoptionSepArg, NULL },
1619 { "-autoflip", "autoFlipView", XrmoptionNoArg, "True" },
1620 { "-xautoflip", "autoFlipView", XrmoptionNoArg, "False" },
1621 { "-autoObserve", "autoObserve", XrmoptionSepArg, NULL },
1622 { "-autobs", "autoObserve", XrmoptionNoArg, "True" },
1623 { "-xautobs", "autoObserve", XrmoptionNoArg, "False" },
1624 { "-autoComment", "autoComment", XrmoptionSepArg, NULL },
1625 { "-autocomm", "autoComment", XrmoptionNoArg, "True" },
1626 { "-xautocomm", "autoComment", XrmoptionNoArg, "False" },
1627 { "-getMoveList", "getMoveList", XrmoptionSepArg, NULL },
1628 { "-moves", "getMoveList", XrmoptionNoArg, "True" },
1629 { "-xmoves", "getMoveList", XrmoptionNoArg, "False" },
1631 { "-highlightDragging", "highlightDragging", XrmoptionSepArg, NULL },
1632 { "-highdrag", "highlightDragging", XrmoptionNoArg, "True" },
1633 { "-xhighdrag", "highlightDragging", XrmoptionNoArg, "False" },
1635 { "-highlightLastMove", "highlightLastMove", XrmoptionSepArg, NULL },
1636 { "-highlight", "highlightLastMove", XrmoptionNoArg, "True" },
1637 { "-xhighlight", "highlightLastMove", XrmoptionNoArg, "False" },
1638 { "-premove", "premove", XrmoptionSepArg, NULL },
1639 { "-pre", "premove", XrmoptionNoArg, "True" },
1640 { "-xpre", "premove", XrmoptionNoArg, "False" },
1641 { "-testLegality", "testLegality", XrmoptionSepArg, NULL },
1642 { "-legal", "testLegality", XrmoptionNoArg, "True" },
1643 { "-xlegal", "testLegality", XrmoptionNoArg, "False" },
1644 { "-flipView", "flipView", XrmoptionSepArg, NULL },
1645 { "-flip", "flipView", XrmoptionNoArg, "True" },
1646 { "-xflip", "flipView", XrmoptionNoArg, "False" },
1647 { "-cmail", "cmailGameName", XrmoptionSepArg, NULL },
1648 { "-alwaysPromoteToQueen", "alwaysPromoteToQueen",
1649 XrmoptionSepArg, NULL },
1650 { "-queen", "alwaysPromoteToQueen", XrmoptionNoArg, "True" },
1651 { "-xqueen", "alwaysPromoteToQueen", XrmoptionNoArg, "False" },
1652 { "-oldSaveStyle", "oldSaveStyle", XrmoptionSepArg, NULL },
1653 { "-oldsave", "oldSaveStyle", XrmoptionNoArg, "True" },
1654 { "-xoldsave", "oldSaveStyle", XrmoptionNoArg, "False" },
1655 { "-quietPlay", "quietPlay", XrmoptionSepArg, NULL },
1656 { "-quiet", "quietPlay", XrmoptionNoArg, "True" },
1657 { "-xquiet", "quietPlay", XrmoptionNoArg, "False" },
1658 { "-titleInWindow", "titleInWindow", XrmoptionSepArg, NULL },
1659 { "-title", "titleInWindow", XrmoptionNoArg, "True" },
1660 { "-xtitle", "titleInWindow", XrmoptionNoArg, "False" },
1662 { "-zippyTalk", "zippyTalk", XrmoptionSepArg, NULL },
1663 { "-zt", "zippyTalk", XrmoptionNoArg, "True" },
1664 { "-xzt", "zippyTalk", XrmoptionNoArg, "False" },
1665 { "-zippyPlay", "zippyPlay", XrmoptionSepArg, NULL },
1666 { "-zp", "zippyPlay", XrmoptionNoArg, "True" },
1667 { "-xzp", "zippyPlay", XrmoptionNoArg, "False" },
1668 { "-zippyLines", "zippyLines", XrmoptionSepArg, NULL },
1669 { "-zippyPinhead", "zippyPinhead", XrmoptionSepArg, NULL },
1670 { "-zippyPassword", "zippyPassword", XrmoptionSepArg, NULL },
1671 { "-zippyPassword2", "zippyPassword2", XrmoptionSepArg, NULL },
1672 { "-zippyWrongPassword", "zippyWrongPassword", XrmoptionSepArg, NULL },
1673 { "-zippyAcceptOnly", "zippyAcceptOnly", XrmoptionSepArg, NULL },
1674 { "-zippyUseI", "zippyUseI", XrmoptionSepArg, NULL },
1675 { "-zui", "zippyUseI", XrmoptionNoArg, "True" },
1676 { "-xzui", "zippyUseI", XrmoptionNoArg, "False" },
1677 { "-zippyBughouse", "zippyBughouse", XrmoptionSepArg, NULL },
1678 { "-zippyNoplayCrafty", "zippyNoplayCrafty", XrmoptionSepArg, NULL },
1679 { "-znc", "zippyNoplayCrafty", XrmoptionNoArg, "True" },
1680 { "-xznc", "zippyNoplayCrafty", XrmoptionNoArg, "False" },
1681 { "-zippyGameEnd", "zippyGameEnd", XrmoptionSepArg, NULL },
1682 { "-zippyGameStart", "zippyGameStart", XrmoptionSepArg, NULL },
1683 { "-zippyAdjourn", "zippyAdjourn", XrmoptionSepArg, NULL },
1684 { "-zadj", "zippyAdjourn", XrmoptionNoArg, "True" },
1685 { "-xzadj", "zippyAdjourn", XrmoptionNoArg, "False" },
1686 { "-zippyAbort", "zippyAbort", XrmoptionSepArg, NULL },
1687 { "-zab", "zippyAbort", XrmoptionNoArg, "True" },
1688 { "-xzab", "zippyAbort", XrmoptionNoArg, "False" },
1689 { "-zippyVariants", "zippyVariants", XrmoptionSepArg, NULL },
1690 { "-zippyMaxGames", "zippyMaxGames", XrmoptionSepArg, NULL },
1691 { "-zippyReplayTimeout", "zippyReplayTimeout", XrmoptionSepArg, NULL },
1692 { "-zippyShortGame", "zippyShortGame", XrmoptionSepArg, NULL },
1694 { "-flashCount", "flashCount", XrmoptionSepArg, NULL },
1695 { "-flash", "flashCount", XrmoptionNoArg, "3" },
1696 { "-xflash", "flashCount", XrmoptionNoArg, "0" },
1697 { "-flashRate", "flashRate", XrmoptionSepArg, NULL },
1698 { "-pixmapDirectory", "pixmapDirectory", XrmoptionSepArg, NULL },
1699 { "-msLoginDelay", "msLoginDelay", XrmoptionSepArg, NULL },
1700 { "-pixmap", "pixmapDirectory", XrmoptionSepArg, NULL },
1701 { "-colorizeMessages", "colorizeMessages", XrmoptionSepArg, NULL },
1702 { "-colorize", "colorizeMessages", XrmoptionNoArg, "True" },
1703 { "-xcolorize", "colorizeMessages", XrmoptionNoArg, "False" },
1704 { "-colorShout", "colorShout", XrmoptionSepArg, NULL },
1705 { "-colorSShout", "colorSShout", XrmoptionSepArg, NULL },
1706 { "-colorCShout", "colorSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1707 { "-colorChannel1", "colorChannel1", XrmoptionSepArg, NULL },
1708 { "-colorChannel", "colorChannel", XrmoptionSepArg, NULL },
1709 { "-colorKibitz", "colorKibitz", XrmoptionSepArg, NULL },
1710 { "-colorTell", "colorTell", XrmoptionSepArg, NULL },
1711 { "-colorChallenge", "colorChallenge", XrmoptionSepArg, NULL },
1712 { "-colorRequest", "colorRequest", XrmoptionSepArg, NULL },
1713 { "-colorSeek", "colorSeek", XrmoptionSepArg, NULL },
1714 { "-colorNormal", "colorNormal", XrmoptionSepArg, NULL },
1715 { "-soundProgram", "soundProgram", XrmoptionSepArg, NULL },
1716 { "-soundShout", "soundShout", XrmoptionSepArg, NULL },
1717 { "-soundSShout", "soundSShout", XrmoptionSepArg, NULL },
1718 { "-soundCShout", "soundSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1719 { "-soundChannel1", "soundChannel1", XrmoptionSepArg, NULL },
1720 { "-soundChannel", "soundChannel", XrmoptionSepArg, NULL },
1721 { "-soundKibitz", "soundKibitz", XrmoptionSepArg, NULL },
1722 { "-soundTell", "soundTell", XrmoptionSepArg, NULL },
1723 { "-soundChallenge", "soundChallenge", XrmoptionSepArg, NULL },
1724 { "-soundRequest", "soundRequest", XrmoptionSepArg, NULL },
1725 { "-soundSeek", "soundSeek", XrmoptionSepArg, NULL },
1726 { "-soundMove", "soundMove", XrmoptionSepArg, NULL },
1727 { "-soundIcsWin", "soundIcsWin", XrmoptionSepArg, NULL },
1728 { "-soundIcsLoss", "soundIcsLoss", XrmoptionSepArg, NULL },
1729 { "-soundIcsDraw", "soundIcsDraw", XrmoptionSepArg, NULL },
1730 { "-soundIcsUnfinished", "soundIcsUnfinished", XrmoptionSepArg, NULL },
1731 { "-soundIcsAlarm", "soundIcsAlarm", XrmoptionSepArg, NULL },
1732 { "-reuseFirst", "reuseFirst", XrmoptionSepArg, NULL },
1733 { "-reuseChessPrograms", "reuseFirst", XrmoptionSepArg, NULL }, /*compat*/
1734 { "-reuse", "reuseFirst", XrmoptionNoArg, "True" },
1735 { "-xreuse", "reuseFirst", XrmoptionNoArg, "False" },
1736 { "-reuseSecond", "reuseSecond", XrmoptionSepArg, NULL },
1737 { "-reuse2", "reuseSecond", XrmoptionNoArg, "True" },
1738 { "-xreuse2", "reuseSecond", XrmoptionNoArg, "False" },
1739 { "-animateMoving", "animateMoving", XrmoptionSepArg, NULL },
1740 { "-animate", "animateMoving", XrmoptionNoArg, "True" },
1741 { "-xanimate", "animateMoving", XrmoptionNoArg, "False" },
1742 { "-animateDragging", "animateDragging", XrmoptionSepArg, NULL },
1743 { "-drag", "animateDragging", XrmoptionNoArg, "True" },
1744 { "-xdrag", "animateDragging", XrmoptionNoArg, "False" },
1745 { "-animateSpeed", "animateSpeed", XrmoptionSepArg, NULL },
1746 { "-popupExitMessage", "popupExitMessage", XrmoptionSepArg, NULL },
1747 { "-exit", "popupExitMessage", XrmoptionNoArg, "True" },
1748 { "-xexit", "popupExitMessage", XrmoptionNoArg, "False" },
1749 { "-popupMoveErrors", "popupMoveErrors", XrmoptionSepArg, NULL },
1750 { "-popup", "popupMoveErrors", XrmoptionNoArg, "True" },
1751 { "-xpopup", "popupMoveErrors", XrmoptionNoArg, "False" },
1752 { "-fontSizeTolerance", "fontSizeTolerance", XrmoptionSepArg, NULL },
1753 { "-initialMode", "initialMode", XrmoptionSepArg, NULL },
1754 { "-mode", "initialMode", XrmoptionSepArg, NULL },
1755 { "-variant", "variant", XrmoptionSepArg, NULL },
1756 { "-firstProtocolVersion", "firstProtocolVersion", XrmoptionSepArg, NULL },
1757 { "-secondProtocolVersion","secondProtocolVersion",XrmoptionSepArg, NULL },
1758 { "-showButtonBar", "showButtonBar", XrmoptionSepArg, NULL },
1759 { "-buttons", "showButtonBar", XrmoptionNoArg, "True" },
1760 { "-xbuttons", "showButtonBar", XrmoptionNoArg, "False" },
1761 { "-lowTimeWarningColor", "lowTimeWarningColor", XrmoptionSepArg, NULL },
1762 { "-lowTimeWarning", "lowTimeWarning", XrmoptionSepArg, NULL },
1763 /* [AS,HR] New features */
1764 { "-firstScoreAbs", "firstScoreAbs", XrmoptionSepArg, NULL },
1765 { "-secondScoreAbs", "secondScoreAbs", XrmoptionSepArg, NULL },
1766 { "-pgnExtendedInfo", "pgnExtendedInfo", XrmoptionSepArg, NULL },
1767 { "-hideThinkingFromHuman", "hideThinkingFromHuman", XrmoptionSepArg, NULL },
1768 { "-adjudicateLossThreshold", "adjudicateLossThreshold", XrmoptionSepArg, NULL },
1769 { "-pgnEventHeader", "pgnEventHeader", XrmoptionSepArg, NULL },
1770 { "-firstIsUCI", "firstIsUCI", XrmoptionSepArg, NULL },
1771 { "-secondIsUCI", "secondIsUCI", XrmoptionSepArg, NULL },
1772 { "-fUCI", "firstIsUCI", XrmoptionNoArg, "True" },
1773 { "-sUCI", "secondIsUCI", XrmoptionNoArg, "True" },
1774 { "-firstHasOwnBookUCI", "firstHasOwnBookUCI", XrmoptionSepArg, NULL },
1775 { "-secondHasOwnBookUCI", "secondHasOwnBookUCI", XrmoptionSepArg, NULL },
1776 { "-fNoOwnBookUCI", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1777 { "-sNoOwnBookUCI", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1778 { "-firstXBook", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1779 { "-secondXBook", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1780 { "-polyglotDir", "polyglotDir", XrmoptionSepArg, NULL },
1781 { "-usePolyglotBook", "usePolyglotBook", XrmoptionSepArg, NULL },
1782 { "-polyglotBook", "polyglotBook", XrmoptionSepArg, NULL },
1783 { "-defaultHashSize", "defaultHashSize", XrmoptionSepArg, NULL },
1784 { "-defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XrmoptionSepArg, NULL },
1785 { "-defaultPathEGTB", "defaultPathEGTB", XrmoptionSepArg, NULL },
1786 { "-defaultFrcPosition", "defaultFrcPosition", XrmoptionSepArg, NULL },
1787 { "-gameListTags", "gameListTags", XrmoptionSepArg, NULL },
1788 // [HGM] I am sure AS added many more options, but we have to fish them out, from the list in winboard.c
1790 /* [HGM,HR] User-selectable board size */
1791 { "-boardWidth", "boardWidth", XrmoptionSepArg, NULL },
1792 { "-boardHeight", "boardHeight", XrmoptionSepArg, NULL },
1793 { "-matchPause", "matchPause", XrmoptionSepArg, NULL },
1795 /* [HGM] new arguments of 4.3.xx. All except first three are back-end options, which should work immediately */
1796 { "-holdingsSize", "holdingsSize", XrmoptionSepArg, NULL }, // requires extensive front-end changes to work
1797 { "-flipBlack", "flipBlack", XrmoptionSepArg, NULL }, // requires front-end changes to work
1798 { "-allWhite", "allWhite", XrmoptionSepArg, NULL }, // requires front-end changes to work
1799 { "-pieceToCharTable", "pieceToCharTable", XrmoptionSepArg, NULL },
1800 { "-alphaRank", "alphaRank", XrmoptionSepArg, NULL },
1801 { "-testClaims", "testClaims", XrmoptionSepArg, NULL },
1802 { "-checkMates", "checkMates", XrmoptionSepArg, NULL },
1803 { "-materialDraws", "materialDraws", XrmoptionSepArg, NULL },
1804 { "-trivialDraws", "trivialDraws", XrmoptionSepArg, NULL },
1805 { "-ruleMoves", "ruleMoves", XrmoptionSepArg, NULL },
1806 { "-repeatsToDraw", "repeatsToDraw", XrmoptionSepArg, NULL },
1807 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1808 { "-userName", "userName", XrmoptionSepArg, NULL },
1809 { "-autoKibitz", "autoKibitz", XrmoptionNoArg, "True" },
1810 { "-firstTimeOdds", "firstTimeOdds", XrmoptionSepArg, NULL },
1811 { "-secondTimeOdds", "secondTimeOdds", XrmoptionSepArg, NULL },
1812 { "-timeOddsMode", "timeOddsMode", XrmoptionSepArg, NULL },
1813 { "-firstAccumulateTC", "firstAccumulateTC", XrmoptionSepArg, NULL },
1814 { "-secondAccumulateTC", "secondAccumulateTC", XrmoptionSepArg, NULL },
1815 { "-firstNPS", "firstNPS", XrmoptionSepArg, NULL },
1816 { "-secondNPS", "secondNPS", XrmoptionSepArg, NULL },
1817 { "-serverMoves", "serverMoves", XrmoptionSepArg, NULL },
1818 { "-serverPause", "serverPause", XrmoptionSepArg, NULL },
1819 { "-suppressLoadMoves", "suppressLoadMoves", XrmoptionSepArg, NULL },
1820 { "-egtFormats", "egtFormats", XrmoptionSepArg, NULL },
1821 { "-userName", "userName", XrmoptionSepArg, NULL },
1822 { "-smpCores", "smpCores", XrmoptionSepArg, NULL },
1823 { "-sameColorGames", "sameColorGames", XrmoptionSepArg, NULL },
1824 { "-rewindIndex", "rewindIndex", XrmoptionSepArg, NULL },
1825 { "-niceEngines", "niceEngines", XrmoptionSepArg, NULL },
1826 { "-delayBeforeQuit", "delayBeforeQuit", XrmoptionSepArg, NULL },
1827 { "-delayAfterQuit", "delayAfterQuit", XrmoptionSepArg, NULL },
1828 { "-nameOfDebugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1829 { "-debugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1830 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1831 { "-noGUI", "noGUI", XrmoptionNoArg, "True" },
1832 { "-firstOptions", "firstOptions", XrmoptionSepArg, NULL },
1833 { "-secondOptions", "secondOptions", XrmoptionSepArg, NULL },
1834 { "-firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1835 { "-secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1839 XtActionsRec boardActions[] = {
1840 { "HandleUserMove", HandleUserMove },
1841 { "AnimateUserMove", AnimateUserMove },
1842 { "FileNameAction", FileNameAction },
1843 { "AskQuestionProc", AskQuestionProc },
1844 { "AskQuestionReplyAction", AskQuestionReplyAction },
1845 { "PieceMenuPopup", PieceMenuPopup },
1846 { "WhiteClock", WhiteClock },
1847 { "BlackClock", BlackClock },
1848 { "Iconify", Iconify },
1849 { "LoadSelectedProc", LoadSelectedProc },
1850 { "LoadPositionProc", LoadPositionProc },
1851 { "LoadNextPositionProc", LoadNextPositionProc },
1852 { "LoadPrevPositionProc", LoadPrevPositionProc },
1853 { "ReloadPositionProc", ReloadPositionProc },
1854 { "CopyPositionProc", CopyPositionProc },
1855 { "PastePositionProc", PastePositionProc },
1856 { "CopyGameProc", CopyGameProc },
1857 { "PasteGameProc", PasteGameProc },
1858 { "SaveGameProc", SaveGameProc },
1859 { "SavePositionProc", SavePositionProc },
1860 { "MailMoveProc", MailMoveProc },
1861 { "ReloadCmailMsgProc", ReloadCmailMsgProc },
1862 // { "MachineWhiteProc", MachineWhiteProc },
1863 // { "MachineBlackProc", MachineBlackProc },
1864 { "AnalysisModeProc", AnalyzeModeProc },
1865 { "AnalyzeFileProc", AnalyzeFileProc },
1866 // { "TwoMachinesProc", TwoMachinesProc },
1867 { "IcsClientProc", IcsClientProc },
1868 { "EditGameProc", EditGameProc },
1869 { "EditPositionProc", EditPositionProc },
1870 { "TrainingProc", EditPositionProc },
1871 { "EngineOutputProc", EngineOutputProc}, // [HGM] Winboard_x engine-output window
1872 { "ShowGameListProc", ShowGameListProc },
1873 { "ShowMoveListProc", HistoryShowProc},
1874 { "EditTagsProc", EditCommentProc },
1875 { "EditCommentProc", EditCommentProc },
1876 { "IcsAlarmProc", IcsAlarmProc },
1877 { "IcsInputBoxProc", IcsInputBoxProc },
1878 // { "AcceptProc", AcceptProc },
1879 // { "DeclineProc", DeclineProc },
1880 // { "RematchProc", RematchProc },
1881 // { "CallFlagProc", CallFlagProc },
1882 // { "DrawProc", DrawProc },
1883 // { "AdjournProc", AdjournProc },
1884 // { "AbortProc", AbortProc },
1885 // { "ResignProc", ResignProc },
1886 // { "AdjuWhiteProc", AdjuWhiteProc },
1887 // { "AdjuBlackProc", AdjuBlackProc },
1888 // { "AdjuDrawProc", AdjuDrawProc },
1889 { "EnterKeyProc", EnterKeyProc },
1890 // { "StopObservingProc", StopObservingProc },
1891 // { "StopExaminingProc", StopExaminingProc },
1892 { "BackwardProc", BackwardProc },
1893 { "ForwardProc", ForwardProc },
1894 { "ToStartProc", ToStartProc },
1895 { "ToEndProc", ToEndProc },
1896 { "RevertProc", RevertProc },
1897 { "TruncateGameProc", TruncateGameProc },
1898 // { "MoveNowProc", MoveNowProc },
1899 { "RetractMoveProc", RetractMoveProc },
1900 { "AlwaysQueenProc", AlwaysQueenProc },
1901 { "AnimateDraggingProc", AnimateDraggingProc },
1902 { "AnimateMovingProc", AnimateMovingProc },
1903 { "AutoflagProc", AutoflagProc },
1904 { "AutoflipProc", AutoflipProc },
1905 { "AutobsProc", AutobsProc },
1906 { "AutoraiseProc", AutoraiseProc },
1907 { "AutosaveProc", AutosaveProc },
1908 { "BlindfoldProc", BlindfoldProc },
1909 { "FlashMovesProc", FlashMovesProc },
1910 { "FlipViewProc", FlipViewProc },
1911 { "GetMoveListProc", GetMoveListProc },
1913 { "HighlightDraggingProc", HighlightDraggingProc },
1915 { "HighlightLastMoveProc", HighlightLastMoveProc },
1916 { "IcsAlarmProc", IcsAlarmProc },
1917 { "MoveSoundProc", MoveSoundProc },
1918 { "OldSaveStyleProc", OldSaveStyleProc },
1919 { "PeriodicUpdatesProc", PeriodicUpdatesProc },
1920 { "PonderNextMoveProc", PonderNextMoveProc },
1921 { "PopupExitMessageProc", PopupExitMessageProc },
1922 { "PopupMoveErrorsProc", PopupMoveErrorsProc },
1923 { "PremoveProc", PremoveProc },
1924 { "QuietPlayProc", QuietPlayProc },
1925 { "ShowThinkingProc", ShowThinkingProc },
1926 { "HideThinkingProc", HideThinkingProc },
1927 { "TestLegalityProc", TestLegalityProc },
1928 { "InfoProc", InfoProc },
1929 { "ManProc", ManProc },
1930 { "HintProc", HintProc },
1931 { "BookProc", BookProc },
1932 { "AboutGameProc", AboutGameProc },
1933 { "DebugProc", DebugProc },
1934 { "NothingProc", NothingProc },
1935 { "CommentPopDown", (XtActionProc) CommentPopDown },
1936 { "EditCommentPopDown", (XtActionProc) EditCommentPopDown },
1937 { "TagsPopDown", (XtActionProc) TagsPopDown },
1938 { "ErrorPopDown", (XtActionProc) ErrorPopDown },
1939 { "ICSInputBoxPopDown", (XtActionProc) ICSInputBoxPopDown },
1940 { "AnalysisPopDown", (XtActionProc) AnalysisPopDown },
1941 { "FileNamePopDown", (XtActionProc) FileNamePopDown },
1942 { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown },
1943 { "GameListPopDown", (XtActionProc) GameListPopDown },
1944 { "PromotionPopDown", (XtActionProc) PromotionPopDown },
1945 { "HistoryPopDown", (XtActionProc) HistoryPopDown },
1946 { "EngineOutputPopDown", (XtActionProc) EngineOutputPopDown },
1947 { "ShufflePopDown", (XtActionProc) ShufflePopDown },
1948 { "EnginePopDown", (XtActionProc) EnginePopDown },
1949 { "UciPopDown", (XtActionProc) UciPopDown },
1950 { "TimeControlPopDown", (XtActionProc) TimeControlPopDown },
1951 { "NewVariantPopDown", (XtActionProc) NewVariantPopDown },
1952 { "SettingsPopDown", (XtActionProc) SettingsPopDown },
1956 char ICSInputTranslations[] =
1957 "<Key>Return: EnterKeyProc() \n";
1959 String xboardResources[] = {
1960 "*fileName*value.translations: #override\\n <Key>Return: FileNameAction()",
1961 "*question*value.translations: #override\\n <Key>Return: AskQuestionReplyAction()",
1962 "*errorpopup*translations: #override\\n <Key>Return: ErrorPopDown()",
1966 static char *cnames[9] = { "black", "red", "green", "yellow", "blue",
1967 "magenta", "cyan", "white" };
1971 TextColors textColors[(int)NColorClasses];
1973 /* String is: "fg, bg, attr". Which is 0, 1, 2 */
1975 parse_color(str, which)
1979 char *p, buf[100], *d;
1982 if (strlen(str) > 99) /* watch bounds on buf */
1987 for (i=0; i<which; ++i) {
1994 /* Could be looking at something like:
1996 .. in which case we want to stop on a comma also */
1997 while (*p && *p != ',' && !isalpha(*p) && !isdigit(*p))
2001 return -1; /* Use default for empty field */
2004 if (which == 2 || isdigit(*p))
2007 while (*p && isalpha(*p))
2012 for (i=0; i<8; ++i) {
2013 if (!StrCaseCmp(buf, cnames[i]))
2014 return which? (i+40) : (i+30);
2016 if (!StrCaseCmp(buf, "default")) return -1;
2018 fprintf(stderr, _("%s: unrecognized color %s\n"), programName, buf);
2023 parse_cpair(cc, str)
2027 if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {
2028 fprintf(stderr, _("%s: can't parse foreground color in `%s'\n"),
2033 /* bg and attr are optional */
2034 textColors[(int)cc].bg = parse_color(str, 1);
2035 if ((textColors[(int)cc].attr = parse_color(str, 2)) < 0) {
2036 textColors[(int)cc].attr = 0;
2042 /* Arrange to catch delete-window events */
2043 Atom wm_delete_window;
2045 CatchDeleteWindow(Widget w, String procname)
2048 XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
2049 snprintf(buf, sizeof(buf), "<Message>WM_PROTOCOLS: %s() \n", procname);
2050 XtAugmentTranslations(w, XtParseTranslationTable(buf));
2056 /* this should raise the board to the top */
2057 gtk_window_present(GTK_WINDOW(GUI_Window));
2062 // eventually, all layout determining code should go into a subroutine, but until then IDSIZE remains undefined
2064 #define BoardSize int
2065 void InitDrawingSizes(BoardSize boardSize, int flags)
2066 { // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
2067 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2069 XtGeometryResult gres;
2072 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2073 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2075 timerWidth = (boardWidth - sep) / 2;
2077 if (appData.titleInWindow)
2082 w = boardWidth - 2*bor;
2086 w = boardWidth - w - sep - 2*bor - 2; // WIDTH_FUDGE
2090 if(!formWidget) return;
2093 * Inhibit shell resizing.
2096 // [HGM] pieces: tailor piece bitmaps to needs of specific variant
2099 for(i=0; i<4; i++) {
2101 for(p=0; p<=(int)WhiteKing; p++)
2102 xpmPieceBitmap[i][p] = xpmPieceBitmap2[i][p]; // defaults
2103 if(gameInfo.variant == VariantShogi) {
2104 xpmPieceBitmap[i][(int)WhiteCannon] = xpmPieceBitmap2[i][(int)WhiteKing+1];
2105 xpmPieceBitmap[i][(int)WhiteNightrider] = xpmPieceBitmap2[i][(int)WhiteKing+2];
2106 xpmPieceBitmap[i][(int)WhiteSilver] = xpmPieceBitmap2[i][(int)WhiteKing+3];
2107 xpmPieceBitmap[i][(int)WhiteGrasshopper] = xpmPieceBitmap2[i][(int)WhiteKing+4];
2108 xpmPieceBitmap[i][(int)WhiteQueen] = xpmPieceBitmap2[i][(int)WhiteLance];
2111 if(gameInfo.variant == VariantGothic) {
2112 xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteSilver];
2116 // [HGM] why are thee ximMasks used at all? the ximPieceBitmaps seem to be never used!
2117 for(p=0; p<=(int)WhiteKing; p++)
2118 ximMaskPm[p] = ximMaskPm2[p]; // defaults
2119 if(gameInfo.variant == VariantShogi) {
2120 ximMaskPm[(int)WhiteCannon] = ximMaskPm2[(int)WhiteKing+1];
2121 ximMaskPm[(int)WhiteNightrider] = ximMaskPm2[(int)WhiteKing+2];
2122 ximMaskPm[(int)WhiteSilver] = ximMaskPm2[(int)WhiteKing+3];
2123 ximMaskPm[(int)WhiteGrasshopper] = ximMaskPm2[(int)WhiteKing+4];
2124 ximMaskPm[(int)WhiteQueen] = ximMaskPm2[(int)WhiteLance];
2127 if(gameInfo.variant == VariantGothic) {
2128 ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[i][(int)WhiteSilver];
2134 for(i=0; i<2; i++) {
2136 for(p=0; p<=(int)WhiteKing; p++)
2137 pieceBitmap[i][p] = pieceBitmap2[i][p]; // defaults
2138 if(gameInfo.variant == VariantShogi) {
2139 pieceBitmap[i][(int)WhiteCannon] = pieceBitmap2[i][(int)WhiteKing+1];
2140 pieceBitmap[i][(int)WhiteNightrider] = pieceBitmap2[i][(int)WhiteKing+2];
2141 pieceBitmap[i][(int)WhiteSilver] = pieceBitmap2[i][(int)WhiteKing+3];
2142 pieceBitmap[i][(int)WhiteGrasshopper] = pieceBitmap2[i][(int)WhiteKing+4];
2143 pieceBitmap[i][(int)WhiteQueen] = pieceBitmap2[i][(int)WhiteLance];
2146 if(gameInfo.variant == VariantGothic) {
2147 pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteSilver];
2163 int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
2164 XSetWindowAttributes window_attributes;
2166 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2167 XrmValue vFrom, vTo;
2168 XtGeometryResult gres;
2171 int forceMono = False;
2175 // [HGM] before anything else, expand any indirection files amongst options
2176 char *argvCopy[1000]; // 1000 seems enough
2177 char newArgs[10000]; // holds actual characters
2180 srandom(time(0)); // [HGM] book: make random truly random
2183 for(i=0; i<argc; i++) {
2184 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2185 //fprintf(stderr, "arg %s\n", argv[i]);
2186 if(argv[i][0] != '@') argvCopy[j++] = argv[i]; else {
2188 FILE *f = fopen(argv[i]+1, "rb");
2189 if(f == NULL) { fprintf(stderr, _("ignore %s\n"), argv[i]); continue; } // do not expand non-existing
2190 argvCopy[j++] = newArgs + k; // get ready for first argument from file
2191 while((c = fgetc(f)) != EOF) { // each line of file inserts 1 argument in the list
2193 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2194 newArgs[k++] = 0; // terminate current arg
2195 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2196 argvCopy[j++] = newArgs + k; // get ready for next
2198 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2211 if(appData.debugMode,1) { // OK, appData is not initialized here yet...
2212 for(i=0; i<argc; i++) fprintf(stderr, "argv[%2d] = '%s'\n", i, argv[i]);
2218 setbuf(stdout, NULL);
2219 setbuf(stderr, NULL);
2222 programName = strrchr(argv[0], '/');
2223 if (programName == NULL)
2224 programName = argv[0];
2229 XtSetLanguageProc(NULL, NULL, NULL);
2230 bindtextdomain(PACKAGE, LOCALEDIR);
2231 textdomain(PACKAGE);
2235 XtAppInitialize(&appContext, "XBoard", shellOptions,
2236 XtNumber(shellOptions),
2237 &argc, argv, xboardResources, NULL, 0);
2241 gtk_init (&argc, &argv);
2243 /* parse glade file to build widgets */
2245 builder = gtk_builder_new ();
2246 gtk_builder_add_from_file (builder, "gtk-interface.xml", NULL);
2248 /* test if everything worked ok */
2250 GUI_Window = GTK_WIDGET (gtk_builder_get_object (builder, "MainWindow"));
2251 if(!GUI_Window) printf("Error: gtk_builder didn't work!\n");
2252 GUI_Board = GTK_WIDGET (gtk_builder_get_object (builder, "Board"));
2253 if(!GUI_Board) printf("Error: gtk_builder didn't work!\n");
2254 GUI_Whiteclock = GTK_WIDGET (gtk_builder_get_object (builder, "WhiteClock"));
2255 if(!GUI_Whiteclock) printf("Error: gtk_builder didn't work!\n");
2256 GUI_Blackclock = GTK_WIDGET (gtk_builder_get_object (builder, "BlackClock"));
2257 if(!GUI_Blackclock) printf("Error: gtk_builder didn't work!\n");
2259 gtk_builder_connect_signals (builder, NULL);
2261 // don't unref the builder, since we use it to get references to widgets
2262 // g_object_unref (G_OBJECT (builder));
2264 /* end parse glade file */
2268 fprintf(stderr, _("%s: unrecognized argument %s\n"),
2269 programName, argv[1]);
2270 fprintf(stderr, "Recognized options:\n");
2271 for(i = 0; i < XtNumber(shellOptions); i++)
2273 j = fprintf(stderr, " %s%s", shellOptions[i].option,
2274 (shellOptions[i].argKind == XrmoptionSepArg
2276 if (i++ < XtNumber(shellOptions))
2278 fprintf(stderr, "%*c%s%s\n", 40 - j, ' ',
2279 shellOptions[i].option,
2280 (shellOptions[i].argKind == XrmoptionSepArg
2285 fprintf(stderr, "\n");
2291 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL)
2297 if (chdir(chessDir) != 0)
2299 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
2306 if (p == NULL) p = "/tmp";
2307 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
2308 gameCopyFilename = (char*) malloc(i);
2309 gamePasteFilename = (char*) malloc(i);
2310 snprintf(gameCopyFilename,i, "%s/.xboard%05uc.pgn", p, getpid());
2311 snprintf(gamePasteFilename,i, "%s/.xboard%05up.pgn", p, getpid());
2313 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
2314 clientResources, XtNumber(clientResources),
2317 if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) {
2318 /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */
2319 if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL) {
2320 printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile);
2323 setbuf(debugFP, NULL);
2326 /* [HGM,HR] make sure board size is acceptable */
2327 if(appData.NrFiles > BOARD_SIZE ||
2328 appData.NrRanks > BOARD_SIZE )
2329 DisplayFatalError(_("Recompile with BOARD_SIZE > 12, to support this size"), 0, 2);
2332 /* This feature does not work; animation needs a rewrite */
2333 appData.highlightDragging = FALSE;
2337 xDisplay = XtDisplay(shellWidget);
2338 xScreen = DefaultScreen(xDisplay);
2339 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
2341 gameInfo.variant = StringToVariant(appData.variant);
2342 InitPosition(FALSE);
2346 * Determine boardSize
2348 gameInfo.boardWidth = gameInfo.boardHeight = 8; // [HGM] boardsize: make sure we start as 8x8
2351 // [HGM] as long as we have not created the possibility to change size while running, start with requested size
2352 gameInfo.boardWidth = appData.NrFiles > 0 ? appData.NrFiles : 8;
2353 gameInfo.boardHeight = appData.NrRanks > 0 ? appData.NrRanks : 8;
2354 gameInfo.holdingsWidth = appData.holdingsSize > 0 ? 2 : 0;
2359 InitDrawingSizes(-1, 0); // [HGM] initsize: make this into a subroutine
2361 if (isdigit(appData.boardSize[0])) {
2362 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
2363 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
2364 &fontPxlSize, &smallLayout, &tinyLayout);
2366 fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
2367 programName, appData.boardSize);
2371 /* Find some defaults; use the nearest known size */
2372 SizeDefaults *szd, *nearest;
2373 int distance = 99999;
2374 nearest = szd = sizeDefaults;
2375 while (szd->name != NULL) {
2376 if (abs(szd->squareSize - squareSize) < distance) {
2378 distance = abs(szd->squareSize - squareSize);
2379 if (distance == 0) break;
2383 if (i < 2) lineGap = nearest->lineGap;
2384 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
2385 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
2386 if (i < 5) fontPxlSize = nearest->fontPxlSize;
2387 if (i < 6) smallLayout = nearest->smallLayout;
2388 if (i < 7) tinyLayout = nearest->tinyLayout;
2391 SizeDefaults *szd = sizeDefaults;
2392 if (*appData.boardSize == NULLCHAR) {
2393 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize ||
2394 DisplayHeight(xDisplay, xScreen) < szd->minScreenSize) {
2397 if (szd->name == NULL) szd--;
2399 while (szd->name != NULL &&
2400 StrCaseCmp(szd->name, appData.boardSize) != 0) szd++;
2401 if (szd->name == NULL) {
2402 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
2403 programName, appData.boardSize);
2407 squareSize = szd->squareSize;
2408 lineGap = szd->lineGap;
2409 clockFontPxlSize = szd->clockFontPxlSize;
2410 coordFontPxlSize = szd->coordFontPxlSize;
2411 fontPxlSize = szd->fontPxlSize;
2412 smallLayout = szd->smallLayout;
2413 tinyLayout = szd->tinyLayout;
2416 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2417 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2418 if (appData.showJail == 1) {
2419 /* Jail on top and bottom */
2420 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2421 XtSetArg(boardArgs[2], XtNheight,
2422 boardHeight + 2*(lineGap + squareSize));
2423 } else if (appData.showJail == 2) {
2425 XtSetArg(boardArgs[1], XtNwidth,
2426 boardWidth + 2*(lineGap + squareSize));
2427 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2430 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2431 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2435 * Determine what fonts to use.
2437 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
2438 clockFontID = XLoadFont(xDisplay, appData.clockFont);
2439 clockFontStruct = XQueryFont(xDisplay, clockFontID);
2440 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
2441 coordFontID = XLoadFont(xDisplay, appData.coordFont);
2442 coordFontStruct = XQueryFont(xDisplay, coordFontID);
2443 appData.font = FindFont(appData.font, fontPxlSize);
2444 countFontID = XLoadFont(xDisplay, appData.coordFont); // [HGM] holdings
2445 countFontStruct = XQueryFont(xDisplay, countFontID);
2446 // appData.font = FindFont(appData.font, fontPxlSize);
2448 xdb = XtDatabase(xDisplay);
2449 XrmPutStringResource(&xdb, "*font", appData.font);
2452 * Detect if there are not enough colors available and adapt.
2454 if (DefaultDepth(xDisplay, xScreen) <= 2) {
2455 appData.monoMode = True;
2458 if (!appData.monoMode) {
2459 vFrom.addr = (caddr_t) appData.lightSquareColor;
2460 vFrom.size = strlen(appData.lightSquareColor);
2461 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2462 if (vTo.addr == NULL) {
2463 appData.monoMode = True;
2466 lightSquareColor = *(Pixel *) vTo.addr;
2469 if (!appData.monoMode) {
2470 vFrom.addr = (caddr_t) appData.darkSquareColor;
2471 vFrom.size = strlen(appData.darkSquareColor);
2472 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2473 if (vTo.addr == NULL) {
2474 appData.monoMode = True;
2477 darkSquareColor = *(Pixel *) vTo.addr;
2480 if (!appData.monoMode) {
2481 vFrom.addr = (caddr_t) appData.whitePieceColor;
2482 vFrom.size = strlen(appData.whitePieceColor);
2483 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2484 if (vTo.addr == NULL) {
2485 appData.monoMode = True;
2488 whitePieceColor = *(Pixel *) vTo.addr;
2491 if (!appData.monoMode) {
2492 vFrom.addr = (caddr_t) appData.blackPieceColor;
2493 vFrom.size = strlen(appData.blackPieceColor);
2494 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2495 if (vTo.addr == NULL) {
2496 appData.monoMode = True;
2499 blackPieceColor = *(Pixel *) vTo.addr;
2503 if (!appData.monoMode) {
2504 vFrom.addr = (caddr_t) appData.highlightSquareColor;
2505 vFrom.size = strlen(appData.highlightSquareColor);
2506 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2507 if (vTo.addr == NULL) {
2508 appData.monoMode = True;
2511 highlightSquareColor = *(Pixel *) vTo.addr;
2515 if (!appData.monoMode) {
2516 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
2517 vFrom.size = strlen(appData.premoveHighlightColor);
2518 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2519 if (vTo.addr == NULL) {
2520 appData.monoMode = True;
2523 premoveHighlightColor = *(Pixel *) vTo.addr;
2528 fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2531 if (appData.bitmapDirectory == NULL ||
2532 appData.bitmapDirectory[0] == NULLCHAR)
2533 appData.bitmapDirectory = DEF_BITMAP_DIR;
2536 if (appData.lowTimeWarning && !appData.monoMode) {
2537 vFrom.addr = (caddr_t) appData.lowTimeWarningColor;
2538 vFrom.size = strlen(appData.lowTimeWarningColor);
2539 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2540 if (vTo.addr == NULL)
2541 appData.monoMode = True;
2543 lowTimeWarningColor = *(Pixel *) vTo.addr;
2546 if (appData.monoMode && appData.debugMode) {
2547 fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2548 (unsigned long) XWhitePixel(xDisplay, xScreen),
2549 (unsigned long) XBlackPixel(xDisplay, xScreen));
2552 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
2553 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
2554 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
2555 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
2556 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
2557 parse_cpair(ColorTell, appData.colorTell) < 0 ||
2558 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
2559 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
2560 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
2561 parse_cpair(ColorNormal, appData.colorNormal) < 0)
2563 if (appData.colorize) {
2565 _("%s: can't parse color names; disabling colorization\n"),
2568 appData.colorize = FALSE;
2570 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2571 textColors[ColorNone].attr = 0;
2573 // XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2579 layoutName = "tinyLayout";
2580 } else if (smallLayout) {
2581 layoutName = "smallLayout";
2583 layoutName = "normalLayout";
2586 if (appData.titleInWindow) {
2587 /* todo check what this appdata does */
2590 if (appData.showButtonBar) {
2591 /* TODO hide button bar if requested */
2595 * gtk set properties of widgets
2598 /* set board size */
2599 gtk_widget_set_size_request(GTK_WIDGET(GUI_Board),
2600 boardWidth,boardHeight);
2602 /* end gtk set properties of widgets */
2604 if (appData.titleInWindow)
2609 if (appData.showButtonBar)
2616 if (appData.showButtonBar)
2625 // [HGM] it seems the layout code ends here, but perhaps the color stuff is size independent and would
2626 // not need to go into InitDrawingSizes().
2629 /* set some checkboxes in the menu according to appData */
2631 if (appData.alwaysPromoteToQueen)
2632 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Always Queen")),TRUE);
2634 if (appData.animateDragging)
2635 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Animate Dragging")),TRUE);
2637 if (appData.animate)
2638 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Animate Moving")),TRUE);
2640 if (appData.autoComment)
2641 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Comment")),TRUE);
2643 if (appData.autoCallFlag)
2644 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Flag")),TRUE);
2646 if (appData.autoFlipView)
2647 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Flip View")),TRUE);
2649 if (appData.autoObserve)
2650 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Observe")),TRUE);
2652 if (appData.autoRaiseBoard)
2653 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Raise Board")),TRUE);
2655 if (appData.autoSaveGames)
2656 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Save")),TRUE);
2658 if (appData.saveGameFile[0] != NULLCHAR)
2660 /* Can't turn this off from menu */
2661 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Save")),TRUE);
2662 gtk_action_set_sensitive(GTK_ACTION (gtk_builder_get_object (builder, "menuOptions.Auto Save")),FALSE);
2665 if (appData.blindfold)
2666 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Blindfold")),TRUE);
2668 if (appData.flashCount > 0)
2669 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Flash Moves")),TRUE);
2671 if (appData.getMoveList)
2672 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Get Move List")),TRUE);
2675 if (appData.highlightDragging)
2676 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Highlight Dragging")),TRUE);
2679 if (appData.highlightLastMove)
2680 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Highlight Last Move")),TRUE);
2682 if (appData.icsAlarm)
2683 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.ICS Alarm")),TRUE);
2685 if (appData.ringBellAfterMoves)
2686 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Move Sound")),TRUE);
2688 if (appData.oldSaveStyle)
2689 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Old Save Style")),TRUE);
2691 if (appData.periodicUpdates)
2692 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Periodic Updates")),TRUE);
2694 if (appData.ponderNextMove)
2695 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Ponder Next Move")),TRUE);
2697 if (appData.popupExitMessage)
2698 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Popup Exit Message")),TRUE);
2700 if (appData.popupMoveErrors)
2701 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Popup Move Errors")),TRUE);
2703 if (appData.premove)
2704 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Premove")),TRUE);
2706 if (appData.quietPlay)
2707 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Quit Play")),TRUE);
2709 if (appData.showCoords)
2710 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Show Coords")),TRUE);
2712 if (appData.showThinking)
2713 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Show Thinking")),TRUE);
2715 if (appData.testLegality)
2716 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Test Legality")),TRUE);
2718 /* end setting check boxes */
2721 /* load square colors */
2722 SVGLightSquare = load_pixbuf("svg/LightSquare.svg",squareSize);
2723 SVGDarkSquare = load_pixbuf("svg/DarkSquare.svg",squareSize);
2724 SVGNeutralSquare = load_pixbuf("svg/NeutralSquare.svg",squareSize);
2726 /* use two icons to indicate if it is white's or black's turn */
2727 WhiteIcon = load_pixbuf("svg/icon_white.svg",0);
2728 BlackIcon = load_pixbuf("svg/icon_black.svg",0);
2729 WindowIcon = WhiteIcon;
2730 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
2732 /* do resizing to a fixed aspect ratio */
2737 GUI_SetAspectRatio(0.7);
2739 /* realize window */
2740 gtk_widget_show (GUI_Window);
2746 if (appData.animate || appData.animateDragging)
2751 if (errorExitStatus == -1) {
2752 if (appData.icsActive) {
2753 /* We now wait until we see "login:" from the ICS before
2754 sending the logon script (problems with timestamp otherwise) */
2755 /*ICSInitScript();*/
2756 if (appData.icsInputBox) ICSInputBoxPopUp();
2759 signal(SIGINT, IntSigHandler);
2760 signal(SIGTERM, IntSigHandler);
2761 if (*appData.cmailGameName != NULLCHAR) {
2762 signal(SIGUSR1, CmailSigHandler);
2765 gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes()
2769 * Create a cursor for the board widget.
2770 * (This needs to be called after the window has been created to have access to board-window)
2773 BoardCursor = gdk_cursor_new(GDK_HAND2);
2774 gdk_window_set_cursor(GUI_Board->window, BoardCursor);
2775 gdk_cursor_destroy(BoardCursor);
2780 if (appData.debugMode) fclose(debugFP); // [DM] debug
2787 if (appData.icsActive && oldICSInteractionTitle != NULL) {
2788 DisplayIcsInteractionTitle(oldICSInteractionTitle);
2790 unlink(gameCopyFilename);
2791 unlink(gamePasteFilename);
2802 CmailSigHandler(sig)
2808 signal(SIGUSR1, SIG_IGN); /* suspend handler */
2810 /* Activate call-back function CmailSigHandlerCallBack() */
2811 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
2813 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
2817 CmailSigHandlerCallBack(isr, closure, message, count, error)
2825 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
2827 /**** end signal code ****/
2837 f = fopen(appData.icsLogon, "r");
2843 strcat(buf, appData.icsLogon);
2844 f = fopen(buf, "r");
2848 ProcessICSInitScript(f);
2855 EditCommentPopDown();
2861 SetMenuEnables(enab)
2866 if (!builder) return;
2867 while (enab->name != NULL) {
2868 o = gtk_builder_get_object(builder, enab->name);
2869 if(GTK_IS_WIDGET(o))
2870 gtk_widget_set_sensitive(GTK_WIDGET (o),enab->value);
2873 if(GTK_IS_ACTION(o))
2874 gtk_action_set_sensitive(GTK_ACTION (o),enab->value);
2876 DisplayError(enab->name, 0);
2884 SetMenuEnables(icsEnables);
2887 if (appData.zippyPlay && !appData.noChessProgram) /* [DM] icsEngineAnalyze */
2888 {}; // XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
2895 SetMenuEnables(ncpEnables);
2901 SetMenuEnables(gnuEnables);
2907 SetMenuEnables(cmailEnables);
2913 SetMenuEnables(trainingOnEnables);
2914 if (appData.showButtonBar) {
2915 // XtSetSensitive(buttonBarWidget, False);
2921 SetTrainingModeOff()
2923 SetMenuEnables(trainingOffEnables);
2924 if (appData.showButtonBar) {
2925 // XtSetSensitive(buttonBarWidget, True);
2930 SetUserThinkingEnables()
2932 if (appData.noChessProgram) return;
2933 SetMenuEnables(userThinkingEnables);
2937 SetMachineThinkingEnables()
2939 if (appData.noChessProgram) return;
2940 SetMenuEnables(machineThinkingEnables);
2942 case MachinePlaysBlack:
2943 case MachinePlaysWhite:
2944 case TwoMachinesPlay:
2945 // XtSetSensitive(XtNameToWidget(menuBarWidget,
2946 // ModeToWidgetName(gameMode)), True);
2953 #define Abs(n) ((n)<0 ? -(n) : (n))
2956 * Find a font that matches "pattern" that is as close as
2957 * possible to the targetPxlSize. Prefer fonts that are k
2958 * pixels smaller to fonts that are k pixels larger. The
2959 * pattern must be in the X Consortium standard format,
2960 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
2961 * The return value should be freed with XtFree when no
2964 char *FindFont(pattern, targetPxlSize)
2968 char **fonts, *p, *best, *scalable, *scalableTail;
2969 int i, j, nfonts, minerr, err, pxlSize;
2972 char **missing_list;
2974 char *def_string, *base_fnt_lst, strInt[3];
2976 XFontStruct **fnt_list;
2978 base_fnt_lst = calloc(1, strlen(pattern) + 3);
2979 sprintf(strInt, "%d", targetPxlSize);
2980 p = strstr(pattern, "--");
2981 strncpy(base_fnt_lst, pattern, p - pattern + 2);
2982 strcat(base_fnt_lst, strInt);
2983 strcat(base_fnt_lst, strchr(p + 2, '-'));
2985 if ((fntSet = XCreateFontSet(xDisplay,
2989 &def_string)) == NULL) {
2991 fprintf(stderr, _("Unable to create font set.\n"));
2995 nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
2997 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
2999 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
3000 programName, pattern);
3008 for (i=0; i<nfonts; i++) {
3011 if (*p != '-') continue;
3013 if (*p == NULLCHAR) break;
3014 if (*p++ == '-') j++;
3016 if (j < 7) continue;
3019 scalable = fonts[i];
3022 err = pxlSize - targetPxlSize;
3023 if (Abs(err) < Abs(minerr) ||
3024 (minerr > 0 && err < 0 && -err == minerr)) {
3030 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
3031 /* If the error is too big and there is a scalable font,
3032 use the scalable font. */
3033 int headlen = scalableTail - scalable;
3034 p = (char *) XtMalloc(strlen(scalable) + 10);
3035 while (isdigit(*scalableTail)) scalableTail++;
3036 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
3038 p = (char *) XtMalloc(strlen(best) + 1);
3041 if (appData.debugMode) {
3042 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
3043 pattern, targetPxlSize, p);
3046 if (missing_count > 0)
3047 XFreeStringList(missing_list);
3048 XFreeFontSet(xDisplay, fntSet);
3050 XFreeFontNames(fonts);
3057 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
3058 | GCBackground | GCFunction | GCPlaneMask;
3059 XGCValues gc_values;
3062 gc_values.plane_mask = AllPlanes;
3063 gc_values.line_width = lineGap;
3064 gc_values.line_style = LineSolid;
3065 gc_values.function = GXcopy;
3067 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3068 gc_values.background = XWhitePixel(xDisplay, xScreen);
3069 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
3070 XSetFont(xDisplay, coordGC, coordFontID);
3072 if (appData.monoMode) {
3073 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3074 gc_values.background = XBlackPixel(xDisplay, xScreen);
3075 lightSquareGC = wbPieceGC
3076 = XtGetGC(shellWidget, value_mask, &gc_values);
3078 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3079 gc_values.background = XWhitePixel(xDisplay, xScreen);
3080 darkSquareGC = bwPieceGC
3081 = XtGetGC(shellWidget, value_mask, &gc_values);
3083 if (DefaultDepth(xDisplay, xScreen) == 1) {
3084 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3085 gc_values.function = GXcopyInverted;
3086 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3087 gc_values.function = GXcopy;
3088 if (XBlackPixel(xDisplay, xScreen) == 1) {
3089 bwPieceGC = darkSquareGC;
3090 wbPieceGC = copyInvertedGC;
3092 bwPieceGC = copyInvertedGC;
3093 wbPieceGC = lightSquareGC;
3097 gc_values.foreground = lightSquareColor;
3098 gc_values.background = darkSquareColor;
3099 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3101 gc_values.foreground = darkSquareColor;
3102 gc_values.background = lightSquareColor;
3103 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3105 gc_values.foreground = jailSquareColor;
3106 gc_values.background = jailSquareColor;
3107 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3109 gc_values.foreground = whitePieceColor;
3110 gc_values.background = darkSquareColor;
3111 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3113 gc_values.foreground = whitePieceColor;
3114 gc_values.background = lightSquareColor;
3115 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3117 gc_values.foreground = whitePieceColor;
3118 gc_values.background = jailSquareColor;
3119 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3121 gc_values.foreground = blackPieceColor;
3122 gc_values.background = darkSquareColor;
3123 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3125 gc_values.foreground = blackPieceColor;
3126 gc_values.background = lightSquareColor;
3127 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3129 gc_values.foreground = blackPieceColor;
3130 gc_values.background = jailSquareColor;
3131 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3138 WhitePawn, WhiteKnight, WhiteBishop, WhiteRook, WhiteQueen, WhiteKing,
3139 BlackPawn, BlackKnight, BlackBishop, BlackRook, BlackQueen, BlackKing,
3143 /* get some defaults going */
3144 for(i=WhitePawn; i<DemotePiece+1; i++)
3145 SVGpieces[i] = load_pixbuf("svg/NeutralSquare.svg",squareSize);
3148 SVGpieces[WhitePawn] = load_pixbuf("svg/WhitePawn.svg",squareSize);
3149 SVGpieces[WhiteKnight] = load_pixbuf("svg/WhiteKnight.svg",squareSize);
3150 SVGpieces[WhiteBishop] = load_pixbuf("svg/WhiteBishop.svg",squareSize);
3151 SVGpieces[WhiteRook] = load_pixbuf("svg/WhiteRook.svg",squareSize);
3152 SVGpieces[WhiteQueen] = load_pixbuf("svg/WhiteQueen.svg",squareSize);
3153 SVGpieces[WhiteKing] = load_pixbuf("svg/WhiteKing.svg",squareSize);
3155 SVGpieces[BlackPawn] = load_pixbuf("svg/BlackPawn.svg",squareSize);
3156 SVGpieces[BlackKnight] = load_pixbuf("svg/BlackKnight.svg",squareSize);
3157 SVGpieces[BlackBishop] = load_pixbuf("svg/BlackBishop.svg",squareSize);
3158 SVGpieces[BlackRook] = load_pixbuf("svg/BlackRook.svg",squareSize);
3159 SVGpieces[BlackQueen] = load_pixbuf("svg/BlackQueen.svg",squareSize);
3160 SVGpieces[BlackKing] = load_pixbuf("svg/BlackKing.svg",squareSize);
3166 static void MenuBarSelect(w, addr, index)
3171 XtActionProc proc = (XtActionProc) addr;
3173 (proc)(NULL, NULL, NULL, NULL);
3176 void CreateMenuBarPopup(parent, name, mb)
3186 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3189 XtSetArg(args[j], XtNleftMargin, 20); j++;
3190 XtSetArg(args[j], XtNrightMargin, 20); j++;
3192 while (mi->string != NULL) {
3193 if (strcmp(mi->string, "----") == 0) {
3194 entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
3197 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string)));
3198 entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass,
3200 XtAddCallback(entry, XtNcallback,
3201 (XtCallbackProc) MenuBarSelect,
3202 (caddr_t) mi->proc);
3208 Widget CreateMenuBar(mb)
3212 Widget anchor, menuBar;
3214 char menuName[MSG_SIZ];
3217 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3218 XtSetArg(args[j], XtNvSpace, 0); j++;
3219 XtSetArg(args[j], XtNborderWidth, 0); j++;
3220 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
3221 formWidget, args, j);
3223 while (mb->name != NULL) {
3224 strcpy(menuName, "menu");
3225 strcat(menuName, mb->name);
3227 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
3230 shortName[0] = _(mb->name)[0];
3231 shortName[1] = NULLCHAR;
3232 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
3235 XtSetArg(args[j], XtNlabel, XtNewString(_(mb->name))); j++;
3238 XtSetArg(args[j], XtNborderWidth, 0); j++;
3239 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
3241 CreateMenuBarPopup(menuBar, menuName, mb);
3247 Widget CreateButtonBar(mi)
3251 Widget button, buttonBar;
3255 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3257 XtSetArg(args[j], XtNhSpace, 0); j++;
3259 XtSetArg(args[j], XtNborderWidth, 0); j++;
3260 XtSetArg(args[j], XtNvSpace, 0); j++;
3261 buttonBar = XtCreateWidget("buttonBar", boxWidgetClass,
3262 formWidget, args, j);
3264 while (mi->string != NULL) {
3267 XtSetArg(args[j], XtNinternalWidth, 2); j++;
3268 XtSetArg(args[j], XtNborderWidth, 0); j++;
3270 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string))); j++;
3271 button = XtCreateManagedWidget(mi->string, commandWidgetClass,
3272 buttonBar, args, j);
3273 XtAddCallback(button, XtNcallback,
3274 (XtCallbackProc) MenuBarSelect,
3275 (caddr_t) mi->proc);
3282 CreatePieceMenu(name, color)
3289 ChessSquare selection;
3291 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3292 boardWidget, args, 0);
3294 for (i = 0; i < PIECE_MENU_SIZE; i++) {
3295 String item = pieceMenuStrings[color][i];
3297 if (strcmp(item, "----") == 0) {
3298 entry = XtCreateManagedWidget(item, smeLineObjectClass,
3301 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3302 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3304 selection = pieceMenuTranslation[color][i];
3305 XtAddCallback(entry, XtNcallback,
3306 (XtCallbackProc) PieceMenuSelect,
3307 (caddr_t) selection);
3308 if (selection == WhitePawn || selection == BlackPawn) {
3309 XtSetArg(args[0], XtNpopupOnEntry, entry);
3310 XtSetValues(menu, args, 1);
3323 ChessSquare selection;
3325 // whitePieceMenu = CreatePieceMenu("menuW", 0);
3326 // blackPieceMenu = CreatePieceMenu("menuB", 1);
3328 // XtRegisterGrabAction(PieceMenuPopup, True,
3329 // (unsigned)(ButtonPressMask|ButtonReleaseMask),
3330 // GrabModeAsync, GrabModeAsync);
3332 // XtSetArg(args[0], XtNlabel, _("Drop"));
3333 // dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
3334 // boardWidget, args, 1);
3335 // for (i = 0; i < DROP_MENU_SIZE; i++) {
3336 // String item = dropMenuStrings[i];
3338 // if (strcmp(item, "----") == 0) {
3339 // entry = XtCreateManagedWidget(item, smeLineObjectClass,
3340 // dropMenu, NULL, 0);
3342 // XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3343 // entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3344 // dropMenu, args, 1);
3345 // selection = dropMenuTranslation[i];
3346 // XtAddCallback(entry, XtNcallback,
3347 // (XtCallbackProc) DropMenuSelect,
3348 // (caddr_t) selection);
3353 void SetupDropMenu()
3361 for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
3362 entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
3363 p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
3364 dmEnables[i].piece);
3365 XtSetSensitive(entry, p != NULL || !appData.testLegality
3366 /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
3367 && !appData.icsActive));
3369 while (p && *p++ == dmEnables[i].piece) count++;
3370 snprintf(label, sizeof(label), "%s %d", dmEnables[i].widget, count);
3372 XtSetArg(args[j], XtNlabel, label); j++;
3373 XtSetValues(entry, args, j);
3377 void PieceMenuPopup(w, event, params, num_params)
3381 Cardinal *num_params;
3384 if (event->type != ButtonPress) return;
3385 if (errorUp) ErrorPopDown();
3389 whichMenu = params[0];
3391 case IcsPlayingWhite:
3392 case IcsPlayingBlack:
3394 case MachinePlaysWhite:
3395 case MachinePlaysBlack:
3396 if (appData.testLegality &&
3397 gameInfo.variant != VariantBughouse &&
3398 gameInfo.variant != VariantCrazyhouse) return;
3400 whichMenu = "menuD";
3406 if (((pmFromX = EventToSquare(event->xbutton.x, BOARD_WIDTH)) < 0) ||
3407 ((pmFromY = EventToSquare(event->xbutton.y, BOARD_HEIGHT)) < 0)) {
3408 pmFromX = pmFromY = -1;
3412 pmFromX = BOARD_WIDTH - 1 - pmFromX;
3414 pmFromY = BOARD_HEIGHT - 1 - pmFromY;
3416 XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
3419 static void PieceMenuSelect(w, piece, junk)
3424 if (pmFromX < 0 || pmFromY < 0) return;
3425 EditPositionMenuEvent(piece, pmFromX, pmFromY);
3428 static void DropMenuSelect(w, piece, junk)
3433 if (pmFromX < 0 || pmFromY < 0) return;
3434 DropMenuEvent(piece, pmFromX, pmFromY);
3437 void WhiteClock(w, event, prms, nprms)
3443 if (gameMode == EditPosition || gameMode == IcsExamining) {
3444 SetWhiteToPlayEvent();
3445 } else if (gameMode == IcsPlayingBlack || gameMode == MachinePlaysWhite) {
3450 void BlackClock(w, event, prms, nprms)
3456 if (gameMode == EditPosition || gameMode == IcsExamining) {
3457 SetBlackToPlayEvent();
3458 } else if (gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) {
3465 * If the user selects on a border boundary, return -1; if off the board,
3466 * return -2. Otherwise map the event coordinate to the square.
3468 int EventToSquare(x, limit)
3476 if ((x % (squareSize + lineGap)) >= squareSize)
3478 x /= (squareSize + lineGap);
3484 static void do_flash_delay(msec)
3490 static void drawHighlight(file, rank, line_type)
3491 int file, rank, line_type;
3496 if (lineGap == 0 || appData.blindfold) return;
3500 x = lineGap/2 + ((BOARD_WIDTH-1)-file) *
3501 (squareSize + lineGap);
3502 y = lineGap/2 + rank * (squareSize + lineGap);
3506 x = lineGap/2 + file * (squareSize + lineGap);
3507 y = lineGap/2 + ((BOARD_HEIGHT-1)-rank) *
3508 (squareSize + lineGap);
3512 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3514 /* draw the highlight */
3515 cairo_move_to (cr, x, y);
3516 cairo_rel_line_to (cr, 0,squareSize+lineGap);
3517 cairo_rel_line_to (cr, squareSize+lineGap,0);
3518 cairo_rel_line_to (cr, 0,-squareSize-lineGap);
3519 cairo_close_path (cr);
3521 cairo_set_line_width (cr, lineGap);
3524 /* TODO: use appdata colors */
3525 case LINE_TYPE_HIGHLIGHT:
3526 cairo_set_source_rgba (cr, 1, 1, 0, 1.0);
3529 cairo_set_source_rgba (cr, 1, 0, 0, 1.0);
3531 case LINE_TYPE_NORMAL:
3533 cairo_set_source_rgba (cr, 0, 1, 0, 1.0);
3544 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
3545 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
3548 SetHighlights(fromX, fromY, toX, toY)
3549 int fromX, fromY, toX, toY;
3551 if (hi1X != fromX || hi1Y != fromY)
3553 if (hi1X >= 0 && hi1Y >= 0)
3555 drawHighlight(hi1X, hi1Y, LINE_TYPE_NORMAL);
3557 if (fromX >= 0 && fromY >= 0)
3559 drawHighlight(fromX, fromY, LINE_TYPE_HIGHLIGHT);
3562 if (hi2X != toX || hi2Y != toY)
3564 if (hi2X >= 0 && hi2Y >= 0)
3566 drawHighlight(hi2X, hi2Y, LINE_TYPE_NORMAL);
3568 if (toX >= 0 && toY >= 0)
3570 drawHighlight(toX, toY, LINE_TYPE_HIGHLIGHT);
3584 SetHighlights(-1, -1, -1, -1);
3589 SetPremoveHighlights(fromX, fromY, toX, toY)
3590 int fromX, fromY, toX, toY;
3592 if (pm1X != fromX || pm1Y != fromY)
3594 if (pm1X >= 0 && pm1Y >= 0)
3596 drawHighlight(pm1X, pm1Y, LINE_TYPE_NORMAL);
3598 if (fromX >= 0 && fromY >= 0)
3600 drawHighlight(fromX, fromY, LINE_TYPE_PRE);
3603 if (pm2X != toX || pm2Y != toY)
3605 if (pm2X >= 0 && pm2Y >= 0)
3607 drawHighlight(pm2X, pm2Y, LINE_TYPE_NORMAL);
3609 if (toX >= 0 && toY >= 0)
3611 drawHighlight(toX, toY, LINE_TYPE_PRE);
3624 ClearPremoveHighlights()
3626 SetPremoveHighlights(-1, -1, -1, -1);
3629 static void BlankSquare(x, y, color, piece, dest)
3642 pb = SVGLightSquare;
3644 case 2: /* neutral */
3646 pb = SVGNeutralSquare;
3649 gdk_draw_pixbuf(GDK_WINDOW(GUI_Board->window),NULL,pb,0,0,x,y,-1,-1, GDK_RGB_DITHER_NORMAL, 0, 0);
3653 static void DrawPiece(piece, square_color, x, y, dest)
3655 int square_color, x, y;
3658 /* redraw background, since piece might be transparent in some areas */
3659 BlankSquare(x,y,square_color,piece,dest);
3662 gdk_draw_pixbuf(GDK_WINDOW(GUI_Board->window),NULL,
3663 GDK_PIXBUF(SVGpieces[piece]),0,0,x,y,-1,-1,
3664 GDK_RGB_DITHER_NORMAL, 0, 0);
3668 /* [HR] determine square color depending on chess variant. */
3669 static int SquareColor(row, column)
3674 if (gameInfo.variant == VariantXiangqi) {
3675 if (column >= 3 && column <= 5 && row >= 0 && row <= 2) {
3677 } else if (column >= 3 && column <= 5 && row >= 7 && row <= 9) {
3679 } else if (row <= 4) {
3685 square_color = ((column + row) % 2) == 1;
3688 /* [hgm] holdings: next line makes all holdings squares light */
3689 if(column < BOARD_LEFT || column >= BOARD_RGHT) square_color = 1;
3691 return square_color;
3694 void DrawSquare(row, column, piece, do_flash)
3695 int row, column, do_flash;
3698 int square_color, x, y;
3703 /* Calculate delay in milliseconds (2-delays per complete flash) */
3704 flash_delay = 500 / appData.flashRate;
3706 /* calculate x and y coordinates from row and column */
3709 x = lineGap + ((BOARD_WIDTH-1)-column) *
3710 (squareSize + lineGap);
3711 y = lineGap + row * (squareSize + lineGap);
3715 x = lineGap + column * (squareSize + lineGap);
3716 y = lineGap + ((BOARD_HEIGHT-1)-row) *
3717 (squareSize + lineGap);
3720 square_color = SquareColor(row, column);
3722 // [HGM] holdings: blank out area between board and holdings
3723 if ( column == BOARD_LEFT-1 || column == BOARD_RGHT
3724 || (column == BOARD_LEFT-2 && row < BOARD_HEIGHT-gameInfo.holdingsSize)
3725 || (column == BOARD_RGHT+1 && row >= gameInfo.holdingsSize) )
3727 BlankSquare(x, y, 2, EmptySquare, xBoardWindow);
3729 // [HGM] print piece counts next to holdings
3730 string[1] = NULLCHAR;
3733 cairo_text_extents_t extents;
3738 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3740 string[0] = '0' + piece;
3742 /* TODO this has to go into the font-selection */
3743 cairo_select_font_face (cr, "Sans",
3744 CAIRO_FONT_SLANT_NORMAL,
3745 CAIRO_FONT_WEIGHT_NORMAL);
3747 cairo_set_font_size (cr, 12.0);
3748 cairo_text_extents (cr, string, &extents);
3750 if (column == (flipView ? BOARD_LEFT-1 : BOARD_RGHT) )
3752 xpos= x + squareSize - extents.width - 2;
3753 ypos= y + extents.y_bearing + 1;
3755 if (column == (flipView ? BOARD_RGHT : BOARD_LEFT-1) && piece > 1)
3758 ypos = y + extents.y_bearing + 1;
3761 /* TODO mono mode? */
3762 cairo_move_to (cr, xpos, ypos);
3763 cairo_text_path (cr, string);
3764 cairo_set_source_rgb (cr, 1.0, 1.0, 1);
3765 cairo_fill_preserve (cr);
3766 cairo_set_source_rgb (cr, 0, 0, 0);
3767 cairo_set_line_width (cr, 0.1);
3776 /* square on the board */
3777 if (piece == EmptySquare || appData.blindfold)
3779 BlankSquare(x, y, square_color, piece, xBoardWindow);
3783 if (do_flash && appData.flashCount > 0)
3785 for (i=0; i<appData.flashCount; ++i)
3788 DrawPiece(piece, square_color, x, y, xBoardWindow);
3789 do_flash_delay(flash_delay);
3791 BlankSquare(x, y, square_color, piece, xBoardWindow);
3792 do_flash_delay(flash_delay);
3795 DrawPiece(piece, square_color, x, y, xBoardWindow);
3799 /* show coordinates if necessary */
3800 if(appData.showCoords)
3802 cairo_text_extents_t extents;
3806 /* TODO this has to go into the font-selection */
3807 cairo_select_font_face (cr, "Sans",
3808 CAIRO_FONT_SLANT_NORMAL,
3809 CAIRO_FONT_WEIGHT_NORMAL);
3810 cairo_set_font_size (cr, 12.0);
3812 string[1] = NULLCHAR;
3815 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3817 if (row == (flipView ? BOARD_HEIGHT-1 : 0) &&
3818 column >= BOARD_LEFT && column < BOARD_RGHT)
3820 string[0] = 'a' + column - BOARD_LEFT;
3821 cairo_text_extents (cr, string, &extents);
3823 xpos = x + squareSize - extents.width - 2;
3824 ypos = y + squareSize - extents.height - extents.y_bearing - 1;
3826 if (appData.monoMode)
3833 cairo_move_to (cr, xpos, ypos);
3834 cairo_text_path (cr, string);
3835 cairo_set_source_rgb (cr, 0.0, 0.0, 0);
3836 cairo_fill_preserve (cr);
3837 cairo_set_source_rgb (cr, 0, 1.0, 0);
3838 cairo_set_line_width (cr, 0.1);
3841 if ( column == (flipView ? BOARD_RGHT-1 : BOARD_LEFT))
3844 string[0] = ONE + row;
3845 cairo_text_extents (cr, string, &extents);
3848 ypos = y + extents.height + 1;
3850 if (appData.monoMode)
3857 cairo_move_to (cr, xpos, ypos);
3858 cairo_text_path (cr, string);
3859 cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
3860 cairo_fill_preserve (cr);
3861 cairo_set_source_rgb (cr, 0, 0, 1.0);
3862 cairo_set_line_width (cr, 0.1);
3874 /* Returns 1 if there are "too many" differences between b1 and b2
3875 (i.e. more than 1 move was made) */
3876 static int too_many_diffs(b1, b2)
3882 for (i=0; i<BOARD_HEIGHT; ++i) {
3883 for (j=0; j<BOARD_WIDTH; ++j) {
3884 if (b1[i][j] != b2[i][j]) {
3885 if (++c > 4) /* Castling causes 4 diffs */
3894 /* Matrix describing castling maneuvers */
3895 /* Row, ColRookFrom, ColKingFrom, ColRookTo, ColKingTo */
3896 static int castling_matrix[4][5] = {
3897 { 0, 0, 4, 3, 2 }, /* 0-0-0, white */
3898 { 0, 7, 4, 5, 6 }, /* 0-0, white */
3899 { 7, 0, 4, 3, 2 }, /* 0-0-0, black */
3900 { 7, 7, 4, 5, 6 } /* 0-0, black */
3903 /* Checks whether castling occurred. If it did, *rrow and *rcol
3904 are set to the destination (row,col) of the rook that moved.
3906 Returns 1 if castling occurred, 0 if not.
3908 Note: Only handles a max of 1 castling move, so be sure
3909 to call too_many_diffs() first.
3911 static int check_castle_draw(newb, oldb, rrow, rcol)
3918 /* For each type of castling... */
3919 for (i=0; i<4; ++i) {
3920 r = castling_matrix[i];
3922 /* Check the 4 squares involved in the castling move */
3924 for (j=1; j<=4; ++j) {
3925 if (newb[r[0]][r[j]] == oldb[r[0]][r[j]]) {
3932 /* All 4 changed, so it must be a castling move */
3941 static int damage[BOARD_SIZE][BOARD_SIZE];
3944 * event handler for redrawing the board
3946 void DrawPosition( repaint, board)
3947 /*Boolean*/int repaint;
3951 static int lastFlipView = 0;
3952 static int lastBoardValid = 0;
3953 static Board lastBoard;
3956 if (board == NULL) {
3957 if (!lastBoardValid) return;
3960 if (!lastBoardValid || lastFlipView != flipView) {
3961 // XtSetArg(args[0], XtNleftBitmap, (flipView ? xMarkPixmap : None));
3962 // XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flip View"),
3967 * It would be simpler to clear the window with XClearWindow()
3968 * but this causes a very distracting flicker.
3971 if (!repaint && lastBoardValid && lastFlipView == flipView)
3973 /* If too much changes (begin observing new game, etc.), don't
3975 do_flash = too_many_diffs(board, lastBoard) ? 0 : 1;
3977 /* Special check for castling so we don't flash both the king
3978 and the rook (just flash the king). */
3981 if (check_castle_draw(board, lastBoard, &rrow, &rcol))
3983 /* Draw rook with NO flashing. King will be drawn flashing later */
3984 DrawSquare(rrow, rcol, board[rrow][rcol], 0);
3985 lastBoard[rrow][rcol] = board[rrow][rcol];
3989 /* First pass -- Draw (newly) empty squares and repair damage.
3990 This prevents you from having a piece show up twice while it
3991 is flashing on its new square */
3992 for (i = 0; i < BOARD_HEIGHT; i++)
3993 for (j = 0; j < BOARD_WIDTH; j++)
3994 if ((board[i][j] != lastBoard[i][j] && board[i][j] == EmptySquare)
3997 DrawSquare(i, j, board[i][j], 0);
3998 damage[i][j] = False;
4001 /* Second pass -- Draw piece(s) in new position and flash them */
4002 for (i = 0; i < BOARD_HEIGHT; i++)
4003 for (j = 0; j < BOARD_WIDTH; j++)
4004 if (board[i][j] != lastBoard[i][j])
4006 DrawSquare(i, j, board[i][j], do_flash);
4018 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
4020 cairo_set_line_width (cr, lineGap);
4022 /* TODO: use appdata colors */
4023 cairo_set_source_rgba (cr, 0, 1, 0, 1.0);
4027 for (i = 0; i < BOARD_HEIGHT + 1; i++)
4030 x2 = lineGap + BOARD_WIDTH * (squareSize + lineGap);
4031 y1 = y2 = lineGap / 2 + (i * (squareSize + lineGap));
4033 cairo_move_to (cr, x1, y1);
4034 cairo_rel_line_to (cr, x2,0);
4038 for (j = 0; j < BOARD_WIDTH + 1; j++)
4041 y2 = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
4042 x1 = x2 = lineGap / 2 + (j * (squareSize + lineGap));
4044 cairo_move_to (cr, x1, y1);
4045 cairo_rel_line_to (cr, 0, y2);
4054 for (i = 0; i < BOARD_HEIGHT; i++)
4055 for (j = 0; j < BOARD_WIDTH; j++)
4057 DrawSquare(i, j, board[i][j], 0);
4058 damage[i][j] = False;
4062 CopyBoard(lastBoard, board);
4064 lastFlipView = flipView;
4066 /* Draw highlights */
4067 if (pm1X >= 0 && pm1Y >= 0)
4069 drawHighlight(pm1X, pm1Y, LINE_TYPE_PRE);
4071 if (pm2X >= 0 && pm2Y >= 0)
4073 drawHighlight(pm2X, pm2Y, LINE_TYPE_PRE);
4075 if (hi1X >= 0 && hi1Y >= 0)
4077 drawHighlight(hi1X, hi1Y, LINE_TYPE_HIGHLIGHT);
4079 if (hi2X >= 0 && hi2Y >= 0)
4081 drawHighlight(hi2X, hi2Y, LINE_TYPE_HIGHLIGHT);
4084 /* If piece being dragged around board, must redraw that too */
4091 * event handler for parsing user moves
4093 // [HGM] This routine will need quite some reworking. Although the backend still supports the old
4094 // way of doing things, by calling UserMoveEvent() to test the legality of the move and then perform
4095 // it at the end, and doing all kind of preliminary tests here (e.g. to weed out self-captures), it
4096 // should be made to use the new way, of calling UserMoveTest early to determine the legality of the
4097 // move, (which will weed out the illegal selfcaptures and moves into the holdings, and flag promotions),
4098 // and at the end FinishMove() to perform the move after optional promotion popups.
4099 // For now I patched it to allow self-capture with King, and suppress clicks between board and holdings.
4100 void HandleUserMove(w, event, prms, nprms)
4107 Boolean saveAnimate;
4108 static int second = 0;
4110 if (w != boardWidget || errorExitStatus != -1) return;
4112 if (event->type == ButtonPress) ErrorPopDown();
4115 if (event->type == ButtonPress) {
4116 // XtPopdown(promotionShell);
4117 // XtDestroyWidget(promotionShell);
4118 promotionUp = False;
4126 x = EventToSquare(event->xbutton.x, BOARD_WIDTH);
4127 y = EventToSquare(event->xbutton.y, BOARD_HEIGHT);
4128 if (!flipView && y >= 0) {
4129 y = BOARD_HEIGHT - 1 - y;
4131 if (flipView && x >= 0) {
4132 x = BOARD_WIDTH - 1 - x;
4135 /* [HGM] holdings: next 5 lines: ignore all clicks between board and holdings */
4136 if(event->type == ButtonPress
4137 && ( x == BOARD_LEFT-1 ||
4139 (x == BOARD_LEFT-2 && y < BOARD_HEIGHT-gameInfo.holdingsSize ) ||
4140 (x == BOARD_RGHT+1 && y >= gameInfo.holdingsSize)) )
4144 if (event->type == ButtonPress) {
4146 if (OKToStartUserMove(x, y)) {
4150 DragPieceBegin(event->xbutton.x, event->xbutton.y);
4151 if (appData.highlightDragging) {
4152 SetHighlights(x, y, -1, -1);
4160 if (event->type == ButtonPress && gameMode != EditPosition &&
4165 /* Check if clicking again on the same color piece */
4166 fromP = boards[currentMove][fromY][fromX];
4167 toP = boards[currentMove][y][x];
4168 if ((WhitePawn <= fromP && fromP < WhiteKing && // [HGM] this test should go, as UserMoveTest now does it.
4169 WhitePawn <= toP && toP <= WhiteKing) || // For now I made it less critical by exempting King
4170 (BlackPawn <= fromP && fromP < BlackKing && // moves, to not interfere with FRC castlings.
4171 BlackPawn <= toP && toP <= BlackKing)) {
4172 /* Clicked again on same color piece -- changed his mind */
4173 second = (x == fromX && y == fromY);
4174 if (appData.highlightDragging) {
4175 SetHighlights(x, y, -1, -1);
4179 if (OKToStartUserMove(x, y)) {
4182 DragPieceBegin(event->xbutton.x, event->xbutton.y);
4188 if (event->type == ButtonRelease && x == fromX && y == fromY) {
4189 DragPieceEnd(event->xbutton.x, event->xbutton.y);
4190 if (appData.animateDragging) {
4191 /* Undo animation damage if any */
4192 DrawPosition(FALSE, NULL);
4195 /* Second up/down in same square; just abort move */
4200 ClearPremoveHighlights();
4202 /* First upclick in same square; start click-click mode */
4203 SetHighlights(x, y, -1, -1);
4208 /* Completed move */
4211 saveAnimate = appData.animate;
4212 if (event->type == ButtonPress) {
4213 /* Finish clickclick move */
4214 if (appData.animate || appData.highlightLastMove) {
4215 SetHighlights(fromX, fromY, toX, toY);
4220 /* Finish drag move */
4221 if (appData.highlightLastMove) {
4222 SetHighlights(fromX, fromY, toX, toY);
4226 DragPieceEnd(event->xbutton.x, event->xbutton.y);
4227 /* Don't animate move and drag both */
4228 appData.animate = FALSE;
4230 if (IsPromotion(fromX, fromY, toX, toY)) {
4231 if (appData.alwaysPromoteToQueen) {
4232 UserMoveEvent(fromX, fromY, toX, toY, 'q');
4233 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
4234 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
4237 SetHighlights(fromX, fromY, toX, toY);
4241 UserMoveEvent(fromX, fromY, toX, toY, NULLCHAR);
4242 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
4243 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
4246 appData.animate = saveAnimate;
4247 if (appData.animate || appData.animateDragging) {
4248 /* Undo animation damage if needed */
4249 DrawPosition(FALSE, NULL);
4253 void AnimateUserMove (Widget w, XEvent * event,
4254 String * params, Cardinal * nParams)
4256 DragPieceMove(event->xmotion.x, event->xmotion.y);
4259 Widget CommentCreate(name, text, mutable, callback, lines)
4261 int /*Boolean*/ mutable;
4262 XtCallbackProc callback;
4266 Widget shell, layout, form, edit, b_ok, b_cancel, b_clear, b_close, b_edit;
4271 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4272 XtGetValues(boardWidget, args, j);
4275 XtSetArg(args[j], XtNresizable, True); j++;
4278 XtCreatePopupShell(name, topLevelShellWidgetClass,
4279 shellWidget, args, j);
4282 XtCreatePopupShell(name, transientShellWidgetClass,
4283 shellWidget, args, j);
4286 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
4287 layoutArgs, XtNumber(layoutArgs));
4289 XtCreateManagedWidget("form", formWidgetClass, layout,
4290 formArgs, XtNumber(formArgs));
4294 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
4295 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
4297 XtSetArg(args[j], XtNstring, text); j++;
4298 XtSetArg(args[j], XtNtop, XtChainTop); j++;
4299 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4300 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4301 XtSetArg(args[j], XtNright, XtChainRight); j++;
4302 XtSetArg(args[j], XtNresizable, True); j++;
4303 XtSetArg(args[j], XtNwidth, bw_width); j++; /*force wider than buttons*/
4305 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
4307 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
4308 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
4310 XtSetArg(args[j], XtNautoFill, True); j++;
4311 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
4313 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
4317 XtSetArg(args[j], XtNfromVert, edit); j++;
4318 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4319 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4320 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4321 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4323 XtCreateManagedWidget(_("ok"), commandWidgetClass, form, args, j);
4324 XtAddCallback(b_ok, XtNcallback, callback, (XtPointer) 0);
4327 XtSetArg(args[j], XtNfromVert, edit); j++;
4328 XtSetArg(args[j], XtNfromHoriz, b_ok); j++;
4329 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4330 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4331 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4332 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4334 XtCreateManagedWidget(_("cancel"), commandWidgetClass, form, args, j);
4335 XtAddCallback(b_cancel, XtNcallback, callback, (XtPointer) 0);
4338 XtSetArg(args[j], XtNfromVert, edit); j++;
4339 XtSetArg(args[j], XtNfromHoriz, b_cancel); j++;
4340 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4341 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4342 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4343 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4345 XtCreateManagedWidget(_("clear"), commandWidgetClass, form, args, j);
4346 XtAddCallback(b_clear, XtNcallback, callback, (XtPointer) 0);
4349 XtSetArg(args[j], XtNfromVert, edit); j++;
4350 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4351 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4352 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4353 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4355 XtCreateManagedWidget(_("close"), commandWidgetClass, form, args, j);
4356 XtAddCallback(b_close, XtNcallback, callback, (XtPointer) 0);
4359 XtSetArg(args[j], XtNfromVert, edit); j++;
4360 XtSetArg(args[j], XtNfromHoriz, b_close); j++;
4361 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4362 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4363 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4364 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4366 XtCreateManagedWidget(_("edit"), commandWidgetClass, form, args, j);
4367 XtAddCallback(b_edit, XtNcallback, callback, (XtPointer) 0);
4370 XtRealizeWidget(shell);
4372 if (commentX == -1) {
4375 Dimension pw_height;
4376 Dimension ew_height;
4379 XtSetArg(args[j], XtNheight, &ew_height); j++;
4380 XtGetValues(edit, args, j);
4383 XtSetArg(args[j], XtNheight, &pw_height); j++;
4384 XtGetValues(shell, args, j);
4385 commentH = pw_height + (lines - 1) * ew_height;
4386 commentW = bw_width - 16;
4388 XSync(xDisplay, False);
4390 /* This code seems to tickle an X bug if it is executed too soon
4391 after xboard starts up. The coordinates get transformed as if
4392 the main window was positioned at (0, 0).
4394 XtTranslateCoords(shellWidget,
4395 (bw_width - commentW) / 2, 0 - commentH / 2,
4396 &commentX, &commentY);
4398 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
4399 RootWindowOfScreen(XtScreen(shellWidget)),
4400 (bw_width - commentW) / 2, 0 - commentH / 2,
4405 if (commentY < 0) commentY = 0; /*avoid positioning top offscreen*/
4408 XtSetArg(args[j], XtNheight, commentH); j++;
4409 XtSetArg(args[j], XtNwidth, commentW); j++;
4410 XtSetArg(args[j], XtNx, commentX); j++;
4411 XtSetArg(args[j], XtNy, commentY); j++;
4412 XtSetValues(shell, args, j);
4413 XtSetKeyboardFocus(shell, edit);
4418 /* Used for analysis window and ICS input window */
4419 Widget MiscCreate(name, text, mutable, callback, lines)
4421 int /*Boolean*/ mutable;
4422 XtCallbackProc callback;
4426 Widget shell, layout, form, edit;
4428 Dimension bw_width, pw_height, ew_height, w, h;
4434 XtSetArg(args[j], XtNresizable, True); j++;
4437 XtCreatePopupShell(name, topLevelShellWidgetClass,
4438 shellWidget, args, j);
4441 XtCreatePopupShell(name, transientShellWidgetClass,
4442 shellWidget, args, j);
4445 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
4446 layoutArgs, XtNumber(layoutArgs));
4448 XtCreateManagedWidget("form", formWidgetClass, layout,
4449 formArgs, XtNumber(formArgs));
4453 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
4454 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
4456 XtSetArg(args[j], XtNstring, text); j++;
4457 XtSetArg(args[j], XtNtop, XtChainTop); j++;
4458 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4459 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4460 XtSetArg(args[j], XtNright, XtChainRight); j++;
4461 XtSetArg(args[j], XtNresizable, True); j++;
4463 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
4465 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
4466 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
4468 XtSetArg(args[j], XtNautoFill, True); j++;
4469 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
4471 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
4473 XtRealizeWidget(shell);
4476 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4477 XtGetValues(boardWidget, args, j);
4480 XtSetArg(args[j], XtNheight, &ew_height); j++;
4481 XtGetValues(edit, args, j);
4484 XtSetArg(args[j], XtNheight, &pw_height); j++;
4485 XtGetValues(shell, args, j);
4486 h = pw_height + (lines - 1) * ew_height;
4489 XSync(xDisplay, False);
4491 /* This code seems to tickle an X bug if it is executed too soon
4492 after xboard starts up. The coordinates get transformed as if
4493 the main window was positioned at (0, 0).
4495 XtTranslateCoords(shellWidget, (bw_width - w) / 2, 0 - h / 2, &x, &y);
4497 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
4498 RootWindowOfScreen(XtScreen(shellWidget)),
4499 (bw_width - w) / 2, 0 - h / 2, &xx, &yy, &junk);
4503 if (y < 0) y = 0; /*avoid positioning top offscreen*/
4506 XtSetArg(args[j], XtNheight, h); j++;
4507 XtSetArg(args[j], XtNwidth, w); j++;
4508 XtSetArg(args[j], XtNx, x); j++;
4509 XtSetArg(args[j], XtNy, y); j++;
4510 XtSetValues(shell, args, j);
4516 static int savedIndex; /* gross that this is global */
4518 void EditCommentPopUp(index, title, text)
4527 if (text == NULL) text = "";
4529 if (editShell == NULL) {
4531 CommentCreate(title, text, True, EditCommentCallback, 4);
4532 XtRealizeWidget(editShell);
4533 CatchDeleteWindow(editShell, "EditCommentPopDown");
4535 edit = XtNameToWidget(editShell, "*form.text");
4537 XtSetArg(args[j], XtNstring, text); j++;
4538 XtSetValues(edit, args, j);
4540 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4541 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4542 XtSetValues(editShell, args, j);
4545 XtPopup(editShell, XtGrabNone);
4549 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
4550 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
4554 void EditCommentCallback(w, client_data, call_data)
4556 XtPointer client_data, call_data;
4564 XtSetArg(args[j], XtNlabel, &name); j++;
4565 XtGetValues(w, args, j);
4567 if (strcmp(name, _("ok")) == 0) {
4568 edit = XtNameToWidget(editShell, "*form.text");
4570 XtSetArg(args[j], XtNstring, &val); j++;
4571 XtGetValues(edit, args, j);
4572 ReplaceComment(savedIndex, val);
4573 EditCommentPopDown();
4574 } else if (strcmp(name, _("cancel")) == 0) {
4575 EditCommentPopDown();
4576 } else if (strcmp(name, _("clear")) == 0) {
4577 edit = XtNameToWidget(editShell, "*form.text");
4578 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
4579 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
4583 void EditCommentPopDown()
4588 if (!editUp) return;
4590 XtSetArg(args[j], XtNx, &commentX); j++;
4591 XtSetArg(args[j], XtNy, &commentY); j++;
4592 XtSetArg(args[j], XtNheight, &commentH); j++;
4593 XtSetArg(args[j], XtNwidth, &commentW); j++;
4594 XtGetValues(editShell, args, j);
4595 XtPopdown(editShell);
4598 XtSetArg(args[j], XtNleftBitmap, None); j++;
4599 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
4603 void ICSInputBoxPopUp()
4608 char *title = _("ICS Input");
4611 if (ICSInputShell == NULL) {
4612 ICSInputShell = MiscCreate(title, "", True, NULL, 1);
4613 tr = XtParseTranslationTable(ICSInputTranslations);
4614 edit = XtNameToWidget(ICSInputShell, "*form.text");
4615 XtOverrideTranslations(edit, tr);
4616 XtRealizeWidget(ICSInputShell);
4617 CatchDeleteWindow(ICSInputShell, "ICSInputBoxPopDown");
4620 edit = XtNameToWidget(ICSInputShell, "*form.text");
4622 XtSetArg(args[j], XtNstring, ""); j++;
4623 XtSetValues(edit, args, j);
4625 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4626 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4627 XtSetValues(ICSInputShell, args, j);
4630 XtPopup(ICSInputShell, XtGrabNone);
4631 XtSetKeyboardFocus(ICSInputShell, edit);
4633 ICSInputBoxUp = True;
4635 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
4636 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
4640 void ICSInputSendText()
4647 edit = XtNameToWidget(ICSInputShell, "*form.text");
4649 XtSetArg(args[j], XtNstring, &val); j++;
4650 XtGetValues(edit, args, j);
4651 SendMultiLineToICS(val);
4652 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
4653 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
4656 void ICSInputBoxPopDown()
4661 if (!ICSInputBoxUp) return;
4663 XtPopdown(ICSInputShell);
4664 ICSInputBoxUp = False;
4666 XtSetArg(args[j], XtNleftBitmap, None); j++;
4667 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
4671 void CommentPopUp(title, text)
4678 if (commentShell == NULL) {
4680 CommentCreate(title, text, False, CommentCallback, 4);
4681 XtRealizeWidget(commentShell);
4682 CatchDeleteWindow(commentShell, "CommentPopDown");
4684 edit = XtNameToWidget(commentShell, "*form.text");
4686 XtSetArg(args[j], XtNstring, text); j++;
4687 XtSetValues(edit, args, j);
4689 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4690 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4691 XtSetValues(commentShell, args, j);
4694 XtPopup(commentShell, XtGrabNone);
4695 XSync(xDisplay, False);
4700 void AnalysisPopUp(title, text)
4707 if (analysisShell == NULL) {
4708 analysisShell = MiscCreate(title, text, False, NULL, 4);
4709 XtRealizeWidget(analysisShell);
4710 CatchDeleteWindow(analysisShell, "AnalysisPopDown");
4713 edit = XtNameToWidget(analysisShell, "*form.text");
4715 XtSetArg(args[j], XtNstring, text); j++;
4716 XtSetValues(edit, args, j);
4718 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4719 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4720 XtSetValues(analysisShell, args, j);
4724 XtPopup(analysisShell, XtGrabNone);
4726 XSync(xDisplay, False);
4731 void CommentCallback(w, client_data, call_data)
4733 XtPointer client_data, call_data;
4740 XtSetArg(args[j], XtNlabel, &name); j++;
4741 XtGetValues(w, args, j);
4743 if (strcmp(name, _("close")) == 0) {
4745 } else if (strcmp(name, _("edit")) == 0) {
4752 void CommentPopDown()
4757 if (!commentUp) return;
4759 XtSetArg(args[j], XtNx, &commentX); j++;
4760 XtSetArg(args[j], XtNy, &commentY); j++;
4761 XtSetArg(args[j], XtNwidth, &commentW); j++;
4762 XtSetArg(args[j], XtNheight, &commentH); j++;
4763 XtGetValues(commentShell, args, j);
4764 XtPopdown(commentShell);
4765 XSync(xDisplay, False);
4769 void AnalysisPopDown()
4771 if (!analysisUp) return;
4772 XtPopdown(analysisShell);
4773 XSync(xDisplay, False);
4775 if (appData.icsEngineAnalyze) ExitAnalyzeMode(); /* [DM] icsEngineAnalyze */
4779 void FileNamePopUp(label, def, proc, openMode)
4786 Widget popup, layout, dialog, edit;
4792 fileProc = proc; /* I can't see a way not */
4793 fileOpenMode = openMode; /* to use globals here */
4796 XtSetArg(args[i], XtNresizable, True); i++;
4797 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
4798 XtSetArg(args[i], XtNtitle, XtNewString(_("File name prompt"))); i++;
4799 fileNameShell = popup =
4800 XtCreatePopupShell("File name prompt", transientShellWidgetClass,
4801 shellWidget, args, i);
4804 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
4805 layoutArgs, XtNumber(layoutArgs));
4808 XtSetArg(args[i], XtNlabel, label); i++;
4809 XtSetArg(args[i], XtNvalue, def); i++;
4810 XtSetArg(args[i], XtNborderWidth, 0); i++;
4811 dialog = XtCreateManagedWidget("fileName", dialogWidgetClass,
4814 XawDialogAddButton(dialog, _("ok"), FileNameCallback, (XtPointer) dialog);
4815 XawDialogAddButton(dialog, _("cancel"), FileNameCallback,
4816 (XtPointer) dialog);
4818 XtRealizeWidget(popup);
4819 CatchDeleteWindow(popup, "FileNamePopDown");
4821 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
4822 &x, &y, &win_x, &win_y, &mask);
4824 XtSetArg(args[0], XtNx, x - 10);
4825 XtSetArg(args[1], XtNy, y - 30);
4826 XtSetValues(popup, args, 2);
4828 XtPopup(popup, XtGrabExclusive);
4831 edit = XtNameToWidget(dialog, "*value");
4832 XtSetKeyboardFocus(popup, edit);
4835 void FileNamePopDown()
4837 if (!filenameUp) return;
4838 XtPopdown(fileNameShell);
4839 XtDestroyWidget(fileNameShell);
4844 void FileNameCallback(w, client_data, call_data)
4846 XtPointer client_data, call_data;
4851 XtSetArg(args[0], XtNlabel, &name);
4852 XtGetValues(w, args, 1);
4854 if (strcmp(name, _("cancel")) == 0) {
4859 FileNameAction(w, NULL, NULL, NULL);
4862 void FileNameAction(w, event, prms, nprms)
4874 name = XawDialogGetValueString(w = XtParent(w));
4876 if ((name != NULL) && (*name != NULLCHAR)) {
4878 XtPopdown(w = XtParent(XtParent(w)));
4882 p = strrchr(buf, ' ');
4889 fullname = ExpandPathName(buf);
4891 ErrorPopUp(_("Error"), _("Can't open file"), FALSE);
4894 f = fopen(fullname, fileOpenMode);
4896 DisplayError(_("Failed to open file"), errno);
4898 (void) (*fileProc)(f, index, buf);
4905 XtPopdown(w = XtParent(XtParent(w)));
4911 void PromotionPopUp()
4914 Widget dialog, layout;
4916 Dimension bw_width, pw_width;
4920 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4921 XtGetValues(boardWidget, args, j);
4924 XtSetArg(args[j], XtNresizable, True); j++;
4925 XtSetArg(args[j], XtNtitle, XtNewString(_("Promotion"))); j++;
4927 XtCreatePopupShell("Promotion", transientShellWidgetClass,
4928 shellWidget, args, j);
4930 XtCreateManagedWidget(layoutName, formWidgetClass, promotionShell,
4931 layoutArgs, XtNumber(layoutArgs));
4934 XtSetArg(args[j], XtNlabel, _("Promote to what?")); j++;
4935 XtSetArg(args[j], XtNborderWidth, 0); j++;
4936 dialog = XtCreateManagedWidget("promotion", dialogWidgetClass,
4939 if(gameInfo.variant != VariantShogi) {
4940 XawDialogAddButton(dialog, _("Queen"), PromotionCallback,
4941 (XtPointer) dialog);
4942 XawDialogAddButton(dialog, _("Rook"), PromotionCallback,
4943 (XtPointer) dialog);
4944 XawDialogAddButton(dialog, _("Bishop"), PromotionCallback,
4945 (XtPointer) dialog);
4946 XawDialogAddButton(dialog, _("Knight"), PromotionCallback,
4947 (XtPointer) dialog);
4948 if (!appData.testLegality || gameInfo.variant == VariantSuicide ||
4949 gameInfo.variant == VariantGiveaway) {
4950 XawDialogAddButton(dialog, _("King"), PromotionCallback,
4951 (XtPointer) dialog);
4953 if(gameInfo.variant == VariantCapablanca ||
4954 gameInfo.variant == VariantGothic ||
4955 gameInfo.variant == VariantCapaRandom) {
4956 XawDialogAddButton(dialog, _("Archbishop"), PromotionCallback,
4957 (XtPointer) dialog);
4958 XawDialogAddButton(dialog, _("Chancellor"), PromotionCallback,
4959 (XtPointer) dialog);
4961 } else // [HGM] shogi
4963 XawDialogAddButton(dialog, _("Promote"), PromotionCallback,
4964 (XtPointer) dialog);
4965 XawDialogAddButton(dialog, _("Defer"), PromotionCallback,
4966 (XtPointer) dialog);
4968 XawDialogAddButton(dialog, _("cancel"), PromotionCallback,
4969 (XtPointer) dialog);
4971 XtRealizeWidget(promotionShell);
4972 CatchDeleteWindow(promotionShell, "PromotionPopDown");
4975 XtSetArg(args[j], XtNwidth, &pw_width); j++;
4976 XtGetValues(promotionShell, args, j);
4978 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
4979 lineGap + squareSize/3 +
4980 ((toY == BOARD_HEIGHT-1) ^ (flipView) ?
4981 0 : 6*(squareSize + lineGap)), &x, &y);
4984 XtSetArg(args[j], XtNx, x); j++;
4985 XtSetArg(args[j], XtNy, y); j++;
4986 XtSetValues(promotionShell, args, j);
4988 XtPopup(promotionShell, XtGrabNone);
4993 void PromotionPopDown()
4995 if (!promotionUp) return;
4996 XtPopdown(promotionShell);
4997 XtDestroyWidget(promotionShell);
4998 promotionUp = False;
5001 void PromotionCallback(w, client_data, call_data)
5003 XtPointer client_data, call_data;
5009 XtSetArg(args[0], XtNlabel, &name);
5010 XtGetValues(w, args, 1);
5014 if (fromX == -1) return;
5016 if (strcmp(name, _("cancel")) == 0) {
5020 } else if (strcmp(name, _("Knight")) == 0) {
5022 } else if (strcmp(name, _("Promote")) == 0) {
5024 } else if (strcmp(name, _("Defer")) == 0) {
5027 promoChar = ToLower(name[0]);
5030 UserMoveEvent(fromX, fromY, toX, toY, promoChar);
5032 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
5033 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
5038 void ErrorCallback(w, client_data, call_data)
5040 XtPointer client_data, call_data;
5043 XtPopdown(w = XtParent(XtParent(XtParent(w))));
5045 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5051 if (!errorUp) return;
5055 gtk_widget_destroy(GTK_WIDGET(GUI_Error));
5057 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5062 void ErrorPopUp(title, label, modal)
5063 char *title, *label;
5066 GUI_Error = gtk_message_dialog_new(GTK_WINDOW(GUI_Window),
5067 GTK_DIALOG_DESTROY_WITH_PARENT,
5072 gtk_window_set_title(GTK_WINDOW(GUI_Error),(gchar *) title);
5075 gtk_dialog_run(GTK_DIALOG(GUI_Error));
5076 gtk_widget_destroy(GTK_WIDGET(GUI_Error));
5080 g_signal_connect_swapped (GUI_Error, "response",
5081 G_CALLBACK (ErrorPopDownProc),
5084 gtk_widget_show(GTK_WIDGET(GUI_Error));
5090 /* Disable all user input other than deleting the window */
5091 static int frozen = 0;
5095 /* Grab by a widget that doesn't accept input */
5096 // XtAddGrab(messageWidget, TRUE, FALSE);
5100 /* Undo a FreezeUI */
5103 if (!frozen) return;
5104 // XtRemoveGrab(messageWidget);
5108 char *ModeToWidgetName(mode)
5112 case BeginningOfGame:
5113 if (appData.icsActive)
5114 return "menuMode.ICS Client";
5115 else if (appData.noChessProgram ||
5116 *appData.cmailGameName != NULLCHAR)
5117 return "menuMode.Edit Game";
5119 return "menuMode.Machine Black";
5120 case MachinePlaysBlack:
5121 return "menuMode.Machine Black";
5122 case MachinePlaysWhite:
5123 return "menuMode.Machine White";
5125 return "menuMode.Analysis Mode";
5127 return "menuMode.Analyze File";
5128 case TwoMachinesPlay:
5129 return "menuMode.Two Machines";
5131 return "menuMode.Edit Game";
5132 case PlayFromGameFile:
5133 return "menuFile.Load Game";
5135 return "menuMode.Edit Position";
5137 return "menuMode.Training";
5138 case IcsPlayingWhite:
5139 case IcsPlayingBlack:
5143 return "menuMode.ICS Client";
5150 void ModeHighlight()
5152 static int oldPausing = FALSE;
5153 static GameMode oldmode = (GameMode) -1;
5156 // todo this toggling of the pause button doesn't seem to work?
5157 // e.g. select pause from buttonbar doesn't activate menumode.pause
5159 // if (!boardWidget || !XtIsRealized(boardWidget)) return;
5161 if (pausing != oldPausing) {
5162 oldPausing = pausing;
5163 gtk_button_set_relief(GTK_BUTTON (gtk_builder_get_object (builder, "menuMode.Pause")),pausing?GTK_RELIEF_NORMAL:GTK_RELIEF_NONE);
5164 /* toggle background color in showbuttonbar */
5165 if (appData.showButtonBar) {
5167 gtk_button_pressed(GTK_BUTTON (gtk_builder_get_object (builder, "buttonbar.Pause")));
5169 gtk_button_released(GTK_BUTTON (gtk_builder_get_object (builder, "buttonbar.Pause")));
5174 wname = ModeToWidgetName(oldmode);
5176 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, wname)),True);
5180 /* Maybe all the enables should be handled here, not just this one */
5181 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuMode.Training")),
5182 gameMode == Training || gameMode == PlayFromGameFile);
5187 * Button/menu procedures
5190 int LoadGamePopUp(f, gameNumber, title)
5195 cmailMsgLoaded = FALSE;
5196 if (gameNumber == 0) {
5197 int error = GameListBuild(f);
5199 DisplayError(_("Cannot build game list"), error);
5200 } else if (!ListEmpty(&gameList) &&
5201 ((ListGame *) gameList.tailPred)->number > 1) {
5202 GameListPopUp(f, title);
5208 return LoadGame(f, gameNumber, title, FALSE);
5212 void LoadNextPositionProc(w, event, prms, nprms)
5221 void LoadPrevPositionProc(w, event, prms, nprms)
5230 void ReloadPositionProc(w, event, prms, nprms)
5239 void LoadPositionProc(w, event, prms, nprms)
5245 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
5248 FileNamePopUp(_("Load position file name?"), "", LoadPosition, "rb");
5251 void SaveGameProc(w, event, prms, nprms)
5257 FileNamePopUp(_("Save game file name?"),
5258 DefaultFileName(appData.oldSaveStyle ? "game" : "pgn"),
5262 void SavePositionProc(w, event, prms, nprms)
5268 FileNamePopUp(_("Save position file name?"),
5269 DefaultFileName(appData.oldSaveStyle ? "pos" : "fen"),
5273 void ReloadCmailMsgProc(w, event, prms, nprms)
5279 ReloadCmailMsgEvent(FALSE);
5282 void MailMoveProc(w, event, prms, nprms)
5291 /* this variable is shared between CopyPositionProc and SendPositionSelection */
5292 static char *selected_fen_position=NULL;
5295 SendPositionSelection(Widget w, Atom *selection, Atom *target,
5296 Atom *type_return, XtPointer *value_return,
5297 unsigned long *length_return, int *format_return)
5299 char *selection_tmp;
5301 if (!selected_fen_position) return False; /* should never happen */
5302 if (*target == XA_STRING){
5303 /* note: since no XtSelectionDoneProc was registered, Xt will
5304 * automatically call XtFree on the value returned. So have to
5305 * make a copy of it allocated with XtMalloc */
5306 selection_tmp= XtMalloc(strlen(selected_fen_position)+16);
5307 strcpy(selection_tmp, selected_fen_position);
5309 *value_return=selection_tmp;
5310 *length_return=strlen(selection_tmp);
5311 *type_return=XA_STRING;
5312 *format_return = 8; /* bits per byte */
5319 /* note: when called from menu all parameters are NULL, so no clue what the
5320 * Widget which was clicked on was, or what the click event was
5322 void CopyPositionProc(w, event, prms, nprms)
5330 if (selected_fen_position) free(selected_fen_position);
5331 selected_fen_position = (char *)PositionToFEN(currentMove, NULL);
5332 if (!selected_fen_position) return;
5333 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
5335 SendPositionSelection,
5336 NULL/* lose_ownership_proc */ ,
5337 NULL/* transfer_done_proc */);
5339 free(selected_fen_position);
5340 selected_fen_position=NULL;
5344 /* function called when the data to Paste is ready */
5346 PastePositionCB(Widget w, XtPointer client_data, Atom *selection,
5347 Atom *type, XtPointer value, unsigned long *len, int *format)
5350 if (value==NULL || *len==0) return; /* nothing had been selected to copy */
5351 fenstr[*len]='\0'; /* normally this string is terminated, but be safe */
5352 EditPositionPasteFEN(fenstr);
5356 /* called when Paste Position button is pressed,
5357 * all parameters will be NULL */
5358 void PastePositionProc(w, event, prms, nprms)
5364 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
5365 /* (XtSelectionCallbackProc) */ PastePositionCB,
5366 NULL, /* client_data passed to PastePositionCB */
5368 /* better to use the time field from the event that triggered the
5369 * call to this function, but that isn't trivial to get
5377 SendGameSelection(Widget w, Atom *selection, Atom *target,
5378 Atom *type_return, XtPointer *value_return,
5379 unsigned long *length_return, int *format_return)
5381 char *selection_tmp;
5383 if (*target == XA_STRING){
5384 FILE* f = fopen(gameCopyFilename, "r");
5387 if (f == NULL) return False;
5391 selection_tmp = XtMalloc(len + 1);
5392 count = fread(selection_tmp, 1, len, f);
5394 XtFree(selection_tmp);
5397 selection_tmp[len] = NULLCHAR;
5398 *value_return = selection_tmp;
5399 *length_return = len;
5400 *type_return = XA_STRING;
5401 *format_return = 8; /* bits per byte */
5408 /* note: when called from menu all parameters are NULL, so no clue what the
5409 * Widget which was clicked on was, or what the click event was
5411 void CopyGameProc(w, event, prms, nprms)
5419 ret = SaveGameToFile(gameCopyFilename, FALSE);
5422 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
5425 NULL/* lose_ownership_proc */ ,
5426 NULL/* transfer_done_proc */);
5429 /* function called when the data to Paste is ready */
5431 PasteGameCB(Widget w, XtPointer client_data, Atom *selection,
5432 Atom *type, XtPointer value, unsigned long *len, int *format)
5435 if (value == NULL || *len == 0) {
5436 return; /* nothing had been selected to copy */
5438 f = fopen(gamePasteFilename, "w");
5440 DisplayError(_("Can't open temp file"), errno);
5443 fwrite(value, 1, *len, f);
5446 LoadGameFromFile(gamePasteFilename, 0, gamePasteFilename, TRUE);
5449 /* called when Paste Game button is pressed,
5450 * all parameters will be NULL */
5451 void PasteGameProc(w, event, prms, nprms)
5457 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
5458 /* (XtSelectionCallbackProc) */ PasteGameCB,
5459 NULL, /* client_data passed to PasteGameCB */
5461 /* better to use the time field from the event that triggered the
5462 * call to this function, but that isn't trivial to get
5472 SaveGameProc(NULL, NULL, NULL, NULL);
5475 void AnalyzeModeProc(w, event, prms, nprms)
5483 if (!first.analysisSupport) {
5484 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
5485 DisplayError(buf, 0);
5488 /* [DM] icsEngineAnalyze [HGM] This is horrible code; reverse the gameMode and isEngineAnalyze tests! */
5489 if (appData.icsActive) {
5490 if (gameMode != IcsObserving) {
5491 sprintf(buf,_("You are not observing a game"));
5492 DisplayError(buf, 0);
5494 if (appData.icsEngineAnalyze) {
5495 if (appData.debugMode)
5496 fprintf(debugFP, _("Found unexpected active ICS engine analyze \n"));
5502 /* if enable, use want disable icsEngineAnalyze */
5503 if (appData.icsEngineAnalyze) {
5508 appData.icsEngineAnalyze = TRUE;
5509 if (appData.debugMode)
5510 fprintf(debugFP, _("ICS engine analyze starting... \n"));
5512 if (!appData.showThinking)
5513 ShowThinkingProc(w,event,prms,nprms);
5518 void AnalyzeFileProc(w, event, prms, nprms)
5524 if (!first.analysisSupport) {
5526 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
5527 DisplayError(buf, 0);
5532 if (!appData.showThinking)
5533 ShowThinkingProc(w,event,prms,nprms);
5536 FileNamePopUp(_("File to analyze"), "", LoadGamePopUp, "rb");
5537 AnalysisPeriodicEvent(1);
5540 void IcsClientProc(w, event, prms, nprms)
5549 void EditGameProc(w, event, prms, nprms)
5558 void EditPositionProc(w, event, prms, nprms)
5564 EditPositionEvent();
5567 void TrainingProc(w, event, prms, nprms)
5576 void EditCommentProc(w, event, prms, nprms)
5583 EditCommentPopDown();
5589 void IcsInputBoxProc(w, event, prms, nprms)
5595 if (ICSInputBoxUp) {
5596 ICSInputBoxPopDown();
5603 void EnterKeyProc(w, event, prms, nprms)
5609 if (ICSInputBoxUp == True)
5614 void ForwardProc(w, event, prms, nprms)
5624 void BackwardProc(w, event, prms, nprms)
5633 void ToStartProc(w, event, prms, nprms)
5642 void ToEndProc(w, event, prms, nprms)
5651 void RevertProc(w, event, prms, nprms)
5660 void TruncateGameProc(w, event, prms, nprms)
5666 TruncateGameEvent();
5668 void RetractMoveProc(w, event, prms, nprms)
5677 void AlwaysQueenProc(w, event, prms, nprms)
5685 appData.alwaysPromoteToQueen = !appData.alwaysPromoteToQueen;
5687 if (appData.alwaysPromoteToQueen) {
5688 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5690 XtSetArg(args[0], XtNleftBitmap, None);
5692 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
5696 void AnimateDraggingProc(w, event, prms, nprms)
5704 appData.animateDragging = !appData.animateDragging;
5706 if (appData.animateDragging) {
5707 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5710 XtSetArg(args[0], XtNleftBitmap, None);
5712 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Dragging"),
5716 void AnimateMovingProc(w, event, prms, nprms)
5724 appData.animate = !appData.animate;
5726 if (appData.animate) {
5727 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5730 XtSetArg(args[0], XtNleftBitmap, None);
5732 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
5736 void AutocommProc(w, event, prms, nprms)
5744 appData.autoComment = !appData.autoComment;
5746 if (appData.autoComment) {
5747 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5749 XtSetArg(args[0], XtNleftBitmap, None);
5751 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
5756 void AutoflagProc(w, event, prms, nprms)
5764 appData.autoCallFlag = !appData.autoCallFlag;
5766 if (appData.autoCallFlag) {
5767 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5769 XtSetArg(args[0], XtNleftBitmap, None);
5771 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
5775 void AutoflipProc(w, event, prms, nprms)
5783 appData.autoFlipView = !appData.autoFlipView;
5785 if (appData.autoFlipView) {
5786 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5788 XtSetArg(args[0], XtNleftBitmap, None);
5790 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flip View"),
5794 void AutobsProc(w, event, prms, nprms)
5802 appData.autoObserve = !appData.autoObserve;
5804 if (appData.autoObserve) {
5805 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5807 XtSetArg(args[0], XtNleftBitmap, None);
5809 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
5813 void AutoraiseProc(w, event, prms, nprms)
5821 appData.autoRaiseBoard = !appData.autoRaiseBoard;
5823 if (appData.autoRaiseBoard) {
5824 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5826 XtSetArg(args[0], XtNleftBitmap, None);
5828 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Raise Board"),
5832 void AutosaveProc(w, event, prms, nprms)
5840 appData.autoSaveGames = !appData.autoSaveGames;
5842 if (appData.autoSaveGames) {
5843 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5845 XtSetArg(args[0], XtNleftBitmap, None);
5847 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
5851 void BlindfoldProc(w, event, prms, nprms)
5859 appData.blindfold = !appData.blindfold;
5861 if (appData.blindfold) {
5862 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5864 XtSetArg(args[0], XtNleftBitmap, None);
5866 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Blindfold"),
5869 DrawPosition(True, NULL);
5872 void TestLegalityProc(w, event, prms, nprms)
5880 appData.testLegality = !appData.testLegality;
5882 if (appData.testLegality) {
5883 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5885 XtSetArg(args[0], XtNleftBitmap, None);
5887 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Test Legality"),
5892 void FlashMovesProc(w, event, prms, nprms)
5900 if (appData.flashCount == 0) {
5901 appData.flashCount = 3;
5903 appData.flashCount = -appData.flashCount;
5906 if (appData.flashCount > 0) {
5907 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5909 XtSetArg(args[0], XtNleftBitmap, None);
5911 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flash Moves"),
5915 void FlipViewProc(w, event, prms, nprms)
5921 flipView = !flipView;
5922 DrawPosition(True, NULL);
5925 void GetMoveListProc(w, event, prms, nprms)
5933 appData.getMoveList = !appData.getMoveList;
5935 if (appData.getMoveList) {
5936 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5939 XtSetArg(args[0], XtNleftBitmap, None);
5941 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
5946 void HighlightDraggingProc(w, event, prms, nprms)
5954 appData.highlightDragging = !appData.highlightDragging;
5956 if (appData.highlightDragging) {
5957 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5959 XtSetArg(args[0], XtNleftBitmap, None);
5961 XtSetValues(XtNameToWidget(menuBarWidget,
5962 "menuOptions.Highlight Dragging"), args, 1);
5966 void HighlightLastMoveProc(w, event, prms, nprms)
5974 appData.highlightLastMove = !appData.highlightLastMove;
5976 if (appData.highlightLastMove) {
5977 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5979 XtSetArg(args[0], XtNleftBitmap, None);
5981 XtSetValues(XtNameToWidget(menuBarWidget,
5982 "menuOptions.Highlight Last Move"), args, 1);
5985 void IcsAlarmProc(w, event, prms, nprms)
5993 appData.icsAlarm = !appData.icsAlarm;
5995 if (appData.icsAlarm) {
5996 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5998 XtSetArg(args[0], XtNleftBitmap, None);
6000 XtSetValues(XtNameToWidget(menuBarWidget,
6001 "menuOptions.ICS Alarm"), args, 1);
6004 void MoveSoundProc(w, event, prms, nprms)
6012 appData.ringBellAfterMoves = !appData.ringBellAfterMoves;
6014 if (appData.ringBellAfterMoves) {
6015 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6017 XtSetArg(args[0], XtNleftBitmap, None);
6019 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
6024 void OldSaveStyleProc(w, event, prms, nprms)
6032 appData.oldSaveStyle = !appData.oldSaveStyle;
6034 if (appData.oldSaveStyle) {
6035 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6037 XtSetArg(args[0], XtNleftBitmap, None);
6039 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Old Save Style"),
6043 void PeriodicUpdatesProc(w, event, prms, nprms)
6051 PeriodicUpdatesEvent(!appData.periodicUpdates);
6053 if (appData.periodicUpdates) {
6054 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6056 XtSetArg(args[0], XtNleftBitmap, None);
6058 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Periodic Updates"),
6062 void PonderNextMoveProc(w, event, prms, nprms)
6070 PonderNextMoveEvent(!appData.ponderNextMove);
6072 if (appData.ponderNextMove) {
6073 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6075 XtSetArg(args[0], XtNleftBitmap, None);
6077 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Ponder Next Move"),
6081 void PopupExitMessageProc(w, event, prms, nprms)
6089 appData.popupExitMessage = !appData.popupExitMessage;
6091 if (appData.popupExitMessage) {
6092 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6094 XtSetArg(args[0], XtNleftBitmap, None);
6096 XtSetValues(XtNameToWidget(menuBarWidget,
6097 "menuOptions.Popup Exit Message"), args, 1);
6100 void PopupMoveErrorsProc(w, event, prms, nprms)
6108 appData.popupMoveErrors = !appData.popupMoveErrors;
6110 if (appData.popupMoveErrors) {
6111 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6113 XtSetArg(args[0], XtNleftBitmap, None);
6115 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Popup Move Errors"),
6119 void PremoveProc(w, event, prms, nprms)
6127 appData.premove = !appData.premove;
6129 if (appData.premove) {
6130 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6132 XtSetArg(args[0], XtNleftBitmap, None);
6134 XtSetValues(XtNameToWidget(menuBarWidget,
6135 "menuOptions.Premove"), args, 1);
6138 void QuietPlayProc(w, event, prms, nprms)
6146 appData.quietPlay = !appData.quietPlay;
6148 if (appData.quietPlay) {
6149 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6151 XtSetArg(args[0], XtNleftBitmap, None);
6153 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Quiet Play"),
6157 void ShowThinkingProc(w, event, prms, nprms)
6165 appData.showThinking = !appData.showThinking; // [HGM] thinking: tken out of ShowThinkingEvent
6166 ShowThinkingEvent();
6168 // [HGM] thinking: currently no suc menu item; replaced by Hide Thinking (From Human)
6169 if (appData.showThinking) {
6170 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6172 XtSetArg(args[0], XtNleftBitmap, None);
6174 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Thinking"),
6179 void HideThinkingProc(w, event, prms, nprms)
6187 appData.hideThinkingFromHuman = !appData.hideThinkingFromHuman; // [HGM] thinking: tken out of ShowThinkingEvent
6188 ShowThinkingEvent();
6190 if (appData.hideThinkingFromHuman) {
6191 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6193 XtSetArg(args[0], XtNleftBitmap, None);
6195 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
6199 void InfoProc(w, event, prms, nprms)
6206 snprintf(buf, sizeof(buf), "xterm -e info --directory %s --directory . -f %s &",
6211 void ManProc(w, event, prms, nprms)
6219 if (nprms && *nprms > 0)
6223 snprintf(buf, sizeof(buf), "xterm -e man %s &", name);
6227 void HintProc(w, event, prms, nprms)
6236 void BookProc(w, event, prms, nprms)
6245 void DebugProc(w, event, prms, nprms)
6251 appData.debugMode = !appData.debugMode;
6254 void AboutGameProc(w, event, prms, nprms)
6263 void NothingProc(w, event, prms, nprms)
6272 void Iconify(w, event, prms, nprms)
6281 XtSetArg(args[0], XtNiconic, True);
6282 XtSetValues(shellWidget, args, 1);
6285 void DisplayMessage(message, extMessage)
6286 gchar *message, *extMessage;
6293 snprintf(buf, sizeof(buf), "%s %s", message, extMessage);
6296 message = extMessage;
6299 gtk_label_set_text( GTK_LABEL(gtk_builder_get_object (builder, "Messages")),message);
6304 void DisplayTitle(text)
6307 gchar title[MSG_SIZ];
6309 if (text == NULL) text = "";
6311 if (appData.titleInWindow)
6316 if (*text != NULLCHAR)
6318 strcpy(title, text);
6320 else if (appData.icsActive)
6322 snprintf(title, sizeof(title), "%s: %s", programName, appData.icsHost);
6324 else if (appData.cmailGameName[0] != NULLCHAR)
6326 snprintf(title,sizeof(title), "%s: %s", programName, "CMail");
6328 // [HGM] license: This stuff should really be done in back-end, but WinBoard already had a pop-up for it
6330 else if (gameInfo.variant == VariantGothic)
6332 strcpy(title, GOTHIC);
6336 else if (gameInfo.variant == VariantFalcon)
6338 strcpy(title, FALCON);
6341 else if (appData.noChessProgram)
6343 strcpy(title, programName);
6347 snprintf(title,sizeof(title), "%s: %s", programName, first.tidy);
6349 gtk_window_set_title(GTK_WINDOW(GUI_Window),title);
6355 void DisplayError(message, error)
6362 if (appData.debugMode || appData.matchMode) {
6363 fprintf(stderr, "%s: %s\n", programName, message);
6366 if (appData.debugMode || appData.matchMode) {
6367 fprintf(stderr, "%s: %s: %s\n",
6368 programName, message, strerror(error));
6370 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
6373 ErrorPopUp(_("Error"), message, FALSE);
6377 void DisplayMoveError(message)
6382 DrawPosition(FALSE, NULL);
6383 if (appData.debugMode || appData.matchMode) {
6384 fprintf(stderr, "%s: %s\n", programName, message);
6386 if (appData.popupMoveErrors) {
6387 ErrorPopUp(_("Error"), message, FALSE);
6389 DisplayMessage(message, "");
6394 void DisplayFatalError(message, error, status)
6400 errorExitStatus = status;
6402 fprintf(stderr, "%s: %s\n", programName, message);
6404 fprintf(stderr, "%s: %s: %s\n",
6405 programName, message, strerror(error));
6406 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
6409 if (appData.popupExitMessage && boardWidget && XtIsRealized(boardWidget)) {
6410 ErrorPopUp(status ? _("Fatal Error") : _("Exiting"), message, TRUE);
6416 void DisplayInformation(message)
6420 ErrorPopUp(_("Information"), message, TRUE);
6423 void DisplayNote(message)
6427 ErrorPopUp(_("Note"), message, FALSE);
6431 NullXErrorCheck(dpy, error_event)
6433 XErrorEvent *error_event;
6438 void DisplayIcsInteractionTitle(message)
6441 if (oldICSInteractionTitle == NULL) {
6442 /* Magic to find the old window title, adapted from vim */
6443 char *wina = getenv("WINDOWID");
6445 Window win = (Window) atoi(wina);
6446 Window root, parent, *children;
6447 unsigned int nchildren;
6448 int (*oldHandler)() = XSetErrorHandler(NullXErrorCheck);
6450 if (XFetchName(xDisplay, win, &oldICSInteractionTitle)) break;
6451 if (!XQueryTree(xDisplay, win, &root, &parent,
6452 &children, &nchildren)) break;
6453 if (children) XFree((void *)children);
6454 if (parent == root || parent == 0) break;
6457 XSetErrorHandler(oldHandler);
6459 if (oldICSInteractionTitle == NULL) {
6460 oldICSInteractionTitle = "xterm";
6463 printf("\033]0;%s\007", message);
6467 char pendingReplyPrefix[MSG_SIZ];
6468 ProcRef pendingReplyPR;
6470 void AskQuestionProc(w, event, prms, nprms)
6477 fprintf(stderr, _("AskQuestionProc needed 4 parameters, got %d\n"),
6481 AskQuestionEvent(prms[0], prms[1], prms[2], prms[3]);
6484 void AskQuestionPopDown()
6486 if (!askQuestionUp) return;
6487 XtPopdown(askQuestionShell);
6488 XtDestroyWidget(askQuestionShell);
6489 askQuestionUp = False;
6492 void AskQuestionReplyAction(w, event, prms, nprms)
6502 reply = XawDialogGetValueString(w = XtParent(w));
6503 strcpy(buf, pendingReplyPrefix);
6504 if (*buf) strcat(buf, " ");
6507 OutputToProcess(pendingReplyPR, buf, strlen(buf), &err);
6508 AskQuestionPopDown();
6510 if (err) DisplayFatalError(_("Error writing to chess program"), err, 0);
6513 void AskQuestionCallback(w, client_data, call_data)
6515 XtPointer client_data, call_data;
6520 XtSetArg(args[0], XtNlabel, &name);
6521 XtGetValues(w, args, 1);
6523 if (strcmp(name, _("cancel")) == 0) {
6524 AskQuestionPopDown();
6526 AskQuestionReplyAction(w, NULL, NULL, NULL);
6530 void AskQuestion(title, question, replyPrefix, pr)
6531 char *title, *question, *replyPrefix;
6535 Widget popup, layout, dialog, edit;
6541 strcpy(pendingReplyPrefix, replyPrefix);
6542 pendingReplyPR = pr;
6545 XtSetArg(args[i], XtNresizable, True); i++;
6546 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
6547 askQuestionShell = popup =
6548 XtCreatePopupShell(title, transientShellWidgetClass,
6549 shellWidget, args, i);
6552 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
6553 layoutArgs, XtNumber(layoutArgs));
6556 XtSetArg(args[i], XtNlabel, question); i++;
6557 XtSetArg(args[i], XtNvalue, ""); i++;
6558 XtSetArg(args[i], XtNborderWidth, 0); i++;
6559 dialog = XtCreateManagedWidget("question", dialogWidgetClass,
6562 XawDialogAddButton(dialog, _("enter"), AskQuestionCallback,
6563 (XtPointer) dialog);
6564 XawDialogAddButton(dialog, _("cancel"), AskQuestionCallback,
6565 (XtPointer) dialog);
6567 XtRealizeWidget(popup);
6568 CatchDeleteWindow(popup, "AskQuestionPopDown");
6570 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
6571 &x, &y, &win_x, &win_y, &mask);
6573 XtSetArg(args[0], XtNx, x - 10);
6574 XtSetArg(args[1], XtNy, y - 30);
6575 XtSetValues(popup, args, 2);
6577 XtPopup(popup, XtGrabExclusive);
6578 askQuestionUp = True;
6580 edit = XtNameToWidget(dialog, "*value");
6581 XtSetKeyboardFocus(popup, edit);
6589 if (*name == NULLCHAR) {
6591 } else if (strcmp(name, "$") == 0) {
6592 putc(BELLCHAR, stderr);
6595 snprintf(buf, sizeof(buf), "%s '%s' &", appData.soundProgram, name);
6603 PlaySound(appData.soundMove);
6609 PlaySound(appData.soundIcsWin);
6615 PlaySound(appData.soundIcsLoss);
6621 PlaySound(appData.soundIcsDraw);
6625 PlayIcsUnfinishedSound()
6627 PlaySound(appData.soundIcsUnfinished);
6633 PlaySound(appData.soundIcsAlarm);
6639 system("stty echo");
6645 system("stty -echo");
6649 Colorize(cc, continuation)
6654 int count, outCount, error;
6656 if (textColors[(int)cc].bg > 0) {
6657 if (textColors[(int)cc].fg > 0) {
6658 sprintf(buf, "\033[0;%d;%d;%dm", textColors[(int)cc].attr,
6659 textColors[(int)cc].fg, textColors[(int)cc].bg);
6661 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
6662 textColors[(int)cc].bg);
6665 if (textColors[(int)cc].fg > 0) {
6666 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
6667 textColors[(int)cc].fg);
6669 sprintf(buf, "\033[0;%dm", textColors[(int)cc].attr);
6672 count = strlen(buf);
6673 outCount = OutputToProcess(NoProc, buf, count, &error);
6674 if (outCount < count) {
6675 DisplayFatalError(_("Error writing to display"), error, 1);
6678 if (continuation) return;
6681 PlaySound(appData.soundShout);
6684 PlaySound(appData.soundSShout);
6687 PlaySound(appData.soundChannel1);
6690 PlaySound(appData.soundChannel);
6693 PlaySound(appData.soundKibitz);
6696 PlaySound(appData.soundTell);
6698 case ColorChallenge:
6699 PlaySound(appData.soundChallenge);
6702 PlaySound(appData.soundRequest);
6705 PlaySound(appData.soundSeek);
6716 return getpwuid(getuid())->pw_name;
6719 static char *ExpandPathName(path)
6722 static char static_buf[2000];
6723 char *d, *s, buf[2000];
6729 while (*s && isspace(*s))
6738 if (*(s+1) == '/') {
6739 strcpy(d, getpwuid(getuid())->pw_dir);
6744 *strchr(buf, '/') = 0;
6745 pwd = getpwnam(buf);
6748 fprintf(stderr, _("ERROR: Unknown user %s (in path %s)\n"),
6752 strcpy(d, pwd->pw_dir);
6753 strcat(d, strchr(s+1, '/'));
6764 static char host_name[MSG_SIZ];
6766 #if HAVE_GETHOSTNAME
6767 gethostname(host_name, MSG_SIZ);
6769 #else /* not HAVE_GETHOSTNAME */
6770 # if HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H
6771 sysinfo(SI_HOSTNAME, host_name, MSG_SIZ);
6773 # else /* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
6775 # endif/* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
6776 #endif /* not HAVE_GETHOSTNAME */
6779 gint delayedEventTimerTag = 0;
6780 DelayedEventCallback delayedEventCallback = 0;
6783 FireDelayedEvent(data)
6786 delayedEventTimerTag = 0;
6787 delayedEventCallback();
6791 ScheduleDelayedEvent(cb, millisec)
6792 DelayedEventCallback cb; long millisec;
6794 delayedEventCallback = cb;
6795 delayedEventTimerTag = gtk_timeout_add(millisec,(GtkFunction) FireDelayedEvent, NULL);
6798 DelayedEventCallback
6801 if (delayedEventTimerTag)
6803 return delayedEventCallback;
6812 CancelDelayedEvent()
6814 if (delayedEventTimerTag)
6816 gtk_timeout_remove(delayedEventTimerTag);
6817 delayedEventTimerTag = 0;
6823 gint loadGameTimerTag = 0;
6825 int LoadGameTimerRunning()
6827 return loadGameTimerTag != 0;
6830 int StopLoadGameTimer()
6832 if (loadGameTimerTag != 0) {
6833 gtk_timeout_remove(loadGameTimerTag);
6834 loadGameTimerTag = 0;
6842 LoadGameTimerCallback(data)
6845 loadGameTimerTag = 0;
6850 StartLoadGameTimer(millisec)
6854 gtk_timeout_add( millisec, (GtkFunction) LoadGameTimerCallback, NULL);
6857 gint analysisClockTag = 0;
6860 AnalysisClockCallback(data)
6863 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile
6864 || appData.icsEngineAnalyze)
6866 AnalysisPeriodicEvent(0);
6867 StartAnalysisClock();
6872 StartAnalysisClock()
6875 gtk_timeout_add( 2000,(GtkFunction) AnalysisClockCallback, NULL);
6878 gint clockTimerTag = 0;
6880 int ClockTimerRunning()
6882 return clockTimerTag != 0;
6885 int StopClockTimer()
6887 if (clockTimerTag != 0)
6889 gtk_timeout_remove(clockTimerTag);
6900 ClockTimerCallback(data)
6909 StartClockTimer(millisec)
6912 clockTimerTag = gtk_timeout_add(millisec,(GtkFunction) ClockTimerCallback,NULL);
6917 DisplayTimerLabel(w, color, timer, highlight)
6926 if (appData.clockMode) {
6927 sprintf(buf, "%s: %s", color, TimeString(timer));
6929 sprintf(buf, "%s ", color);
6931 gtk_label_set_text(GTK_LABEL(w),buf);
6933 /* check for low time warning */
6934 // Pixel foregroundOrWarningColor = timerForegroundPixel;
6937 // appData.lowTimeWarning &&
6938 // (timer / 1000) < appData.icsAlarmTime)
6939 // foregroundOrWarningColor = lowTimeWarningColor;
6941 // if (appData.clockMode) {
6942 // sprintf(buf, "%s: %s", color, TimeString(timer));
6943 // XtSetArg(args[0], XtNlabel, buf);
6945 // sprintf(buf, "%s ", color);
6946 // XtSetArg(args[0], XtNlabel, buf);
6951 // XtSetArg(args[1], XtNbackground, foregroundOrWarningColor);
6952 // XtSetArg(args[2], XtNforeground, timerBackgroundPixel);
6954 // XtSetArg(args[1], XtNbackground, timerBackgroundPixel);
6955 // XtSetArg(args[2], XtNforeground, foregroundOrWarningColor);
6958 // XtSetValues(w, args, 3);
6963 DisplayWhiteClock(timeRemaining, highlight)
6967 if(appData.noGUI) return;
6969 DisplayTimerLabel(GUI_Whiteclock, _("White"), timeRemaining, highlight);
6970 if (highlight && WindowIcon == BlackIcon)
6972 WindowIcon = WhiteIcon;
6973 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
6978 DisplayBlackClock(timeRemaining, highlight)
6982 if(appData.noGUI) return;
6984 DisplayTimerLabel(GUI_Blackclock, _("Black"), timeRemaining, highlight);
6985 if (highlight && WindowIcon == WhiteIcon)
6987 WindowIcon = BlackIcon;
6988 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
7006 int StartChildProcess(cmdLine, dir, pr)
7013 int to_prog[2], from_prog[2];
7017 if (appData.debugMode) {
7018 fprintf(stderr, "StartChildProcess (dir=\"%s\") %s\n",dir, cmdLine);
7021 /* We do NOT feed the cmdLine to the shell; we just
7022 parse it into blank-separated arguments in the
7023 most simple-minded way possible.
7026 strcpy(buf, cmdLine);
7031 if (p == NULL) break;
7036 SetUpChildIO(to_prog, from_prog);
7038 if ((pid = fork()) == 0) {
7040 // [HGM] PSWBTM: made order resistant against case where fd of created pipe was 0 or 1
7041 close(to_prog[1]); // first close the unused pipe ends
7042 close(from_prog[0]);
7043 dup2(to_prog[0], 0); // to_prog was created first, nd is the only one to use 0 or 1
7044 dup2(from_prog[1], 1);
7045 if(to_prog[0] >= 2) close(to_prog[0]); // if 0 or 1, the dup2 already cosed the original
7046 close(from_prog[1]); // and closing again loses one of the pipes!
7047 if(fileno(stderr) >= 2) // better safe than sorry...
7048 dup2(1, fileno(stderr)); /* force stderr to the pipe */
7050 if (dir[0] != NULLCHAR && chdir(dir) != 0) {
7055 nice(appData.niceEngines); // [HGM] nice: adjust priority of engine proc
7057 execvp(argv[0], argv);
7059 /* If we get here, exec failed */
7064 /* Parent process */
7066 close(from_prog[1]);
7068 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7071 cp->fdFrom = from_prog[0];
7072 cp->fdTo = to_prog[1];
7077 // [HGM] kill: implement the 'hard killing' of AS's Winboard_x
7078 static RETSIGTYPE AlarmCallBack(int n)
7084 DestroyChildProcess(pr, signalType)
7088 ChildProc *cp = (ChildProc *) pr;
7090 if (cp->kind != CPReal) return;
7092 if (signalType == 10) { // [HGM] kill: if it does not terminate in 3 sec, kill
7093 signal(SIGALRM, AlarmCallBack);
7095 if(wait((int *) 0) == -1) { // process does not terminate on its own accord
7096 kill(cp->pid, SIGKILL); // kill it forcefully
7097 wait((int *) 0); // and wait again
7101 kill(cp->pid, signalType == 9 ? SIGKILL : SIGTERM); // [HGM] kill: use hard kill if so requested
7103 /* Process is exiting either because of the kill or because of
7104 a quit command sent by the backend; either way, wait for it to die.
7113 InterruptChildProcess(pr)
7116 ChildProc *cp = (ChildProc *) pr;
7118 if (cp->kind != CPReal) return;
7119 (void) kill(cp->pid, SIGINT); /* stop it thinking */
7122 int OpenTelnet(host, port, pr)
7127 char cmdLine[MSG_SIZ];
7129 if (port[0] == NULLCHAR) {
7130 snprintf(cmdLine, sizeof(cmdLine), "%s %s", appData.telnetProgram, host);
7132 snprintf(cmdLine, sizeof(cmdLine), "%s %s %s", appData.telnetProgram, host, port);
7134 return StartChildProcess(cmdLine, "", pr);
7137 int OpenTCP(host, port, pr)
7143 DisplayFatalError(_("Socket support is not configured in"), 0, 2);
7144 #else /* !OMIT_SOCKETS */
7146 struct sockaddr_in sa;
7148 unsigned short uport;
7151 if ((s = socket(AF_INET, SOCK_STREAM, 6)) < 0) {
7155 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
7156 sa.sin_family = AF_INET;
7157 sa.sin_addr.s_addr = INADDR_ANY;
7158 uport = (unsigned short) 0;
7159 sa.sin_port = htons(uport);
7160 if (bind(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)) < 0) {
7164 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
7165 if (!(hp = gethostbyname(host))) {
7167 if (sscanf(host, "%d.%d.%d.%d", &b0, &b1, &b2, &b3) == 4) {
7168 hp = (struct hostent *) calloc(1, sizeof(struct hostent));
7169 hp->h_addrtype = AF_INET;
7171 hp->h_addr_list = (char **) calloc(2, sizeof(char *));
7172 hp->h_addr_list[0] = (char *) malloc(4);
7173 hp->h_addr_list[0][0] = b0;
7174 hp->h_addr_list[0][1] = b1;
7175 hp->h_addr_list[0][2] = b2;
7176 hp->h_addr_list[0][3] = b3;
7181 sa.sin_family = hp->h_addrtype;
7182 uport = (unsigned short) atoi(port);
7183 sa.sin_port = htons(uport);
7184 memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);
7186 if (connect(s, (struct sockaddr *) &sa,
7187 sizeof(struct sockaddr_in)) < 0) {
7191 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7198 #endif /* !OMIT_SOCKETS */
7203 int OpenCommPort(name, pr)
7210 fd = open(name, 2, 0);
7211 if (fd < 0) return errno;
7213 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7223 int OpenLoopback(pr)
7229 SetUpChildIO(to, from);
7231 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7234 cp->fdFrom = to[0]; /* note not from[0]; we are doing a loopback */
7241 int OpenRcmd(host, user, cmd, pr)
7242 char *host, *user, *cmd;
7245 DisplayFatalError(_("internal rcmd not implemented for Unix"), 0, 1);
7249 #define INPUT_SOURCE_BUF_SIZE 8192
7258 char buf[INPUT_SOURCE_BUF_SIZE];
7263 DoInputCallback(closure, source, xid)
7268 InputSource *is = (InputSource *) closure;
7273 if (is->lineByLine) {
7274 count = read(is->fd, is->unused,
7275 INPUT_SOURCE_BUF_SIZE - (is->unused - is->buf));
7277 (is->func)(is, is->closure, is->buf, count, count ? errno : 0);
7280 is->unused += count;
7282 while (p < is->unused) {
7283 q = memchr(p, '\n', is->unused - p);
7284 if (q == NULL) break;
7286 (is->func)(is, is->closure, p, q - p, 0);
7290 while (p < is->unused) {
7295 count = read(is->fd, is->buf, INPUT_SOURCE_BUF_SIZE);
7300 (is->func)(is, is->closure, is->buf, count, error);
7304 InputSourceRef AddInputSource(pr, lineByLine, func, closure)
7311 ChildProc *cp = (ChildProc *) pr;
7313 is = (InputSource *) calloc(1, sizeof(InputSource));
7314 is->lineByLine = lineByLine;
7318 is->fd = fileno(stdin);
7320 is->kind = cp->kind;
7321 is->fd = cp->fdFrom;
7324 is->unused = is->buf;
7327 is->xid = XtAppAddInput(appContext, is->fd,
7328 (XtPointer) (XtInputReadMask),
7329 (XtInputCallbackProc) DoInputCallback,
7331 is->closure = closure;
7332 return (InputSourceRef) is;
7336 RemoveInputSource(isr)
7339 InputSource *is = (InputSource *) isr;
7341 if (is->xid == 0) return;
7342 XtRemoveInput(is->xid);
7346 int OutputToProcess(pr, message, count, outError)
7352 ChildProc *cp = (ChildProc *) pr;
7356 outCount = fwrite(message, 1, count, stdout);
7358 outCount = write(cp->fdTo, message, count);
7368 /* Output message to process, with "ms" milliseconds of delay
7369 between each character. This is needed when sending the logon
7370 script to ICC, which for some reason doesn't like the
7371 instantaneous send. */
7372 int OutputToProcessDelayed(pr, message, count, outError, msdelay)
7379 ChildProc *cp = (ChildProc *) pr;
7384 r = write(cp->fdTo, message++, 1);
7397 /**** Animation code by Hugh Fisher, DCS, ANU.
7399 Known problem: if a window overlapping the board is
7400 moved away while a piece is being animated underneath,
7401 the newly exposed area won't be updated properly.
7402 I can live with this.
7404 Known problem: if you look carefully at the animation
7405 of pieces in mono mode, they are being drawn as solid
7406 shapes without interior detail while moving. Fixing
7407 this would be a major complication for minimal return.
7410 /* Masks for XPM pieces. Black and white pieces can have
7411 different shapes, but in the interest of retaining my
7412 sanity pieces must have the same outline on both light
7413 and dark squares, and all pieces must use the same
7414 background square colors/images. */
7416 static int xpmDone = 0;
7419 CreateAnimMasks (pieceDepth)
7426 unsigned long plane;
7429 /* just return for gtk at the moment */
7432 /* Need a bitmap just to get a GC with right depth */
7433 buf = XCreatePixmap(xDisplay, xBoardWindow,
7435 values.foreground = 1;
7436 values.background = 0;
7437 /* Don't use XtGetGC, not read only */
7438 maskGC = XCreateGC(xDisplay, buf,
7439 GCForeground | GCBackground, &values);
7440 XFreePixmap(xDisplay, buf);
7442 buf = XCreatePixmap(xDisplay, xBoardWindow,
7443 squareSize, squareSize, pieceDepth);
7444 values.foreground = XBlackPixel(xDisplay, xScreen);
7445 values.background = XWhitePixel(xDisplay, xScreen);
7446 bufGC = XCreateGC(xDisplay, buf,
7447 GCForeground | GCBackground, &values);
7449 for (piece = WhitePawn; piece <= BlackKing; piece++) {
7450 /* Begin with empty mask */
7451 if(!xpmDone) // [HGM] pieces: keep using existing
7452 xpmMask[piece] = XCreatePixmap(xDisplay, xBoardWindow,
7453 squareSize, squareSize, 1);
7454 XSetFunction(xDisplay, maskGC, GXclear);
7455 XFillRectangle(xDisplay, xpmMask[piece], maskGC,
7456 0, 0, squareSize, squareSize);
7458 /* Take a copy of the piece */
7463 XSetFunction(xDisplay, bufGC, GXcopy);
7464 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn],
7466 0, 0, squareSize, squareSize, 0, 0);
7468 /* XOR the background (light) over the piece */
7469 XSetFunction(xDisplay, bufGC, GXxor);
7471 XCopyArea(xDisplay, xpmLightSquare, buf, bufGC,
7472 0, 0, squareSize, squareSize, 0, 0);
7474 XSetForeground(xDisplay, bufGC, lightSquareColor);
7475 XFillRectangle(xDisplay, buf, bufGC, 0, 0, squareSize, squareSize);
7478 /* We now have an inverted piece image with the background
7479 erased. Construct mask by just selecting all the non-zero
7480 pixels - no need to reconstruct the original image. */
7481 XSetFunction(xDisplay, maskGC, GXor);
7483 /* Might be quicker to download an XImage and create bitmap
7484 data from it rather than this N copies per piece, but it
7485 only takes a fraction of a second and there is a much
7486 longer delay for loading the pieces. */
7487 for (n = 0; n < pieceDepth; n ++) {
7488 XCopyPlane(xDisplay, buf, xpmMask[piece], maskGC,
7489 0, 0, squareSize, squareSize,
7495 XFreePixmap(xDisplay, buf);
7496 XFreeGC(xDisplay, bufGC);
7497 XFreeGC(xDisplay, maskGC);
7501 InitAnimState (anim, info)
7503 XWindowAttributes * info;
7508 /* Each buffer is square size, same depth as window */
7509 // anim->saveBuf = XCreatePixmap(xDisplay, xBoardWindow,
7510 // squareSize, squareSize, info->depth);
7511 // anim->newBuf = XCreatePixmap(xDisplay, xBoardWindow,
7512 // squareSize, squareSize, info->depth);
7514 // /* Create a plain GC for blitting */
7515 // mask = GCForeground | GCBackground | GCFunction |
7516 // GCPlaneMask | GCGraphicsExposures;
7517 // values.foreground = XBlackPixel(xDisplay, xScreen);
7518 // values.background = XWhitePixel(xDisplay, xScreen);
7519 // values.function = GXcopy;
7520 // values.plane_mask = AllPlanes;
7521 // values.graphics_exposures = False;
7522 // anim->blitGC = XCreateGC(xDisplay, xBoardWindow, mask, &values);
7524 // /* Piece will be copied from an existing context at
7525 // the start of each new animation/drag. */
7526 // anim->pieceGC = XCreateGC(xDisplay, xBoardWindow, 0, &values);
7528 // /* Outline will be a read-only copy of an existing */
7529 // anim->outlineGC = None;
7535 static VariantClass old = (VariantClass) -1; // [HGM] pieces: redo every time variant changes
7536 XWindowAttributes info;
7538 /* for gtk at the moment just ... */
7541 if (xpmDone && gameInfo.variant == old) return;
7542 if(xpmDone) old = gameInfo.variant; // first time pieces might not be created yet
7543 // XGetWindowAttributes(xDisplay, xBoardWindow, &info);
7545 // InitAnimState(&game, &info);
7546 // InitAnimState(&player, &info);
7548 /* For XPM pieces, we need bitmaps to use as masks. */
7550 // CreateAnimMasks(info.depth);
7556 static Boolean frameWaiting;
7558 static RETSIGTYPE FrameAlarm (sig)
7561 frameWaiting = False;
7562 /* In case System-V style signals. Needed?? */
7563 signal(SIGALRM, FrameAlarm);
7570 struct itimerval delay;
7572 XSync(xDisplay, False);
7575 frameWaiting = True;
7576 signal(SIGALRM, FrameAlarm);
7577 delay.it_interval.tv_sec =
7578 delay.it_value.tv_sec = time / 1000;
7579 delay.it_interval.tv_usec =
7580 delay.it_value.tv_usec = (time % 1000) * 1000;
7581 setitimer(ITIMER_REAL, &delay, NULL);
7583 /* Ugh -- busy-wait! --tpm */
7584 while (frameWaiting);
7586 while (frameWaiting) pause();
7588 delay.it_interval.tv_sec = delay.it_value.tv_sec = 0;
7589 delay.it_interval.tv_usec = delay.it_value.tv_usec = 0;
7590 setitimer(ITIMER_REAL, &delay, NULL);
7600 // XSync(xDisplay, False);
7602 usleep(time * 1000);
7607 /* Convert board position to corner of screen rect and color */
7610 ScreenSquare(column, row, pt, color)
7611 int column; int row; XPoint * pt; int * color;
7614 pt->x = lineGap + ((BOARD_WIDTH-1)-column) * (squareSize + lineGap);
7615 pt->y = lineGap + row * (squareSize + lineGap);
7617 pt->x = lineGap + column * (squareSize + lineGap);
7618 pt->y = lineGap + ((BOARD_HEIGHT-1)-row) * (squareSize + lineGap);
7620 *color = SquareColor(row, column);
7623 /* Convert window coords to square */
7626 BoardSquare(x, y, column, row)
7627 int x; int y; int * column; int * row;
7629 *column = EventToSquare(x, BOARD_WIDTH);
7630 if (flipView && *column >= 0)
7631 *column = BOARD_WIDTH - 1 - *column;
7632 *row = EventToSquare(y, BOARD_HEIGHT);
7633 if (!flipView && *row >= 0)
7634 *row = BOARD_HEIGHT - 1 - *row;
7639 #undef Max /* just in case */
7641 #define Max(a, b) ((a) > (b) ? (a) : (b))
7642 #define Min(a, b) ((a) < (b) ? (a) : (b))
7645 SetRect(rect, x, y, width, height)
7646 XRectangle * rect; int x; int y; int width; int height;
7650 rect->width = width;
7651 rect->height = height;
7654 /* Test if two frames overlap. If they do, return
7655 intersection rect within old and location of
7656 that rect within new. */
7659 Intersect(old, new, size, area, pt)
7660 XPoint * old; XPoint * new;
7661 int size; XRectangle * area; XPoint * pt;
7663 if (old->x > new->x + size || new->x > old->x + size ||
7664 old->y > new->y + size || new->y > old->y + size) {
7667 SetRect(area, Max(new->x - old->x, 0), Max(new->y - old->y, 0),
7668 size - abs(old->x - new->x), size - abs(old->y - new->y));
7669 pt->x = Max(old->x - new->x, 0);
7670 pt->y = Max(old->y - new->y, 0);
7675 /* For two overlapping frames, return the rect(s)
7676 in the old that do not intersect with the new. */
7679 CalcUpdateRects(old, new, size, update, nUpdates)
7680 XPoint * old; XPoint * new; int size;
7681 XRectangle update[]; int * nUpdates;
7685 /* If old = new (shouldn't happen) then nothing to draw */
7686 if (old->x == new->x && old->y == new->y) {
7690 /* Work out what bits overlap. Since we know the rects
7691 are the same size we don't need a full intersect calc. */
7693 /* Top or bottom edge? */
7694 if (new->y > old->y) {
7695 SetRect(&(update[count]), old->x, old->y, size, new->y - old->y);
7697 } else if (old->y > new->y) {
7698 SetRect(&(update[count]), old->x, old->y + size - (old->y - new->y),
7699 size, old->y - new->y);
7702 /* Left or right edge - don't overlap any update calculated above. */
7703 if (new->x > old->x) {
7704 SetRect(&(update[count]), old->x, Max(new->y, old->y),
7705 new->x - old->x, size - abs(new->y - old->y));
7707 } else if (old->x > new->x) {
7708 SetRect(&(update[count]), new->x + size, Max(new->y, old->y),
7709 old->x - new->x, size - abs(new->y - old->y));
7716 /* Generate a series of frame coords from start->mid->finish.
7717 The movement rate doubles until the half way point is
7718 reached, then halves back down to the final destination,
7719 which gives a nice slow in/out effect. The algorithmn
7720 may seem to generate too many intermediates for short
7721 moves, but remember that the purpose is to attract the
7722 viewers attention to the piece about to be moved and
7723 then to where it ends up. Too few frames would be less
7727 Tween(start, mid, finish, factor, frames, nFrames)
7728 XPoint * start; XPoint * mid;
7729 XPoint * finish; int factor;
7730 XPoint frames[]; int * nFrames;
7732 int fraction, n, count;
7736 /* Slow in, stepping 1/16th, then 1/8th, ... */
7738 for (n = 0; n < factor; n++)
7740 for (n = 0; n < factor; n++) {
7741 frames[count].x = start->x + (mid->x - start->x) / fraction;
7742 frames[count].y = start->y + (mid->y - start->y) / fraction;
7744 fraction = fraction / 2;
7748 frames[count] = *mid;
7751 /* Slow out, stepping 1/2, then 1/4, ... */
7753 for (n = 0; n < factor; n++) {
7754 frames[count].x = finish->x - (finish->x - mid->x) / fraction;
7755 frames[count].y = finish->y - (finish->y - mid->y) / fraction;
7757 fraction = fraction * 2;
7762 /* Draw a piece on the screen without disturbing what's there */
7765 SelectGCMask(piece, clip, outline, mask)
7766 ChessSquare piece; GC * clip; GC * outline; Pixmap * mask;
7770 /* Bitmap for piece being moved. */
7771 if (appData.monoMode) {
7772 *mask = *pieceToSolid(piece);
7773 } else if (useImages) {
7775 *mask = xpmMask[piece];
7777 *mask = ximMaskPm[piece];
7780 *mask = *pieceToSolid(piece);
7783 /* GC for piece being moved. Square color doesn't matter, but
7784 since it gets modified we make a copy of the original. */
7786 if (appData.monoMode)
7791 if (appData.monoMode)
7796 // XCopyGC(xDisplay, source, 0xFFFFFFFF, *clip);
7798 /* Outline only used in mono mode and is not modified */
7800 *outline = bwPieceGC;
7802 *outline = wbPieceGC;
7806 OverlayPiece(piece, clip, outline, dest)
7807 ChessSquare piece; GC clip; GC outline; Drawable dest;
7812 /* Draw solid rectangle which will be clipped to shape of piece */
7813 // XFillRectangle(xDisplay, dest, clip,
7814 // 0, 0, squareSize, squareSize)
7816 if (appData.monoMode)
7817 /* Also draw outline in contrasting color for black
7818 on black / white on white cases */
7819 // XCopyPlane(xDisplay, *pieceToOutline(piece), dest, outline,
7820 // 0, 0, squareSize, squareSize, 0, 0, 1)
7823 /* Copy the piece */
7828 // XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
7830 // 0, 0, squareSize, squareSize,
7835 /* Animate the movement of a single piece */
7838 BeginAnimation(anim, piece, startColor, start)
7846 /* The old buffer is initialised with the start square (empty) */
7847 BlankSquare(0, 0, startColor, EmptySquare, anim->saveBuf);
7848 anim->prevFrame = *start;
7850 /* The piece will be drawn using its own bitmap as a matte */
7851 // SelectGCMask(piece, &anim->pieceGC, &anim->outlineGC, &mask);
7852 // XSetClipMask(xDisplay, anim->pieceGC, mask);
7856 AnimationFrame(anim, frame, piece)
7861 XRectangle updates[4];
7866 /* Save what we are about to draw into the new buffer */
7867 // XCopyArea(xDisplay, xBoardWindow, anim->newBuf, anim->blitGC,
7868 // frame->x, frame->y, squareSize, squareSize,
7871 /* Erase bits of the previous frame */
7872 if (Intersect(&anim->prevFrame, frame, squareSize, &overlap, &pt)) {
7873 /* Where the new frame overlapped the previous,
7874 the contents in newBuf are wrong. */
7875 // XCopyArea(xDisplay, anim->saveBuf, anim->newBuf, anim->blitGC,
7876 // overlap.x, overlap.y,
7877 // overlap.width, overlap.height,
7879 /* Repaint the areas in the old that don't overlap new */
7880 CalcUpdateRects(&anim->prevFrame, frame, squareSize, updates, &count);
7881 for (i = 0; i < count; i++)
7882 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
7883 // updates[i].x - anim->prevFrame.x,
7884 // updates[i].y - anim->prevFrame.y,
7885 // updates[i].width, updates[i].height,
7886 // updates[i].x, updates[i].y)
7889 /* Easy when no overlap */
7890 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
7891 // 0, 0, squareSize, squareSize,
7892 // anim->prevFrame.x, anim->prevFrame.y);
7895 /* Save this frame for next time round */
7896 // XCopyArea(xDisplay, anim->newBuf, anim->saveBuf, anim->blitGC,
7897 // 0, 0, squareSize, squareSize,
7899 anim->prevFrame = *frame;
7901 /* Draw piece over original screen contents, not current,
7902 and copy entire rect. Wipes out overlapping piece images. */
7903 OverlayPiece(piece, anim->pieceGC, anim->outlineGC, anim->newBuf);
7904 // XCopyArea(xDisplay, anim->newBuf, xBoardWindow, anim->blitGC,
7905 // 0, 0, squareSize, squareSize,
7906 // frame->x, frame->y);
7910 EndAnimation (anim, finish)
7914 XRectangle updates[4];
7919 /* The main code will redraw the final square, so we
7920 only need to erase the bits that don't overlap. */
7921 if (Intersect(&anim->prevFrame, finish, squareSize, &overlap, &pt)) {
7922 CalcUpdateRects(&anim->prevFrame, finish, squareSize, updates, &count);
7923 for (i = 0; i < count; i++)
7924 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
7925 // updates[i].x - anim->prevFrame.x,
7926 // updates[i].y - anim->prevFrame.y,
7927 // updates[i].width, updates[i].height,
7928 // updates[i].x, updates[i].y)
7931 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
7932 // 0, 0, squareSize, squareSize,
7933 // anim->prevFrame.x, anim->prevFrame.y);
7938 FrameSequence(anim, piece, startColor, start, finish, frames, nFrames)
7940 ChessSquare piece; int startColor;
7941 XPoint * start; XPoint * finish;
7942 XPoint frames[]; int nFrames;
7946 BeginAnimation(anim, piece, startColor, start);
7947 for (n = 0; n < nFrames; n++) {
7948 AnimationFrame(anim, &(frames[n]), piece);
7949 FrameDelay(appData.animSpeed);
7951 EndAnimation(anim, finish);
7954 /* Main control logic for deciding what to animate and how */
7957 AnimateMove(board, fromX, fromY, toX, toY)
7966 XPoint start, finish, mid;
7967 XPoint frames[kFactor * 2 + 1];
7968 int nFrames, startColor, endColor;
7970 /* Are we animating? */
7971 if (!appData.animate || appData.blindfold)
7974 if(board[toY][toX] == WhiteRook && board[fromY][fromX] == WhiteKing ||
7975 board[toY][toX] == BlackRook && board[fromY][fromX] == BlackKing)
7976 return; // [HGM] FRC: no animtion of FRC castlings, as to-square is not true to-square
7978 if (fromY < 0 || fromX < 0 || toX < 0 || toY < 0) return;
7979 piece = board[fromY][fromX];
7980 if (piece >= EmptySquare) return;
7985 hop = (piece == WhiteKnight || piece == BlackKnight);
7988 if (appData.debugMode) {
7989 fprintf(debugFP, hop ? _("AnimateMove: piece %d hops from %d,%d to %d,%d \n") :
7990 _("AnimateMove: piece %d slides from %d,%d to %d,%d \n"),
7991 piece, fromX, fromY, toX, toY); }
7993 ScreenSquare(fromX, fromY, &start, &startColor);
7994 ScreenSquare(toX, toY, &finish, &endColor);
7997 /* Knight: make diagonal movement then straight */
7998 if (abs(toY - fromY) < abs(toX - fromX)) {
7999 mid.x = start.x + (finish.x - start.x) / 2;
8003 mid.y = start.y + (finish.y - start.y) / 2;
8006 mid.x = start.x + (finish.x - start.x) / 2;
8007 mid.y = start.y + (finish.y - start.y) / 2;
8010 /* Don't use as many frames for very short moves */
8011 if (abs(toY - fromY) + abs(toX - fromX) <= 2)
8012 Tween(&start, &mid, &finish, kFactor - 1, frames, &nFrames);
8014 Tween(&start, &mid, &finish, kFactor, frames, &nFrames);
8015 FrameSequence(&game, piece, startColor, &start, &finish, frames, nFrames);
8017 /* Be sure end square is redrawn */
8018 damage[toY][toX] = True;
8022 DragPieceBegin(x, y)
8025 int boardX, boardY, color;
8028 /* Are we animating? */
8029 if (!appData.animateDragging || appData.blindfold)
8032 /* Figure out which square we start in and the
8033 mouse position relative to top left corner. */
8034 BoardSquare(x, y, &boardX, &boardY);
8035 player.startBoardX = boardX;
8036 player.startBoardY = boardY;
8037 ScreenSquare(boardX, boardY, &corner, &color);
8038 player.startSquare = corner;
8039 player.startColor = color;
8041 /* Start from exactly where the piece is. This can be confusing
8042 if you start dragging far from the center of the square; most
8043 or all of the piece can be over a different square from the one
8044 the mouse pointer is in. */
8045 player.mouseDelta.x = x - corner.x;
8046 player.mouseDelta.y = y - corner.y;
8048 /* As soon as we start dragging, the piece will jump slightly to
8049 be centered over the mouse pointer. */
8050 player.mouseDelta.x = squareSize/2;
8051 player.mouseDelta.y = squareSize/2;
8053 /* Initialise animation */
8054 player.dragPiece = PieceForSquare(boardX, boardY);
8056 if (player.dragPiece >= 0 && player.dragPiece < EmptySquare) {
8057 player.dragActive = True;
8058 BeginAnimation(&player, player.dragPiece, color, &corner);
8059 /* Mark this square as needing to be redrawn. Note that
8060 we don't remove the piece though, since logically (ie
8061 as seen by opponent) the move hasn't been made yet. */
8062 if(boardX == BOARD_RGHT+1 && PieceForSquare(boardX-1, boardY) > 1 ||
8063 boardX == BOARD_LEFT-2 && PieceForSquare(boardX+1, boardY) > 1)
8064 // XCopyArea(xDisplay, xBoardWindow, player.saveBuf, player.blitGC,
8065 // corner.x, corner.y, squareSize, squareSize,
8066 // 0, 0); // [HGM] zh: unstack in stead of grab
8067 damage[boardY][boardX] = True;
8069 player.dragActive = False;
8079 /* Are we animating? */
8080 if (!appData.animateDragging || appData.blindfold)
8084 if (! player.dragActive)
8086 /* Move piece, maintaining same relative position
8087 of mouse within square */
8088 corner.x = x - player.mouseDelta.x;
8089 corner.y = y - player.mouseDelta.y;
8090 AnimationFrame(&player, &corner, player.dragPiece);
8092 if (appData.highlightDragging) {
8094 BoardSquare(x, y, &boardX, &boardY);
8095 SetHighlights(fromX, fromY, boardX, boardY);
8104 int boardX, boardY, color;
8107 /* Are we animating? */
8108 if (!appData.animateDragging || appData.blindfold)
8112 if (! player.dragActive)
8114 /* Last frame in sequence is square piece is
8115 placed on, which may not match mouse exactly. */
8116 BoardSquare(x, y, &boardX, &boardY);
8117 ScreenSquare(boardX, boardY, &corner, &color);
8118 EndAnimation(&player, &corner);
8120 /* Be sure end square is redrawn */
8121 damage[boardY][boardX] = True;
8123 /* This prevents weird things happening with fast successive
8124 clicks which on my Sun at least can cause motion events
8125 without corresponding press/release. */
8126 player.dragActive = False;
8129 /* Handle expose event while piece being dragged */
8134 if (!player.dragActive || appData.blindfold)
8137 /* What we're doing: logically, the move hasn't been made yet,
8138 so the piece is still in it's original square. But visually
8139 it's being dragged around the board. So we erase the square
8140 that the piece is on and draw it at the last known drag point. */
8141 BlankSquare(player.startSquare.x, player.startSquare.y,
8142 player.startColor, EmptySquare, xBoardWindow);
8143 AnimationFrame(&player, &player.prevFrame, player.dragPiece);
8144 damage[player.startBoardY][player.startBoardX] = TRUE;
8148 SetProgramStats( FrontEndProgramStats * stats )
8151 // [HGM] done, but perhaps backend should call this directly?
8152 EngineOutputUpdate( stats );