2 * xboard.c -- X front end for XBoard
4 * Copyright 1991 by Digital Equipment Corporation, Maynard,
7 * Enhancements Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006,
8 * 2007, 2008, 2009 Free Software Foundation, Inc.
10 * The following terms apply to Digital Equipment Corporation's copyright
12 * ------------------------------------------------------------------------
15 * Permission to use, copy, modify, and distribute this software and its
16 * documentation for any purpose and without fee is hereby granted,
17 * provided that the above copyright notice appear in all copies and that
18 * both that copyright notice and this permission notice appear in
19 * supporting documentation, and that the name of Digital not be
20 * used in advertising or publicity pertaining to distribution of the
21 * software without specific, written prior permission.
23 * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
24 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
25 * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
26 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
27 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
28 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
30 * ------------------------------------------------------------------------
32 * The following terms apply to the enhanced version of XBoard
33 * distributed by the Free Software Foundation:
34 * ------------------------------------------------------------------------
36 * GNU XBoard is free software: you can redistribute it and/or modify
37 * it under the terms of the GNU General Public License as published by
38 * the Free Software Foundation, either version 3 of the License, or (at
39 * your option) any later version.
41 * GNU XBoard is distributed in the hope that it will be useful, but
42 * WITHOUT ANY WARRANTY; without even the implied warranty of
43 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
44 * General Public License for more details.
46 * You should have received a copy of the GNU General Public License
47 * along with this program. If not, see http://www.gnu.org/licenses/. *
49 *------------------------------------------------------------------------
50 ** See the file ChangeLog for a revision history. */
58 #include <sys/types.h>
63 # if HAVE_SYS_SOCKET_H
64 # include <sys/socket.h>
65 # include <netinet/in.h>
67 # else /* not HAVE_SYS_SOCKET_H */
68 # if HAVE_LAN_SOCKET_H
69 # include <lan/socket.h>
71 # include <lan/netdb.h>
72 # else /* not HAVE_LAN_SOCKET_H */
73 # define OMIT_SOCKETS 1
74 # endif /* not HAVE_LAN_SOCKET_H */
75 # endif /* not HAVE_SYS_SOCKET_H */
76 #endif /* !OMIT_SOCKETS */
81 #else /* not STDC_HEADERS */
82 extern char *getenv();
85 # else /* not HAVE_STRING_H */
87 # endif /* not HAVE_STRING_H */
88 #endif /* not STDC_HEADERS */
91 # include <sys/fcntl.h>
92 #else /* not HAVE_SYS_FCNTL_H */
95 # endif /* HAVE_FCNTL_H */
96 #endif /* not HAVE_SYS_FCNTL_H */
98 #if HAVE_SYS_SYSTEMINFO_H
99 # include <sys/systeminfo.h>
100 #endif /* HAVE_SYS_SYSTEMINFO_H */
102 #if TIME_WITH_SYS_TIME
103 # include <sys/time.h>
107 # include <sys/time.h>
118 # include <sys/wait.h>
123 # define NAMLEN(dirent) strlen((dirent)->d_name)
124 # define HAVE_DIR_STRUCT
126 # define dirent direct
127 # define NAMLEN(dirent) (dirent)->d_namlen
129 # include <sys/ndir.h>
130 # define HAVE_DIR_STRUCT
133 # include <sys/dir.h>
134 # define HAVE_DIR_STRUCT
138 # define HAVE_DIR_STRUCT
142 #include <X11/Intrinsic.h>
143 #include <X11/StringDefs.h>
144 #include <X11/Shell.h>
145 #include <X11/cursorfont.h>
146 #include <X11/Xatom.h>
148 #include <X11/Xaw3d/Dialog.h>
149 #include <X11/Xaw3d/Form.h>
150 #include <X11/Xaw3d/List.h>
151 #include <X11/Xaw3d/Label.h>
152 #include <X11/Xaw3d/SimpleMenu.h>
153 #include <X11/Xaw3d/SmeBSB.h>
154 #include <X11/Xaw3d/SmeLine.h>
155 #include <X11/Xaw3d/Box.h>
156 #include <X11/Xaw3d/MenuButton.h>
157 #include <X11/Xaw3d/Text.h>
158 #include <X11/Xaw3d/AsciiText.h>
160 #include <X11/Xaw/Dialog.h>
161 #include <X11/Xaw/Form.h>
162 #include <X11/Xaw/List.h>
163 #include <X11/Xaw/Label.h>
164 #include <X11/Xaw/SimpleMenu.h>
165 #include <X11/Xaw/SmeBSB.h>
166 #include <X11/Xaw/SmeLine.h>
167 #include <X11/Xaw/Box.h>
168 #include <X11/Xaw/MenuButton.h>
169 #include <X11/Xaw/Text.h>
170 #include <X11/Xaw/AsciiText.h>
173 // [HGM] bitmaps: put before incuding the bitmaps / pixmaps, to know how many piece types there are.
178 #include "pixmaps/pixmaps.h"
179 #define IMAGE_EXT "xpm"
181 #define IMAGE_EXT "xim"
182 #include "bitmaps/bitmaps.h"
187 #include <gdk-pixbuf/gdk-pixbuf.h>
189 #include "bitmaps/icon_white.bm"
190 #include "bitmaps/icon_black.bm"
191 #include "bitmaps/checkmark.bm"
193 #include "frontend.h"
198 #include "xgamelist.h"
199 #include "xhistory.h"
200 #include "xedittags.h"
202 #include "callback.h"
203 #include "interface.h"
205 // must be moved to xengineoutput.h
207 void EngineOutputProc P((Widget w, XEvent *event,
208 String *prms, Cardinal *nprms));
210 void EngineOutputPopDown();
217 #define usleep(t) _sleep2(((t)+500)/1000)
221 # define _(s) gettext (s)
222 # define N_(s) gettext_noop (s)
245 int main P((int argc, char **argv));
246 RETSIGTYPE CmailSigHandler P((int sig));
247 RETSIGTYPE IntSigHandler P((int sig));
248 void CreateGCs P((void));
249 void CreateXIMPieces P((void));
250 void CreateXPMPieces P((void));
251 void CreatePieces P((void));
252 void CreatePieceMenus P((void));
253 Widget CreateMenuBar P((Menu *mb));
254 Widget CreateButtonBar P ((MenuItem *mi));
255 char *FindFont P((char *pattern, int targetPxlSize));
256 void PieceMenuPopup P((Widget w, XEvent *event,
257 String *params, Cardinal *num_params));
258 static void PieceMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
259 static void DropMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
260 int EventToSquare P((int x, int limit));
261 void DrawSquare P((int row, int column, ChessSquare piece, int do_flash));
262 void HandleUserMove P((Widget w, XEvent *event,
263 String *prms, Cardinal *nprms));
264 void AnimateUserMove P((Widget w, XEvent * event,
265 String * params, Cardinal * nParams));
266 void WhiteClock P((Widget w, XEvent *event,
267 String *prms, Cardinal *nprms));
268 void BlackClock P((Widget w, XEvent *event,
269 String *prms, Cardinal *nprms));
270 void CommentPopUp P((char *title, char *label));
271 void CommentPopDown P((void));
272 void CommentCallback P((Widget w, XtPointer client_data,
273 XtPointer call_data));
274 void ICSInputBoxPopUp P((void));
275 void ICSInputBoxPopDown P((void));
276 void FileNamePopUp P((char *label, char *def,
277 FileProc proc, char *openMode));
278 void FileNamePopDown P((void));
279 void FileNameCallback P((Widget w, XtPointer client_data,
280 XtPointer call_data));
281 void FileNameAction P((Widget w, XEvent *event,
282 String *prms, Cardinal *nprms));
283 void AskQuestionReplyAction P((Widget w, XEvent *event,
284 String *prms, Cardinal *nprms));
285 void AskQuestionProc P((Widget w, XEvent *event,
286 String *prms, Cardinal *nprms));
287 void AskQuestionPopDown P((void));
288 void PromotionPopUp P((void));
289 void PromotionPopDown P((void));
290 void PromotionCallback P((Widget w, XtPointer client_data,
291 XtPointer call_data));
292 void EditCommentPopDown P((void));
293 void EditCommentCallback P((Widget w, XtPointer client_data,
294 XtPointer call_data));
295 void SelectCommand P((Widget w, XtPointer client_data, XtPointer call_data));
296 void LoadPositionProc P((Widget w, XEvent *event,
297 String *prms, Cardinal *nprms));
298 void LoadNextPositionProc P((Widget w, XEvent *event, String *prms,
300 void LoadPrevPositionProc P((Widget w, XEvent *event, String *prms,
302 void ReloadPositionProc P((Widget w, XEvent *event, String *prms,
304 void CopyPositionProc P((Widget w, XEvent *event, String *prms,
306 void PastePositionProc P((Widget w, XEvent *event, String *prms,
308 void CopyGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
309 void PasteGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
310 void SaveGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
311 void SavePositionProc P((Widget w, XEvent *event,
312 String *prms, Cardinal *nprms));
313 void MailMoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
314 void ReloadCmailMsgProc P((Widget w, XEvent *event, String *prms,
316 void AnalyzeModeProc P((Widget w, XEvent *event,
317 String *prms, Cardinal *nprms));
318 void AnalyzeFileProc P((Widget w, XEvent *event,
319 String *prms, Cardinal *nprms));
320 void EditGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
321 void EditPositionProc P((Widget w, XEvent *event,
322 String *prms, Cardinal *nprms));
323 void TrainingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
324 void EditCommentProc P((Widget w, XEvent *event,
325 String *prms, Cardinal *nprms));
326 void IcsInputBoxProc P((Widget w, XEvent *event,
327 String *prms, Cardinal *nprms));
328 void EnterKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
329 void AlwaysQueenProc P((Widget w, XEvent *event, String *prms,
331 void AnimateDraggingProc P((Widget w, XEvent *event, String *prms,
333 void AnimateMovingProc P((Widget w, XEvent *event, String *prms,
335 void AutocommProc P((Widget w, XEvent *event, String *prms,
337 void AutoflagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
338 void AutoflipProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
339 void AutobsProc P((Widget w, XEvent *event, String *prms,
341 void AutoraiseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
342 void AutosaveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
343 void BlindfoldProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
344 void FlashMovesProc P((Widget w, XEvent *event, String *prms,
346 void HighlightDraggingProc P((Widget w, XEvent *event, String *prms,
348 void HighlightLastMoveProc P((Widget w, XEvent *event, String *prms,
350 void MoveSoundProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
351 void IcsAlarmProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
352 void OldSaveStyleProc P((Widget w, XEvent *event, String *prms,
354 void PeriodicUpdatesProc P((Widget w, XEvent *event, String *prms,
356 void PonderNextMoveProc P((Widget w, XEvent *event, String *prms,
358 void PopupMoveErrorsProc P((Widget w, XEvent *event, String *prms,
360 void PopupExitMessageProc P((Widget w, XEvent *event, String *prms,
362 void PremoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
363 void QuietPlayProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
364 void ShowThinkingProc P((Widget w, XEvent *event, String *prms,
366 void HideThinkingProc P((Widget w, XEvent *event, String *prms,
368 void TestLegalityProc P((Widget w, XEvent *event, String *prms,
370 void AboutGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
371 void DebugProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
372 void NothingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
373 void Iconify P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
374 void DisplayMove P((int moveNumber));
375 void DisplayTitle P((char *title));
376 void ICSInitScript P((void));
377 int LoadGamePopUp P((FILE *f, int gameNumber, char *title));
378 void ErrorPopUp P((char *title, char *text, int modal));
379 void ErrorPopDown P((void));
380 static char *ExpandPathName P((char *path));
381 static void CreateAnimVars P((void));
382 void DragPieceBegin P((int x, int y));
383 static void DragPieceMove P((int x, int y));
384 void DragPieceEnd P((int x, int y));
385 static void DrawDragPiece P((void));
386 char *ModeToWidgetName P((GameMode mode));
387 void EngineOutputUpdate( FrontEndProgramStats * stats );
388 void ShuffleMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
389 void EngineMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
390 void UciMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
391 void TimeControlProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
392 void NewVariantProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
393 void FirstSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
394 void SecondSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
395 void ShufflePopDown P(());
396 void EnginePopDown P(());
397 void UciPopDown P(());
398 void TimeControlPopDown P(());
399 void NewVariantPopDown P(());
400 void SettingsPopDown P(());
401 void SetMenuEnables P((Enables *enab));
404 * XBoard depends on Xt R4 or higher
406 int xtVersion = XtSpecificationRelease;
411 Pixel lightSquareColor, darkSquareColor, whitePieceColor, blackPieceColor,
412 jailSquareColor, highlightSquareColor, premoveHighlightColor;
413 Pixel lowTimeWarningColor;
415 #define LINE_TYPE_NORMAL 0
416 #define LINE_TYPE_HIGHLIGHT 1
417 #define LINE_TYPE_PRE 2
420 GC lightSquareGC, darkSquareGC, jailSquareGC, wdPieceGC, wlPieceGC,
421 bdPieceGC, blPieceGC, wbPieceGC, bwPieceGC, coordGC,
422 wjPieceGC, bjPieceGC;
423 Pixmap iconPixmap, wIconPixmap, bIconPixmap, xMarkPixmap;
424 Widget shellWidget, layoutWidget, formWidget, boardWidget, messageWidget,
425 whiteTimerWidget, blackTimerWidget, titleWidget, widgetList[16],
426 commentShell, promotionShell, whitePieceMenu, blackPieceMenu, dropMenu,
427 menuBarWidget, buttonBarWidget, editShell, errorShell, analysisShell,
428 ICSInputShell, fileNameShell, askQuestionShell;
429 Font clockFontID, coordFontID, countFontID;
430 XFontStruct *clockFontStruct, *coordFontStruct, *countFontStruct;
431 XtAppContext appContext;
433 char *oldICSInteractionTitle;
437 char installDir[] = "."; // [HGM] UCI: needed for UCI; probably needs run-time initializtion
439 Position commentX = -1, commentY = -1;
440 Dimension commentW, commentH;
442 int squareSize, smallLayout = 0, tinyLayout = 0,
443 marginW, marginH, // [HGM] for run-time resizing
444 fromX = -1, fromY = -1, toX, toY, commentUp = False, analysisUp = False,
445 ICSInputBoxUp = False, askQuestionUp = False,
446 filenameUp = False, promotionUp = False, pmFromX = -1, pmFromY = -1,
447 editUp = False, errorUp = False, errorExitStatus = -1, lineGap;
448 Pixel timerForegroundPixel, timerBackgroundPixel;
449 Pixel buttonForegroundPixel, buttonBackgroundPixel;
450 char *chessDir, *programName, *programVersion,
451 *gameCopyFilename, *gamePasteFilename;
455 Pixmap pieceBitmap[2][(int)BlackPawn];
456 Pixmap pieceBitmap2[2][(int)BlackPawn+4]; /* [HGM] pieces */
457 Pixmap xpmPieceBitmap[4][(int)BlackPawn]; /* LL, LD, DL, DD actually used*/
458 Pixmap xpmPieceBitmap2[4][(int)BlackPawn+4]; /* LL, LD, DL, DD set to select from */
459 Pixmap xpmLightSquare, xpmDarkSquare, xpmJailSquare;
460 int useImages=0, useImageSqs;
461 XImage *ximPieceBitmap[4][(int)BlackPawn+4]; /* LL, LD, DL, DD */
462 Pixmap ximMaskPm[(int)BlackPawn]; /* clipmasks, used for XIM pieces */
463 Pixmap ximMaskPm2[(int)BlackPawn+4]; /* clipmasks, used for XIM pieces */
464 XImage *ximLightSquare, *ximDarkSquare;
467 #define pieceToSolid(piece) &pieceBitmap[SOLID][(piece) % (int)BlackPawn]
468 #define pieceToOutline(piece) &pieceBitmap[OUTLINE][(piece) % (int)BlackPawn]
470 #define White(piece) ((int)(piece) < (int)BlackPawn)
472 /* Variables for doing smooth animation. This whole thing
473 would be much easier if the board was double-buffered,
474 but that would require a fairly major rewrite. */
479 GC blitGC, pieceGC, outlineGC;
480 XPoint startSquare, prevFrame, mouseDelta;
484 int startBoardX, startBoardY;
487 /* There can be two pieces being animated at once: a player
488 can begin dragging a piece before the remote opponent has moved. */
490 static AnimState game, player;
492 /* Bitmaps for use as masks when drawing XPM pieces.
493 Need one for each black and white piece. */
494 static Pixmap xpmMask[BlackKing + 1];
496 /* This magic number is the number of intermediate frames used
497 in each half of the animation. For short moves it's reduced
498 by 1. The total number of frames will be factor * 2 + 1. */
501 SizeDefaults sizeDefaults[] = SIZE_DEFAULTS;
503 Enables icsEnables[] = {
504 { "menuFile.Mail Move", False },
505 { "menuFile.Reload CMail Message", False },
506 { "menuMode.Machine Black", False },
507 { "menuMode.Machine White", False },
508 { "menuMode.Analysis Mode", False },
509 { "menuMode.Analyze File", False },
510 { "menuMode.Two Machines", False },
512 { "menuHelp.Hint", False },
513 { "menuHelp.Book", False },
514 { "menuStep.Move Now", False },
515 { "menuOptions.Periodic Updates", False },
516 { "menuOptions.Hide Thinking", False },
517 { "menuOptions.Ponder Next Move", False },
522 Enables ncpEnables[] = {
523 { "menuFile.Mail Move", False },
524 { "menuFile.Reload CMail Message", False },
525 { "menuMode.Machine White", False },
526 { "menuMode.Machine Black", False },
527 { "menuMode.Analysis Mode", False },
528 { "menuMode.Analyze File", False },
529 { "menuMode.Two Machines", False },
530 { "menuMode.ICS Client", False },
531 { "menuMode.ICS Input Box", False },
533 { "menuStep.Revert", False },
534 { "menuStep.Move Now", False },
535 { "menuStep.Retract Move", False },
536 { "menuOptions.Auto Comment", False },
537 { "menuOptions.Auto Flag", False },
538 { "menuOptions.Auto Flip View", False },
539 { "menuOptions.Auto Observe", False },
540 { "menuOptions.Auto Raise Board", False },
541 { "menuOptions.Get Move List", False },
542 { "menuOptions.ICS Alarm", False },
543 { "menuOptions.Move Sound", False },
544 { "menuOptions.Quiet Play", False },
545 { "menuOptions.Hide Thinking", False },
546 { "menuOptions.Periodic Updates", False },
547 { "menuOptions.Ponder Next Move", False },
548 { "menuHelp.Hint", False },
549 { "menuHelp.Book", False },
553 Enables gnuEnables[] = {
554 { "menuMode.ICS Client", False },
555 { "menuMode.ICS Input Box", False },
556 { "menuAction.Accept", False },
557 { "menuAction.Decline", False },
558 { "menuAction.Rematch", False },
559 { "menuAction.Adjourn", False },
560 { "menuAction.Stop Examining", False },
561 { "menuAction.Stop Observing", False },
562 { "menuStep.Revert", False },
563 { "menuOptions.Auto Comment", False },
564 { "menuOptions.Auto Observe", False },
565 { "menuOptions.Auto Raise Board", False },
566 { "menuOptions.Get Move List", False },
567 { "menuOptions.Premove", False },
568 { "menuOptions.Quiet Play", False },
570 /* The next two options rely on SetCmailMode being called *after* */
571 /* SetGNUMode so that when GNU is being used to give hints these */
572 /* menu options are still available */
574 { "menuFile.Mail Move", False },
575 { "menuFile.Reload CMail Message", False },
579 Enables cmailEnables[] = {
581 { "menuAction.Call Flag", False },
582 { "menuAction.Draw", True },
583 { "menuAction.Adjourn", False },
584 { "menuAction.Abort", False },
585 { "menuAction.Stop Observing", False },
586 { "menuAction.Stop Examining", False },
587 { "menuFile.Mail Move", True },
588 { "menuFile.Reload CMail Message", True },
592 Enables trainingOnEnables[] = {
593 { "menuMode.Edit Comment", False },
594 { "menuMode.Pause", False },
595 { "menuStep.Forward", False },
596 { "menuStep.Backward", False },
597 { "menuStep.Forward to End", False },
598 { "menuStep.Back to Start", False },
599 { "menuStep.Move Now", False },
600 { "menuStep.Truncate Game", False },
604 Enables trainingOffEnables[] = {
605 { "menuMode.Edit Comment", True },
606 { "menuMode.Pause", True },
607 { "menuStep.Forward", True },
608 { "menuStep.Backward", True },
609 { "menuStep.Forward to End", True },
610 { "menuStep.Back to Start", True },
611 { "menuStep.Move Now", True },
612 { "menuStep.Truncate Game", True },
616 Enables machineThinkingEnables[] = {
617 { "menuFile.Load Game", False },
618 { "menuFile.Load Next Game", False },
619 { "menuFile.Load Previous Game", False },
620 { "menuFile.Reload Same Game", False },
621 { "menuFile.Paste Game", False },
622 { "menuFile.Load Position", False },
623 { "menuFile.Load Next Position", False },
624 { "menuFile.Load Previous Position", False },
625 { "menuFile.Reload Same Position", False },
626 { "menuFile.Paste Position", False },
627 { "menuMode.Machine White", False },
628 { "menuMode.Machine Black", False },
629 { "menuMode.Two Machines", False },
630 { "menuStep.Retract Move", False },
634 Enables userThinkingEnables[] = {
635 { "menuFile.Load Game", True },
636 { "menuFile.Load Next Game", True },
637 { "menuFile.Load Previous Game", True },
638 { "menuFile.Reload Same Game", True },
639 { "menuFile.Paste Game", True },
640 { "menuFile.Load Position", True },
641 { "menuFile.Load Next Position", True },
642 { "menuFile.Load Previous Position", True },
643 { "menuFile.Reload Same Position", True },
644 { "menuFile.Paste Position", True },
645 { "menuMode.Machine White", True },
646 { "menuMode.Machine Black", True },
647 { "menuMode.Two Machines", True },
648 { "menuStep.Retract Move", True },
654 MenuItem fileMenu[] = {
655 {N_("New Shuffle Game ..."), ShuffleMenuProc},
656 {N_("New Variant ..."), NewVariantProc}, // [HGM] variant: not functional yet
657 {"----", NothingProc},
658 {N_("Save Game"), SaveGameProc},
659 {"----", NothingProc},
660 {N_("Copy Game"), CopyGameProc},
661 {N_("Paste Game"), PasteGameProc},
662 {"----", NothingProc},
663 {N_("Load Position"), LoadPositionProc},
664 {N_("Load Next Position"), LoadNextPositionProc},
665 {N_("Load Previous Position"), LoadPrevPositionProc},
666 {N_("Reload Same Position"), ReloadPositionProc},
667 {N_("Save Position"), SavePositionProc},
668 {"----", NothingProc},
669 {N_("Copy Position"), CopyPositionProc},
670 {N_("Paste Position"), PastePositionProc},
671 {"----", NothingProc},
672 {N_("Mail Move"), MailMoveProc},
673 {N_("Reload CMail Message"), ReloadCmailMsgProc},
674 {"----", NothingProc},
678 MenuItem modeMenu[] = {
679 // {N_("Machine White"), MachineWhiteProc},
680 // {N_("Machine Black"), MachineBlackProc},
681 // {N_("Two Machines"), TwoMachinesProc},
682 {N_("Analysis Mode"), AnalyzeModeProc},
683 {N_("Analyze File"), AnalyzeFileProc },
684 // {N_("ICS Client"), IcsClientProc},
685 {N_("Edit Game"), EditGameProc},
686 {N_("Edit Position"), EditPositionProc},
687 {N_("Training"), TrainingProc},
688 {"----", NothingProc},
689 {N_("Show Engine Output"), EngineOutputProc},
690 {N_("Show Evaluation Graph"), NothingProc}, // [HGM] evalgr: not functional yet
691 {N_("Show Game List"), ShowGameListProc},
692 // {"Show Move History", HistoryShowProc}, // [HGM] hist: activate 4.2.7 code
693 {"----", NothingProc},
694 {N_("Edit Tags"), EditTagsProc},
695 {N_("Edit Comment"), EditCommentProc},
696 {N_("ICS Input Box"), IcsInputBoxProc},
700 MenuItem optionsMenu[] = {
701 // {N_("Flip View"), FlipViewProc},
702 // {"----", NothingProc},
703 {N_("Adjudications ..."), EngineMenuProc},
704 {N_("General Settings ..."), UciMenuProc},
705 {N_("Engine #1 Settings ..."), FirstSettingsProc},
706 {N_("Engine #2 Settings ..."), SecondSettingsProc},
707 {N_("Time Control ..."), TimeControlProc},
708 {"----", NothingProc},
709 {N_("Always Queen"), AlwaysQueenProc},
710 {N_("Animate Dragging"), AnimateDraggingProc},
711 {N_("Animate Moving"), AnimateMovingProc},
712 {N_("Auto Comment"), AutocommProc},
713 {N_("Auto Flag"), AutoflagProc},
714 {N_("Auto Flip View"), AutoflipProc},
715 {N_("Auto Observe"), AutobsProc},
716 {N_("Auto Raise Board"), AutoraiseProc},
717 {N_("Auto Save"), AutosaveProc},
718 {N_("Blindfold"), BlindfoldProc},
719 {N_("Flash Moves"), FlashMovesProc},
720 // {N_("Get Move List"), GetMoveListProc},
722 {N_("Highlight Dragging"), HighlightDraggingProc},
724 {N_("Highlight Last Move"), HighlightLastMoveProc},
725 {N_("Move Sound"), MoveSoundProc},
726 {N_("ICS Alarm"), IcsAlarmProc},
727 {N_("Old Save Style"), OldSaveStyleProc},
728 {N_("Periodic Updates"), PeriodicUpdatesProc},
729 {N_("Ponder Next Move"), PonderNextMoveProc},
730 {N_("Popup Exit Message"), PopupExitMessageProc},
731 {N_("Popup Move Errors"), PopupMoveErrorsProc},
732 {N_("Premove"), PremoveProc},
733 {N_("Quiet Play"), QuietPlayProc},
734 {N_("Hide Thinking"), HideThinkingProc},
735 {N_("Test Legality"), TestLegalityProc},
740 {N_("File"), fileMenu},
741 {N_("Mode"), modeMenu},
742 {N_("Options"), optionsMenu},
746 #define PAUSE_BUTTON N_("P")
747 MenuItem buttonBar[] = {
748 // {"<<", ToStartProc},
749 // {"<", BackwardProc},
750 // {PAUSE_BUTTON, PauseProc},
751 // {">", ForwardProc},
752 // {">>", ToEndProc},
756 #define PIECE_MENU_SIZE 18
757 String pieceMenuStrings[2][PIECE_MENU_SIZE] = {
758 { N_("White"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
759 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
760 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
761 N_("Empty square"), N_("Clear board") },
762 { N_("Black"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
763 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
764 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
765 N_("Empty square"), N_("Clear board") }
767 /* must be in same order as PieceMenuStrings! */
768 ChessSquare pieceMenuTranslation[2][PIECE_MENU_SIZE] = {
769 { WhitePlay, (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
770 WhiteRook, WhiteQueen, WhiteKing, (ChessSquare) 0, WhiteAlfil,
771 WhiteCannon, WhiteAngel, WhiteMarshall, (ChessSquare) 0,
772 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
773 { BlackPlay, (ChessSquare) 0, BlackPawn, BlackKnight, BlackBishop,
774 BlackRook, BlackQueen, BlackKing, (ChessSquare) 0, BlackAlfil,
775 BlackCannon, BlackAngel, BlackMarshall, (ChessSquare) 0,
776 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
779 #define DROP_MENU_SIZE 6
780 String dropMenuStrings[DROP_MENU_SIZE] = {
781 "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"), N_("Queen")
783 /* must be in same order as PieceMenuStrings! */
784 ChessSquare dropMenuTranslation[DROP_MENU_SIZE] = {
785 (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
786 WhiteRook, WhiteQueen
794 DropMenuEnables dmEnables[] = {
803 { XtNborderWidth, 0 },
804 { XtNdefaultDistance, 0 },
808 { XtNborderWidth, 0 },
809 { XtNresizable, (XtArgVal) True },
813 { XtNborderWidth, 0 },
818 XtResource clientResources[] = {
819 { "whitePieceColor", "whitePieceColor", XtRString, sizeof(String),
820 XtOffset(AppDataPtr, whitePieceColor), XtRString,
822 { "blackPieceColor", "blackPieceColor", XtRString, sizeof(String),
823 XtOffset(AppDataPtr, blackPieceColor), XtRString,
825 { "lightSquareColor", "lightSquareColor", XtRString,
826 sizeof(String), XtOffset(AppDataPtr, lightSquareColor),
827 XtRString, LIGHT_SQUARE_COLOR },
828 { "darkSquareColor", "darkSquareColor", XtRString, sizeof(String),
829 XtOffset(AppDataPtr, darkSquareColor), XtRString,
831 { "highlightSquareColor", "highlightSquareColor", XtRString,
832 sizeof(String), XtOffset(AppDataPtr, highlightSquareColor),
833 XtRString, HIGHLIGHT_SQUARE_COLOR },
834 { "premoveHighlightColor", "premoveHighlightColor", XtRString,
835 sizeof(String), XtOffset(AppDataPtr, premoveHighlightColor),
836 XtRString, PREMOVE_HIGHLIGHT_COLOR },
837 { "movesPerSession", "movesPerSession", XtRInt, sizeof(int),
838 XtOffset(AppDataPtr, movesPerSession), XtRImmediate,
839 (XtPointer) MOVES_PER_SESSION },
840 { "timeIncrement", "timeIncrement", XtRInt, sizeof(int),
841 XtOffset(AppDataPtr, timeIncrement), XtRImmediate,
842 (XtPointer) TIME_INCREMENT },
843 { "initString", "initString", XtRString, sizeof(String),
844 XtOffset(AppDataPtr, initString), XtRString, INIT_STRING },
845 { "secondInitString", "secondInitString", XtRString, sizeof(String),
846 XtOffset(AppDataPtr, secondInitString), XtRString, INIT_STRING },
847 { "firstComputerString", "firstComputerString", XtRString,
848 sizeof(String), XtOffset(AppDataPtr, firstComputerString), XtRString,
850 { "secondComputerString", "secondComputerString", XtRString,
851 sizeof(String), XtOffset(AppDataPtr, secondComputerString), XtRString,
853 { "firstChessProgram", "firstChessProgram", XtRString,
854 sizeof(String), XtOffset(AppDataPtr, firstChessProgram),
855 XtRString, FIRST_CHESS_PROGRAM },
856 { "secondChessProgram", "secondChessProgram", XtRString,
857 sizeof(String), XtOffset(AppDataPtr, secondChessProgram),
858 XtRString, SECOND_CHESS_PROGRAM },
859 { "firstPlaysBlack", "firstPlaysBlack", XtRBoolean,
860 sizeof(Boolean), XtOffset(AppDataPtr, firstPlaysBlack),
861 XtRImmediate, (XtPointer) False },
862 { "noChessProgram", "noChessProgram", XtRBoolean,
863 sizeof(Boolean), XtOffset(AppDataPtr, noChessProgram),
864 XtRImmediate, (XtPointer) False },
865 { "firstHost", "firstHost", XtRString, sizeof(String),
866 XtOffset(AppDataPtr, firstHost), XtRString, FIRST_HOST },
867 { "secondHost", "secondHost", XtRString, sizeof(String),
868 XtOffset(AppDataPtr, secondHost), XtRString, SECOND_HOST },
869 { "firstDirectory", "firstDirectory", XtRString, sizeof(String),
870 XtOffset(AppDataPtr, firstDirectory), XtRString, "." },
871 { "secondDirectory", "secondDirectory", XtRString, sizeof(String),
872 XtOffset(AppDataPtr, secondDirectory), XtRString, "." },
873 { "bitmapDirectory", "bitmapDirectory", XtRString,
874 sizeof(String), XtOffset(AppDataPtr, bitmapDirectory),
876 { "remoteShell", "remoteShell", XtRString, sizeof(String),
877 XtOffset(AppDataPtr, remoteShell), XtRString, REMOTE_SHELL },
878 { "remoteUser", "remoteUser", XtRString, sizeof(String),
879 XtOffset(AppDataPtr, remoteUser), XtRString, "" },
880 { "timeDelay", "timeDelay", XtRFloat, sizeof(float),
881 XtOffset(AppDataPtr, timeDelay), XtRString,
882 (XtPointer) TIME_DELAY_QUOTE },
883 { "timeControl", "timeControl", XtRString, sizeof(String),
884 XtOffset(AppDataPtr, timeControl), XtRString,
885 (XtPointer) TIME_CONTROL },
886 { "internetChessServerMode", "internetChessServerMode",
887 XtRBoolean, sizeof(Boolean),
888 XtOffset(AppDataPtr, icsActive), XtRImmediate,
890 { "internetChessServerHost", "internetChessServerHost",
891 XtRString, sizeof(String),
892 XtOffset(AppDataPtr, icsHost),
893 XtRString, (XtPointer) ICS_HOST },
894 { "internetChessServerPort", "internetChessServerPort",
895 XtRString, sizeof(String),
896 XtOffset(AppDataPtr, icsPort), XtRString,
897 (XtPointer) ICS_PORT },
898 { "internetChessServerCommPort", "internetChessServerCommPort",
899 XtRString, sizeof(String),
900 XtOffset(AppDataPtr, icsCommPort), XtRString,
902 { "internetChessServerLogonScript", "internetChessServerLogonScript",
903 XtRString, sizeof(String),
904 XtOffset(AppDataPtr, icsLogon), XtRString,
906 { "internetChessServerHelper", "internetChessServerHelper",
907 XtRString, sizeof(String),
908 XtOffset(AppDataPtr, icsHelper), XtRString, "" },
909 { "internetChessServerInputBox", "internetChessServerInputBox",
910 XtRBoolean, sizeof(Boolean),
911 XtOffset(AppDataPtr, icsInputBox), XtRImmediate,
913 { "icsAlarm", "icsAlarm",
914 XtRBoolean, sizeof(Boolean),
915 XtOffset(AppDataPtr, icsAlarm), XtRImmediate,
917 { "icsAlarmTime", "icsAlarmTime",
919 XtOffset(AppDataPtr, icsAlarmTime), XtRImmediate,
921 { "useTelnet", "useTelnet", XtRBoolean, sizeof(Boolean),
922 XtOffset(AppDataPtr, useTelnet), XtRImmediate,
924 { "telnetProgram", "telnetProgram", XtRString, sizeof(String),
925 XtOffset(AppDataPtr, telnetProgram), XtRString, TELNET_PROGRAM },
926 { "gateway", "gateway", XtRString, sizeof(String),
927 XtOffset(AppDataPtr, gateway), XtRString, "" },
928 { "loadGameFile", "loadGameFile", XtRString, sizeof(String),
929 XtOffset(AppDataPtr, loadGameFile), XtRString, "" },
930 { "loadGameIndex", "loadGameIndex",
932 XtOffset(AppDataPtr, loadGameIndex), XtRImmediate,
934 { "saveGameFile", "saveGameFile", XtRString, sizeof(String),
935 XtOffset(AppDataPtr, saveGameFile), XtRString, "" },
936 { "autoRaiseBoard", "autoRaiseBoard", XtRBoolean,
937 sizeof(Boolean), XtOffset(AppDataPtr, autoRaiseBoard),
938 XtRImmediate, (XtPointer) True },
939 { "autoSaveGames", "autoSaveGames", XtRBoolean,
940 sizeof(Boolean), XtOffset(AppDataPtr, autoSaveGames),
941 XtRImmediate, (XtPointer) False },
942 { "blindfold", "blindfold", XtRBoolean,
943 sizeof(Boolean), XtOffset(AppDataPtr, blindfold),
944 XtRImmediate, (XtPointer) False },
945 { "loadPositionFile", "loadPositionFile", XtRString,
946 sizeof(String), XtOffset(AppDataPtr, loadPositionFile),
948 { "loadPositionIndex", "loadPositionIndex",
950 XtOffset(AppDataPtr, loadPositionIndex), XtRImmediate,
952 { "savePositionFile", "savePositionFile", XtRString,
953 sizeof(String), XtOffset(AppDataPtr, savePositionFile),
955 { "matchMode", "matchMode", XtRBoolean, sizeof(Boolean),
956 XtOffset(AppDataPtr, matchMode), XtRImmediate, (XtPointer) False },
957 { "matchGames", "matchGames", XtRInt, sizeof(int),
958 XtOffset(AppDataPtr, matchGames), XtRImmediate,
960 { "monoMode", "monoMode", XtRBoolean, sizeof(Boolean),
961 XtOffset(AppDataPtr, monoMode), XtRImmediate,
963 { "debugMode", "debugMode", XtRBoolean, sizeof(Boolean),
964 XtOffset(AppDataPtr, debugMode), XtRImmediate,
966 { "clockMode", "clockMode", XtRBoolean, sizeof(Boolean),
967 XtOffset(AppDataPtr, clockMode), XtRImmediate,
969 { "boardSize", "boardSize", XtRString, sizeof(String),
970 XtOffset(AppDataPtr, boardSize), XtRString, "" },
971 { "searchTime", "searchTime", XtRString, sizeof(String),
972 XtOffset(AppDataPtr, searchTime), XtRString,
974 { "searchDepth", "searchDepth", XtRInt, sizeof(int),
975 XtOffset(AppDataPtr, searchDepth), XtRImmediate,
977 { "showCoords", "showCoords", XtRBoolean, sizeof(Boolean),
978 XtOffset(AppDataPtr, showCoords), XtRImmediate,
980 { "showJail", "showJail", XtRInt, sizeof(int),
981 XtOffset(AppDataPtr, showJail), XtRImmediate,
983 { "showThinking", "showThinking", XtRBoolean, sizeof(Boolean),
984 XtOffset(AppDataPtr, showThinking), XtRImmediate,
986 { "ponderNextMove", "ponderNextMove", XtRBoolean, sizeof(Boolean),
987 XtOffset(AppDataPtr, ponderNextMove), XtRImmediate,
989 { "periodicUpdates", "periodicUpdates", XtRBoolean, sizeof(Boolean),
990 XtOffset(AppDataPtr, periodicUpdates), XtRImmediate,
992 { "clockFont", "clockFont", XtRString, sizeof(String),
993 XtOffset(AppDataPtr, clockFont), XtRString, CLOCK_FONT },
994 { "coordFont", "coordFont", XtRString, sizeof(String),
995 XtOffset(AppDataPtr, coordFont), XtRString, COORD_FONT },
996 { "font", "font", XtRString, sizeof(String),
997 XtOffset(AppDataPtr, font), XtRString, DEFAULT_FONT },
998 { "ringBellAfterMoves", "ringBellAfterMoves",
999 XtRBoolean, sizeof(Boolean),
1000 XtOffset(AppDataPtr, ringBellAfterMoves),
1001 XtRImmediate, (XtPointer) False },
1002 { "autoCallFlag", "autoCallFlag", XtRBoolean,
1003 sizeof(Boolean), XtOffset(AppDataPtr, autoCallFlag),
1004 XtRImmediate, (XtPointer) False },
1005 { "autoFlipView", "autoFlipView", XtRBoolean,
1006 sizeof(Boolean), XtOffset(AppDataPtr, autoFlipView),
1007 XtRImmediate, (XtPointer) True },
1008 { "autoObserve", "autoObserve", XtRBoolean,
1009 sizeof(Boolean), XtOffset(AppDataPtr, autoObserve),
1010 XtRImmediate, (XtPointer) False },
1011 { "autoComment", "autoComment", XtRBoolean,
1012 sizeof(Boolean), XtOffset(AppDataPtr, autoComment),
1013 XtRImmediate, (XtPointer) False },
1014 { "getMoveList", "getMoveList", XtRBoolean,
1015 sizeof(Boolean), XtOffset(AppDataPtr, getMoveList),
1016 XtRImmediate, (XtPointer) True },
1018 { "highlightDragging", "highlightDragging", XtRBoolean,
1019 sizeof(Boolean), XtOffset(AppDataPtr, highlightDragging),
1020 XtRImmediate, (XtPointer) False },
1022 { "highlightLastMove", "highlightLastMove", XtRBoolean,
1023 sizeof(Boolean), XtOffset(AppDataPtr, highlightLastMove),
1024 XtRImmediate, (XtPointer) False },
1025 { "premove", "premove", XtRBoolean,
1026 sizeof(Boolean), XtOffset(AppDataPtr, premove),
1027 XtRImmediate, (XtPointer) True },
1028 { "testLegality", "testLegality", XtRBoolean,
1029 sizeof(Boolean), XtOffset(AppDataPtr, testLegality),
1030 XtRImmediate, (XtPointer) True },
1031 { "flipView", "flipView", XtRBoolean,
1032 sizeof(Boolean), XtOffset(AppDataPtr, flipView),
1033 XtRImmediate, (XtPointer) False },
1034 { "cmail", "cmailGameName", XtRString, sizeof(String),
1035 XtOffset(AppDataPtr, cmailGameName), XtRString, "" },
1036 { "alwaysPromoteToQueen", "alwaysPromoteToQueen", XtRBoolean,
1037 sizeof(Boolean), XtOffset(AppDataPtr, alwaysPromoteToQueen),
1038 XtRImmediate, (XtPointer) False },
1039 { "oldSaveStyle", "oldSaveStyle", XtRBoolean,
1040 sizeof(Boolean), XtOffset(AppDataPtr, oldSaveStyle),
1041 XtRImmediate, (XtPointer) False },
1042 { "quietPlay", "quietPlay", XtRBoolean,
1043 sizeof(Boolean), XtOffset(AppDataPtr, quietPlay),
1044 XtRImmediate, (XtPointer) False },
1045 { "titleInWindow", "titleInWindow", XtRBoolean,
1046 sizeof(Boolean), XtOffset(AppDataPtr, titleInWindow),
1047 XtRImmediate, (XtPointer) False },
1048 { "localLineEditing", "localLineEditing", XtRBoolean,
1049 sizeof(Boolean), XtOffset(AppDataPtr, localLineEditing),
1050 XtRImmediate, (XtPointer) True }, /* not implemented, must be True */
1052 { "zippyTalk", "zippyTalk", XtRBoolean,
1053 sizeof(Boolean), XtOffset(AppDataPtr, zippyTalk),
1054 XtRImmediate, (XtPointer) ZIPPY_TALK },
1055 { "zippyPlay", "zippyPlay", XtRBoolean,
1056 sizeof(Boolean), XtOffset(AppDataPtr, zippyPlay),
1057 XtRImmediate, (XtPointer) ZIPPY_PLAY },
1058 { "zippyLines", "zippyLines", XtRString, sizeof(String),
1059 XtOffset(AppDataPtr, zippyLines), XtRString, ZIPPY_LINES },
1060 { "zippyPinhead", "zippyPinhead", XtRString, sizeof(String),
1061 XtOffset(AppDataPtr, zippyPinhead), XtRString, ZIPPY_PINHEAD },
1062 { "zippyPassword", "zippyPassword", XtRString, sizeof(String),
1063 XtOffset(AppDataPtr, zippyPassword), XtRString, ZIPPY_PASSWORD },
1064 { "zippyPassword2", "zippyPassword2", XtRString, sizeof(String),
1065 XtOffset(AppDataPtr, zippyPassword2), XtRString, ZIPPY_PASSWORD2 },
1066 { "zippyWrongPassword", "zippyWrongPassword", XtRString, sizeof(String),
1067 XtOffset(AppDataPtr, zippyWrongPassword), XtRString,
1068 ZIPPY_WRONG_PASSWORD },
1069 { "zippyAcceptOnly", "zippyAcceptOnly", XtRString, sizeof(String),
1070 XtOffset(AppDataPtr, zippyAcceptOnly), XtRString, ZIPPY_ACCEPT_ONLY },
1071 { "zippyUseI", "zippyUseI", XtRBoolean,
1072 sizeof(Boolean), XtOffset(AppDataPtr, zippyUseI),
1073 XtRImmediate, (XtPointer) ZIPPY_USE_I },
1074 { "zippyBughouse", "zippyBughouse", XtRInt,
1075 sizeof(int), XtOffset(AppDataPtr, zippyBughouse),
1076 XtRImmediate, (XtPointer) ZIPPY_BUGHOUSE },
1077 { "zippyNoplayCrafty", "zippyNoplayCrafty", XtRBoolean,
1078 sizeof(Boolean), XtOffset(AppDataPtr, zippyNoplayCrafty),
1079 XtRImmediate, (XtPointer) ZIPPY_NOPLAY_CRAFTY },
1080 { "zippyGameEnd", "zippyGameEnd", XtRString, sizeof(String),
1081 XtOffset(AppDataPtr, zippyGameEnd), XtRString, ZIPPY_GAME_END },
1082 { "zippyGameStart", "zippyGameStart", XtRString, sizeof(String),
1083 XtOffset(AppDataPtr, zippyGameStart), XtRString, ZIPPY_GAME_START },
1084 { "zippyAdjourn", "zippyAdjourn", XtRBoolean,
1085 sizeof(Boolean), XtOffset(AppDataPtr, zippyAdjourn),
1086 XtRImmediate, (XtPointer) ZIPPY_ADJOURN },
1087 { "zippyAbort", "zippyAbort", XtRBoolean,
1088 sizeof(Boolean), XtOffset(AppDataPtr, zippyAbort),
1089 XtRImmediate, (XtPointer) ZIPPY_ABORT },
1090 { "zippyVariants", "zippyVariants", XtRString, sizeof(String),
1091 XtOffset(AppDataPtr, zippyVariants), XtRString, ZIPPY_VARIANTS },
1092 { "zippyMaxGames", "zippyMaxGames", XtRInt, sizeof(int),
1093 XtOffset(AppDataPtr, zippyMaxGames), XtRImmediate,
1094 (XtPointer) ZIPPY_MAX_GAMES },
1095 { "zippyReplayTimeout", "zippyReplayTimeout", XtRInt, sizeof(int),
1096 XtOffset(AppDataPtr, zippyReplayTimeout), XtRImmediate,
1097 (XtPointer) ZIPPY_REPLAY_TIMEOUT },
1098 { "zippyShortGame", "zippyShortGame", XtRInt, sizeof(int),
1099 XtOffset(AppDataPtr, zippyShortGame), XtRImmediate,
1102 { "flashCount", "flashCount", XtRInt, sizeof(int),
1103 XtOffset(AppDataPtr, flashCount), XtRImmediate,
1104 (XtPointer) FLASH_COUNT },
1105 { "flashRate", "flashRate", XtRInt, sizeof(int),
1106 XtOffset(AppDataPtr, flashRate), XtRImmediate,
1107 (XtPointer) FLASH_RATE },
1108 { "pixmapDirectory", "pixmapDirectory", XtRString,
1109 sizeof(String), XtOffset(AppDataPtr, pixmapDirectory),
1111 { "msLoginDelay", "msLoginDelay", XtRInt, sizeof(int),
1112 XtOffset(AppDataPtr, msLoginDelay), XtRImmediate,
1113 (XtPointer) MS_LOGIN_DELAY },
1114 { "colorizeMessages", "colorizeMessages", XtRBoolean,
1115 sizeof(Boolean), XtOffset(AppDataPtr, colorize),
1116 XtRImmediate, (XtPointer) False },
1117 { "colorShout", "colorShout", XtRString,
1118 sizeof(String), XtOffset(AppDataPtr, colorShout),
1119 XtRString, COLOR_SHOUT },
1120 { "colorSShout", "colorSShout", XtRString,
1121 sizeof(String), XtOffset(AppDataPtr, colorSShout),
1122 XtRString, COLOR_SSHOUT },
1123 { "colorChannel1", "colorChannel1", XtRString,
1124 sizeof(String), XtOffset(AppDataPtr, colorChannel1),
1125 XtRString, COLOR_CHANNEL1 },
1126 { "colorChannel", "colorChannel", XtRString,
1127 sizeof(String), XtOffset(AppDataPtr, colorChannel),
1128 XtRString, COLOR_CHANNEL },
1129 { "colorKibitz", "colorKibitz", XtRString,
1130 sizeof(String), XtOffset(AppDataPtr, colorKibitz),
1131 XtRString, COLOR_KIBITZ },
1132 { "colorTell", "colorTell", XtRString,
1133 sizeof(String), XtOffset(AppDataPtr, colorTell),
1134 XtRString, COLOR_TELL },
1135 { "colorChallenge", "colorChallenge", XtRString,
1136 sizeof(String), XtOffset(AppDataPtr, colorChallenge),
1137 XtRString, COLOR_CHALLENGE },
1138 { "colorRequest", "colorRequest", XtRString,
1139 sizeof(String), XtOffset(AppDataPtr, colorRequest),
1140 XtRString, COLOR_REQUEST },
1141 { "colorSeek", "colorSeek", XtRString,
1142 sizeof(String), XtOffset(AppDataPtr, colorSeek),
1143 XtRString, COLOR_SEEK },
1144 { "colorNormal", "colorNormal", XtRString,
1145 sizeof(String), XtOffset(AppDataPtr, colorNormal),
1146 XtRString, COLOR_NORMAL },
1147 { "soundProgram", "soundProgram", XtRString,
1148 sizeof(String), XtOffset(AppDataPtr, soundProgram),
1149 XtRString, "play" },
1150 { "soundShout", "soundShout", XtRString,
1151 sizeof(String), XtOffset(AppDataPtr, soundShout),
1153 { "soundSShout", "soundSShout", XtRString,
1154 sizeof(String), XtOffset(AppDataPtr, soundSShout),
1156 { "soundChannel1", "soundChannel1", XtRString,
1157 sizeof(String), XtOffset(AppDataPtr, soundChannel1),
1159 { "soundChannel", "soundChannel", XtRString,
1160 sizeof(String), XtOffset(AppDataPtr, soundChannel),
1162 { "soundKibitz", "soundKibitz", XtRString,
1163 sizeof(String), XtOffset(AppDataPtr, soundKibitz),
1165 { "soundTell", "soundTell", XtRString,
1166 sizeof(String), XtOffset(AppDataPtr, soundTell),
1168 { "soundChallenge", "soundChallenge", XtRString,
1169 sizeof(String), XtOffset(AppDataPtr, soundChallenge),
1171 { "soundRequest", "soundRequest", XtRString,
1172 sizeof(String), XtOffset(AppDataPtr, soundRequest),
1174 { "soundSeek", "soundSeek", XtRString,
1175 sizeof(String), XtOffset(AppDataPtr, soundSeek),
1177 { "soundMove", "soundMove", XtRString,
1178 sizeof(String), XtOffset(AppDataPtr, soundMove),
1180 { "soundIcsWin", "soundIcsWin", XtRString,
1181 sizeof(String), XtOffset(AppDataPtr, soundIcsWin),
1183 { "soundIcsLoss", "soundIcsLoss", XtRString,
1184 sizeof(String), XtOffset(AppDataPtr, soundIcsLoss),
1186 { "soundIcsDraw", "soundIcsDraw", XtRString,
1187 sizeof(String), XtOffset(AppDataPtr, soundIcsDraw),
1189 { "soundIcsUnfinished", "soundIcsUnfinished", XtRString,
1190 sizeof(String), XtOffset(AppDataPtr, soundIcsUnfinished),
1192 { "soundIcsAlarm", "soundIcsAlarm", XtRString,
1193 sizeof(String), XtOffset(AppDataPtr, soundIcsAlarm),
1195 { "reuseFirst", "reuseFirst", XtRBoolean,
1196 sizeof(Boolean), XtOffset(AppDataPtr, reuseFirst),
1197 XtRImmediate, (XtPointer) True },
1198 { "reuseSecond", "reuseSecond", XtRBoolean,
1199 sizeof(Boolean), XtOffset(AppDataPtr, reuseSecond),
1200 XtRImmediate, (XtPointer) True },
1201 { "animateDragging", "animateDragging", XtRBoolean,
1202 sizeof(Boolean), XtOffset(AppDataPtr, animateDragging),
1203 XtRImmediate, (XtPointer) True },
1204 { "animateMoving", "animateMoving", XtRBoolean,
1205 sizeof(Boolean), XtOffset(AppDataPtr, animate),
1206 XtRImmediate, (XtPointer) True },
1207 { "animateSpeed", "animateSpeed", XtRInt,
1208 sizeof(int), XtOffset(AppDataPtr, animSpeed),
1209 XtRImmediate, (XtPointer)10 },
1210 { "popupExitMessage", "popupExitMessage", XtRBoolean,
1211 sizeof(Boolean), XtOffset(AppDataPtr, popupExitMessage),
1212 XtRImmediate, (XtPointer) True },
1213 { "popupMoveErrors", "popupMoveErrors", XtRBoolean,
1214 sizeof(Boolean), XtOffset(AppDataPtr, popupMoveErrors),
1215 XtRImmediate, (XtPointer) False },
1216 { "fontSizeTolerance", "fontSizeTolerance", XtRInt,
1217 sizeof(int), XtOffset(AppDataPtr, fontSizeTolerance),
1218 XtRImmediate, (XtPointer)4 },
1219 { "initialMode", "initialMode", XtRString,
1220 sizeof(String), XtOffset(AppDataPtr, initialMode),
1221 XtRImmediate, (XtPointer) "" },
1222 { "variant", "variant", XtRString,
1223 sizeof(String), XtOffset(AppDataPtr, variant),
1224 XtRImmediate, (XtPointer) "normal" },
1225 { "firstProtocolVersion", "firstProtocolVersion", XtRInt,
1226 sizeof(int), XtOffset(AppDataPtr, firstProtocolVersion),
1227 XtRImmediate, (XtPointer)PROTOVER },
1228 { "secondProtocolVersion", "secondProtocolVersion", XtRInt,
1229 sizeof(int), XtOffset(AppDataPtr, secondProtocolVersion),
1230 XtRImmediate, (XtPointer)PROTOVER },
1231 { "showButtonBar", "showButtonBar", XtRBoolean,
1232 sizeof(Boolean), XtOffset(AppDataPtr, showButtonBar),
1233 XtRImmediate, (XtPointer) True },
1234 { "lowTimeWarningColor", "lowTimeWarningColor", XtRString,
1235 sizeof(String), XtOffset(AppDataPtr, lowTimeWarningColor),
1236 XtRString, COLOR_LOWTIMEWARNING },
1237 { "lowTimeWarning", "lowTimeWarning", XtRBoolean,
1238 sizeof(Boolean), XtOffset(AppDataPtr, lowTimeWarning),
1239 XtRImmediate, (XtPointer) False },
1240 {"icsEngineAnalyze", "icsEngineAnalyze", XtRBoolean, /* [DM] icsEngineAnalyze */
1241 sizeof(Boolean), XtOffset(AppDataPtr, icsEngineAnalyze),
1242 XtRImmediate, (XtPointer) False },
1243 { "firstScoreAbs", "firstScoreAbs", XtRBoolean,
1244 sizeof(Boolean), XtOffset(AppDataPtr, firstScoreIsAbsolute),
1245 XtRImmediate, (XtPointer) False },
1246 { "secondScoreAbs", "secondScoreAbs", XtRBoolean,
1247 sizeof(Boolean), XtOffset(AppDataPtr, secondScoreIsAbsolute),
1248 XtRImmediate, (XtPointer) False },
1249 { "pgnExtendedInfo", "pgnExtendedInfo", XtRBoolean,
1250 sizeof(Boolean), XtOffset(AppDataPtr, saveExtendedInfoInPGN),
1251 XtRImmediate, (XtPointer) False },
1252 { "hideThinkingFromHuman", "hideThinkingFromHuman", XtRBoolean,
1253 sizeof(Boolean), XtOffset(AppDataPtr, hideThinkingFromHuman),
1254 XtRImmediate, (XtPointer) True },
1255 { "adjudicateLossThreshold", "adjudicateLossThreshold", XtRInt,
1256 sizeof(int), XtOffset(AppDataPtr, adjudicateLossThreshold),
1257 XtRImmediate, (XtPointer) 0},
1258 { "adjudicateDrawMoves", "adjudicateDrawMoves", XtRInt,
1259 sizeof(int), XtOffset(AppDataPtr, adjudicateDrawMoves),
1260 XtRImmediate, (XtPointer) 0},
1261 { "pgnEventHeader", "pgnEventHeader", XtRString,
1262 sizeof(String), XtOffset(AppDataPtr, pgnEventHeader),
1263 XtRImmediate, (XtPointer) "Computer Chess Game" },
1264 { "defaultFrcPosition", "defaultFrcPositon", XtRInt,
1265 sizeof(int), XtOffset(AppDataPtr, defaultFrcPosition),
1266 XtRImmediate, (XtPointer) -1},
1267 { "gameListTags", "gameListTags", XtRString,
1268 sizeof(String), XtOffset(AppDataPtr, gameListTags),
1269 XtRImmediate, (XtPointer) GLT_DEFAULT_TAGS },
1271 // [HGM] 4.3.xx options
1272 { "boardWidth", "boardWidth", XtRInt,
1273 sizeof(int), XtOffset(AppDataPtr, NrFiles),
1274 XtRImmediate, (XtPointer) -1},
1275 { "boardHeight", "boardHeight", XtRInt,
1276 sizeof(int), XtOffset(AppDataPtr, NrRanks),
1277 XtRImmediate, (XtPointer) -1},
1278 { "matchPause", "matchPause", XtRInt,
1279 sizeof(int), XtOffset(AppDataPtr, matchPause),
1280 XtRImmediate, (XtPointer) 10000},
1281 { "holdingsSize", "holdingsSize", XtRInt,
1282 sizeof(int), XtOffset(AppDataPtr, holdingsSize),
1283 XtRImmediate, (XtPointer) -1},
1284 { "flipBlack", "flipBlack", XtRBoolean,
1285 sizeof(Boolean), XtOffset(AppDataPtr, upsideDown),
1286 XtRImmediate, (XtPointer) False},
1287 { "allWhite", "allWhite", XtRBoolean,
1288 sizeof(Boolean), XtOffset(AppDataPtr, allWhite),
1289 XtRImmediate, (XtPointer) False},
1290 { "pieceToCharTable", "pieceToCharTable", XtRString,
1291 sizeof(String), XtOffset(AppDataPtr, pieceToCharTable),
1292 XtRImmediate, (XtPointer) 0},
1293 { "alphaRank", "alphaRank", XtRBoolean,
1294 sizeof(Boolean), XtOffset(AppDataPtr, alphaRank),
1295 XtRImmediate, (XtPointer) False},
1296 { "testClaims", "testClaims", XtRBoolean,
1297 sizeof(Boolean), XtOffset(AppDataPtr, testClaims),
1298 XtRImmediate, (XtPointer) True},
1299 { "checkMates", "checkMates", XtRBoolean,
1300 sizeof(Boolean), XtOffset(AppDataPtr, checkMates),
1301 XtRImmediate, (XtPointer) True},
1302 { "materialDraws", "materialDraws", XtRBoolean,
1303 sizeof(Boolean), XtOffset(AppDataPtr, materialDraws),
1304 XtRImmediate, (XtPointer) True},
1305 { "trivialDraws", "trivialDraws", XtRBoolean,
1306 sizeof(Boolean), XtOffset(AppDataPtr, trivialDraws),
1307 XtRImmediate, (XtPointer) False},
1308 { "ruleMoves", "ruleMoves", XtRInt,
1309 sizeof(int), XtOffset(AppDataPtr, ruleMoves),
1310 XtRImmediate, (XtPointer) 51},
1311 { "repeatsToDraw", "repeatsToDraw", XtRInt,
1312 sizeof(int), XtOffset(AppDataPtr, drawRepeats),
1313 XtRImmediate, (XtPointer) 6},
1314 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1315 sizeof(int), XtOffset(AppDataPtr, engineComments),
1316 XtRImmediate, (XtPointer) 1},
1317 { "userName", "userName", XtRString,
1318 sizeof(int), XtOffset(AppDataPtr, userName),
1319 XtRImmediate, (XtPointer) 0},
1320 { "autoKibitz", "autoKibitz", XtRBoolean,
1321 sizeof(Boolean), XtOffset(AppDataPtr, autoKibitz),
1322 XtRImmediate, (XtPointer) False},
1323 { "firstTimeOdds", "firstTimeOdds", XtRInt,
1324 sizeof(int), XtOffset(AppDataPtr, firstTimeOdds),
1325 XtRImmediate, (XtPointer) 1},
1326 { "secondTimeOdds", "secondTimeOdds", XtRInt,
1327 sizeof(int), XtOffset(AppDataPtr, secondTimeOdds),
1328 XtRImmediate, (XtPointer) 1},
1329 { "timeOddsMode", "timeOddsMode", XtRInt,
1330 sizeof(int), XtOffset(AppDataPtr, timeOddsMode),
1331 XtRImmediate, (XtPointer) 0},
1332 { "firstAccumulateTC", "firstAccumulateTC", XtRInt,
1333 sizeof(int), XtOffset(AppDataPtr, firstAccumulateTC),
1334 XtRImmediate, (XtPointer) 1},
1335 { "secondAccumulateTC", "secondAccumulateTC", XtRInt,
1336 sizeof(int), XtOffset(AppDataPtr, secondAccumulateTC),
1337 XtRImmediate, (XtPointer) 1},
1338 { "firstNPS", "firstNPS", XtRInt,
1339 sizeof(int), XtOffset(AppDataPtr, firstNPS),
1340 XtRImmediate, (XtPointer) -1},
1341 { "secondNPS", "secondNPS", XtRInt,
1342 sizeof(int), XtOffset(AppDataPtr, secondNPS),
1343 XtRImmediate, (XtPointer) -1},
1344 { "serverMoves", "serverMoves", XtRString,
1345 sizeof(String), XtOffset(AppDataPtr, serverMovesName),
1346 XtRImmediate, (XtPointer) 0},
1347 { "serverPause", "serverPause", XtRInt,
1348 sizeof(int), XtOffset(AppDataPtr, serverPause),
1349 XtRImmediate, (XtPointer) 0},
1350 { "suppressLoadMoves", "suppressLoadMoves", XtRBoolean,
1351 sizeof(Boolean), XtOffset(AppDataPtr, suppressLoadMoves),
1352 XtRImmediate, (XtPointer) False},
1353 { "userName", "userName", XtRString,
1354 sizeof(String), XtOffset(AppDataPtr, userName),
1355 XtRImmediate, (XtPointer) 0},
1356 { "egtFormats", "egtFormats", XtRString,
1357 sizeof(String), XtOffset(AppDataPtr, egtFormats),
1358 XtRImmediate, (XtPointer) 0},
1359 { "rewindIndex", "rewindIndex", XtRInt,
1360 sizeof(int), XtOffset(AppDataPtr, rewindIndex),
1361 XtRImmediate, (XtPointer) 0},
1362 { "sameColorGames", "sameColorGames", XtRInt,
1363 sizeof(int), XtOffset(AppDataPtr, sameColorGames),
1364 XtRImmediate, (XtPointer) 0},
1365 { "smpCores", "smpCores", XtRInt,
1366 sizeof(int), XtOffset(AppDataPtr, smpCores),
1367 XtRImmediate, (XtPointer) 1},
1368 { "niceEngines", "niceEngines", XtRInt,
1369 sizeof(int), XtOffset(AppDataPtr, niceEngines),
1370 XtRImmediate, (XtPointer) 0},
1371 { "nameOfDebugFile", "nameOfDebugFile", XtRString,
1372 sizeof(String), XtOffset(AppDataPtr, nameOfDebugFile),
1373 XtRImmediate, (XtPointer) "xboard.debug"},
1374 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1375 sizeof(int), XtOffset(AppDataPtr, engineComments),
1376 XtRImmediate, (XtPointer) 1},
1377 { "noGUI", "noGUI", XtRBoolean,
1378 sizeof(Boolean), XtOffset(AppDataPtr, noGUI),
1379 XtRImmediate, (XtPointer) 0},
1380 { "firstOptions", "firstOptions", XtRString,
1381 sizeof(String), XtOffset(AppDataPtr, firstOptions),
1382 XtRImmediate, (XtPointer) "" },
1383 { "secondOptions", "secondOptions", XtRString,
1384 sizeof(String), XtOffset(AppDataPtr, secondOptions),
1385 XtRImmediate, (XtPointer) "" },
1386 { "firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XtRString,
1387 sizeof(String), XtOffset(AppDataPtr, fenOverride1),
1388 XtRImmediate, (XtPointer) 0 },
1389 { "secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XtRString,
1390 sizeof(String), XtOffset(AppDataPtr, fenOverride2),
1391 XtRImmediate, (XtPointer) 0 },
1393 // [HGM] Winboard_x UCI options
1394 { "firstIsUCI", "firstIsUCI", XtRBoolean,
1395 sizeof(Boolean), XtOffset(AppDataPtr, firstIsUCI),
1396 XtRImmediate, (XtPointer) False},
1397 { "secondIsUCI", "secondIsUCI", XtRBoolean,
1398 sizeof(Boolean), XtOffset(AppDataPtr, secondIsUCI),
1399 XtRImmediate, (XtPointer) False},
1400 { "firstHasOwnBookUCI", "firstHasOwnBookUCI", XtRBoolean,
1401 sizeof(Boolean), XtOffset(AppDataPtr, firstHasOwnBookUCI),
1402 XtRImmediate, (XtPointer) True},
1403 { "secondHasOwnBookUCI", "secondHasOwnBookUCI", XtRBoolean,
1404 sizeof(Boolean), XtOffset(AppDataPtr, secondHasOwnBookUCI),
1405 XtRImmediate, (XtPointer) True},
1406 { "usePolyglotBook", "usePolyglotBook", XtRBoolean,
1407 sizeof(Boolean), XtOffset(AppDataPtr, usePolyglotBook),
1408 XtRImmediate, (XtPointer) False},
1409 { "defaultHashSize", "defaultHashSize", XtRInt,
1410 sizeof(int), XtOffset(AppDataPtr, defaultHashSize),
1411 XtRImmediate, (XtPointer) 64},
1412 { "defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XtRInt,
1413 sizeof(int), XtOffset(AppDataPtr, defaultCacheSizeEGTB),
1414 XtRImmediate, (XtPointer) 4},
1415 { "polyglotDir", "polyglotDir", XtRString,
1416 sizeof(String), XtOffset(AppDataPtr, polyglotDir),
1417 XtRImmediate, (XtPointer) "." },
1418 { "polyglotBook", "polyglotBook", XtRString,
1419 sizeof(String), XtOffset(AppDataPtr, polyglotBook),
1420 XtRImmediate, (XtPointer) "" },
1421 { "defaultPathEGTB", "defaultPathEGTB", XtRString,
1422 sizeof(String), XtOffset(AppDataPtr, defaultPathEGTB),
1423 XtRImmediate, (XtPointer) "/usr/local/share/egtb"},
1424 { "delayBeforeQuit", "delayBeforeQuit", XtRInt,
1425 sizeof(int), XtOffset(AppDataPtr, delayBeforeQuit),
1426 XtRImmediate, (XtPointer) 0},
1427 { "delayAfterQuit", "delayAfterQuit", XtRInt,
1428 sizeof(int), XtOffset(AppDataPtr, delayAfterQuit),
1429 XtRImmediate, (XtPointer) 0},
1430 { "keepAlive", "keepAlive", XtRInt,
1431 sizeof(int), XtOffset(AppDataPtr, keepAlive),
1432 XtRImmediate, (XtPointer) 0},
1435 XrmOptionDescRec shellOptions[] = {
1436 { "-whitePieceColor", "whitePieceColor", XrmoptionSepArg, NULL },
1437 { "-blackPieceColor", "blackPieceColor", XrmoptionSepArg, NULL },
1438 { "-lightSquareColor", "lightSquareColor", XrmoptionSepArg, NULL },
1439 { "-darkSquareColor", "darkSquareColor", XrmoptionSepArg, NULL },
1440 { "-highlightSquareColor", "highlightSquareColor", XrmoptionSepArg, NULL },
1441 { "-premoveHighlightColor", "premoveHighlightColor", XrmoptionSepArg,NULL},
1442 { "-movesPerSession", "movesPerSession", XrmoptionSepArg, NULL },
1443 { "-mps", "movesPerSession", XrmoptionSepArg, NULL },
1444 { "-timeIncrement", "timeIncrement", XrmoptionSepArg, NULL },
1445 { "-inc", "timeIncrement", XrmoptionSepArg, NULL },
1446 { "-initString", "initString", XrmoptionSepArg, NULL },
1447 { "-firstInitString", "initString", XrmoptionSepArg, NULL },
1448 { "-secondInitString", "secondInitString", XrmoptionSepArg, NULL },
1449 { "-firstComputerString", "firstComputerString", XrmoptionSepArg, NULL },
1450 { "-secondComputerString", "secondComputerString", XrmoptionSepArg, NULL },
1451 { "-firstChessProgram", "firstChessProgram", XrmoptionSepArg, NULL },
1452 { "-fcp", "firstChessProgram", XrmoptionSepArg, NULL },
1453 { "-secondChessProgram", "secondChessProgram", XrmoptionSepArg, NULL },
1454 { "-scp", "secondChessProgram", XrmoptionSepArg, NULL },
1455 { "-firstPlaysBlack", "firstPlaysBlack", XrmoptionSepArg, NULL },
1456 { "-fb", "firstPlaysBlack", XrmoptionNoArg, "True" },
1457 { "-xfb", "firstPlaysBlack", XrmoptionNoArg, "False" },
1458 { "-noChessProgram", "noChessProgram", XrmoptionSepArg, NULL },
1459 { "-ncp", "noChessProgram", XrmoptionNoArg, "True" },
1460 { "-xncp", "noChessProgram", XrmoptionNoArg, "False" },
1461 { "-firstHost", "firstHost", XrmoptionSepArg, NULL },
1462 { "-fh", "firstHost", XrmoptionSepArg, NULL },
1463 { "-secondHost", "secondHost", XrmoptionSepArg, NULL },
1464 { "-sh", "secondHost", XrmoptionSepArg, NULL },
1465 { "-firstDirectory", "firstDirectory", XrmoptionSepArg, NULL },
1466 { "-fd", "firstDirectory", XrmoptionSepArg, NULL },
1467 { "-secondDirectory", "secondDirectory", XrmoptionSepArg, NULL },
1468 { "-sd", "secondDirectory", XrmoptionSepArg, NULL },
1469 { "-bitmapDirectory", "bitmapDirectory", XrmoptionSepArg, NULL },
1470 { "-bm", "bitmapDirectory", XrmoptionSepArg, NULL },
1471 { "-remoteShell", "remoteShell", XrmoptionSepArg, NULL },
1472 { "-rsh", "remoteShell", XrmoptionSepArg, NULL },
1473 { "-remoteUser", "remoteUser", XrmoptionSepArg, NULL },
1474 { "-ruser", "remoteUser", XrmoptionSepArg, NULL },
1475 { "-timeDelay", "timeDelay", XrmoptionSepArg, NULL },
1476 { "-td", "timeDelay", XrmoptionSepArg, NULL },
1477 { "-timeControl", "timeControl", XrmoptionSepArg, NULL },
1478 { "-tc", "timeControl", XrmoptionSepArg, NULL },
1479 { "-internetChessServerMode", "internetChessServerMode",
1480 XrmoptionSepArg, NULL },
1481 { "-ics", "internetChessServerMode", XrmoptionNoArg, "True" },
1482 { "-xics", "internetChessServerMode", XrmoptionNoArg, "False" },
1483 { "-internetChessServerHost", "internetChessServerHost",
1484 XrmoptionSepArg, NULL },
1485 { "-icshost", "internetChessServerHost", XrmoptionSepArg, NULL },
1486 { "-internetChessServerPort", "internetChessServerPort",
1487 XrmoptionSepArg, NULL },
1488 { "-icsport", "internetChessServerPort", XrmoptionSepArg, NULL },
1489 { "-internetChessServerCommPort", "internetChessServerCommPort",
1490 XrmoptionSepArg, NULL },
1491 { "-icscomm", "internetChessServerCommPort", XrmoptionSepArg, NULL },
1492 { "-internetChessServerLogonScript", "internetChessServerLogonScript",
1493 XrmoptionSepArg, NULL },
1494 { "-icslogon", "internetChessServerLogonScript", XrmoptionSepArg, NULL },
1495 { "-internetChessServerHelper", "internetChessServerHelper",
1496 XrmoptionSepArg, NULL },
1497 { "-icshelper", "internetChessServerHelper", XrmoptionSepArg, NULL },
1498 { "-internetChessServerInputBox", "internetChessServerInputBox",
1499 XrmoptionSepArg, NULL },
1500 { "-icsinput", "internetChessServerInputBox", XrmoptionNoArg, "True" },
1501 { "-xicsinput", "internetChessServerInputBox", XrmoptionNoArg, "False" },
1502 { "-icsAlarm", "icsAlarm", XrmoptionSepArg, NULL },
1503 { "-alarm", "icsAlarm", XrmoptionNoArg, "True" },
1504 { "-xalarm", "icsAlarm", XrmoptionNoArg, "False" },
1505 { "-icsAlarmTime", "icsAlarmTime", XrmoptionSepArg, NULL },
1506 { "-useTelnet", "useTelnet", XrmoptionSepArg, NULL },
1507 { "-telnet", "useTelnet", XrmoptionNoArg, "True" },
1508 { "-xtelnet", "useTelnet", XrmoptionNoArg, "False" },
1509 { "-telnetProgram", "telnetProgram", XrmoptionSepArg, NULL },
1510 { "-gateway", "gateway", XrmoptionSepArg, NULL },
1511 { "-loadGameFile", "loadGameFile", XrmoptionSepArg, NULL },
1512 { "-lgf", "loadGameFile", XrmoptionSepArg, NULL },
1513 { "-loadGameIndex", "loadGameIndex", XrmoptionSepArg, NULL },
1514 { "-lgi", "loadGameIndex", XrmoptionSepArg, NULL },
1515 { "-saveGameFile", "saveGameFile", XrmoptionSepArg, NULL },
1516 { "-sgf", "saveGameFile", XrmoptionSepArg, NULL },
1517 { "-autoSaveGames", "autoSaveGames", XrmoptionSepArg, NULL },
1518 { "-autosave", "autoSaveGames", XrmoptionNoArg, "True" },
1519 { "-xautosave", "autoSaveGames", XrmoptionNoArg, "False" },
1520 { "-autoRaiseBoard", "autoRaiseBoard", XrmoptionSepArg, NULL },
1521 { "-autoraise", "autoRaiseBoard", XrmoptionNoArg, "True" },
1522 { "-xautoraise", "autoRaiseBoard", XrmoptionNoArg, "False" },
1523 { "-blindfold", "blindfold", XrmoptionSepArg, NULL },
1524 { "-blind", "blindfold", XrmoptionNoArg, "True" },
1525 { "-xblind", "blindfold", XrmoptionNoArg, "False" },
1526 { "-loadPositionFile", "loadPositionFile", XrmoptionSepArg, NULL },
1527 { "-lpf", "loadPositionFile", XrmoptionSepArg, NULL },
1528 { "-loadPositionIndex", "loadPositionIndex", XrmoptionSepArg, NULL },
1529 { "-lpi", "loadPositionIndex", XrmoptionSepArg, NULL },
1530 { "-savePositionFile", "savePositionFile", XrmoptionSepArg, NULL },
1531 { "-spf", "savePositionFile", XrmoptionSepArg, NULL },
1532 { "-matchMode", "matchMode", XrmoptionSepArg, NULL },
1533 { "-mm", "matchMode", XrmoptionNoArg, "True" },
1534 { "-xmm", "matchMode", XrmoptionNoArg, "False" },
1535 { "-matchGames", "matchGames", XrmoptionSepArg, NULL },
1536 { "-mg", "matchGames", XrmoptionSepArg, NULL },
1537 { "-monoMode", "monoMode", XrmoptionSepArg, NULL },
1538 { "-mono", "monoMode", XrmoptionNoArg, "True" },
1539 { "-xmono", "monoMode", XrmoptionNoArg, "False" },
1540 { "-debugMode", "debugMode", XrmoptionSepArg, NULL },
1541 { "-debug", "debugMode", XrmoptionNoArg, "True" },
1542 { "-xdebug", "debugMode", XrmoptionNoArg, "False" },
1543 { "-clockMode", "clockMode", XrmoptionSepArg, NULL },
1544 { "-clock", "clockMode", XrmoptionNoArg, "True" },
1545 { "-xclock", "clockMode", XrmoptionNoArg, "False" },
1546 { "-boardSize", "boardSize", XrmoptionSepArg, NULL },
1547 { "-size", "boardSize", XrmoptionSepArg, NULL },
1548 { "-searchTime", "searchTime", XrmoptionSepArg, NULL },
1549 { "-st", "searchTime", XrmoptionSepArg, NULL },
1550 { "-searchDepth", "searchDepth", XrmoptionSepArg, NULL },
1551 { "-depth", "searchDepth", XrmoptionSepArg, NULL },
1552 { "-showCoords", "showCoords", XrmoptionSepArg, NULL },
1553 { "-coords", "showCoords", XrmoptionNoArg, "True" },
1554 { "-xcoords", "showCoords", XrmoptionNoArg, "False" },
1556 { "-showJail", "showJail", XrmoptionSepArg, NULL },
1557 { "-jail", "showJail", XrmoptionNoArg, "1" },
1558 { "-sidejail", "showJail", XrmoptionNoArg, "2" },
1559 { "-xjail", "showJail", XrmoptionNoArg, "0" },
1561 { "-showThinking", "showThinking", XrmoptionSepArg, NULL },
1562 { "-thinking", "showThinking", XrmoptionNoArg, "True" },
1563 { "-xthinking", "showThinking", XrmoptionNoArg, "False" },
1564 { "-ponderNextMove", "ponderNextMove", XrmoptionSepArg, NULL },
1565 { "-ponder", "ponderNextMove", XrmoptionNoArg, "True" },
1566 { "-xponder", "ponderNextMove", XrmoptionNoArg, "False" },
1567 { "-periodicUpdates", "periodicUpdates", XrmoptionSepArg, NULL },
1568 { "-periodic", "periodicUpdates", XrmoptionNoArg, "True" },
1569 { "-xperiodic", "periodicUpdates", XrmoptionNoArg, "False" },
1570 { "-clockFont", "clockFont", XrmoptionSepArg, NULL },
1571 { "-coordFont", "coordFont", XrmoptionSepArg, NULL },
1572 { "-font", "font", XrmoptionSepArg, NULL },
1573 { "-ringBellAfterMoves", "ringBellAfterMoves", XrmoptionSepArg, NULL },
1574 { "-bell", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1575 { "-xbell", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1576 { "-movesound", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1577 { "-xmovesound", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1578 { "-autoCallFlag", "autoCallFlag", XrmoptionSepArg, NULL },
1579 { "-autoflag", "autoCallFlag", XrmoptionNoArg, "True" },
1580 { "-xautoflag", "autoCallFlag", XrmoptionNoArg, "False" },
1581 { "-autoFlipView", "autoFlipView", XrmoptionSepArg, NULL },
1582 { "-autoflip", "autoFlipView", XrmoptionNoArg, "True" },
1583 { "-xautoflip", "autoFlipView", XrmoptionNoArg, "False" },
1584 { "-autoObserve", "autoObserve", XrmoptionSepArg, NULL },
1585 { "-autobs", "autoObserve", XrmoptionNoArg, "True" },
1586 { "-xautobs", "autoObserve", XrmoptionNoArg, "False" },
1587 { "-autoComment", "autoComment", XrmoptionSepArg, NULL },
1588 { "-autocomm", "autoComment", XrmoptionNoArg, "True" },
1589 { "-xautocomm", "autoComment", XrmoptionNoArg, "False" },
1590 { "-getMoveList", "getMoveList", XrmoptionSepArg, NULL },
1591 { "-moves", "getMoveList", XrmoptionNoArg, "True" },
1592 { "-xmoves", "getMoveList", XrmoptionNoArg, "False" },
1594 { "-highlightDragging", "highlightDragging", XrmoptionSepArg, NULL },
1595 { "-highdrag", "highlightDragging", XrmoptionNoArg, "True" },
1596 { "-xhighdrag", "highlightDragging", XrmoptionNoArg, "False" },
1598 { "-highlightLastMove", "highlightLastMove", XrmoptionSepArg, NULL },
1599 { "-highlight", "highlightLastMove", XrmoptionNoArg, "True" },
1600 { "-xhighlight", "highlightLastMove", XrmoptionNoArg, "False" },
1601 { "-premove", "premove", XrmoptionSepArg, NULL },
1602 { "-pre", "premove", XrmoptionNoArg, "True" },
1603 { "-xpre", "premove", XrmoptionNoArg, "False" },
1604 { "-testLegality", "testLegality", XrmoptionSepArg, NULL },
1605 { "-legal", "testLegality", XrmoptionNoArg, "True" },
1606 { "-xlegal", "testLegality", XrmoptionNoArg, "False" },
1607 { "-flipView", "flipView", XrmoptionSepArg, NULL },
1608 { "-flip", "flipView", XrmoptionNoArg, "True" },
1609 { "-xflip", "flipView", XrmoptionNoArg, "False" },
1610 { "-cmail", "cmailGameName", XrmoptionSepArg, NULL },
1611 { "-alwaysPromoteToQueen", "alwaysPromoteToQueen",
1612 XrmoptionSepArg, NULL },
1613 { "-queen", "alwaysPromoteToQueen", XrmoptionNoArg, "True" },
1614 { "-xqueen", "alwaysPromoteToQueen", XrmoptionNoArg, "False" },
1615 { "-oldSaveStyle", "oldSaveStyle", XrmoptionSepArg, NULL },
1616 { "-oldsave", "oldSaveStyle", XrmoptionNoArg, "True" },
1617 { "-xoldsave", "oldSaveStyle", XrmoptionNoArg, "False" },
1618 { "-quietPlay", "quietPlay", XrmoptionSepArg, NULL },
1619 { "-quiet", "quietPlay", XrmoptionNoArg, "True" },
1620 { "-xquiet", "quietPlay", XrmoptionNoArg, "False" },
1621 { "-titleInWindow", "titleInWindow", XrmoptionSepArg, NULL },
1622 { "-title", "titleInWindow", XrmoptionNoArg, "True" },
1623 { "-xtitle", "titleInWindow", XrmoptionNoArg, "False" },
1625 { "-zippyTalk", "zippyTalk", XrmoptionSepArg, NULL },
1626 { "-zt", "zippyTalk", XrmoptionNoArg, "True" },
1627 { "-xzt", "zippyTalk", XrmoptionNoArg, "False" },
1628 { "-zippyPlay", "zippyPlay", XrmoptionSepArg, NULL },
1629 { "-zp", "zippyPlay", XrmoptionNoArg, "True" },
1630 { "-xzp", "zippyPlay", XrmoptionNoArg, "False" },
1631 { "-zippyLines", "zippyLines", XrmoptionSepArg, NULL },
1632 { "-zippyPinhead", "zippyPinhead", XrmoptionSepArg, NULL },
1633 { "-zippyPassword", "zippyPassword", XrmoptionSepArg, NULL },
1634 { "-zippyPassword2", "zippyPassword2", XrmoptionSepArg, NULL },
1635 { "-zippyWrongPassword", "zippyWrongPassword", XrmoptionSepArg, NULL },
1636 { "-zippyAcceptOnly", "zippyAcceptOnly", XrmoptionSepArg, NULL },
1637 { "-zippyUseI", "zippyUseI", XrmoptionSepArg, NULL },
1638 { "-zui", "zippyUseI", XrmoptionNoArg, "True" },
1639 { "-xzui", "zippyUseI", XrmoptionNoArg, "False" },
1640 { "-zippyBughouse", "zippyBughouse", XrmoptionSepArg, NULL },
1641 { "-zippyNoplayCrafty", "zippyNoplayCrafty", XrmoptionSepArg, NULL },
1642 { "-znc", "zippyNoplayCrafty", XrmoptionNoArg, "True" },
1643 { "-xznc", "zippyNoplayCrafty", XrmoptionNoArg, "False" },
1644 { "-zippyGameEnd", "zippyGameEnd", XrmoptionSepArg, NULL },
1645 { "-zippyGameStart", "zippyGameStart", XrmoptionSepArg, NULL },
1646 { "-zippyAdjourn", "zippyAdjourn", XrmoptionSepArg, NULL },
1647 { "-zadj", "zippyAdjourn", XrmoptionNoArg, "True" },
1648 { "-xzadj", "zippyAdjourn", XrmoptionNoArg, "False" },
1649 { "-zippyAbort", "zippyAbort", XrmoptionSepArg, NULL },
1650 { "-zab", "zippyAbort", XrmoptionNoArg, "True" },
1651 { "-xzab", "zippyAbort", XrmoptionNoArg, "False" },
1652 { "-zippyVariants", "zippyVariants", XrmoptionSepArg, NULL },
1653 { "-zippyMaxGames", "zippyMaxGames", XrmoptionSepArg, NULL },
1654 { "-zippyReplayTimeout", "zippyReplayTimeout", XrmoptionSepArg, NULL },
1655 { "-zippyShortGame", "zippyShortGame", XrmoptionSepArg, NULL },
1657 { "-flashCount", "flashCount", XrmoptionSepArg, NULL },
1658 { "-flash", "flashCount", XrmoptionNoArg, "3" },
1659 { "-xflash", "flashCount", XrmoptionNoArg, "0" },
1660 { "-flashRate", "flashRate", XrmoptionSepArg, NULL },
1661 { "-pixmapDirectory", "pixmapDirectory", XrmoptionSepArg, NULL },
1662 { "-msLoginDelay", "msLoginDelay", XrmoptionSepArg, NULL },
1663 { "-pixmap", "pixmapDirectory", XrmoptionSepArg, NULL },
1664 { "-colorizeMessages", "colorizeMessages", XrmoptionSepArg, NULL },
1665 { "-colorize", "colorizeMessages", XrmoptionNoArg, "True" },
1666 { "-xcolorize", "colorizeMessages", XrmoptionNoArg, "False" },
1667 { "-colorShout", "colorShout", XrmoptionSepArg, NULL },
1668 { "-colorSShout", "colorSShout", XrmoptionSepArg, NULL },
1669 { "-colorCShout", "colorSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1670 { "-colorChannel1", "colorChannel1", XrmoptionSepArg, NULL },
1671 { "-colorChannel", "colorChannel", XrmoptionSepArg, NULL },
1672 { "-colorKibitz", "colorKibitz", XrmoptionSepArg, NULL },
1673 { "-colorTell", "colorTell", XrmoptionSepArg, NULL },
1674 { "-colorChallenge", "colorChallenge", XrmoptionSepArg, NULL },
1675 { "-colorRequest", "colorRequest", XrmoptionSepArg, NULL },
1676 { "-colorSeek", "colorSeek", XrmoptionSepArg, NULL },
1677 { "-colorNormal", "colorNormal", XrmoptionSepArg, NULL },
1678 { "-soundProgram", "soundProgram", XrmoptionSepArg, NULL },
1679 { "-soundShout", "soundShout", XrmoptionSepArg, NULL },
1680 { "-soundSShout", "soundSShout", XrmoptionSepArg, NULL },
1681 { "-soundCShout", "soundSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1682 { "-soundChannel1", "soundChannel1", XrmoptionSepArg, NULL },
1683 { "-soundChannel", "soundChannel", XrmoptionSepArg, NULL },
1684 { "-soundKibitz", "soundKibitz", XrmoptionSepArg, NULL },
1685 { "-soundTell", "soundTell", XrmoptionSepArg, NULL },
1686 { "-soundChallenge", "soundChallenge", XrmoptionSepArg, NULL },
1687 { "-soundRequest", "soundRequest", XrmoptionSepArg, NULL },
1688 { "-soundSeek", "soundSeek", XrmoptionSepArg, NULL },
1689 { "-soundMove", "soundMove", XrmoptionSepArg, NULL },
1690 { "-soundIcsWin", "soundIcsWin", XrmoptionSepArg, NULL },
1691 { "-soundIcsLoss", "soundIcsLoss", XrmoptionSepArg, NULL },
1692 { "-soundIcsDraw", "soundIcsDraw", XrmoptionSepArg, NULL },
1693 { "-soundIcsUnfinished", "soundIcsUnfinished", XrmoptionSepArg, NULL },
1694 { "-soundIcsAlarm", "soundIcsAlarm", XrmoptionSepArg, NULL },
1695 { "-reuseFirst", "reuseFirst", XrmoptionSepArg, NULL },
1696 { "-reuseChessPrograms", "reuseFirst", XrmoptionSepArg, NULL }, /*compat*/
1697 { "-reuse", "reuseFirst", XrmoptionNoArg, "True" },
1698 { "-xreuse", "reuseFirst", XrmoptionNoArg, "False" },
1699 { "-reuseSecond", "reuseSecond", XrmoptionSepArg, NULL },
1700 { "-reuse2", "reuseSecond", XrmoptionNoArg, "True" },
1701 { "-xreuse2", "reuseSecond", XrmoptionNoArg, "False" },
1702 { "-animateMoving", "animateMoving", XrmoptionSepArg, NULL },
1703 { "-animate", "animateMoving", XrmoptionNoArg, "True" },
1704 { "-xanimate", "animateMoving", XrmoptionNoArg, "False" },
1705 { "-animateDragging", "animateDragging", XrmoptionSepArg, NULL },
1706 { "-drag", "animateDragging", XrmoptionNoArg, "True" },
1707 { "-xdrag", "animateDragging", XrmoptionNoArg, "False" },
1708 { "-animateSpeed", "animateSpeed", XrmoptionSepArg, NULL },
1709 { "-popupExitMessage", "popupExitMessage", XrmoptionSepArg, NULL },
1710 { "-exit", "popupExitMessage", XrmoptionNoArg, "True" },
1711 { "-xexit", "popupExitMessage", XrmoptionNoArg, "False" },
1712 { "-popupMoveErrors", "popupMoveErrors", XrmoptionSepArg, NULL },
1713 { "-popup", "popupMoveErrors", XrmoptionNoArg, "True" },
1714 { "-xpopup", "popupMoveErrors", XrmoptionNoArg, "False" },
1715 { "-fontSizeTolerance", "fontSizeTolerance", XrmoptionSepArg, NULL },
1716 { "-initialMode", "initialMode", XrmoptionSepArg, NULL },
1717 { "-mode", "initialMode", XrmoptionSepArg, NULL },
1718 { "-variant", "variant", XrmoptionSepArg, NULL },
1719 { "-firstProtocolVersion", "firstProtocolVersion", XrmoptionSepArg, NULL },
1720 { "-secondProtocolVersion","secondProtocolVersion",XrmoptionSepArg, NULL },
1721 { "-showButtonBar", "showButtonBar", XrmoptionSepArg, NULL },
1722 { "-buttons", "showButtonBar", XrmoptionNoArg, "True" },
1723 { "-xbuttons", "showButtonBar", XrmoptionNoArg, "False" },
1724 { "-lowTimeWarningColor", "lowTimeWarningColor", XrmoptionSepArg, NULL },
1725 { "-lowTimeWarning", "lowTimeWarning", XrmoptionSepArg, NULL },
1726 /* [AS,HR] New features */
1727 { "-firstScoreAbs", "firstScoreAbs", XrmoptionSepArg, NULL },
1728 { "-secondScoreAbs", "secondScoreAbs", XrmoptionSepArg, NULL },
1729 { "-pgnExtendedInfo", "pgnExtendedInfo", XrmoptionSepArg, NULL },
1730 { "-hideThinkingFromHuman", "hideThinkingFromHuman", XrmoptionSepArg, NULL },
1731 { "-adjudicateLossThreshold", "adjudicateLossThreshold", XrmoptionSepArg, NULL },
1732 { "-adjudicateDrawMoves", "adjudicateDrawMoves", XrmoptionSepArg, NULL },
1733 { "-pgnEventHeader", "pgnEventHeader", XrmoptionSepArg, NULL },
1734 { "-firstIsUCI", "firstIsUCI", XrmoptionSepArg, NULL },
1735 { "-secondIsUCI", "secondIsUCI", XrmoptionSepArg, NULL },
1736 { "-fUCI", "firstIsUCI", XrmoptionNoArg, "True" },
1737 { "-sUCI", "secondIsUCI", XrmoptionNoArg, "True" },
1738 { "-firstHasOwnBookUCI", "firstHasOwnBookUCI", XrmoptionSepArg, NULL },
1739 { "-secondHasOwnBookUCI", "secondHasOwnBookUCI", XrmoptionSepArg, NULL },
1740 { "-fNoOwnBookUCI", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1741 { "-sNoOwnBookUCI", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1742 { "-firstXBook", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1743 { "-secondXBook", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1744 { "-polyglotDir", "polyglotDir", XrmoptionSepArg, NULL },
1745 { "-usePolyglotBook", "usePolyglotBook", XrmoptionSepArg, NULL },
1746 { "-polyglotBook", "polyglotBook", XrmoptionSepArg, NULL },
1747 { "-defaultHashSize", "defaultHashSize", XrmoptionSepArg, NULL },
1748 { "-defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XrmoptionSepArg, NULL },
1749 { "-defaultPathEGTB", "defaultPathEGTB", XrmoptionSepArg, NULL },
1750 { "-defaultFrcPosition", "defaultFrcPosition", XrmoptionSepArg, NULL },
1751 { "-gameListTags", "gameListTags", XrmoptionSepArg, NULL },
1752 // [HGM] I am sure AS added many more options, but we have to fish them out, from the list in winboard.c
1754 /* [HGM,HR] User-selectable board size */
1755 { "-boardWidth", "boardWidth", XrmoptionSepArg, NULL },
1756 { "-boardHeight", "boardHeight", XrmoptionSepArg, NULL },
1757 { "-matchPause", "matchPause", XrmoptionSepArg, NULL },
1759 /* [HGM] new arguments of 4.3.xx. All except first three are back-end options, which should work immediately */
1760 { "-holdingsSize", "holdingsSize", XrmoptionSepArg, NULL }, // requires extensive front-end changes to work
1761 { "-flipBlack", "flipBlack", XrmoptionSepArg, NULL }, // requires front-end changes to work
1762 { "-allWhite", "allWhite", XrmoptionSepArg, NULL }, // requires front-end changes to work
1763 { "-pieceToCharTable", "pieceToCharTable", XrmoptionSepArg, NULL },
1764 { "-alphaRank", "alphaRank", XrmoptionSepArg, NULL },
1765 { "-testClaims", "testClaims", XrmoptionSepArg, NULL },
1766 { "-checkMates", "checkMates", XrmoptionSepArg, NULL },
1767 { "-materialDraws", "materialDraws", XrmoptionSepArg, NULL },
1768 { "-trivialDraws", "trivialDraws", XrmoptionSepArg, NULL },
1769 { "-ruleMoves", "ruleMoves", XrmoptionSepArg, NULL },
1770 { "-repeatsToDraw", "repeatsToDraw", XrmoptionSepArg, NULL },
1771 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1772 { "-userName", "userName", XrmoptionSepArg, NULL },
1773 { "-autoKibitz", "autoKibitz", XrmoptionNoArg, "True" },
1774 { "-firstTimeOdds", "firstTimeOdds", XrmoptionSepArg, NULL },
1775 { "-secondTimeOdds", "secondTimeOdds", XrmoptionSepArg, NULL },
1776 { "-timeOddsMode", "timeOddsMode", XrmoptionSepArg, NULL },
1777 { "-firstAccumulateTC", "firstAccumulateTC", XrmoptionSepArg, NULL },
1778 { "-secondAccumulateTC", "secondAccumulateTC", XrmoptionSepArg, NULL },
1779 { "-firstNPS", "firstNPS", XrmoptionSepArg, NULL },
1780 { "-secondNPS", "secondNPS", XrmoptionSepArg, NULL },
1781 { "-serverMoves", "serverMoves", XrmoptionSepArg, NULL },
1782 { "-serverPause", "serverPause", XrmoptionSepArg, NULL },
1783 { "-suppressLoadMoves", "suppressLoadMoves", XrmoptionSepArg, NULL },
1784 { "-egtFormats", "egtFormats", XrmoptionSepArg, NULL },
1785 { "-userName", "userName", XrmoptionSepArg, NULL },
1786 { "-smpCores", "smpCores", XrmoptionSepArg, NULL },
1787 { "-sameColorGames", "sameColorGames", XrmoptionSepArg, NULL },
1788 { "-rewindIndex", "rewindIndex", XrmoptionSepArg, NULL },
1789 { "-niceEngines", "niceEngines", XrmoptionSepArg, NULL },
1790 { "-delayBeforeQuit", "delayBeforeQuit", XrmoptionSepArg, NULL },
1791 { "-delayAfterQuit", "delayAfterQuit", XrmoptionSepArg, NULL },
1792 { "-nameOfDebugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1793 { "-debugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1794 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1795 { "-noGUI", "noGUI", XrmoptionNoArg, "True" },
1796 { "-firstOptions", "firstOptions", XrmoptionSepArg, NULL },
1797 { "-secondOptions", "secondOptions", XrmoptionSepArg, NULL },
1798 { "-firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1799 { "-secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1800 { "-keepAlive", "keepAlive", XrmoptionSepArg, NULL },
1804 XtActionsRec boardActions[] = {
1805 { "HandleUserMove", HandleUserMove },
1806 { "AnimateUserMove", AnimateUserMove },
1807 { "FileNameAction", FileNameAction },
1808 { "AskQuestionProc", AskQuestionProc },
1809 { "AskQuestionReplyAction", AskQuestionReplyAction },
1810 { "PieceMenuPopup", PieceMenuPopup },
1811 { "WhiteClock", WhiteClock },
1812 { "BlackClock", BlackClock },
1813 { "Iconify", Iconify },
1814 { "LoadSelectedProc", LoadSelectedProc },
1815 { "LoadPositionProc", LoadPositionProc },
1816 { "LoadNextPositionProc", LoadNextPositionProc },
1817 { "LoadPrevPositionProc", LoadPrevPositionProc },
1818 { "ReloadPositionProc", ReloadPositionProc },
1819 { "CopyPositionProc", CopyPositionProc },
1820 { "PastePositionProc", PastePositionProc },
1821 { "CopyGameProc", CopyGameProc },
1822 { "PasteGameProc", PasteGameProc },
1823 { "SaveGameProc", SaveGameProc },
1824 { "SavePositionProc", SavePositionProc },
1825 { "MailMoveProc", MailMoveProc },
1826 { "ReloadCmailMsgProc", ReloadCmailMsgProc },
1827 // { "MachineWhiteProc", MachineWhiteProc },
1828 // { "MachineBlackProc", MachineBlackProc },
1829 { "AnalysisModeProc", AnalyzeModeProc },
1830 { "AnalyzeFileProc", AnalyzeFileProc },
1831 // { "TwoMachinesProc", TwoMachinesProc },
1832 // { "IcsClientProc", IcsClientProc },
1833 { "EditGameProc", EditGameProc },
1834 { "EditPositionProc", EditPositionProc },
1835 { "TrainingProc", EditPositionProc },
1836 { "EngineOutputProc", EngineOutputProc}, // [HGM] Winboard_x engine-output window
1837 { "ShowGameListProc", ShowGameListProc },
1838 // { "ShowMoveListProc", HistoryShowProc},
1839 { "EditTagsProc", EditCommentProc },
1840 { "EditCommentProc", EditCommentProc },
1841 { "IcsAlarmProc", IcsAlarmProc },
1842 { "IcsInputBoxProc", IcsInputBoxProc },
1843 // { "AcceptProc", AcceptProc },
1844 // { "DeclineProc", DeclineProc },
1845 // { "RematchProc", RematchProc },
1846 // { "CallFlagProc", CallFlagProc },
1847 // { "DrawProc", DrawProc },
1848 // { "AdjournProc", AdjournProc },
1849 // { "AbortProc", AbortProc },
1850 // { "ResignProc", ResignProc },
1851 // { "AdjuWhiteProc", AdjuWhiteProc },
1852 // { "AdjuBlackProc", AdjuBlackProc },
1853 // { "AdjuDrawProc", AdjuDrawProc },
1854 { "EnterKeyProc", EnterKeyProc },
1855 // { "StopObservingProc", StopObservingProc },
1856 // { "StopExaminingProc", StopExaminingProc },
1857 // { "BackwardProc", BackwardProc },
1858 // { "ForwardProc", ForwardProc },
1859 // { "ToStartProc", ToStartProc },
1860 // { "ToEndProc", ToEndProc },
1861 // { "RevertProc", RevertProc },
1862 // { "TruncateGameProc", TruncateGameProc },
1863 // { "MoveNowProc", MoveNowProc },
1864 // { "RetractMoveProc", RetractMoveProc },
1865 { "AlwaysQueenProc", AlwaysQueenProc },
1866 { "AnimateDraggingProc", AnimateDraggingProc },
1867 { "AnimateMovingProc", AnimateMovingProc },
1868 { "AutoflagProc", AutoflagProc },
1869 { "AutoflipProc", AutoflipProc },
1870 { "AutobsProc", AutobsProc },
1871 { "AutoraiseProc", AutoraiseProc },
1872 { "AutosaveProc", AutosaveProc },
1873 { "BlindfoldProc", BlindfoldProc },
1874 { "FlashMovesProc", FlashMovesProc },
1875 // { "FlipViewProc", FlipViewProc },
1876 // { "GetMoveListProc", GetMoveListProc },
1878 { "HighlightDraggingProc", HighlightDraggingProc },
1880 { "HighlightLastMoveProc", HighlightLastMoveProc },
1881 { "IcsAlarmProc", IcsAlarmProc },
1882 { "MoveSoundProc", MoveSoundProc },
1883 { "OldSaveStyleProc", OldSaveStyleProc },
1884 { "PeriodicUpdatesProc", PeriodicUpdatesProc },
1885 { "PonderNextMoveProc", PonderNextMoveProc },
1886 { "PopupExitMessageProc", PopupExitMessageProc },
1887 { "PopupMoveErrorsProc", PopupMoveErrorsProc },
1888 { "PremoveProc", PremoveProc },
1889 { "QuietPlayProc", QuietPlayProc },
1890 { "ShowThinkingProc", ShowThinkingProc },
1891 { "HideThinkingProc", HideThinkingProc },
1892 { "TestLegalityProc", TestLegalityProc },
1893 // { "InfoProc", InfoProc },
1894 // { "ManProc", ManProc },
1895 // { "HintProc", HintProc },
1896 // { "BookProc", BookProc },
1897 { "AboutGameProc", AboutGameProc },
1898 { "DebugProc", DebugProc },
1899 { "NothingProc", NothingProc },
1900 { "CommentPopDown", (XtActionProc) CommentPopDown },
1901 { "EditCommentPopDown", (XtActionProc) EditCommentPopDown },
1902 { "TagsPopDown", (XtActionProc) TagsPopDown },
1903 { "ErrorPopDown", (XtActionProc) ErrorPopDown },
1904 { "ICSInputBoxPopDown", (XtActionProc) ICSInputBoxPopDown },
1905 { "AnalysisPopDown", (XtActionProc) AnalysisPopDown },
1906 { "FileNamePopDown", (XtActionProc) FileNamePopDown },
1907 { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown },
1908 { "GameListPopDown", (XtActionProc) GameListPopDown },
1909 { "PromotionPopDown", (XtActionProc) PromotionPopDown },
1910 // { "HistoryPopDown", (XtActionProc) HistoryPopDown },
1911 { "EngineOutputPopDown", (XtActionProc) EngineOutputPopDown },
1912 { "ShufflePopDown", (XtActionProc) ShufflePopDown },
1913 { "EnginePopDown", (XtActionProc) EnginePopDown },
1914 { "UciPopDown", (XtActionProc) UciPopDown },
1915 { "TimeControlPopDown", (XtActionProc) TimeControlPopDown },
1916 { "NewVariantPopDown", (XtActionProc) NewVariantPopDown },
1917 { "SettingsPopDown", (XtActionProc) SettingsPopDown },
1921 char ICSInputTranslations[] =
1922 "<Key>Return: EnterKeyProc() \n";
1924 String xboardResources[] = {
1925 "*fileName*value.translations: #override\\n <Key>Return: FileNameAction()",
1926 "*question*value.translations: #override\\n <Key>Return: AskQuestionReplyAction()",
1927 "*errorpopup*translations: #override\\n <Key>Return: ErrorPopDown()",
1931 static char *cnames[9] = { "black", "red", "green", "yellow", "blue",
1932 "magenta", "cyan", "white" };
1936 TextColors textColors[(int)NColorClasses];
1938 /* String is: "fg, bg, attr". Which is 0, 1, 2 */
1940 parse_color(str, which)
1944 char *p, buf[100], *d;
1947 if (strlen(str) > 99) /* watch bounds on buf */
1952 for (i=0; i<which; ++i) {
1959 /* Could be looking at something like:
1961 .. in which case we want to stop on a comma also */
1962 while (*p && *p != ',' && !isalpha(*p) && !isdigit(*p))
1966 return -1; /* Use default for empty field */
1969 if (which == 2 || isdigit(*p))
1972 while (*p && isalpha(*p))
1977 for (i=0; i<8; ++i) {
1978 if (!StrCaseCmp(buf, cnames[i]))
1979 return which? (i+40) : (i+30);
1981 if (!StrCaseCmp(buf, "default")) return -1;
1983 fprintf(stderr, _("%s: unrecognized color %s\n"), programName, buf);
1988 parse_cpair(cc, str)
1992 if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {
1993 fprintf(stderr, _("%s: can't parse foreground color in `%s'\n"),
1998 /* bg and attr are optional */
1999 textColors[(int)cc].bg = parse_color(str, 1);
2000 if ((textColors[(int)cc].attr = parse_color(str, 2)) < 0) {
2001 textColors[(int)cc].attr = 0;
2007 /* Arrange to catch delete-window events */
2008 Atom wm_delete_window;
2010 CatchDeleteWindow(Widget w, String procname)
2013 XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
2014 snprintf(buf, sizeof(buf), "<Message>WM_PROTOCOLS: %s() \n", procname);
2015 XtAugmentTranslations(w, XtParseTranslationTable(buf));
2021 /* this should raise the board to the top */
2022 gtk_window_present(GTK_WINDOW(GUI_Window));
2027 // eventually, all layout determining code should go into a subroutine, but until then IDSIZE remains undefined
2029 #define BoardSize int
2030 void InitDrawingSizes(BoardSize boardSize, int flags)
2031 { // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
2032 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2034 XtGeometryResult gres;
2037 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2038 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2040 timerWidth = (boardWidth - sep) / 2;
2042 if (appData.titleInWindow)
2047 w = boardWidth - 2*bor;
2051 w = boardWidth - w - sep - 2*bor - 2; // WIDTH_FUDGE
2055 if(!formWidget) return;
2058 * Inhibit shell resizing.
2061 // [HGM] pieces: tailor piece bitmaps to needs of specific variant
2064 for(i=0; i<4; i++) {
2066 for(p=0; p<=(int)WhiteKing; p++)
2067 xpmPieceBitmap[i][p] = xpmPieceBitmap2[i][p]; // defaults
2068 if(gameInfo.variant == VariantShogi) {
2069 xpmPieceBitmap[i][(int)WhiteCannon] = xpmPieceBitmap2[i][(int)WhiteKing+1];
2070 xpmPieceBitmap[i][(int)WhiteNightrider] = xpmPieceBitmap2[i][(int)WhiteKing+2];
2071 xpmPieceBitmap[i][(int)WhiteSilver] = xpmPieceBitmap2[i][(int)WhiteKing+3];
2072 xpmPieceBitmap[i][(int)WhiteGrasshopper] = xpmPieceBitmap2[i][(int)WhiteKing+4];
2073 xpmPieceBitmap[i][(int)WhiteQueen] = xpmPieceBitmap2[i][(int)WhiteLance];
2076 if(gameInfo.variant == VariantGothic) {
2077 xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteSilver];
2081 // [HGM] why are thee ximMasks used at all? the ximPieceBitmaps seem to be never used!
2082 for(p=0; p<=(int)WhiteKing; p++)
2083 ximMaskPm[p] = ximMaskPm2[p]; // defaults
2084 if(gameInfo.variant == VariantShogi) {
2085 ximMaskPm[(int)WhiteCannon] = ximMaskPm2[(int)WhiteKing+1];
2086 ximMaskPm[(int)WhiteNightrider] = ximMaskPm2[(int)WhiteKing+2];
2087 ximMaskPm[(int)WhiteSilver] = ximMaskPm2[(int)WhiteKing+3];
2088 ximMaskPm[(int)WhiteGrasshopper] = ximMaskPm2[(int)WhiteKing+4];
2089 ximMaskPm[(int)WhiteQueen] = ximMaskPm2[(int)WhiteLance];
2092 if(gameInfo.variant == VariantGothic) {
2093 ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[(int)WhiteSilver];
2099 for(i=0; i<2; i++) {
2101 for(p=0; p<=(int)WhiteKing; p++)
2102 pieceBitmap[i][p] = pieceBitmap2[i][p]; // defaults
2103 if(gameInfo.variant == VariantShogi) {
2104 pieceBitmap[i][(int)WhiteCannon] = pieceBitmap2[i][(int)WhiteKing+1];
2105 pieceBitmap[i][(int)WhiteNightrider] = pieceBitmap2[i][(int)WhiteKing+2];
2106 pieceBitmap[i][(int)WhiteSilver] = pieceBitmap2[i][(int)WhiteKing+3];
2107 pieceBitmap[i][(int)WhiteGrasshopper] = pieceBitmap2[i][(int)WhiteKing+4];
2108 pieceBitmap[i][(int)WhiteQueen] = pieceBitmap2[i][(int)WhiteLance];
2111 if(gameInfo.variant == VariantGothic) {
2112 pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteSilver];
2123 void EscapeExpand(char *p, char *q)
2124 { // [HGM] initstring: routine to shape up string arguments
2125 while(*p++ = *q++) if(p[-1] == '\\')
2127 case 'n': p[-1] = '\n'; break;
2128 case 'r': p[-1] = '\r'; break;
2129 case 't': p[-1] = '\t'; break;
2130 case '\\': p[-1] = '\\'; break;
2131 case 0: *p = 0; return;
2132 default: p[-1] = q[-1]; break;
2141 int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
2142 XSetWindowAttributes window_attributes;
2144 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2145 XrmValue vFrom, vTo;
2146 XtGeometryResult gres;
2149 int forceMono = False;
2153 // [HGM] before anything else, expand any indirection files amongst options
2154 char *argvCopy[1000]; // 1000 seems enough
2155 char newArgs[10000]; // holds actual characters
2158 srandom(time(0)); // [HGM] book: make random truly random
2161 for(i=0; i<argc; i++) {
2162 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2163 //fprintf(stderr, "arg %s\n", argv[i]);
2164 if(argv[i][0] != '@') argvCopy[j++] = argv[i]; else {
2166 FILE *f = fopen(argv[i]+1, "rb");
2167 if(f == NULL) { fprintf(stderr, _("ignore %s\n"), argv[i]); continue; } // do not expand non-existing
2168 argvCopy[j++] = newArgs + k; // get ready for first argument from file
2169 while((c = fgetc(f)) != EOF) { // each line of file inserts 1 argument in the list
2171 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2172 newArgs[k++] = 0; // terminate current arg
2173 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2174 argvCopy[j++] = newArgs + k; // get ready for next
2176 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2190 setbuf(stdout, NULL);
2191 setbuf(stderr, NULL);
2194 programName = strrchr(argv[0], '/');
2195 if (programName == NULL)
2196 programName = argv[0];
2201 XtSetLanguageProc(NULL, NULL, NULL);
2202 bindtextdomain(PACKAGE, LOCALEDIR);
2203 textdomain(PACKAGE);
2207 XtAppInitialize(&appContext, "XBoard", shellOptions,
2208 XtNumber(shellOptions),
2209 &argc, argv, xboardResources, NULL, 0);
2213 gtk_init (&argc, &argv);
2215 /* parse glade file to build widgets */
2217 builder = gtk_builder_new ();
2218 gtk_builder_add_from_file (builder, "gtk-interface.xml", NULL);
2220 /* test if everything worked ok */
2222 GUI_Window = GTK_WIDGET (gtk_builder_get_object (builder, "MainWindow"));
2223 if(!GUI_Window) printf("Error: gtk_builder didn't work!\n");
2225 GUI_History = GTK_WIDGET (gtk_builder_get_object (builder, "MoveHistory"));
2226 if(!GUI_History) printf("Error: gtk_builder didn't work!\n");
2228 GUI_Board = GTK_WIDGET (gtk_builder_get_object (builder, "Board"));
2229 if(!GUI_Board) printf("Error: gtk_builder didn't work!\n");
2231 GUI_Whiteclock = GTK_WIDGET (gtk_builder_get_object (builder, "WhiteClock"));
2232 if(!GUI_Whiteclock) printf("Error: gtk_builder didn't work!\n");
2234 GUI_Blackclock = GTK_WIDGET (gtk_builder_get_object (builder, "BlackClock"));
2235 if(!GUI_Blackclock) printf("Error: gtk_builder didn't work!\n");
2237 LIST_MoveHistory = GTK_LIST_STORE (gtk_builder_get_object (builder, "MoveHistoryStore"));
2238 if(!LIST_MoveHistory) printf("Error: gtk_builder didn't work!\n");
2241 gtk_builder_connect_signals (builder, NULL);
2243 // don't unref the builder, since we use it to get references to widgets
2244 // g_object_unref (G_OBJECT (builder));
2246 /* end parse glade file */
2250 fprintf(stderr, _("%s: unrecognized argument %s\n"),
2251 programName, argv[1]);
2252 fprintf(stderr, "Recognized options:\n");
2253 for(i = 0; i < XtNumber(shellOptions); i++)
2255 j = fprintf(stderr, " %s%s", shellOptions[i].option,
2256 (shellOptions[i].argKind == XrmoptionSepArg
2258 if (i++ < XtNumber(shellOptions))
2260 fprintf(stderr, "%*c%s%s\n", 40 - j, ' ',
2261 shellOptions[i].option,
2262 (shellOptions[i].argKind == XrmoptionSepArg
2267 fprintf(stderr, "\n");
2273 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL)
2279 if (chdir(chessDir) != 0)
2281 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
2288 if (p == NULL) p = "/tmp";
2289 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
2290 gameCopyFilename = (char*) malloc(i);
2291 gamePasteFilename = (char*) malloc(i);
2292 snprintf(gameCopyFilename,i, "%s/.xboard%05uc.pgn", p, getpid());
2293 snprintf(gamePasteFilename,i, "%s/.xboard%05up.pgn", p, getpid());
2295 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
2296 clientResources, XtNumber(clientResources),
2299 { // [HGM] initstring: kludge to fix bad bug. expand '\n' characters in init string and computer string.
2300 static char buf[MSG_SIZ];
2301 EscapeExpand(buf, appData.initString);
2302 appData.initString = strdup(buf);
2303 EscapeExpand(buf, appData.secondInitString);
2304 appData.secondInitString = strdup(buf);
2305 EscapeExpand(buf, appData.firstComputerString);
2306 appData.firstComputerString = strdup(buf);
2307 EscapeExpand(buf, appData.secondComputerString);
2308 appData.secondComputerString = strdup(buf);
2311 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
2314 if (chdir(chessDir) != 0) {
2315 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
2321 if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) {
2322 /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */
2323 if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL) {
2324 printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile);
2327 setbuf(debugFP, NULL);
2330 /* [HGM,HR] make sure board size is acceptable */
2331 if(appData.NrFiles > BOARD_SIZE ||
2332 appData.NrRanks > BOARD_SIZE )
2333 DisplayFatalError(_("Recompile with BOARD_SIZE > 12, to support this size"), 0, 2);
2336 /* This feature does not work; animation needs a rewrite */
2337 appData.highlightDragging = FALSE;
2341 xDisplay = XtDisplay(shellWidget);
2342 xScreen = DefaultScreen(xDisplay);
2343 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
2345 gameInfo.variant = StringToVariant(appData.variant);
2346 InitPosition(FALSE);
2350 * Determine boardSize
2352 gameInfo.boardWidth = gameInfo.boardHeight = 8; // [HGM] boardsize: make sure we start as 8x8
2355 // [HGM] as long as we have not created the possibility to change size while running, start with requested size
2356 gameInfo.boardWidth = appData.NrFiles > 0 ? appData.NrFiles : 8;
2357 gameInfo.boardHeight = appData.NrRanks > 0 ? appData.NrRanks : 8;
2358 gameInfo.holdingsWidth = appData.holdingsSize > 0 ? 2 : 0;
2363 InitDrawingSizes(-1, 0); // [HGM] initsize: make this into a subroutine
2365 if (isdigit(appData.boardSize[0])) {
2366 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
2367 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
2368 &fontPxlSize, &smallLayout, &tinyLayout);
2370 fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
2371 programName, appData.boardSize);
2375 /* Find some defaults; use the nearest known size */
2376 SizeDefaults *szd, *nearest;
2377 int distance = 99999;
2378 nearest = szd = sizeDefaults;
2379 while (szd->name != NULL) {
2380 if (abs(szd->squareSize - squareSize) < distance) {
2382 distance = abs(szd->squareSize - squareSize);
2383 if (distance == 0) break;
2387 if (i < 2) lineGap = nearest->lineGap;
2388 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
2389 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
2390 if (i < 5) fontPxlSize = nearest->fontPxlSize;
2391 if (i < 6) smallLayout = nearest->smallLayout;
2392 if (i < 7) tinyLayout = nearest->tinyLayout;
2395 SizeDefaults *szd = sizeDefaults;
2396 if (*appData.boardSize == NULLCHAR) {
2397 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize ||
2398 DisplayHeight(xDisplay, xScreen) < szd->minScreenSize) {
2401 if (szd->name == NULL) szd--;
2403 while (szd->name != NULL &&
2404 StrCaseCmp(szd->name, appData.boardSize) != 0) szd++;
2405 if (szd->name == NULL) {
2406 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
2407 programName, appData.boardSize);
2411 squareSize = szd->squareSize;
2412 lineGap = szd->lineGap;
2413 clockFontPxlSize = szd->clockFontPxlSize;
2414 coordFontPxlSize = szd->coordFontPxlSize;
2415 fontPxlSize = szd->fontPxlSize;
2416 smallLayout = szd->smallLayout;
2417 tinyLayout = szd->tinyLayout;
2420 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2421 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2422 if (appData.showJail == 1) {
2423 /* Jail on top and bottom */
2424 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2425 XtSetArg(boardArgs[2], XtNheight,
2426 boardHeight + 2*(lineGap + squareSize));
2427 } else if (appData.showJail == 2) {
2429 XtSetArg(boardArgs[1], XtNwidth,
2430 boardWidth + 2*(lineGap + squareSize));
2431 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2434 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2435 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2439 * Determine what fonts to use.
2441 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
2442 clockFontID = XLoadFont(xDisplay, appData.clockFont);
2443 clockFontStruct = XQueryFont(xDisplay, clockFontID);
2444 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
2445 coordFontID = XLoadFont(xDisplay, appData.coordFont);
2446 coordFontStruct = XQueryFont(xDisplay, coordFontID);
2447 appData.font = FindFont(appData.font, fontPxlSize);
2448 countFontID = XLoadFont(xDisplay, appData.coordFont); // [HGM] holdings
2449 countFontStruct = XQueryFont(xDisplay, countFontID);
2450 // appData.font = FindFont(appData.font, fontPxlSize);
2452 xdb = XtDatabase(xDisplay);
2453 XrmPutStringResource(&xdb, "*font", appData.font);
2456 * Detect if there are not enough colors available and adapt.
2458 if (DefaultDepth(xDisplay, xScreen) <= 2) {
2459 appData.monoMode = True;
2462 if (!appData.monoMode) {
2463 vFrom.addr = (caddr_t) appData.lightSquareColor;
2464 vFrom.size = strlen(appData.lightSquareColor);
2465 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2466 if (vTo.addr == NULL) {
2467 appData.monoMode = True;
2470 lightSquareColor = *(Pixel *) vTo.addr;
2473 if (!appData.monoMode) {
2474 vFrom.addr = (caddr_t) appData.darkSquareColor;
2475 vFrom.size = strlen(appData.darkSquareColor);
2476 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2477 if (vTo.addr == NULL) {
2478 appData.monoMode = True;
2481 darkSquareColor = *(Pixel *) vTo.addr;
2484 if (!appData.monoMode) {
2485 vFrom.addr = (caddr_t) appData.whitePieceColor;
2486 vFrom.size = strlen(appData.whitePieceColor);
2487 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2488 if (vTo.addr == NULL) {
2489 appData.monoMode = True;
2492 whitePieceColor = *(Pixel *) vTo.addr;
2495 if (!appData.monoMode) {
2496 vFrom.addr = (caddr_t) appData.blackPieceColor;
2497 vFrom.size = strlen(appData.blackPieceColor);
2498 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2499 if (vTo.addr == NULL) {
2500 appData.monoMode = True;
2503 blackPieceColor = *(Pixel *) vTo.addr;
2507 if (!appData.monoMode) {
2508 vFrom.addr = (caddr_t) appData.highlightSquareColor;
2509 vFrom.size = strlen(appData.highlightSquareColor);
2510 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2511 if (vTo.addr == NULL) {
2512 appData.monoMode = True;
2515 highlightSquareColor = *(Pixel *) vTo.addr;
2519 if (!appData.monoMode) {
2520 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
2521 vFrom.size = strlen(appData.premoveHighlightColor);
2522 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2523 if (vTo.addr == NULL) {
2524 appData.monoMode = True;
2527 premoveHighlightColor = *(Pixel *) vTo.addr;
2532 fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2535 if (appData.bitmapDirectory == NULL ||
2536 appData.bitmapDirectory[0] == NULLCHAR)
2537 appData.bitmapDirectory = DEF_BITMAP_DIR;
2540 if (appData.lowTimeWarning && !appData.monoMode) {
2541 vFrom.addr = (caddr_t) appData.lowTimeWarningColor;
2542 vFrom.size = strlen(appData.lowTimeWarningColor);
2543 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2544 if (vTo.addr == NULL)
2545 appData.monoMode = True;
2547 lowTimeWarningColor = *(Pixel *) vTo.addr;
2550 if (appData.monoMode && appData.debugMode) {
2551 fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2552 (unsigned long) XWhitePixel(xDisplay, xScreen),
2553 (unsigned long) XBlackPixel(xDisplay, xScreen));
2556 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
2557 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
2558 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
2559 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
2560 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
2561 parse_cpair(ColorTell, appData.colorTell) < 0 ||
2562 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
2563 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
2564 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
2565 parse_cpair(ColorNormal, appData.colorNormal) < 0)
2567 if (appData.colorize) {
2569 _("%s: can't parse color names; disabling colorization\n"),
2572 appData.colorize = FALSE;
2574 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2575 textColors[ColorNone].attr = 0;
2577 // XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2583 layoutName = "tinyLayout";
2584 } else if (smallLayout) {
2585 layoutName = "smallLayout";
2587 layoutName = "normalLayout";
2590 if (appData.titleInWindow) {
2591 /* todo check what this appdata does */
2594 if (appData.showButtonBar) {
2595 /* TODO hide button bar if requested */
2599 * gtk set properties of widgets
2602 /* set board size */
2603 gtk_widget_set_size_request(GTK_WIDGET(GUI_Board),
2604 boardWidth,boardHeight);
2606 /* end gtk set properties of widgets */
2608 if (appData.titleInWindow)
2613 if (appData.showButtonBar)
2620 if (appData.showButtonBar)
2629 // [HGM] it seems the layout code ends here, but perhaps the color stuff is size independent and would
2630 // not need to go into InitDrawingSizes().
2633 /* set some checkboxes in the menu according to appData */
2635 if (appData.alwaysPromoteToQueen)
2636 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Always Queen")),TRUE);
2638 if (appData.animateDragging)
2639 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Animate Dragging")),TRUE);
2641 if (appData.animate)
2642 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Animate Moving")),TRUE);
2644 if (appData.autoComment)
2645 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Comment")),TRUE);
2647 if (appData.autoCallFlag)
2648 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Flag")),TRUE);
2650 if (appData.autoFlipView)
2651 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Flip View")),TRUE);
2653 if (appData.autoObserve)
2654 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Observe")),TRUE);
2656 if (appData.autoRaiseBoard)
2657 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Raise Board")),TRUE);
2659 if (appData.autoSaveGames)
2660 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Save")),TRUE);
2662 if (appData.saveGameFile[0] != NULLCHAR)
2664 /* Can't turn this off from menu */
2665 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Save")),TRUE);
2666 gtk_action_set_sensitive(GTK_ACTION (gtk_builder_get_object (builder, "menuOptions.Auto Save")),FALSE);
2669 if (appData.blindfold)
2670 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Blindfold")),TRUE);
2672 if (appData.flashCount > 0)
2673 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Flash Moves")),TRUE);
2675 if (appData.getMoveList)
2676 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Get Move List")),TRUE);
2679 if (appData.highlightDragging)
2680 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Highlight Dragging")),TRUE);
2683 if (appData.highlightLastMove)
2684 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Highlight Last Move")),TRUE);
2686 if (appData.icsAlarm)
2687 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.ICS Alarm")),TRUE);
2689 if (appData.ringBellAfterMoves)
2690 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Move Sound")),TRUE);
2692 if (appData.oldSaveStyle)
2693 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Old Save Style")),TRUE);
2695 if (appData.periodicUpdates)
2696 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Periodic Updates")),TRUE);
2698 if (appData.ponderNextMove)
2699 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Ponder Next Move")),TRUE);
2701 if (appData.popupExitMessage)
2702 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Popup Exit Message")),TRUE);
2704 if (appData.popupMoveErrors)
2705 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Popup Move Errors")),TRUE);
2707 if (appData.premove)
2708 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Premove")),TRUE);
2710 if (appData.quietPlay)
2711 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Quit Play")),TRUE);
2713 if (appData.showCoords)
2714 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Show Coords")),TRUE);
2716 if (appData.showThinking)
2717 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Show Thinking")),TRUE);
2719 if (appData.testLegality)
2720 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Test Legality")),TRUE);
2722 /* end setting check boxes */
2725 /* load square colors */
2726 SVGLightSquare = load_pixbuf("svg/LightSquare.svg",squareSize);
2727 SVGDarkSquare = load_pixbuf("svg/DarkSquare.svg",squareSize);
2728 SVGNeutralSquare = load_pixbuf("svg/NeutralSquare.svg",squareSize);
2730 /* use two icons to indicate if it is white's or black's turn */
2731 WhiteIcon = load_pixbuf("svg/icon_white.svg",0);
2732 BlackIcon = load_pixbuf("svg/icon_black.svg",0);
2733 WindowIcon = WhiteIcon;
2734 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
2736 /* do resizing to a fixed aspect ratio */
2741 GUI_SetAspectRatio(0.7);
2743 /* realize window */
2744 gtk_widget_show (GUI_Window);
2750 if (appData.animate || appData.animateDragging)
2755 if (errorExitStatus == -1) {
2756 if (appData.icsActive) {
2757 /* We now wait until we see "login:" from the ICS before
2758 sending the logon script (problems with timestamp otherwise) */
2759 /*ICSInitScript();*/
2760 if (appData.icsInputBox) ICSInputBoxPopUp();
2763 signal(SIGINT, IntSigHandler);
2764 signal(SIGTERM, IntSigHandler);
2765 if (*appData.cmailGameName != NULLCHAR) {
2766 signal(SIGUSR1, CmailSigHandler);
2769 gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes()
2773 * Create a cursor for the board widget.
2774 * (This needs to be called after the window has been created to have access to board-window)
2777 BoardCursor = gdk_cursor_new(GDK_HAND2);
2778 gdk_window_set_cursor(GUI_Board->window, BoardCursor);
2779 gdk_cursor_destroy(BoardCursor);
2784 if (appData.debugMode) fclose(debugFP); // [DM] debug
2791 if (appData.icsActive && oldICSInteractionTitle != NULL) {
2792 DisplayIcsInteractionTitle(oldICSInteractionTitle);
2794 unlink(gameCopyFilename);
2795 unlink(gamePasteFilename);
2806 CmailSigHandler(sig)
2812 signal(SIGUSR1, SIG_IGN); /* suspend handler */
2814 /* Activate call-back function CmailSigHandlerCallBack() */
2815 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
2817 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
2821 CmailSigHandlerCallBack(isr, closure, message, count, error)
2829 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
2831 /**** end signal code ****/
2841 f = fopen(appData.icsLogon, "r");
2847 strcat(buf, appData.icsLogon);
2848 f = fopen(buf, "r");
2852 ProcessICSInitScript(f);
2859 EditCommentPopDown();
2865 SetMenuEnables(enab)
2870 if (!builder) return;
2871 while (enab->name != NULL) {
2872 o = gtk_builder_get_object(builder, enab->name);
2873 if(GTK_IS_WIDGET(o))
2874 gtk_widget_set_sensitive(GTK_WIDGET (o),enab->value);
2877 if(GTK_IS_ACTION(o))
2878 gtk_action_set_sensitive(GTK_ACTION (o),enab->value);
2880 DisplayError(enab->name, 0);
2888 SetMenuEnables(icsEnables);
2891 if (appData.zippyPlay && !appData.noChessProgram) /* [DM] icsEngineAnalyze */
2892 {}; // XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
2899 SetMenuEnables(ncpEnables);
2905 SetMenuEnables(gnuEnables);
2911 SetMenuEnables(cmailEnables);
2917 SetMenuEnables(trainingOnEnables);
2918 if (appData.showButtonBar) {
2919 // XtSetSensitive(buttonBarWidget, False);
2925 SetTrainingModeOff()
2927 SetMenuEnables(trainingOffEnables);
2928 if (appData.showButtonBar) {
2929 // XtSetSensitive(buttonBarWidget, True);
2934 SetUserThinkingEnables()
2936 if (appData.noChessProgram) return;
2937 SetMenuEnables(userThinkingEnables);
2941 SetMachineThinkingEnables()
2943 if (appData.noChessProgram) return;
2944 SetMenuEnables(machineThinkingEnables);
2946 case MachinePlaysBlack:
2947 case MachinePlaysWhite:
2948 case TwoMachinesPlay:
2949 // XtSetSensitive(XtNameToWidget(menuBarWidget,
2950 // ModeToWidgetName(gameMode)), True);
2957 #define Abs(n) ((n)<0 ? -(n) : (n))
2960 * Find a font that matches "pattern" that is as close as
2961 * possible to the targetPxlSize. Prefer fonts that are k
2962 * pixels smaller to fonts that are k pixels larger. The
2963 * pattern must be in the X Consortium standard format,
2964 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
2965 * The return value should be freed with XtFree when no
2968 char *FindFont(pattern, targetPxlSize)
2972 char **fonts, *p, *best, *scalable, *scalableTail;
2973 int i, j, nfonts, minerr, err, pxlSize;
2976 char **missing_list;
2978 char *def_string, *base_fnt_lst, strInt[3];
2980 XFontStruct **fnt_list;
2982 base_fnt_lst = calloc(1, strlen(pattern) + 3);
2983 sprintf(strInt, "%d", targetPxlSize);
2984 p = strstr(pattern, "--");
2985 strncpy(base_fnt_lst, pattern, p - pattern + 2);
2986 strcat(base_fnt_lst, strInt);
2987 strcat(base_fnt_lst, strchr(p + 2, '-'));
2989 if ((fntSet = XCreateFontSet(xDisplay,
2993 &def_string)) == NULL) {
2995 fprintf(stderr, _("Unable to create font set.\n"));
2999 nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
3001 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
3003 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
3004 programName, pattern);
3012 for (i=0; i<nfonts; i++) {
3015 if (*p != '-') continue;
3017 if (*p == NULLCHAR) break;
3018 if (*p++ == '-') j++;
3020 if (j < 7) continue;
3023 scalable = fonts[i];
3026 err = pxlSize - targetPxlSize;
3027 if (Abs(err) < Abs(minerr) ||
3028 (minerr > 0 && err < 0 && -err == minerr)) {
3034 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
3035 /* If the error is too big and there is a scalable font,
3036 use the scalable font. */
3037 int headlen = scalableTail - scalable;
3038 p = (char *) XtMalloc(strlen(scalable) + 10);
3039 while (isdigit(*scalableTail)) scalableTail++;
3040 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
3042 p = (char *) XtMalloc(strlen(best) + 1);
3045 if (appData.debugMode) {
3046 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
3047 pattern, targetPxlSize, p);
3050 if (missing_count > 0)
3051 XFreeStringList(missing_list);
3052 XFreeFontSet(xDisplay, fntSet);
3054 XFreeFontNames(fonts);
3061 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
3062 | GCBackground | GCFunction | GCPlaneMask;
3063 XGCValues gc_values;
3066 gc_values.plane_mask = AllPlanes;
3067 gc_values.line_width = lineGap;
3068 gc_values.line_style = LineSolid;
3069 gc_values.function = GXcopy;
3071 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3072 gc_values.background = XWhitePixel(xDisplay, xScreen);
3073 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
3074 XSetFont(xDisplay, coordGC, coordFontID);
3076 if (appData.monoMode) {
3077 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3078 gc_values.background = XBlackPixel(xDisplay, xScreen);
3079 lightSquareGC = wbPieceGC
3080 = XtGetGC(shellWidget, value_mask, &gc_values);
3082 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3083 gc_values.background = XWhitePixel(xDisplay, xScreen);
3084 darkSquareGC = bwPieceGC
3085 = XtGetGC(shellWidget, value_mask, &gc_values);
3087 if (DefaultDepth(xDisplay, xScreen) == 1) {
3088 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3089 gc_values.function = GXcopyInverted;
3090 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3091 gc_values.function = GXcopy;
3092 if (XBlackPixel(xDisplay, xScreen) == 1) {
3093 bwPieceGC = darkSquareGC;
3094 wbPieceGC = copyInvertedGC;
3096 bwPieceGC = copyInvertedGC;
3097 wbPieceGC = lightSquareGC;
3101 gc_values.foreground = lightSquareColor;
3102 gc_values.background = darkSquareColor;
3103 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3105 gc_values.foreground = darkSquareColor;
3106 gc_values.background = lightSquareColor;
3107 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3109 gc_values.foreground = jailSquareColor;
3110 gc_values.background = jailSquareColor;
3111 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3113 gc_values.foreground = whitePieceColor;
3114 gc_values.background = darkSquareColor;
3115 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3117 gc_values.foreground = whitePieceColor;
3118 gc_values.background = lightSquareColor;
3119 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3121 gc_values.foreground = whitePieceColor;
3122 gc_values.background = jailSquareColor;
3123 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3125 gc_values.foreground = blackPieceColor;
3126 gc_values.background = darkSquareColor;
3127 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3129 gc_values.foreground = blackPieceColor;
3130 gc_values.background = lightSquareColor;
3131 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3133 gc_values.foreground = blackPieceColor;
3134 gc_values.background = jailSquareColor;
3135 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3142 WhitePawn, WhiteKnight, WhiteBishop, WhiteRook, WhiteQueen, WhiteKing,
3143 BlackPawn, BlackKnight, BlackBishop, BlackRook, BlackQueen, BlackKing,
3147 /* get some defaults going */
3148 for(i=WhitePawn; i<DemotePiece+1; i++)
3149 SVGpieces[i] = load_pixbuf("svg/NeutralSquare.svg",squareSize);
3152 SVGpieces[WhitePawn] = load_pixbuf("svg/WhitePawn.svg",squareSize);
3153 SVGpieces[WhiteKnight] = load_pixbuf("svg/WhiteKnight.svg",squareSize);
3154 SVGpieces[WhiteBishop] = load_pixbuf("svg/WhiteBishop.svg",squareSize);
3155 SVGpieces[WhiteRook] = load_pixbuf("svg/WhiteRook.svg",squareSize);
3156 SVGpieces[WhiteQueen] = load_pixbuf("svg/WhiteQueen.svg",squareSize);
3157 SVGpieces[WhiteKing] = load_pixbuf("svg/WhiteKing.svg",squareSize);
3159 SVGpieces[BlackPawn] = load_pixbuf("svg/BlackPawn.svg",squareSize);
3160 SVGpieces[BlackKnight] = load_pixbuf("svg/BlackKnight.svg",squareSize);
3161 SVGpieces[BlackBishop] = load_pixbuf("svg/BlackBishop.svg",squareSize);
3162 SVGpieces[BlackRook] = load_pixbuf("svg/BlackRook.svg",squareSize);
3163 SVGpieces[BlackQueen] = load_pixbuf("svg/BlackQueen.svg",squareSize);
3164 SVGpieces[BlackKing] = load_pixbuf("svg/BlackKing.svg",squareSize);
3170 static void MenuBarSelect(w, addr, index)
3175 XtActionProc proc = (XtActionProc) addr;
3177 (proc)(NULL, NULL, NULL, NULL);
3180 void CreateMenuBarPopup(parent, name, mb)
3190 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3193 XtSetArg(args[j], XtNleftMargin, 20); j++;
3194 XtSetArg(args[j], XtNrightMargin, 20); j++;
3196 while (mi->string != NULL) {
3197 if (strcmp(mi->string, "----") == 0) {
3198 entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
3201 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string)));
3202 entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass,
3204 XtAddCallback(entry, XtNcallback,
3205 (XtCallbackProc) MenuBarSelect,
3206 (caddr_t) mi->proc);
3212 Widget CreateMenuBar(mb)
3216 Widget anchor, menuBar;
3218 char menuName[MSG_SIZ];
3221 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3222 XtSetArg(args[j], XtNvSpace, 0); j++;
3223 XtSetArg(args[j], XtNborderWidth, 0); j++;
3224 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
3225 formWidget, args, j);
3227 while (mb->name != NULL) {
3228 strcpy(menuName, "menu");
3229 strcat(menuName, mb->name);
3231 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
3234 shortName[0] = _(mb->name)[0];
3235 shortName[1] = NULLCHAR;
3236 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
3239 XtSetArg(args[j], XtNlabel, XtNewString(_(mb->name))); j++;
3242 XtSetArg(args[j], XtNborderWidth, 0); j++;
3243 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
3245 CreateMenuBarPopup(menuBar, menuName, mb);
3251 Widget CreateButtonBar(mi)
3255 Widget button, buttonBar;
3259 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3261 XtSetArg(args[j], XtNhSpace, 0); j++;
3263 XtSetArg(args[j], XtNborderWidth, 0); j++;
3264 XtSetArg(args[j], XtNvSpace, 0); j++;
3265 buttonBar = XtCreateWidget("buttonBar", boxWidgetClass,
3266 formWidget, args, j);
3268 while (mi->string != NULL) {
3271 XtSetArg(args[j], XtNinternalWidth, 2); j++;
3272 XtSetArg(args[j], XtNborderWidth, 0); j++;
3274 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string))); j++;
3275 button = XtCreateManagedWidget(mi->string, commandWidgetClass,
3276 buttonBar, args, j);
3277 XtAddCallback(button, XtNcallback,
3278 (XtCallbackProc) MenuBarSelect,
3279 (caddr_t) mi->proc);
3286 CreatePieceMenu(name, color)
3293 ChessSquare selection;
3295 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3296 boardWidget, args, 0);
3298 for (i = 0; i < PIECE_MENU_SIZE; i++) {
3299 String item = pieceMenuStrings[color][i];
3301 if (strcmp(item, "----") == 0) {
3302 entry = XtCreateManagedWidget(item, smeLineObjectClass,
3305 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3306 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3308 selection = pieceMenuTranslation[color][i];
3309 XtAddCallback(entry, XtNcallback,
3310 (XtCallbackProc) PieceMenuSelect,
3311 (caddr_t) selection);
3312 if (selection == WhitePawn || selection == BlackPawn) {
3313 XtSetArg(args[0], XtNpopupOnEntry, entry);
3314 XtSetValues(menu, args, 1);
3327 ChessSquare selection;
3329 // whitePieceMenu = CreatePieceMenu("menuW", 0);
3330 // blackPieceMenu = CreatePieceMenu("menuB", 1);
3332 // XtRegisterGrabAction(PieceMenuPopup, True,
3333 // (unsigned)(ButtonPressMask|ButtonReleaseMask),
3334 // GrabModeAsync, GrabModeAsync);
3336 // XtSetArg(args[0], XtNlabel, _("Drop"));
3337 // dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
3338 // boardWidget, args, 1);
3339 // for (i = 0; i < DROP_MENU_SIZE; i++) {
3340 // String item = dropMenuStrings[i];
3342 // if (strcmp(item, "----") == 0) {
3343 // entry = XtCreateManagedWidget(item, smeLineObjectClass,
3344 // dropMenu, NULL, 0);
3346 // XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3347 // entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3348 // dropMenu, args, 1);
3349 // selection = dropMenuTranslation[i];
3350 // XtAddCallback(entry, XtNcallback,
3351 // (XtCallbackProc) DropMenuSelect,
3352 // (caddr_t) selection);
3357 void SetupDropMenu()
3365 for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
3366 entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
3367 p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
3368 dmEnables[i].piece);
3369 XtSetSensitive(entry, p != NULL || !appData.testLegality
3370 /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
3371 && !appData.icsActive));
3373 while (p && *p++ == dmEnables[i].piece) count++;
3374 snprintf(label, sizeof(label), "%s %d", dmEnables[i].widget, count);
3376 XtSetArg(args[j], XtNlabel, label); j++;
3377 XtSetValues(entry, args, j);
3381 void PieceMenuPopup(w, event, params, num_params)
3385 Cardinal *num_params;
3388 if (event->type != ButtonPress) return;
3389 if (errorUp) ErrorPopDown();
3393 whichMenu = params[0];
3395 case IcsPlayingWhite:
3396 case IcsPlayingBlack:
3398 case MachinePlaysWhite:
3399 case MachinePlaysBlack:
3400 if (appData.testLegality &&
3401 gameInfo.variant != VariantBughouse &&
3402 gameInfo.variant != VariantCrazyhouse) return;
3404 whichMenu = "menuD";
3410 if (((pmFromX = EventToSquare(event->xbutton.x, BOARD_WIDTH)) < 0) ||
3411 ((pmFromY = EventToSquare(event->xbutton.y, BOARD_HEIGHT)) < 0)) {
3412 pmFromX = pmFromY = -1;
3416 pmFromX = BOARD_WIDTH - 1 - pmFromX;
3418 pmFromY = BOARD_HEIGHT - 1 - pmFromY;
3420 XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
3423 static void PieceMenuSelect(w, piece, junk)
3428 if (pmFromX < 0 || pmFromY < 0) return;
3429 EditPositionMenuEvent(piece, pmFromX, pmFromY);
3432 static void DropMenuSelect(w, piece, junk)
3437 if (pmFromX < 0 || pmFromY < 0) return;
3438 DropMenuEvent(piece, pmFromX, pmFromY);
3441 void WhiteClock(w, event, prms, nprms)
3447 if (gameMode == EditPosition || gameMode == IcsExamining) {
3448 SetWhiteToPlayEvent();
3449 } else if (gameMode == IcsPlayingBlack || gameMode == MachinePlaysWhite) {
3454 void BlackClock(w, event, prms, nprms)
3460 if (gameMode == EditPosition || gameMode == IcsExamining) {
3461 SetBlackToPlayEvent();
3462 } else if (gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) {
3469 * If the user selects on a border boundary, return -1; if off the board,
3470 * return -2. Otherwise map the event coordinate to the square.
3472 int EventToSquare(x, limit)
3480 if ((x % (squareSize + lineGap)) >= squareSize)
3482 x /= (squareSize + lineGap);
3488 static void do_flash_delay(msec)
3494 static void drawHighlight(file, rank, line_type)
3495 int file, rank, line_type;
3500 if (lineGap == 0 || appData.blindfold) return;
3504 x = lineGap/2 + ((BOARD_WIDTH-1)-file) *
3505 (squareSize + lineGap);
3506 y = lineGap/2 + rank * (squareSize + lineGap);
3510 x = lineGap/2 + file * (squareSize + lineGap);
3511 y = lineGap/2 + ((BOARD_HEIGHT-1)-rank) *
3512 (squareSize + lineGap);
3516 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3518 /* draw the highlight */
3519 cairo_move_to (cr, x, y);
3520 cairo_rel_line_to (cr, 0,squareSize+lineGap);
3521 cairo_rel_line_to (cr, squareSize+lineGap,0);
3522 cairo_rel_line_to (cr, 0,-squareSize-lineGap);
3523 cairo_close_path (cr);
3525 cairo_set_line_width (cr, lineGap);
3528 /* TODO: use appdata colors */
3529 case LINE_TYPE_HIGHLIGHT:
3530 cairo_set_source_rgba (cr, 1, 1, 0, 1.0);
3533 cairo_set_source_rgba (cr, 1, 0, 0, 1.0);
3535 case LINE_TYPE_NORMAL:
3537 cairo_set_source_rgba (cr, 0, 1, 0, 1.0);
3548 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
3549 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
3552 SetHighlights(fromX, fromY, toX, toY)
3553 int fromX, fromY, toX, toY;
3555 if (hi1X != fromX || hi1Y != fromY)
3557 if (hi1X >= 0 && hi1Y >= 0)
3559 drawHighlight(hi1X, hi1Y, LINE_TYPE_NORMAL);
3561 if (fromX >= 0 && fromY >= 0)
3563 drawHighlight(fromX, fromY, LINE_TYPE_HIGHLIGHT);
3566 if (hi2X != toX || hi2Y != toY)
3568 if (hi2X >= 0 && hi2Y >= 0)
3570 drawHighlight(hi2X, hi2Y, LINE_TYPE_NORMAL);
3572 if (toX >= 0 && toY >= 0)
3574 drawHighlight(toX, toY, LINE_TYPE_HIGHLIGHT);
3588 SetHighlights(-1, -1, -1, -1);
3593 SetPremoveHighlights(fromX, fromY, toX, toY)
3594 int fromX, fromY, toX, toY;
3596 if (pm1X != fromX || pm1Y != fromY)
3598 if (pm1X >= 0 && pm1Y >= 0)
3600 drawHighlight(pm1X, pm1Y, LINE_TYPE_NORMAL);
3602 if (fromX >= 0 && fromY >= 0)
3604 drawHighlight(fromX, fromY, LINE_TYPE_PRE);
3607 if (pm2X != toX || pm2Y != toY)
3609 if (pm2X >= 0 && pm2Y >= 0)
3611 drawHighlight(pm2X, pm2Y, LINE_TYPE_NORMAL);
3613 if (toX >= 0 && toY >= 0)
3615 drawHighlight(toX, toY, LINE_TYPE_PRE);
3628 ClearPremoveHighlights()
3630 SetPremoveHighlights(-1, -1, -1, -1);
3633 static void BlankSquare(x, y, color, piece, dest)
3646 pb = SVGLightSquare;
3648 case 2: /* neutral */
3650 pb = SVGNeutralSquare;
3653 gdk_draw_pixbuf(GDK_WINDOW(GUI_Board->window),NULL,pb,0,0,x,y,-1,-1, GDK_RGB_DITHER_NORMAL, 0, 0);
3657 static void DrawPiece(piece, square_color, x, y, dest)
3659 int square_color, x, y;
3662 /* redraw background, since piece might be transparent in some areas */
3663 BlankSquare(x,y,square_color,piece,dest);
3666 gdk_draw_pixbuf(GDK_WINDOW(GUI_Board->window),NULL,
3667 GDK_PIXBUF(SVGpieces[piece]),0,0,x,y,-1,-1,
3668 GDK_RGB_DITHER_NORMAL, 0, 0);
3672 /* [HR] determine square color depending on chess variant. */
3673 static int SquareColor(row, column)
3678 if (gameInfo.variant == VariantXiangqi) {
3679 if (column >= 3 && column <= 5 && row >= 0 && row <= 2) {
3681 } else if (column >= 3 && column <= 5 && row >= 7 && row <= 9) {
3683 } else if (row <= 4) {
3689 square_color = ((column + row) % 2) == 1;
3692 /* [hgm] holdings: next line makes all holdings squares light */
3693 if(column < BOARD_LEFT || column >= BOARD_RGHT) square_color = 1;
3695 return square_color;
3698 void DrawSquare(row, column, piece, do_flash)
3699 int row, column, do_flash;
3702 int square_color, x, y;
3707 /* Calculate delay in milliseconds (2-delays per complete flash) */
3708 flash_delay = 500 / appData.flashRate;
3710 /* calculate x and y coordinates from row and column */
3713 x = lineGap + ((BOARD_WIDTH-1)-column) *
3714 (squareSize + lineGap);
3715 y = lineGap + row * (squareSize + lineGap);
3719 x = lineGap + column * (squareSize + lineGap);
3720 y = lineGap + ((BOARD_HEIGHT-1)-row) *
3721 (squareSize + lineGap);
3724 square_color = SquareColor(row, column);
3726 // [HGM] holdings: blank out area between board and holdings
3727 if ( column == BOARD_LEFT-1 || column == BOARD_RGHT
3728 || (column == BOARD_LEFT-2 && row < BOARD_HEIGHT-gameInfo.holdingsSize)
3729 || (column == BOARD_RGHT+1 && row >= gameInfo.holdingsSize) )
3731 BlankSquare(x, y, 2, EmptySquare, xBoardWindow);
3733 // [HGM] print piece counts next to holdings
3734 string[1] = NULLCHAR;
3737 cairo_text_extents_t extents;
3742 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3744 string[0] = '0' + piece;
3746 /* TODO this has to go into the font-selection */
3747 cairo_select_font_face (cr, "Sans",
3748 CAIRO_FONT_SLANT_NORMAL,
3749 CAIRO_FONT_WEIGHT_NORMAL);
3751 cairo_set_font_size (cr, 12.0);
3752 cairo_text_extents (cr, string, &extents);
3754 if (column == (flipView ? BOARD_LEFT-1 : BOARD_RGHT) )
3756 xpos= x + squareSize - extents.width - 2;
3757 ypos= y + extents.y_bearing + 1;
3759 if (column == (flipView ? BOARD_RGHT : BOARD_LEFT-1) && piece > 1)
3762 ypos = y + extents.y_bearing + 1;
3765 /* TODO mono mode? */
3766 cairo_move_to (cr, xpos, ypos);
3767 cairo_text_path (cr, string);
3768 cairo_set_source_rgb (cr, 1.0, 1.0, 1);
3769 cairo_fill_preserve (cr);
3770 cairo_set_source_rgb (cr, 0, 0, 0);
3771 cairo_set_line_width (cr, 0.1);
3780 /* square on the board */
3781 if (piece == EmptySquare || appData.blindfold)
3783 BlankSquare(x, y, square_color, piece, xBoardWindow);
3787 if (do_flash && appData.flashCount > 0)
3789 for (i=0; i<appData.flashCount; ++i)
3792 DrawPiece(piece, square_color, x, y, xBoardWindow);
3793 do_flash_delay(flash_delay);
3795 BlankSquare(x, y, square_color, piece, xBoardWindow);
3796 do_flash_delay(flash_delay);
3799 DrawPiece(piece, square_color, x, y, xBoardWindow);
3803 /* show coordinates if necessary */
3804 if(appData.showCoords)
3806 cairo_text_extents_t extents;
3810 /* TODO this has to go into the font-selection */
3811 cairo_select_font_face (cr, "Sans",
3812 CAIRO_FONT_SLANT_NORMAL,
3813 CAIRO_FONT_WEIGHT_NORMAL);
3814 cairo_set_font_size (cr, 12.0);
3816 string[1] = NULLCHAR;
3819 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3821 if (row == (flipView ? BOARD_HEIGHT-1 : 0) &&
3822 column >= BOARD_LEFT && column < BOARD_RGHT)
3824 string[0] = 'a' + column - BOARD_LEFT;
3825 cairo_text_extents (cr, string, &extents);
3827 xpos = x + squareSize - extents.width - 2;
3828 ypos = y + squareSize - extents.height - extents.y_bearing - 1;
3830 if (appData.monoMode)
3837 cairo_move_to (cr, xpos, ypos);
3838 cairo_text_path (cr, string);
3839 cairo_set_source_rgb (cr, 0.0, 0.0, 0);
3840 cairo_fill_preserve (cr);
3841 cairo_set_source_rgb (cr, 0, 1.0, 0);
3842 cairo_set_line_width (cr, 0.1);
3845 if ( column == (flipView ? BOARD_RGHT-1 : BOARD_LEFT))
3848 string[0] = ONE + row;
3849 cairo_text_extents (cr, string, &extents);
3852 ypos = y + extents.height + 1;
3854 if (appData.monoMode)
3861 cairo_move_to (cr, xpos, ypos);
3862 cairo_text_path (cr, string);
3863 cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
3864 cairo_fill_preserve (cr);
3865 cairo_set_source_rgb (cr, 0, 0, 1.0);
3866 cairo_set_line_width (cr, 0.1);
3878 /* Returns 1 if there are "too many" differences between b1 and b2
3879 (i.e. more than 1 move was made) */
3880 static int too_many_diffs(b1, b2)
3886 for (i=0; i<BOARD_HEIGHT; ++i) {
3887 for (j=0; j<BOARD_WIDTH; ++j) {
3888 if (b1[i][j] != b2[i][j]) {
3889 if (++c > 4) /* Castling causes 4 diffs */
3898 /* Matrix describing castling maneuvers */
3899 /* Row, ColRookFrom, ColKingFrom, ColRookTo, ColKingTo */
3900 static int castling_matrix[4][5] = {
3901 { 0, 0, 4, 3, 2 }, /* 0-0-0, white */
3902 { 0, 7, 4, 5, 6 }, /* 0-0, white */
3903 { 7, 0, 4, 3, 2 }, /* 0-0-0, black */
3904 { 7, 7, 4, 5, 6 } /* 0-0, black */
3907 /* Checks whether castling occurred. If it did, *rrow and *rcol
3908 are set to the destination (row,col) of the rook that moved.
3910 Returns 1 if castling occurred, 0 if not.
3912 Note: Only handles a max of 1 castling move, so be sure
3913 to call too_many_diffs() first.
3915 static int check_castle_draw(newb, oldb, rrow, rcol)
3922 /* For each type of castling... */
3923 for (i=0; i<4; ++i) {
3924 r = castling_matrix[i];
3926 /* Check the 4 squares involved in the castling move */
3928 for (j=1; j<=4; ++j) {
3929 if (newb[r[0]][r[j]] == oldb[r[0]][r[j]]) {
3936 /* All 4 changed, so it must be a castling move */
3945 static int damage[BOARD_SIZE][BOARD_SIZE];
3948 * event handler for redrawing the board
3950 void DrawPosition( repaint, board)
3951 /*Boolean*/int repaint;
3955 static int lastFlipView = 0;
3956 static int lastBoardValid = 0;
3957 static Board lastBoard;
3960 if (board == NULL) {
3961 if (!lastBoardValid) return;
3964 if (!lastBoardValid || lastFlipView != flipView) {
3965 // XtSetArg(args[0], XtNleftBitmap, (flipView ? xMarkPixmap : None));
3966 // XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flip View"),
3971 * It would be simpler to clear the window with XClearWindow()
3972 * but this causes a very distracting flicker.
3975 if (!repaint && lastBoardValid && lastFlipView == flipView)
3977 /* If too much changes (begin observing new game, etc.), don't
3979 do_flash = too_many_diffs(board, lastBoard) ? 0 : 1;
3981 /* Special check for castling so we don't flash both the king
3982 and the rook (just flash the king). */
3985 if (check_castle_draw(board, lastBoard, &rrow, &rcol))
3987 /* Draw rook with NO flashing. King will be drawn flashing later */
3988 DrawSquare(rrow, rcol, board[rrow][rcol], 0);
3989 lastBoard[rrow][rcol] = board[rrow][rcol];
3993 /* First pass -- Draw (newly) empty squares and repair damage.
3994 This prevents you from having a piece show up twice while it
3995 is flashing on its new square */
3996 for (i = 0; i < BOARD_HEIGHT; i++)
3997 for (j = 0; j < BOARD_WIDTH; j++)
3998 if ((board[i][j] != lastBoard[i][j] && board[i][j] == EmptySquare)
4001 DrawSquare(i, j, board[i][j], 0);
4002 damage[i][j] = False;
4005 /* Second pass -- Draw piece(s) in new position and flash them */
4006 for (i = 0; i < BOARD_HEIGHT; i++)
4007 for (j = 0; j < BOARD_WIDTH; j++)
4008 if (board[i][j] != lastBoard[i][j])
4010 DrawSquare(i, j, board[i][j], do_flash);
4022 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
4024 cairo_set_line_width (cr, lineGap);
4026 /* TODO: use appdata colors */
4027 cairo_set_source_rgba (cr, 0, 1, 0, 1.0);
4031 for (i = 0; i < BOARD_HEIGHT + 1; i++)
4034 x2 = lineGap + BOARD_WIDTH * (squareSize + lineGap);
4035 y1 = y2 = lineGap / 2 + (i * (squareSize + lineGap));
4037 cairo_move_to (cr, x1, y1);
4038 cairo_rel_line_to (cr, x2,0);
4042 for (j = 0; j < BOARD_WIDTH + 1; j++)
4045 y2 = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
4046 x1 = x2 = lineGap / 2 + (j * (squareSize + lineGap));
4048 cairo_move_to (cr, x1, y1);
4049 cairo_rel_line_to (cr, 0, y2);
4058 for (i = 0; i < BOARD_HEIGHT; i++)
4059 for (j = 0; j < BOARD_WIDTH; j++)
4061 DrawSquare(i, j, board[i][j], 0);
4062 damage[i][j] = False;
4066 CopyBoard(lastBoard, board);
4068 lastFlipView = flipView;
4070 /* Draw highlights */
4071 if (pm1X >= 0 && pm1Y >= 0)
4073 drawHighlight(pm1X, pm1Y, LINE_TYPE_PRE);
4075 if (pm2X >= 0 && pm2Y >= 0)
4077 drawHighlight(pm2X, pm2Y, LINE_TYPE_PRE);
4079 if (hi1X >= 0 && hi1Y >= 0)
4081 drawHighlight(hi1X, hi1Y, LINE_TYPE_HIGHLIGHT);
4083 if (hi2X >= 0 && hi2Y >= 0)
4085 drawHighlight(hi2X, hi2Y, LINE_TYPE_HIGHLIGHT);
4088 /* If piece being dragged around board, must redraw that too */
4095 * event handler for parsing user moves
4097 // [HGM] This routine will need quite some reworking. Although the backend still supports the old
4098 // way of doing things, by calling UserMoveEvent() to test the legality of the move and then perform
4099 // it at the end, and doing all kind of preliminary tests here (e.g. to weed out self-captures), it
4100 // should be made to use the new way, of calling UserMoveTest early to determine the legality of the
4101 // move, (which will weed out the illegal selfcaptures and moves into the holdings, and flag promotions),
4102 // and at the end FinishMove() to perform the move after optional promotion popups.
4103 // For now I patched it to allow self-capture with King, and suppress clicks between board and holdings.
4104 void HandleUserMove(w, event, prms, nprms)
4111 Boolean saveAnimate;
4112 static int second = 0;
4114 if (w != boardWidget || errorExitStatus != -1) return;
4116 if (event->type == ButtonPress) ErrorPopDown();
4119 if (event->type == ButtonPress) {
4120 // XtPopdown(promotionShell);
4121 // XtDestroyWidget(promotionShell);
4122 promotionUp = False;
4130 x = EventToSquare(event->xbutton.x, BOARD_WIDTH);
4131 y = EventToSquare(event->xbutton.y, BOARD_HEIGHT);
4132 if (!flipView && y >= 0) {
4133 y = BOARD_HEIGHT - 1 - y;
4135 if (flipView && x >= 0) {
4136 x = BOARD_WIDTH - 1 - x;
4139 /* [HGM] holdings: next 5 lines: ignore all clicks between board and holdings */
4140 if(event->type == ButtonPress
4141 && ( x == BOARD_LEFT-1 ||
4143 (x == BOARD_LEFT-2 && y < BOARD_HEIGHT-gameInfo.holdingsSize ) ||
4144 (x == BOARD_RGHT+1 && y >= gameInfo.holdingsSize)) )
4148 if (event->type == ButtonPress) {
4150 if (OKToStartUserMove(x, y)) {
4154 DragPieceBegin(event->xbutton.x, event->xbutton.y);
4155 if (appData.highlightDragging) {
4156 SetHighlights(x, y, -1, -1);
4164 if (event->type == ButtonPress && gameMode != EditPosition &&
4170 /* Check if clicking again on the same color piece */
4171 fromP = boards[currentMove][fromY][fromX];
4172 toP = boards[currentMove][y][x];
4173 frc = gameInfo.variant == VariantFischeRandom || gameInfo.variant == VariantCapaRandom;
4174 if ((WhitePawn <= fromP && fromP <= WhiteKing && // [HGM] this test should go, as UserMoveTest now does it.
4175 WhitePawn <= toP && toP <= WhiteKing &&
4176 !(fromP == WhiteKing && toP == WhiteRook && frc)) ||
4177 (BlackPawn <= fromP && fromP <= BlackKing &&
4178 BlackPawn <= toP && toP <= BlackKing &&
4179 !(fromP == BlackKing && toP == BlackRook && frc))) {
4180 /* Clicked again on same color piece -- changed his mind */
4181 second = (x == fromX && y == fromY);
4182 if (appData.highlightDragging) {
4183 SetHighlights(x, y, -1, -1);
4187 if (OKToStartUserMove(x, y)) {
4190 DragPieceBegin(event->xbutton.x, event->xbutton.y);
4196 if (event->type == ButtonRelease && x == fromX && y == fromY) {
4197 DragPieceEnd(event->xbutton.x, event->xbutton.y);
4198 if (appData.animateDragging) {
4199 /* Undo animation damage if any */
4200 DrawPosition(FALSE, NULL);
4203 /* Second up/down in same square; just abort move */
4208 ClearPremoveHighlights();
4210 /* First upclick in same square; start click-click mode */
4211 SetHighlights(x, y, -1, -1);
4216 /* Completed move */
4219 saveAnimate = appData.animate;
4220 if (event->type == ButtonPress) {
4221 /* Finish clickclick move */
4222 if (appData.animate || appData.highlightLastMove) {
4223 SetHighlights(fromX, fromY, toX, toY);
4228 /* Finish drag move */
4229 if (appData.highlightLastMove) {
4230 SetHighlights(fromX, fromY, toX, toY);
4234 DragPieceEnd(event->xbutton.x, event->xbutton.y);
4235 /* Don't animate move and drag both */
4236 appData.animate = FALSE;
4238 if (IsPromotion(fromX, fromY, toX, toY)) {
4239 if (appData.alwaysPromoteToQueen) {
4240 UserMoveEvent(fromX, fromY, toX, toY, 'q');
4241 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
4242 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
4245 SetHighlights(fromX, fromY, toX, toY);
4249 UserMoveEvent(fromX, fromY, toX, toY, NULLCHAR);
4250 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
4251 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
4254 appData.animate = saveAnimate;
4255 if (appData.animate || appData.animateDragging) {
4256 /* Undo animation damage if needed */
4257 DrawPosition(FALSE, NULL);
4261 void AnimateUserMove (Widget w, XEvent * event,
4262 String * params, Cardinal * nParams)
4264 DragPieceMove(event->xmotion.x, event->xmotion.y);
4267 Widget CommentCreate(name, text, mutable, callback, lines)
4269 int /*Boolean*/ mutable;
4270 XtCallbackProc callback;
4274 Widget shell, layout, form, edit, b_ok, b_cancel, b_clear, b_close, b_edit;
4279 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4280 XtGetValues(boardWidget, args, j);
4283 XtSetArg(args[j], XtNresizable, True); j++;
4286 XtCreatePopupShell(name, topLevelShellWidgetClass,
4287 shellWidget, args, j);
4290 XtCreatePopupShell(name, transientShellWidgetClass,
4291 shellWidget, args, j);
4294 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
4295 layoutArgs, XtNumber(layoutArgs));
4297 XtCreateManagedWidget("form", formWidgetClass, layout,
4298 formArgs, XtNumber(formArgs));
4302 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
4303 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
4305 XtSetArg(args[j], XtNstring, text); j++;
4306 XtSetArg(args[j], XtNtop, XtChainTop); j++;
4307 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4308 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4309 XtSetArg(args[j], XtNright, XtChainRight); j++;
4310 XtSetArg(args[j], XtNresizable, True); j++;
4311 XtSetArg(args[j], XtNwidth, bw_width); j++; /*force wider than buttons*/
4313 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
4315 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
4316 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
4318 XtSetArg(args[j], XtNautoFill, True); j++;
4319 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
4321 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
4325 XtSetArg(args[j], XtNfromVert, edit); j++;
4326 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4327 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4328 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4329 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4331 XtCreateManagedWidget(_("ok"), commandWidgetClass, form, args, j);
4332 XtAddCallback(b_ok, XtNcallback, callback, (XtPointer) 0);
4335 XtSetArg(args[j], XtNfromVert, edit); j++;
4336 XtSetArg(args[j], XtNfromHoriz, b_ok); j++;
4337 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4338 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4339 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4340 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4342 XtCreateManagedWidget(_("cancel"), commandWidgetClass, form, args, j);
4343 XtAddCallback(b_cancel, XtNcallback, callback, (XtPointer) 0);
4346 XtSetArg(args[j], XtNfromVert, edit); j++;
4347 XtSetArg(args[j], XtNfromHoriz, b_cancel); j++;
4348 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4349 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4350 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4351 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4353 XtCreateManagedWidget(_("clear"), commandWidgetClass, form, args, j);
4354 XtAddCallback(b_clear, XtNcallback, callback, (XtPointer) 0);
4357 XtSetArg(args[j], XtNfromVert, edit); j++;
4358 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4359 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4360 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4361 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4363 XtCreateManagedWidget(_("close"), commandWidgetClass, form, args, j);
4364 XtAddCallback(b_close, XtNcallback, callback, (XtPointer) 0);
4367 XtSetArg(args[j], XtNfromVert, edit); j++;
4368 XtSetArg(args[j], XtNfromHoriz, b_close); j++;
4369 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4370 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4371 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4372 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4374 XtCreateManagedWidget(_("edit"), commandWidgetClass, form, args, j);
4375 XtAddCallback(b_edit, XtNcallback, callback, (XtPointer) 0);
4378 XtRealizeWidget(shell);
4380 if (commentX == -1) {
4383 Dimension pw_height;
4384 Dimension ew_height;
4387 XtSetArg(args[j], XtNheight, &ew_height); j++;
4388 XtGetValues(edit, args, j);
4391 XtSetArg(args[j], XtNheight, &pw_height); j++;
4392 XtGetValues(shell, args, j);
4393 commentH = pw_height + (lines - 1) * ew_height;
4394 commentW = bw_width - 16;
4396 XSync(xDisplay, False);
4398 /* This code seems to tickle an X bug if it is executed too soon
4399 after xboard starts up. The coordinates get transformed as if
4400 the main window was positioned at (0, 0).
4402 XtTranslateCoords(shellWidget,
4403 (bw_width - commentW) / 2, 0 - commentH / 2,
4404 &commentX, &commentY);
4406 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
4407 RootWindowOfScreen(XtScreen(shellWidget)),
4408 (bw_width - commentW) / 2, 0 - commentH / 2,
4413 if (commentY < 0) commentY = 0; /*avoid positioning top offscreen*/
4416 XtSetArg(args[j], XtNheight, commentH); j++;
4417 XtSetArg(args[j], XtNwidth, commentW); j++;
4418 XtSetArg(args[j], XtNx, commentX); j++;
4419 XtSetArg(args[j], XtNy, commentY); j++;
4420 XtSetValues(shell, args, j);
4421 XtSetKeyboardFocus(shell, edit);
4426 /* Used for analysis window and ICS input window */
4427 Widget MiscCreate(name, text, mutable, callback, lines)
4429 int /*Boolean*/ mutable;
4430 XtCallbackProc callback;
4434 Widget shell, layout, form, edit;
4436 Dimension bw_width, pw_height, ew_height, w, h;
4442 XtSetArg(args[j], XtNresizable, True); j++;
4445 XtCreatePopupShell(name, topLevelShellWidgetClass,
4446 shellWidget, args, j);
4449 XtCreatePopupShell(name, transientShellWidgetClass,
4450 shellWidget, args, j);
4453 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
4454 layoutArgs, XtNumber(layoutArgs));
4456 XtCreateManagedWidget("form", formWidgetClass, layout,
4457 formArgs, XtNumber(formArgs));
4461 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
4462 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
4464 XtSetArg(args[j], XtNstring, text); j++;
4465 XtSetArg(args[j], XtNtop, XtChainTop); j++;
4466 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4467 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4468 XtSetArg(args[j], XtNright, XtChainRight); j++;
4469 XtSetArg(args[j], XtNresizable, True); j++;
4471 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
4473 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
4474 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
4476 XtSetArg(args[j], XtNautoFill, True); j++;
4477 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
4479 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
4481 XtRealizeWidget(shell);
4484 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4485 XtGetValues(boardWidget, args, j);
4488 XtSetArg(args[j], XtNheight, &ew_height); j++;
4489 XtGetValues(edit, args, j);
4492 XtSetArg(args[j], XtNheight, &pw_height); j++;
4493 XtGetValues(shell, args, j);
4494 h = pw_height + (lines - 1) * ew_height;
4497 XSync(xDisplay, False);
4499 /* This code seems to tickle an X bug if it is executed too soon
4500 after xboard starts up. The coordinates get transformed as if
4501 the main window was positioned at (0, 0).
4503 XtTranslateCoords(shellWidget, (bw_width - w) / 2, 0 - h / 2, &x, &y);
4505 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
4506 RootWindowOfScreen(XtScreen(shellWidget)),
4507 (bw_width - w) / 2, 0 - h / 2, &xx, &yy, &junk);
4511 if (y < 0) y = 0; /*avoid positioning top offscreen*/
4514 XtSetArg(args[j], XtNheight, h); j++;
4515 XtSetArg(args[j], XtNwidth, w); j++;
4516 XtSetArg(args[j], XtNx, x); j++;
4517 XtSetArg(args[j], XtNy, y); j++;
4518 XtSetValues(shell, args, j);
4524 static int savedIndex; /* gross that this is global */
4526 void EditCommentPopUp(index, title, text)
4535 if (text == NULL) text = "";
4537 if (editShell == NULL) {
4539 CommentCreate(title, text, True, EditCommentCallback, 4);
4540 XtRealizeWidget(editShell);
4541 CatchDeleteWindow(editShell, "EditCommentPopDown");
4543 edit = XtNameToWidget(editShell, "*form.text");
4545 XtSetArg(args[j], XtNstring, text); j++;
4546 XtSetValues(edit, args, j);
4548 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4549 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4550 XtSetValues(editShell, args, j);
4553 XtPopup(editShell, XtGrabNone);
4557 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
4558 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
4562 void EditCommentCallback(w, client_data, call_data)
4564 XtPointer client_data, call_data;
4572 XtSetArg(args[j], XtNlabel, &name); j++;
4573 XtGetValues(w, args, j);
4575 if (strcmp(name, _("ok")) == 0) {
4576 edit = XtNameToWidget(editShell, "*form.text");
4578 XtSetArg(args[j], XtNstring, &val); j++;
4579 XtGetValues(edit, args, j);
4580 ReplaceComment(savedIndex, val);
4581 EditCommentPopDown();
4582 } else if (strcmp(name, _("cancel")) == 0) {
4583 EditCommentPopDown();
4584 } else if (strcmp(name, _("clear")) == 0) {
4585 edit = XtNameToWidget(editShell, "*form.text");
4586 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
4587 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
4591 void EditCommentPopDown()
4596 if (!editUp) return;
4598 XtSetArg(args[j], XtNx, &commentX); j++;
4599 XtSetArg(args[j], XtNy, &commentY); j++;
4600 XtSetArg(args[j], XtNheight, &commentH); j++;
4601 XtSetArg(args[j], XtNwidth, &commentW); j++;
4602 XtGetValues(editShell, args, j);
4603 XtPopdown(editShell);
4606 XtSetArg(args[j], XtNleftBitmap, None); j++;
4607 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
4611 void ICSInputBoxPopUp()
4616 char *title = _("ICS Input");
4619 if (ICSInputShell == NULL) {
4620 ICSInputShell = MiscCreate(title, "", True, NULL, 1);
4621 tr = XtParseTranslationTable(ICSInputTranslations);
4622 edit = XtNameToWidget(ICSInputShell, "*form.text");
4623 XtOverrideTranslations(edit, tr);
4624 XtRealizeWidget(ICSInputShell);
4625 CatchDeleteWindow(ICSInputShell, "ICSInputBoxPopDown");
4628 edit = XtNameToWidget(ICSInputShell, "*form.text");
4630 XtSetArg(args[j], XtNstring, ""); j++;
4631 XtSetValues(edit, args, j);
4633 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4634 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4635 XtSetValues(ICSInputShell, args, j);
4638 XtPopup(ICSInputShell, XtGrabNone);
4639 XtSetKeyboardFocus(ICSInputShell, edit);
4641 ICSInputBoxUp = True;
4643 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
4644 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
4648 void ICSInputSendText()
4655 edit = XtNameToWidget(ICSInputShell, "*form.text");
4657 XtSetArg(args[j], XtNstring, &val); j++;
4658 XtGetValues(edit, args, j);
4659 SendMultiLineToICS(val);
4660 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
4661 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
4664 void ICSInputBoxPopDown()
4669 if (!ICSInputBoxUp) return;
4671 XtPopdown(ICSInputShell);
4672 ICSInputBoxUp = False;
4674 XtSetArg(args[j], XtNleftBitmap, None); j++;
4675 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
4679 void CommentPopUp(title, text)
4686 if (commentShell == NULL) {
4688 CommentCreate(title, text, False, CommentCallback, 4);
4689 XtRealizeWidget(commentShell);
4690 CatchDeleteWindow(commentShell, "CommentPopDown");
4692 edit = XtNameToWidget(commentShell, "*form.text");
4694 XtSetArg(args[j], XtNstring, text); j++;
4695 XtSetValues(edit, args, j);
4697 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4698 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4699 XtSetValues(commentShell, args, j);
4702 XtPopup(commentShell, XtGrabNone);
4703 XSync(xDisplay, False);
4708 void AnalysisPopUp(title, text)
4715 if (analysisShell == NULL) {
4716 analysisShell = MiscCreate(title, text, False, NULL, 4);
4717 XtRealizeWidget(analysisShell);
4718 CatchDeleteWindow(analysisShell, "AnalysisPopDown");
4721 edit = XtNameToWidget(analysisShell, "*form.text");
4723 XtSetArg(args[j], XtNstring, text); j++;
4724 XtSetValues(edit, args, j);
4726 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4727 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4728 XtSetValues(analysisShell, args, j);
4732 XtPopup(analysisShell, XtGrabNone);
4734 XSync(xDisplay, False);
4739 void CommentCallback(w, client_data, call_data)
4741 XtPointer client_data, call_data;
4748 XtSetArg(args[j], XtNlabel, &name); j++;
4749 XtGetValues(w, args, j);
4751 if (strcmp(name, _("close")) == 0) {
4753 } else if (strcmp(name, _("edit")) == 0) {
4760 void CommentPopDown()
4765 if (!commentUp) return;
4767 XtSetArg(args[j], XtNx, &commentX); j++;
4768 XtSetArg(args[j], XtNy, &commentY); j++;
4769 XtSetArg(args[j], XtNwidth, &commentW); j++;
4770 XtSetArg(args[j], XtNheight, &commentH); j++;
4771 XtGetValues(commentShell, args, j);
4772 XtPopdown(commentShell);
4773 XSync(xDisplay, False);
4777 void AnalysisPopDown()
4779 if (!analysisUp) return;
4780 XtPopdown(analysisShell);
4781 XSync(xDisplay, False);
4783 if (appData.icsEngineAnalyze) ExitAnalyzeMode(); /* [DM] icsEngineAnalyze */
4787 void FileNamePopUp(label, def, proc, openMode)
4794 Widget popup, layout, dialog, edit;
4800 fileProc = proc; /* I can't see a way not */
4801 fileOpenMode = openMode; /* to use globals here */
4804 XtSetArg(args[i], XtNresizable, True); i++;
4805 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
4806 XtSetArg(args[i], XtNtitle, XtNewString(_("File name prompt"))); i++;
4807 fileNameShell = popup =
4808 XtCreatePopupShell("File name prompt", transientShellWidgetClass,
4809 shellWidget, args, i);
4812 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
4813 layoutArgs, XtNumber(layoutArgs));
4816 XtSetArg(args[i], XtNlabel, label); i++;
4817 XtSetArg(args[i], XtNvalue, def); i++;
4818 XtSetArg(args[i], XtNborderWidth, 0); i++;
4819 dialog = XtCreateManagedWidget("fileName", dialogWidgetClass,
4822 XawDialogAddButton(dialog, _("ok"), FileNameCallback, (XtPointer) dialog);
4823 XawDialogAddButton(dialog, _("cancel"), FileNameCallback,
4824 (XtPointer) dialog);
4826 XtRealizeWidget(popup);
4827 CatchDeleteWindow(popup, "FileNamePopDown");
4829 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
4830 &x, &y, &win_x, &win_y, &mask);
4832 XtSetArg(args[0], XtNx, x - 10);
4833 XtSetArg(args[1], XtNy, y - 30);
4834 XtSetValues(popup, args, 2);
4836 XtPopup(popup, XtGrabExclusive);
4839 edit = XtNameToWidget(dialog, "*value");
4840 XtSetKeyboardFocus(popup, edit);
4843 void FileNamePopDown()
4845 if (!filenameUp) return;
4846 XtPopdown(fileNameShell);
4847 XtDestroyWidget(fileNameShell);
4852 void FileNameCallback(w, client_data, call_data)
4854 XtPointer client_data, call_data;
4859 XtSetArg(args[0], XtNlabel, &name);
4860 XtGetValues(w, args, 1);
4862 if (strcmp(name, _("cancel")) == 0) {
4867 FileNameAction(w, NULL, NULL, NULL);
4870 void FileNameAction(w, event, prms, nprms)
4882 name = XawDialogGetValueString(w = XtParent(w));
4884 if ((name != NULL) && (*name != NULLCHAR)) {
4886 XtPopdown(w = XtParent(XtParent(w)));
4890 p = strrchr(buf, ' ');
4897 fullname = ExpandPathName(buf);
4899 ErrorPopUp(_("Error"), _("Can't open file"), FALSE);
4902 f = fopen(fullname, fileOpenMode);
4904 DisplayError(_("Failed to open file"), errno);
4906 (void) (*fileProc)(f, index, buf);
4913 XtPopdown(w = XtParent(XtParent(w)));
4919 void PromotionPopUp()
4922 Widget dialog, layout;
4924 Dimension bw_width, pw_width;
4928 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4929 XtGetValues(boardWidget, args, j);
4932 XtSetArg(args[j], XtNresizable, True); j++;
4933 XtSetArg(args[j], XtNtitle, XtNewString(_("Promotion"))); j++;
4935 XtCreatePopupShell("Promotion", transientShellWidgetClass,
4936 shellWidget, args, j);
4938 XtCreateManagedWidget(layoutName, formWidgetClass, promotionShell,
4939 layoutArgs, XtNumber(layoutArgs));
4942 XtSetArg(args[j], XtNlabel, _("Promote to what?")); j++;
4943 XtSetArg(args[j], XtNborderWidth, 0); j++;
4944 dialog = XtCreateManagedWidget("promotion", dialogWidgetClass,
4947 if(gameInfo.variant != VariantShogi) {
4948 XawDialogAddButton(dialog, _("Queen"), PromotionCallback,
4949 (XtPointer) dialog);
4950 XawDialogAddButton(dialog, _("Rook"), PromotionCallback,
4951 (XtPointer) dialog);
4952 XawDialogAddButton(dialog, _("Bishop"), PromotionCallback,
4953 (XtPointer) dialog);
4954 XawDialogAddButton(dialog, _("Knight"), PromotionCallback,
4955 (XtPointer) dialog);
4956 if (!appData.testLegality || gameInfo.variant == VariantSuicide ||
4957 gameInfo.variant == VariantGiveaway) {
4958 XawDialogAddButton(dialog, _("King"), PromotionCallback,
4959 (XtPointer) dialog);
4961 if(gameInfo.variant == VariantCapablanca ||
4962 gameInfo.variant == VariantGothic ||
4963 gameInfo.variant == VariantCapaRandom) {
4964 XawDialogAddButton(dialog, _("Archbishop"), PromotionCallback,
4965 (XtPointer) dialog);
4966 XawDialogAddButton(dialog, _("Chancellor"), PromotionCallback,
4967 (XtPointer) dialog);
4969 } else // [HGM] shogi
4971 XawDialogAddButton(dialog, _("Promote"), PromotionCallback,
4972 (XtPointer) dialog);
4973 XawDialogAddButton(dialog, _("Defer"), PromotionCallback,
4974 (XtPointer) dialog);
4976 XawDialogAddButton(dialog, _("cancel"), PromotionCallback,
4977 (XtPointer) dialog);
4979 XtRealizeWidget(promotionShell);
4980 CatchDeleteWindow(promotionShell, "PromotionPopDown");
4983 XtSetArg(args[j], XtNwidth, &pw_width); j++;
4984 XtGetValues(promotionShell, args, j);
4986 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
4987 lineGap + squareSize/3 +
4988 ((toY == BOARD_HEIGHT-1) ^ (flipView) ?
4989 0 : 6*(squareSize + lineGap)), &x, &y);
4992 XtSetArg(args[j], XtNx, x); j++;
4993 XtSetArg(args[j], XtNy, y); j++;
4994 XtSetValues(promotionShell, args, j);
4996 XtPopup(promotionShell, XtGrabNone);
5001 void PromotionPopDown()
5003 if (!promotionUp) return;
5004 XtPopdown(promotionShell);
5005 XtDestroyWidget(promotionShell);
5006 promotionUp = False;
5009 void PromotionCallback(w, client_data, call_data)
5011 XtPointer client_data, call_data;
5017 XtSetArg(args[0], XtNlabel, &name);
5018 XtGetValues(w, args, 1);
5022 if (fromX == -1) return;
5024 if (strcmp(name, _("cancel")) == 0) {
5028 } else if (strcmp(name, _("Knight")) == 0) {
5030 } else if (strcmp(name, _("Promote")) == 0) {
5032 } else if (strcmp(name, _("Defer")) == 0) {
5035 promoChar = ToLower(name[0]);
5038 UserMoveEvent(fromX, fromY, toX, toY, promoChar);
5040 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
5041 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
5046 void ErrorCallback(w, client_data, call_data)
5048 XtPointer client_data, call_data;
5051 XtPopdown(w = XtParent(XtParent(XtParent(w))));
5053 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5059 if (!errorUp) return;
5063 gtk_widget_destroy(GTK_WIDGET(GUI_Error));
5065 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5070 void ErrorPopUp(title, label, modal)
5071 char *title, *label;
5074 GUI_Error = gtk_message_dialog_new(GTK_WINDOW(GUI_Window),
5075 GTK_DIALOG_DESTROY_WITH_PARENT,
5080 gtk_window_set_title(GTK_WINDOW(GUI_Error),(gchar *) title);
5083 gtk_dialog_run(GTK_DIALOG(GUI_Error));
5084 gtk_widget_destroy(GTK_WIDGET(GUI_Error));
5088 g_signal_connect_swapped (GUI_Error, "response",
5089 G_CALLBACK (ErrorPopDownProc),
5092 gtk_widget_show(GTK_WIDGET(GUI_Error));
5098 /* Disable all user input other than deleting the window */
5099 static int frozen = 0;
5103 /* Grab by a widget that doesn't accept input */
5104 // XtAddGrab(messageWidget, TRUE, FALSE);
5108 /* Undo a FreezeUI */
5111 if (!frozen) return;
5112 // XtRemoveGrab(messageWidget);
5116 char *ModeToWidgetName(mode)
5120 case BeginningOfGame:
5121 if (appData.icsActive)
5122 return "menuMode.ICS Client";
5123 else if (appData.noChessProgram ||
5124 *appData.cmailGameName != NULLCHAR)
5125 return "menuMode.Edit Game";
5127 return "menuMode.Machine Black";
5128 case MachinePlaysBlack:
5129 return "menuMode.Machine Black";
5130 case MachinePlaysWhite:
5131 return "menuMode.Machine White";
5133 return "menuMode.Analysis Mode";
5135 return "menuMode.Analyze File";
5136 case TwoMachinesPlay:
5137 return "menuMode.Two Machines";
5139 return "menuMode.Edit Game";
5140 case PlayFromGameFile:
5141 return "menuFile.Load Game";
5143 return "menuMode.Edit Position";
5145 return "menuMode.Training";
5146 case IcsPlayingWhite:
5147 case IcsPlayingBlack:
5151 return "menuMode.ICS Client";
5158 void ModeHighlight()
5160 static int oldPausing = FALSE;
5161 static GameMode oldmode = (GameMode) -1;
5164 // todo this toggling of the pause button doesn't seem to work?
5165 // e.g. select pause from buttonbar doesn't activate menumode.pause
5167 // if (!boardWidget || !XtIsRealized(boardWidget)) return;
5169 if (pausing != oldPausing) {
5170 oldPausing = pausing;
5171 gtk_button_set_relief(GTK_BUTTON (gtk_builder_get_object (builder, "menuMode.Pause")),pausing?GTK_RELIEF_NORMAL:GTK_RELIEF_NONE);
5172 /* toggle background color in showbuttonbar */
5173 if (appData.showButtonBar) {
5175 gtk_button_pressed(GTK_BUTTON (gtk_builder_get_object (builder, "buttonbar.Pause")));
5177 gtk_button_released(GTK_BUTTON (gtk_builder_get_object (builder, "buttonbar.Pause")));
5182 wname = ModeToWidgetName(oldmode);
5184 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, wname)),True);
5188 /* Maybe all the enables should be handled here, not just this one */
5189 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuMode.Training")),
5190 gameMode == Training || gameMode == PlayFromGameFile);
5195 * Button/menu procedures
5198 int LoadGamePopUp(f, gameNumber, title)
5203 cmailMsgLoaded = FALSE;
5205 if (gameNumber == 0)
5207 int error = GameListBuild(f);
5211 DisplayError(_("Cannot build game list"), error);
5213 else if (!ListEmpty(&gameList)
5214 && ((ListGame *) gameList.tailPred)->number > 1)
5216 GameListPopUp(f, title);
5224 return LoadGame(f, gameNumber, title, FALSE);
5228 void LoadNextPositionProc(w, event, prms, nprms)
5237 void LoadPrevPositionProc(w, event, prms, nprms)
5246 void ReloadPositionProc(w, event, prms, nprms)
5255 void LoadPositionProc(w, event, prms, nprms)
5261 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
5264 FileNamePopUp(_("Load position file name?"), "", LoadPosition, "rb");
5267 void SaveGameProc(w, event, prms, nprms)
5273 FileNamePopUp(_("Save game file name?"),
5274 DefaultFileName(appData.oldSaveStyle ? "game" : "pgn"),
5278 void SavePositionProc(w, event, prms, nprms)
5284 FileNamePopUp(_("Save position file name?"),
5285 DefaultFileName(appData.oldSaveStyle ? "pos" : "fen"),
5289 void ReloadCmailMsgProc(w, event, prms, nprms)
5295 ReloadCmailMsgEvent(FALSE);
5298 void MailMoveProc(w, event, prms, nprms)
5307 /* this variable is shared between CopyPositionProc and SendPositionSelection */
5308 static char *selected_fen_position=NULL;
5311 SendPositionSelection(Widget w, Atom *selection, Atom *target,
5312 Atom *type_return, XtPointer *value_return,
5313 unsigned long *length_return, int *format_return)
5315 char *selection_tmp;
5317 if (!selected_fen_position) return False; /* should never happen */
5318 if (*target == XA_STRING){
5319 /* note: since no XtSelectionDoneProc was registered, Xt will
5320 * automatically call XtFree on the value returned. So have to
5321 * make a copy of it allocated with XtMalloc */
5322 selection_tmp= XtMalloc(strlen(selected_fen_position)+16);
5323 strcpy(selection_tmp, selected_fen_position);
5325 *value_return=selection_tmp;
5326 *length_return=strlen(selection_tmp);
5327 *type_return=XA_STRING;
5328 *format_return = 8; /* bits per byte */
5335 /* note: when called from menu all parameters are NULL, so no clue what the
5336 * Widget which was clicked on was, or what the click event was
5338 void CopyPositionProc(w, event, prms, nprms)
5346 if (selected_fen_position) free(selected_fen_position);
5347 selected_fen_position = (char *)PositionToFEN(currentMove, NULL);
5348 if (!selected_fen_position) return;
5349 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
5351 SendPositionSelection,
5352 NULL/* lose_ownership_proc */ ,
5353 NULL/* transfer_done_proc */);
5355 free(selected_fen_position);
5356 selected_fen_position=NULL;
5360 /* function called when the data to Paste is ready */
5362 PastePositionCB(Widget w, XtPointer client_data, Atom *selection,
5363 Atom *type, XtPointer value, unsigned long *len, int *format)
5366 if (value==NULL || *len==0) return; /* nothing had been selected to copy */
5367 fenstr[*len]='\0'; /* normally this string is terminated, but be safe */
5368 EditPositionPasteFEN(fenstr);
5372 /* called when Paste Position button is pressed,
5373 * all parameters will be NULL */
5374 void PastePositionProc(w, event, prms, nprms)
5380 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
5381 /* (XtSelectionCallbackProc) */ PastePositionCB,
5382 NULL, /* client_data passed to PastePositionCB */
5384 /* better to use the time field from the event that triggered the
5385 * call to this function, but that isn't trivial to get
5393 SendGameSelection(Widget w, Atom *selection, Atom *target,
5394 Atom *type_return, XtPointer *value_return,
5395 unsigned long *length_return, int *format_return)
5397 char *selection_tmp;
5399 if (*target == XA_STRING){
5400 FILE* f = fopen(gameCopyFilename, "r");
5403 if (f == NULL) return False;
5407 selection_tmp = XtMalloc(len + 1);
5408 count = fread(selection_tmp, 1, len, f);
5410 XtFree(selection_tmp);
5413 selection_tmp[len] = NULLCHAR;
5414 *value_return = selection_tmp;
5415 *length_return = len;
5416 *type_return = XA_STRING;
5417 *format_return = 8; /* bits per byte */
5424 /* note: when called from menu all parameters are NULL, so no clue what the
5425 * Widget which was clicked on was, or what the click event was
5427 void CopyGameProc(w, event, prms, nprms)
5435 ret = SaveGameToFile(gameCopyFilename, FALSE);
5438 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
5441 NULL/* lose_ownership_proc */ ,
5442 NULL/* transfer_done_proc */);
5445 /* function called when the data to Paste is ready */
5447 PasteGameCB(Widget w, XtPointer client_data, Atom *selection,
5448 Atom *type, XtPointer value, unsigned long *len, int *format)
5451 if (value == NULL || *len == 0) {
5452 return; /* nothing had been selected to copy */
5454 f = fopen(gamePasteFilename, "w");
5456 DisplayError(_("Can't open temp file"), errno);
5459 fwrite(value, 1, *len, f);
5462 LoadGameFromFile(gamePasteFilename, 0, gamePasteFilename, TRUE);
5465 /* called when Paste Game button is pressed,
5466 * all parameters will be NULL */
5467 void PasteGameProc(w, event, prms, nprms)
5473 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
5474 /* (XtSelectionCallbackProc) */ PasteGameCB,
5475 NULL, /* client_data passed to PasteGameCB */
5477 /* better to use the time field from the event that triggered the
5478 * call to this function, but that isn't trivial to get
5488 SaveGameProc(NULL, NULL, NULL, NULL);
5491 void AnalyzeModeProc(w, event, prms, nprms)
5499 if (!first.analysisSupport) {
5500 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
5501 DisplayError(buf, 0);
5504 /* [DM] icsEngineAnalyze [HGM] This is horrible code; reverse the gameMode and isEngineAnalyze tests! */
5505 if (appData.icsActive) {
5506 if (gameMode != IcsObserving) {
5507 sprintf(buf,_("You are not observing a game"));
5508 DisplayError(buf, 0);
5510 if (appData.icsEngineAnalyze) {
5511 if (appData.debugMode)
5512 fprintf(debugFP, _("Found unexpected active ICS engine analyze \n"));
5518 /* if enable, use want disable icsEngineAnalyze */
5519 if (appData.icsEngineAnalyze) {
5524 appData.icsEngineAnalyze = TRUE;
5525 if (appData.debugMode)
5526 fprintf(debugFP, _("ICS engine analyze starting... \n"));
5528 if (!appData.showThinking)
5529 ShowThinkingProc(w,event,prms,nprms);
5534 void AnalyzeFileProc(w, event, prms, nprms)
5540 if (!first.analysisSupport) {
5542 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
5543 DisplayError(buf, 0);
5548 if (!appData.showThinking)
5549 ShowThinkingProc(w,event,prms,nprms);
5552 FileNamePopUp(_("File to analyze"), "", LoadGamePopUp, "rb");
5553 AnalysisPeriodicEvent(1);
5557 void EditGameProc(w, event, prms, nprms)
5566 void EditPositionProc(w, event, prms, nprms)
5572 EditPositionEvent();
5575 void TrainingProc(w, event, prms, nprms)
5584 void EditCommentProc(w, event, prms, nprms)
5591 EditCommentPopDown();
5597 void IcsInputBoxProc(w, event, prms, nprms)
5603 if (ICSInputBoxUp) {
5604 ICSInputBoxPopDown();
5611 void EnterKeyProc(w, event, prms, nprms)
5617 if (ICSInputBoxUp == True)
5621 void AlwaysQueenProc(w, event, prms, nprms)
5629 appData.alwaysPromoteToQueen = !appData.alwaysPromoteToQueen;
5631 if (appData.alwaysPromoteToQueen) {
5632 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5634 XtSetArg(args[0], XtNleftBitmap, None);
5636 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
5640 void AnimateDraggingProc(w, event, prms, nprms)
5648 appData.animateDragging = !appData.animateDragging;
5650 if (appData.animateDragging) {
5651 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5654 XtSetArg(args[0], XtNleftBitmap, None);
5656 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Dragging"),
5660 void AnimateMovingProc(w, event, prms, nprms)
5668 appData.animate = !appData.animate;
5670 if (appData.animate) {
5671 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5674 XtSetArg(args[0], XtNleftBitmap, None);
5676 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
5680 void AutocommProc(w, event, prms, nprms)
5688 appData.autoComment = !appData.autoComment;
5690 if (appData.autoComment) {
5691 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5693 XtSetArg(args[0], XtNleftBitmap, None);
5695 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
5700 void AutoflagProc(w, event, prms, nprms)
5708 appData.autoCallFlag = !appData.autoCallFlag;
5710 if (appData.autoCallFlag) {
5711 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5713 XtSetArg(args[0], XtNleftBitmap, None);
5715 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
5719 void AutoflipProc(w, event, prms, nprms)
5727 appData.autoFlipView = !appData.autoFlipView;
5729 if (appData.autoFlipView) {
5730 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5732 XtSetArg(args[0], XtNleftBitmap, None);
5734 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flip View"),
5738 void AutobsProc(w, event, prms, nprms)
5746 appData.autoObserve = !appData.autoObserve;
5748 if (appData.autoObserve) {
5749 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5751 XtSetArg(args[0], XtNleftBitmap, None);
5753 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
5757 void AutoraiseProc(w, event, prms, nprms)
5765 appData.autoRaiseBoard = !appData.autoRaiseBoard;
5767 if (appData.autoRaiseBoard) {
5768 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5770 XtSetArg(args[0], XtNleftBitmap, None);
5772 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Raise Board"),
5776 void AutosaveProc(w, event, prms, nprms)
5784 appData.autoSaveGames = !appData.autoSaveGames;
5786 if (appData.autoSaveGames) {
5787 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5789 XtSetArg(args[0], XtNleftBitmap, None);
5791 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
5795 void BlindfoldProc(w, event, prms, nprms)
5803 appData.blindfold = !appData.blindfold;
5805 if (appData.blindfold) {
5806 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5808 XtSetArg(args[0], XtNleftBitmap, None);
5810 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Blindfold"),
5813 DrawPosition(True, NULL);
5816 void TestLegalityProc(w, event, prms, nprms)
5824 appData.testLegality = !appData.testLegality;
5826 if (appData.testLegality) {
5827 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5829 XtSetArg(args[0], XtNleftBitmap, None);
5831 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Test Legality"),
5836 void FlashMovesProc(w, event, prms, nprms)
5844 if (appData.flashCount == 0) {
5845 appData.flashCount = 3;
5847 appData.flashCount = -appData.flashCount;
5850 if (appData.flashCount > 0) {
5851 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5853 XtSetArg(args[0], XtNleftBitmap, None);
5855 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flash Moves"),
5860 void HighlightDraggingProc(w, event, prms, nprms)
5868 appData.highlightDragging = !appData.highlightDragging;
5870 if (appData.highlightDragging) {
5871 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5873 XtSetArg(args[0], XtNleftBitmap, None);
5875 XtSetValues(XtNameToWidget(menuBarWidget,
5876 "menuOptions.Highlight Dragging"), args, 1);
5880 void HighlightLastMoveProc(w, event, prms, nprms)
5888 appData.highlightLastMove = !appData.highlightLastMove;
5890 if (appData.highlightLastMove) {
5891 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5893 XtSetArg(args[0], XtNleftBitmap, None);
5895 XtSetValues(XtNameToWidget(menuBarWidget,
5896 "menuOptions.Highlight Last Move"), args, 1);
5899 void IcsAlarmProc(w, event, prms, nprms)
5907 appData.icsAlarm = !appData.icsAlarm;
5909 if (appData.icsAlarm) {
5910 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5912 XtSetArg(args[0], XtNleftBitmap, None);
5914 XtSetValues(XtNameToWidget(menuBarWidget,
5915 "menuOptions.ICS Alarm"), args, 1);
5918 void MoveSoundProc(w, event, prms, nprms)
5926 appData.ringBellAfterMoves = !appData.ringBellAfterMoves;
5928 if (appData.ringBellAfterMoves) {
5929 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5931 XtSetArg(args[0], XtNleftBitmap, None);
5933 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
5938 void OldSaveStyleProc(w, event, prms, nprms)
5946 appData.oldSaveStyle = !appData.oldSaveStyle;
5948 if (appData.oldSaveStyle) {
5949 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5951 XtSetArg(args[0], XtNleftBitmap, None);
5953 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Old Save Style"),
5957 void PeriodicUpdatesProc(w, event, prms, nprms)
5965 PeriodicUpdatesEvent(!appData.periodicUpdates);
5967 if (appData.periodicUpdates) {
5968 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5970 XtSetArg(args[0], XtNleftBitmap, None);
5972 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Periodic Updates"),
5976 void PonderNextMoveProc(w, event, prms, nprms)
5984 PonderNextMoveEvent(!appData.ponderNextMove);
5986 if (appData.ponderNextMove) {
5987 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5989 XtSetArg(args[0], XtNleftBitmap, None);
5991 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Ponder Next Move"),
5995 void PopupExitMessageProc(w, event, prms, nprms)
6003 appData.popupExitMessage = !appData.popupExitMessage;
6005 if (appData.popupExitMessage) {
6006 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6008 XtSetArg(args[0], XtNleftBitmap, None);
6010 XtSetValues(XtNameToWidget(menuBarWidget,
6011 "menuOptions.Popup Exit Message"), args, 1);
6014 void PopupMoveErrorsProc(w, event, prms, nprms)
6022 appData.popupMoveErrors = !appData.popupMoveErrors;
6024 if (appData.popupMoveErrors) {
6025 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6027 XtSetArg(args[0], XtNleftBitmap, None);
6029 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Popup Move Errors"),
6033 void PremoveProc(w, event, prms, nprms)
6041 appData.premove = !appData.premove;
6043 if (appData.premove) {
6044 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6046 XtSetArg(args[0], XtNleftBitmap, None);
6048 XtSetValues(XtNameToWidget(menuBarWidget,
6049 "menuOptions.Premove"), args, 1);
6052 void QuietPlayProc(w, event, prms, nprms)
6060 appData.quietPlay = !appData.quietPlay;
6062 if (appData.quietPlay) {
6063 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6065 XtSetArg(args[0], XtNleftBitmap, None);
6067 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Quiet Play"),
6071 void ShowThinkingProc(w, event, prms, nprms)
6079 appData.showThinking = !appData.showThinking; // [HGM] thinking: tken out of ShowThinkingEvent
6080 ShowThinkingEvent();
6082 // [HGM] thinking: currently no suc menu item; replaced by Hide Thinking (From Human)
6083 if (appData.showThinking) {
6084 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6086 XtSetArg(args[0], XtNleftBitmap, None);
6088 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Thinking"),
6093 void HideThinkingProc(w, event, prms, nprms)
6101 appData.hideThinkingFromHuman = !appData.hideThinkingFromHuman; // [HGM] thinking: tken out of ShowThinkingEvent
6102 ShowThinkingEvent();
6104 if (appData.hideThinkingFromHuman) {
6105 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6107 XtSetArg(args[0], XtNleftBitmap, None);
6109 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
6113 void DebugProc(w, event, prms, nprms)
6119 appData.debugMode = !appData.debugMode;
6122 void AboutGameProc(w, event, prms, nprms)
6131 void NothingProc(w, event, prms, nprms)
6140 void Iconify(w, event, prms, nprms)
6149 XtSetArg(args[0], XtNiconic, True);
6150 XtSetValues(shellWidget, args, 1);
6153 void DisplayMessage(message, extMessage)
6154 gchar *message, *extMessage;
6161 snprintf(buf, sizeof(buf), "%s %s", message, extMessage);
6164 message = extMessage;
6167 gtk_label_set_text( GTK_LABEL(gtk_builder_get_object (builder, "Messages")),message);
6172 void DisplayTitle(text)
6175 gchar title[MSG_SIZ];
6177 if (text == NULL) text = "";
6179 if (appData.titleInWindow)
6184 if (*text != NULLCHAR)
6186 strcpy(title, text);
6188 else if (appData.icsActive)
6190 snprintf(title, sizeof(title), "%s: %s", programName, appData.icsHost);
6192 else if (appData.cmailGameName[0] != NULLCHAR)
6194 snprintf(title,sizeof(title), "%s: %s", programName, "CMail");
6196 // [HGM] license: This stuff should really be done in back-end, but WinBoard already had a pop-up for it
6198 else if (gameInfo.variant == VariantGothic)
6200 strcpy(title, GOTHIC);
6204 else if (gameInfo.variant == VariantFalcon)
6206 strcpy(title, FALCON);
6209 else if (appData.noChessProgram)
6211 strcpy(title, programName);
6215 snprintf(title,sizeof(title), "%s: %s", programName, first.tidy);
6217 gtk_window_set_title(GTK_WINDOW(GUI_Window),title);
6223 void DisplayError(message, error)
6230 if (appData.debugMode || appData.matchMode) {
6231 fprintf(stderr, "%s: %s\n", programName, message);
6234 if (appData.debugMode || appData.matchMode) {
6235 fprintf(stderr, "%s: %s: %s\n",
6236 programName, message, strerror(error));
6238 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
6241 ErrorPopUp(_("Error"), message, FALSE);
6245 void DisplayMoveError(message)
6250 DrawPosition(FALSE, NULL);
6251 if (appData.debugMode || appData.matchMode) {
6252 fprintf(stderr, "%s: %s\n", programName, message);
6254 if (appData.popupMoveErrors) {
6255 ErrorPopUp(_("Error"), message, FALSE);
6257 DisplayMessage(message, "");
6262 void DisplayFatalError(message, error, status)
6268 errorExitStatus = status;
6270 fprintf(stderr, "%s: %s\n", programName, message);
6272 fprintf(stderr, "%s: %s: %s\n",
6273 programName, message, strerror(error));
6274 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
6277 if (appData.popupExitMessage && boardWidget && XtIsRealized(boardWidget)) {
6278 ErrorPopUp(status ? _("Fatal Error") : _("Exiting"), message, TRUE);
6284 void DisplayInformation(message)
6288 ErrorPopUp(_("Information"), message, TRUE);
6291 void DisplayNote(message)
6295 ErrorPopUp(_("Note"), message, FALSE);
6299 NullXErrorCheck(dpy, error_event)
6301 XErrorEvent *error_event;
6306 void DisplayIcsInteractionTitle(message)
6309 if (oldICSInteractionTitle == NULL) {
6310 /* Magic to find the old window title, adapted from vim */
6311 char *wina = getenv("WINDOWID");
6313 Window win = (Window) atoi(wina);
6314 Window root, parent, *children;
6315 unsigned int nchildren;
6316 int (*oldHandler)() = XSetErrorHandler(NullXErrorCheck);
6318 if (XFetchName(xDisplay, win, &oldICSInteractionTitle)) break;
6319 if (!XQueryTree(xDisplay, win, &root, &parent,
6320 &children, &nchildren)) break;
6321 if (children) XFree((void *)children);
6322 if (parent == root || parent == 0) break;
6325 XSetErrorHandler(oldHandler);
6327 if (oldICSInteractionTitle == NULL) {
6328 oldICSInteractionTitle = "xterm";
6331 printf("\033]0;%s\007", message);
6335 char pendingReplyPrefix[MSG_SIZ];
6336 ProcRef pendingReplyPR;
6338 void AskQuestionProc(w, event, prms, nprms)
6345 fprintf(stderr, _("AskQuestionProc needed 4 parameters, got %d\n"),
6349 AskQuestionEvent(prms[0], prms[1], prms[2], prms[3]);
6352 void AskQuestionPopDown()
6354 if (!askQuestionUp) return;
6355 XtPopdown(askQuestionShell);
6356 XtDestroyWidget(askQuestionShell);
6357 askQuestionUp = False;
6360 void AskQuestionReplyAction(w, event, prms, nprms)
6370 reply = XawDialogGetValueString(w = XtParent(w));
6371 strcpy(buf, pendingReplyPrefix);
6372 if (*buf) strcat(buf, " ");
6375 OutputToProcess(pendingReplyPR, buf, strlen(buf), &err);
6376 AskQuestionPopDown();
6378 if (err) DisplayFatalError(_("Error writing to chess program"), err, 0);
6381 void AskQuestionCallback(w, client_data, call_data)
6383 XtPointer client_data, call_data;
6388 XtSetArg(args[0], XtNlabel, &name);
6389 XtGetValues(w, args, 1);
6391 if (strcmp(name, _("cancel")) == 0) {
6392 AskQuestionPopDown();
6394 AskQuestionReplyAction(w, NULL, NULL, NULL);
6398 void AskQuestion(title, question, replyPrefix, pr)
6399 char *title, *question, *replyPrefix;
6403 Widget popup, layout, dialog, edit;
6409 strcpy(pendingReplyPrefix, replyPrefix);
6410 pendingReplyPR = pr;
6413 XtSetArg(args[i], XtNresizable, True); i++;
6414 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
6415 askQuestionShell = popup =
6416 XtCreatePopupShell(title, transientShellWidgetClass,
6417 shellWidget, args, i);
6420 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
6421 layoutArgs, XtNumber(layoutArgs));
6424 XtSetArg(args[i], XtNlabel, question); i++;
6425 XtSetArg(args[i], XtNvalue, ""); i++;
6426 XtSetArg(args[i], XtNborderWidth, 0); i++;
6427 dialog = XtCreateManagedWidget("question", dialogWidgetClass,
6430 XawDialogAddButton(dialog, _("enter"), AskQuestionCallback,
6431 (XtPointer) dialog);
6432 XawDialogAddButton(dialog, _("cancel"), AskQuestionCallback,
6433 (XtPointer) dialog);
6435 XtRealizeWidget(popup);
6436 CatchDeleteWindow(popup, "AskQuestionPopDown");
6438 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
6439 &x, &y, &win_x, &win_y, &mask);
6441 XtSetArg(args[0], XtNx, x - 10);
6442 XtSetArg(args[1], XtNy, y - 30);
6443 XtSetValues(popup, args, 2);
6445 XtPopup(popup, XtGrabExclusive);
6446 askQuestionUp = True;
6448 edit = XtNameToWidget(dialog, "*value");
6449 XtSetKeyboardFocus(popup, edit);
6457 if (*name == NULLCHAR) {
6459 } else if (strcmp(name, "$") == 0) {
6460 putc(BELLCHAR, stderr);
6463 snprintf(buf, sizeof(buf), "%s '%s' &", appData.soundProgram, name);
6471 PlaySound(appData.soundMove);
6477 PlaySound(appData.soundIcsWin);
6483 PlaySound(appData.soundIcsLoss);
6489 PlaySound(appData.soundIcsDraw);
6493 PlayIcsUnfinishedSound()
6495 PlaySound(appData.soundIcsUnfinished);
6501 PlaySound(appData.soundIcsAlarm);
6507 system("stty echo");
6513 system("stty -echo");
6517 Colorize(cc, continuation)
6522 int count, outCount, error;
6524 if (textColors[(int)cc].bg > 0) {
6525 if (textColors[(int)cc].fg > 0) {
6526 sprintf(buf, "\033[0;%d;%d;%dm", textColors[(int)cc].attr,
6527 textColors[(int)cc].fg, textColors[(int)cc].bg);
6529 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
6530 textColors[(int)cc].bg);
6533 if (textColors[(int)cc].fg > 0) {
6534 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
6535 textColors[(int)cc].fg);
6537 sprintf(buf, "\033[0;%dm", textColors[(int)cc].attr);
6540 count = strlen(buf);
6541 outCount = OutputToProcess(NoProc, buf, count, &error);
6542 if (outCount < count) {
6543 DisplayFatalError(_("Error writing to display"), error, 1);
6546 if (continuation) return;
6549 PlaySound(appData.soundShout);
6552 PlaySound(appData.soundSShout);
6555 PlaySound(appData.soundChannel1);
6558 PlaySound(appData.soundChannel);
6561 PlaySound(appData.soundKibitz);
6564 PlaySound(appData.soundTell);
6566 case ColorChallenge:
6567 PlaySound(appData.soundChallenge);
6570 PlaySound(appData.soundRequest);
6573 PlaySound(appData.soundSeek);
6584 return getpwuid(getuid())->pw_name;
6587 static char *ExpandPathName(path)
6590 static char static_buf[2000];
6591 char *d, *s, buf[2000];
6597 while (*s && isspace(*s))
6606 if (*(s+1) == '/') {
6607 strcpy(d, getpwuid(getuid())->pw_dir);
6612 *strchr(buf, '/') = 0;
6613 pwd = getpwnam(buf);
6616 fprintf(stderr, _("ERROR: Unknown user %s (in path %s)\n"),
6620 strcpy(d, pwd->pw_dir);
6621 strcat(d, strchr(s+1, '/'));
6632 static char host_name[MSG_SIZ];
6634 #if HAVE_GETHOSTNAME
6635 gethostname(host_name, MSG_SIZ);
6637 #else /* not HAVE_GETHOSTNAME */
6638 # if HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H
6639 sysinfo(SI_HOSTNAME, host_name, MSG_SIZ);
6641 # else /* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
6643 # endif/* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
6644 #endif /* not HAVE_GETHOSTNAME */
6647 guint delayedEventTimerTag = 0;
6648 DelayedEventCallback delayedEventCallback = 0;
6651 FireDelayedEvent(data)
6655 g_source_remove(delayedEventTimerTag);
6656 delayedEventTimerTag = 0;
6659 delayedEventCallback();
6665 ScheduleDelayedEvent(cb, millisec)
6666 DelayedEventCallback cb; guint millisec;
6668 if(delayedEventTimerTag && delayedEventCallback == cb)
6669 // [HGM] alive: replace, rather than add or flush identical event
6670 g_source_remove(delayedEventTimerTag);
6671 delayedEventCallback = cb;
6672 delayedEventTimerTag = g_timeout_add(millisec,(GSourceFunc) FireDelayedEvent, NULL);
6676 DelayedEventCallback
6679 if (delayedEventTimerTag)
6681 return delayedEventCallback;
6690 CancelDelayedEvent()
6692 if (delayedEventTimerTag)
6694 g_source_remove(delayedEventTimerTag);
6695 delayedEventTimerTag = 0;
6701 guint loadGameTimerTag = 0;
6703 int LoadGameTimerRunning()
6705 return loadGameTimerTag != 0;
6708 int StopLoadGameTimer()
6710 if (loadGameTimerTag != 0) {
6711 g_source_remove(loadGameTimerTag);
6712 loadGameTimerTag = 0;
6720 LoadGameTimerCallback(data)
6724 g_source_remove(loadGameTimerTag);
6725 loadGameTimerTag = 0;
6732 StartLoadGameTimer(millisec)
6736 g_timeout_add( millisec, (GSourceFunc) LoadGameTimerCallback, NULL);
6740 guint analysisClockTag = 0;
6743 AnalysisClockCallback(data)
6746 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile
6747 || appData.icsEngineAnalyze)
6749 AnalysisPeriodicEvent(0);
6750 return 1; /* keep on going */
6752 return 0; /* stop timer */
6756 StartAnalysisClock()
6759 g_timeout_add( 2000,(GSourceFunc) AnalysisClockCallback, NULL);
6763 guint clockTimerTag = 0;
6765 int ClockTimerRunning()
6767 return clockTimerTag != 0;
6770 int StopClockTimer()
6772 if (clockTimerTag != 0)
6774 g_source_remove(clockTimerTag);
6785 ClockTimerCallback(data)
6789 g_source_remove(clockTimerTag);
6797 StartClockTimer(millisec)
6800 clockTimerTag = g_timeout_add(millisec,(GSourceFunc) ClockTimerCallback,NULL);
6805 DisplayTimerLabel(w, color, timer, highlight)
6814 if (appData.clockMode) {
6815 sprintf(buf, "%s: %s", color, TimeString(timer));
6817 sprintf(buf, "%s ", color);
6819 gtk_label_set_text(GTK_LABEL(w),buf);
6821 /* check for low time warning */
6822 // Pixel foregroundOrWarningColor = timerForegroundPixel;
6825 // appData.lowTimeWarning &&
6826 // (timer / 1000) < appData.icsAlarmTime)
6827 // foregroundOrWarningColor = lowTimeWarningColor;
6829 // if (appData.clockMode) {
6830 // sprintf(buf, "%s: %s", color, TimeString(timer));
6831 // XtSetArg(args[0], XtNlabel, buf);
6833 // sprintf(buf, "%s ", color);
6834 // XtSetArg(args[0], XtNlabel, buf);
6839 // XtSetArg(args[1], XtNbackground, foregroundOrWarningColor);
6840 // XtSetArg(args[2], XtNforeground, timerBackgroundPixel);
6842 // XtSetArg(args[1], XtNbackground, timerBackgroundPixel);
6843 // XtSetArg(args[2], XtNforeground, foregroundOrWarningColor);
6846 // XtSetValues(w, args, 3);
6851 DisplayWhiteClock(timeRemaining, highlight)
6855 if(appData.noGUI) return;
6857 DisplayTimerLabel(GUI_Whiteclock, _("White"), timeRemaining, highlight);
6858 if (highlight && WindowIcon == BlackIcon)
6860 WindowIcon = WhiteIcon;
6861 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
6866 DisplayBlackClock(timeRemaining, highlight)
6870 if(appData.noGUI) return;
6872 DisplayTimerLabel(GUI_Blackclock, _("Black"), timeRemaining, highlight);
6873 if (highlight && WindowIcon == WhiteIcon)
6875 WindowIcon = BlackIcon;
6876 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
6894 int StartChildProcess(cmdLine, dir, pr)
6901 int to_prog[2], from_prog[2];
6905 if (appData.debugMode) {
6906 fprintf(stderr, "StartChildProcess (dir=\"%s\") %s\n",dir, cmdLine);
6909 /* We do NOT feed the cmdLine to the shell; we just
6910 parse it into blank-separated arguments in the
6911 most simple-minded way possible.
6914 strcpy(buf, cmdLine);
6919 if (p == NULL) break;
6924 SetUpChildIO(to_prog, from_prog);
6926 if ((pid = fork()) == 0) {
6928 // [HGM] PSWBTM: made order resistant against case where fd of created pipe was 0 or 1
6929 close(to_prog[1]); // first close the unused pipe ends
6930 close(from_prog[0]);
6931 dup2(to_prog[0], 0); // to_prog was created first, nd is the only one to use 0 or 1
6932 dup2(from_prog[1], 1);
6933 if(to_prog[0] >= 2) close(to_prog[0]); // if 0 or 1, the dup2 already cosed the original
6934 close(from_prog[1]); // and closing again loses one of the pipes!
6935 if(fileno(stderr) >= 2) // better safe than sorry...
6936 dup2(1, fileno(stderr)); /* force stderr to the pipe */
6938 if (dir[0] != NULLCHAR && chdir(dir) != 0) {
6943 nice(appData.niceEngines); // [HGM] nice: adjust priority of engine proc
6945 execvp(argv[0], argv);
6947 /* If we get here, exec failed */
6952 /* Parent process */
6954 close(from_prog[1]);
6956 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
6959 cp->fdFrom = from_prog[0];
6960 cp->fdTo = to_prog[1];
6965 // [HGM] kill: implement the 'hard killing' of AS's Winboard_x
6966 static RETSIGTYPE AlarmCallBack(int n)
6972 DestroyChildProcess(pr, signalType)
6976 ChildProc *cp = (ChildProc *) pr;
6978 if (cp->kind != CPReal) return;
6980 if (signalType == 10) { // [HGM] kill: if it does not terminate in 3 sec, kill
6981 signal(SIGALRM, AlarmCallBack);
6983 if(wait((int *) 0) == -1) { // process does not terminate on its own accord
6984 kill(cp->pid, SIGKILL); // kill it forcefully
6985 wait((int *) 0); // and wait again
6989 kill(cp->pid, signalType == 9 ? SIGKILL : SIGTERM); // [HGM] kill: use hard kill if so requested
6991 /* Process is exiting either because of the kill or because of
6992 a quit command sent by the backend; either way, wait for it to die.
7001 InterruptChildProcess(pr)
7004 ChildProc *cp = (ChildProc *) pr;
7006 if (cp->kind != CPReal) return;
7007 (void) kill(cp->pid, SIGINT); /* stop it thinking */
7010 int OpenTelnet(host, port, pr)
7015 char cmdLine[MSG_SIZ];
7017 if (port[0] == NULLCHAR) {
7018 snprintf(cmdLine, sizeof(cmdLine), "%s %s", appData.telnetProgram, host);
7020 snprintf(cmdLine, sizeof(cmdLine), "%s %s %s", appData.telnetProgram, host, port);
7022 return StartChildProcess(cmdLine, "", pr);
7025 int OpenTCP(host, port, pr)
7031 DisplayFatalError(_("Socket support is not configured in"), 0, 2);
7032 #else /* !OMIT_SOCKETS */
7034 struct sockaddr_in sa;
7036 unsigned short uport;
7039 if ((s = socket(AF_INET, SOCK_STREAM, 6)) < 0) {
7043 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
7044 sa.sin_family = AF_INET;
7045 sa.sin_addr.s_addr = INADDR_ANY;
7046 uport = (unsigned short) 0;
7047 sa.sin_port = htons(uport);
7048 if (bind(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)) < 0) {
7052 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
7053 if (!(hp = gethostbyname(host))) {
7055 if (sscanf(host, "%d.%d.%d.%d", &b0, &b1, &b2, &b3) == 4) {
7056 hp = (struct hostent *) calloc(1, sizeof(struct hostent));
7057 hp->h_addrtype = AF_INET;
7059 hp->h_addr_list = (char **) calloc(2, sizeof(char *));
7060 hp->h_addr_list[0] = (char *) malloc(4);
7061 hp->h_addr_list[0][0] = b0;
7062 hp->h_addr_list[0][1] = b1;
7063 hp->h_addr_list[0][2] = b2;
7064 hp->h_addr_list[0][3] = b3;
7069 sa.sin_family = hp->h_addrtype;
7070 uport = (unsigned short) atoi(port);
7071 sa.sin_port = htons(uport);
7072 memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);
7074 if (connect(s, (struct sockaddr *) &sa,
7075 sizeof(struct sockaddr_in)) < 0) {
7079 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7086 #endif /* !OMIT_SOCKETS */
7091 int OpenCommPort(name, pr)
7098 fd = open(name, 2, 0);
7099 if (fd < 0) return errno;
7101 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7111 int OpenLoopback(pr)
7117 SetUpChildIO(to, from);
7119 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7122 cp->fdFrom = to[0]; /* note not from[0]; we are doing a loopback */
7129 int OpenRcmd(host, user, cmd, pr)
7130 char *host, *user, *cmd;
7133 DisplayFatalError(_("internal rcmd not implemented for Unix"), 0, 1);
7137 #define INPUT_SOURCE_BUF_SIZE 8192
7146 char buf[INPUT_SOURCE_BUF_SIZE];
7151 DoInputCallback(io,cond,data)
7156 /* read input from one of the input source (for example a chess program, ICS, etc).
7157 * and call a function that will handle the input
7160 int count; /* how many bytes did we read */
7164 /* All information (callback function, file descriptor, etc) is
7165 * saved in an InputSource structure
7167 InputSource *is = (InputSource *) data;
7171 count = read(is->fd, is->unused,
7172 INPUT_SOURCE_BUF_SIZE - (is->unused - is->buf));
7176 (is->func)(is, is->closure, is->buf, count, count ? errno : 0);
7179 is->unused += count;
7181 /* break input into lines and call the callback function on each
7184 while (p < is->unused)
7186 q = memchr(p, '\n', is->unused - p);
7187 if (q == NULL) break;
7189 (is->func)(is, is->closure, p, q - p, 0);
7192 /* remember not yet used part of the buffer */
7194 while (p < is->unused)
7202 /* read maximum length of input buffer and send the whole buffer
7203 * to the callback function
7205 count = read(is->fd, is->buf, INPUT_SOURCE_BUF_SIZE);
7210 (is->func)(is, is->closure, is->buf, count, error);
7216 InputSourceRef AddInputSource(pr, lineByLine, func, closure)
7223 GIOChannel *channel;
7224 ChildProc *cp = (ChildProc *) pr;
7226 is = (InputSource *) calloc(1, sizeof(InputSource));
7227 is->lineByLine = lineByLine;
7231 is->fd = fileno(stdin);
7233 is->kind = cp->kind;
7234 is->fd = cp->fdFrom;
7237 is->unused = is->buf;
7241 // is->xid = XtAppAddInput(appContext, is->fd,
7242 // (XtPointer) (XtInputReadMask),
7243 // (XtInputCallbackProc) DoInputCallback,
7247 /* TODO: will this work on windows?*/
7248 printf("DEBUG: fd=%d %d\n",is->fd,is);
7250 channel = g_io_channel_unix_new(is->fd);
7251 g_io_channel_set_close_on_unref (channel, TRUE);
7252 is->sid = g_io_add_watch(channel, G_IO_IN,(GIOFunc) DoInputCallback, is);
7253 is->closure = closure;
7254 return (InputSourceRef) is;
7258 RemoveInputSource(isr)
7261 InputSource *is = (InputSource *) isr;
7263 if (is->sid == 0) return;
7264 g_source_remove(is->sid);
7269 int OutputToProcess(pr, message, count, outError)
7275 ChildProc *cp = (ChildProc *) pr;
7279 outCount = fwrite(message, 1, count, stdout);
7281 outCount = write(cp->fdTo, message, count);
7291 /* Output message to process, with "ms" milliseconds of delay
7292 between each character. This is needed when sending the logon
7293 script to ICC, which for some reason doesn't like the
7294 instantaneous send. */
7295 int OutputToProcessDelayed(pr, message, count, outError, msdelay)
7302 ChildProc *cp = (ChildProc *) pr;
7307 r = write(cp->fdTo, message++, 1);
7320 /**** Animation code by Hugh Fisher, DCS, ANU.
7322 Known problem: if a window overlapping the board is
7323 moved away while a piece is being animated underneath,
7324 the newly exposed area won't be updated properly.
7325 I can live with this.
7327 Known problem: if you look carefully at the animation
7328 of pieces in mono mode, they are being drawn as solid
7329 shapes without interior detail while moving. Fixing
7330 this would be a major complication for minimal return.
7333 /* Masks for XPM pieces. Black and white pieces can have
7334 different shapes, but in the interest of retaining my
7335 sanity pieces must have the same outline on both light
7336 and dark squares, and all pieces must use the same
7337 background square colors/images. */
7339 static int xpmDone = 0;
7342 CreateAnimMasks (pieceDepth)
7349 unsigned long plane;
7352 /* just return for gtk at the moment */
7355 /* Need a bitmap just to get a GC with right depth */
7356 buf = XCreatePixmap(xDisplay, xBoardWindow,
7358 values.foreground = 1;
7359 values.background = 0;
7360 /* Don't use XtGetGC, not read only */
7361 maskGC = XCreateGC(xDisplay, buf,
7362 GCForeground | GCBackground, &values);
7363 XFreePixmap(xDisplay, buf);
7365 buf = XCreatePixmap(xDisplay, xBoardWindow,
7366 squareSize, squareSize, pieceDepth);
7367 values.foreground = XBlackPixel(xDisplay, xScreen);
7368 values.background = XWhitePixel(xDisplay, xScreen);
7369 bufGC = XCreateGC(xDisplay, buf,
7370 GCForeground | GCBackground, &values);
7372 for (piece = WhitePawn; piece <= BlackKing; piece++) {
7373 /* Begin with empty mask */
7374 if(!xpmDone) // [HGM] pieces: keep using existing
7375 xpmMask[piece] = XCreatePixmap(xDisplay, xBoardWindow,
7376 squareSize, squareSize, 1);
7377 XSetFunction(xDisplay, maskGC, GXclear);
7378 XFillRectangle(xDisplay, xpmMask[piece], maskGC,
7379 0, 0, squareSize, squareSize);
7381 /* Take a copy of the piece */
7386 XSetFunction(xDisplay, bufGC, GXcopy);
7387 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn],
7389 0, 0, squareSize, squareSize, 0, 0);
7391 /* XOR the background (light) over the piece */
7392 XSetFunction(xDisplay, bufGC, GXxor);
7394 XCopyArea(xDisplay, xpmLightSquare, buf, bufGC,
7395 0, 0, squareSize, squareSize, 0, 0);
7397 XSetForeground(xDisplay, bufGC, lightSquareColor);
7398 XFillRectangle(xDisplay, buf, bufGC, 0, 0, squareSize, squareSize);
7401 /* We now have an inverted piece image with the background
7402 erased. Construct mask by just selecting all the non-zero
7403 pixels - no need to reconstruct the original image. */
7404 XSetFunction(xDisplay, maskGC, GXor);
7406 /* Might be quicker to download an XImage and create bitmap
7407 data from it rather than this N copies per piece, but it
7408 only takes a fraction of a second and there is a much
7409 longer delay for loading the pieces. */
7410 for (n = 0; n < pieceDepth; n ++) {
7411 XCopyPlane(xDisplay, buf, xpmMask[piece], maskGC,
7412 0, 0, squareSize, squareSize,
7418 XFreePixmap(xDisplay, buf);
7419 XFreeGC(xDisplay, bufGC);
7420 XFreeGC(xDisplay, maskGC);
7424 InitAnimState (anim, info)
7426 XWindowAttributes * info;
7431 /* Each buffer is square size, same depth as window */
7432 // anim->saveBuf = XCreatePixmap(xDisplay, xBoardWindow,
7433 // squareSize, squareSize, info->depth);
7434 // anim->newBuf = XCreatePixmap(xDisplay, xBoardWindow,
7435 // squareSize, squareSize, info->depth);
7437 // /* Create a plain GC for blitting */
7438 // mask = GCForeground | GCBackground | GCFunction |
7439 // GCPlaneMask | GCGraphicsExposures;
7440 // values.foreground = XBlackPixel(xDisplay, xScreen);
7441 // values.background = XWhitePixel(xDisplay, xScreen);
7442 // values.function = GXcopy;
7443 // values.plane_mask = AllPlanes;
7444 // values.graphics_exposures = False;
7445 // anim->blitGC = XCreateGC(xDisplay, xBoardWindow, mask, &values);
7447 // /* Piece will be copied from an existing context at
7448 // the start of each new animation/drag. */
7449 // anim->pieceGC = XCreateGC(xDisplay, xBoardWindow, 0, &values);
7451 // /* Outline will be a read-only copy of an existing */
7452 // anim->outlineGC = None;
7458 static VariantClass old = (VariantClass) -1; // [HGM] pieces: redo every time variant changes
7459 XWindowAttributes info;
7461 /* for gtk at the moment just ... */
7464 if (xpmDone && gameInfo.variant == old) return;
7465 if(xpmDone) old = gameInfo.variant; // first time pieces might not be created yet
7466 // XGetWindowAttributes(xDisplay, xBoardWindow, &info);
7468 // InitAnimState(&game, &info);
7469 // InitAnimState(&player, &info);
7471 /* For XPM pieces, we need bitmaps to use as masks. */
7473 // CreateAnimMasks(info.depth);
7479 static Boolean frameWaiting;
7481 static RETSIGTYPE FrameAlarm (sig)
7484 frameWaiting = False;
7485 /* In case System-V style signals. Needed?? */
7486 signal(SIGALRM, FrameAlarm);
7493 struct itimerval delay;
7495 XSync(xDisplay, False);
7498 frameWaiting = True;
7499 signal(SIGALRM, FrameAlarm);
7500 delay.it_interval.tv_sec =
7501 delay.it_value.tv_sec = time / 1000;
7502 delay.it_interval.tv_usec =
7503 delay.it_value.tv_usec = (time % 1000) * 1000;
7504 setitimer(ITIMER_REAL, &delay, NULL);
7506 /* Ugh -- busy-wait! --tpm */
7507 while (frameWaiting);
7509 while (frameWaiting) pause();
7511 delay.it_interval.tv_sec = delay.it_value.tv_sec = 0;
7512 delay.it_interval.tv_usec = delay.it_value.tv_usec = 0;
7513 setitimer(ITIMER_REAL, &delay, NULL);
7523 // XSync(xDisplay, False);
7525 usleep(time * 1000);
7530 /* Convert board position to corner of screen rect and color */
7533 ScreenSquare(column, row, pt, color)
7534 int column; int row; XPoint * pt; int * color;
7537 pt->x = lineGap + ((BOARD_WIDTH-1)-column) * (squareSize + lineGap);
7538 pt->y = lineGap + row * (squareSize + lineGap);
7540 pt->x = lineGap + column * (squareSize + lineGap);
7541 pt->y = lineGap + ((BOARD_HEIGHT-1)-row) * (squareSize + lineGap);
7543 *color = SquareColor(row, column);
7546 /* Convert window coords to square */
7549 BoardSquare(x, y, column, row)
7550 int x; int y; int * column; int * row;
7552 *column = EventToSquare(x, BOARD_WIDTH);
7553 if (flipView && *column >= 0)
7554 *column = BOARD_WIDTH - 1 - *column;
7555 *row = EventToSquare(y, BOARD_HEIGHT);
7556 if (!flipView && *row >= 0)
7557 *row = BOARD_HEIGHT - 1 - *row;
7562 #undef Max /* just in case */
7564 #define Max(a, b) ((a) > (b) ? (a) : (b))
7565 #define Min(a, b) ((a) < (b) ? (a) : (b))
7568 SetRect(rect, x, y, width, height)
7569 XRectangle * rect; int x; int y; int width; int height;
7573 rect->width = width;
7574 rect->height = height;
7577 /* Test if two frames overlap. If they do, return
7578 intersection rect within old and location of
7579 that rect within new. */
7582 Intersect(old, new, size, area, pt)
7583 XPoint * old; XPoint * new;
7584 int size; XRectangle * area; XPoint * pt;
7586 if (old->x > new->x + size || new->x > old->x + size ||
7587 old->y > new->y + size || new->y > old->y + size) {
7590 SetRect(area, Max(new->x - old->x, 0), Max(new->y - old->y, 0),
7591 size - abs(old->x - new->x), size - abs(old->y - new->y));
7592 pt->x = Max(old->x - new->x, 0);
7593 pt->y = Max(old->y - new->y, 0);
7598 /* For two overlapping frames, return the rect(s)
7599 in the old that do not intersect with the new. */
7602 CalcUpdateRects(old, new, size, update, nUpdates)
7603 XPoint * old; XPoint * new; int size;
7604 XRectangle update[]; int * nUpdates;
7608 /* If old = new (shouldn't happen) then nothing to draw */
7609 if (old->x == new->x && old->y == new->y) {
7613 /* Work out what bits overlap. Since we know the rects
7614 are the same size we don't need a full intersect calc. */
7616 /* Top or bottom edge? */
7617 if (new->y > old->y) {
7618 SetRect(&(update[count]), old->x, old->y, size, new->y - old->y);
7620 } else if (old->y > new->y) {
7621 SetRect(&(update[count]), old->x, old->y + size - (old->y - new->y),
7622 size, old->y - new->y);
7625 /* Left or right edge - don't overlap any update calculated above. */
7626 if (new->x > old->x) {
7627 SetRect(&(update[count]), old->x, Max(new->y, old->y),
7628 new->x - old->x, size - abs(new->y - old->y));
7630 } else if (old->x > new->x) {
7631 SetRect(&(update[count]), new->x + size, Max(new->y, old->y),
7632 old->x - new->x, size - abs(new->y - old->y));
7639 /* Generate a series of frame coords from start->mid->finish.
7640 The movement rate doubles until the half way point is
7641 reached, then halves back down to the final destination,
7642 which gives a nice slow in/out effect. The algorithmn
7643 may seem to generate too many intermediates for short
7644 moves, but remember that the purpose is to attract the
7645 viewers attention to the piece about to be moved and
7646 then to where it ends up. Too few frames would be less
7650 Tween(start, mid, finish, factor, frames, nFrames)
7651 XPoint * start; XPoint * mid;
7652 XPoint * finish; int factor;
7653 XPoint frames[]; int * nFrames;
7655 int fraction, n, count;
7659 /* Slow in, stepping 1/16th, then 1/8th, ... */
7661 for (n = 0; n < factor; n++)
7663 for (n = 0; n < factor; n++) {
7664 frames[count].x = start->x + (mid->x - start->x) / fraction;
7665 frames[count].y = start->y + (mid->y - start->y) / fraction;
7667 fraction = fraction / 2;
7671 frames[count] = *mid;
7674 /* Slow out, stepping 1/2, then 1/4, ... */
7676 for (n = 0; n < factor; n++) {
7677 frames[count].x = finish->x - (finish->x - mid->x) / fraction;
7678 frames[count].y = finish->y - (finish->y - mid->y) / fraction;
7680 fraction = fraction * 2;
7685 /* Draw a piece on the screen without disturbing what's there */
7688 SelectGCMask(piece, clip, outline, mask)
7689 ChessSquare piece; GC * clip; GC * outline; Pixmap * mask;
7693 /* Bitmap for piece being moved. */
7694 if (appData.monoMode) {
7695 *mask = *pieceToSolid(piece);
7696 } else if (useImages) {
7698 *mask = xpmMask[piece];
7700 *mask = ximMaskPm[piece];
7703 *mask = *pieceToSolid(piece);
7706 /* GC for piece being moved. Square color doesn't matter, but
7707 since it gets modified we make a copy of the original. */
7709 if (appData.monoMode)
7714 if (appData.monoMode)
7719 // XCopyGC(xDisplay, source, 0xFFFFFFFF, *clip);
7721 /* Outline only used in mono mode and is not modified */
7723 *outline = bwPieceGC;
7725 *outline = wbPieceGC;
7729 OverlayPiece(piece, clip, outline, dest)
7730 ChessSquare piece; GC clip; GC outline; Drawable dest;
7735 /* Draw solid rectangle which will be clipped to shape of piece */
7736 // XFillRectangle(xDisplay, dest, clip,
7737 // 0, 0, squareSize, squareSize)
7739 if (appData.monoMode)
7740 /* Also draw outline in contrasting color for black
7741 on black / white on white cases */
7742 // XCopyPlane(xDisplay, *pieceToOutline(piece), dest, outline,
7743 // 0, 0, squareSize, squareSize, 0, 0, 1)
7746 /* Copy the piece */
7751 // XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
7753 // 0, 0, squareSize, squareSize,
7758 /* Animate the movement of a single piece */
7761 BeginAnimation(anim, piece, startColor, start)
7769 /* The old buffer is initialised with the start square (empty) */
7770 BlankSquare(0, 0, startColor, EmptySquare, anim->saveBuf);
7771 anim->prevFrame = *start;
7773 /* The piece will be drawn using its own bitmap as a matte */
7774 // SelectGCMask(piece, &anim->pieceGC, &anim->outlineGC, &mask);
7775 // XSetClipMask(xDisplay, anim->pieceGC, mask);
7779 AnimationFrame(anim, frame, piece)
7784 XRectangle updates[4];
7789 /* Save what we are about to draw into the new buffer */
7790 // XCopyArea(xDisplay, xBoardWindow, anim->newBuf, anim->blitGC,
7791 // frame->x, frame->y, squareSize, squareSize,
7794 /* Erase bits of the previous frame */
7795 if (Intersect(&anim->prevFrame, frame, squareSize, &overlap, &pt)) {
7796 /* Where the new frame overlapped the previous,
7797 the contents in newBuf are wrong. */
7798 // XCopyArea(xDisplay, anim->saveBuf, anim->newBuf, anim->blitGC,
7799 // overlap.x, overlap.y,
7800 // overlap.width, overlap.height,
7802 /* Repaint the areas in the old that don't overlap new */
7803 CalcUpdateRects(&anim->prevFrame, frame, squareSize, updates, &count);
7804 for (i = 0; i < count; i++)
7805 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
7806 // updates[i].x - anim->prevFrame.x,
7807 // updates[i].y - anim->prevFrame.y,
7808 // updates[i].width, updates[i].height,
7809 // updates[i].x, updates[i].y)
7812 /* Easy when no overlap */
7813 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
7814 // 0, 0, squareSize, squareSize,
7815 // anim->prevFrame.x, anim->prevFrame.y);
7818 /* Save this frame for next time round */
7819 // XCopyArea(xDisplay, anim->newBuf, anim->saveBuf, anim->blitGC,
7820 // 0, 0, squareSize, squareSize,
7822 anim->prevFrame = *frame;
7824 /* Draw piece over original screen contents, not current,
7825 and copy entire rect. Wipes out overlapping piece images. */
7826 OverlayPiece(piece, anim->pieceGC, anim->outlineGC, anim->newBuf);
7827 // XCopyArea(xDisplay, anim->newBuf, xBoardWindow, anim->blitGC,
7828 // 0, 0, squareSize, squareSize,
7829 // frame->x, frame->y);
7833 EndAnimation (anim, finish)
7837 XRectangle updates[4];
7842 /* The main code will redraw the final square, so we
7843 only need to erase the bits that don't overlap. */
7844 if (Intersect(&anim->prevFrame, finish, squareSize, &overlap, &pt)) {
7845 CalcUpdateRects(&anim->prevFrame, finish, squareSize, updates, &count);
7846 for (i = 0; i < count; i++)
7847 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
7848 // updates[i].x - anim->prevFrame.x,
7849 // updates[i].y - anim->prevFrame.y,
7850 // updates[i].width, updates[i].height,
7851 // updates[i].x, updates[i].y)
7854 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
7855 // 0, 0, squareSize, squareSize,
7856 // anim->prevFrame.x, anim->prevFrame.y);
7861 FrameSequence(anim, piece, startColor, start, finish, frames, nFrames)
7863 ChessSquare piece; int startColor;
7864 XPoint * start; XPoint * finish;
7865 XPoint frames[]; int nFrames;
7869 BeginAnimation(anim, piece, startColor, start);
7870 for (n = 0; n < nFrames; n++) {
7871 AnimationFrame(anim, &(frames[n]), piece);
7872 FrameDelay(appData.animSpeed);
7874 EndAnimation(anim, finish);
7877 /* Main control logic for deciding what to animate and how */
7880 AnimateMove(board, fromX, fromY, toX, toY)
7889 XPoint start, finish, mid;
7890 XPoint frames[kFactor * 2 + 1];
7891 int nFrames, startColor, endColor;
7893 /* Are we animating? */
7894 if (!appData.animate || appData.blindfold)
7897 if(board[toY][toX] == WhiteRook && board[fromY][fromX] == WhiteKing ||
7898 board[toY][toX] == BlackRook && board[fromY][fromX] == BlackKing)
7899 return; // [HGM] FRC: no animtion of FRC castlings, as to-square is not true to-square
7901 if (fromY < 0 || fromX < 0 || toX < 0 || toY < 0) return;
7902 piece = board[fromY][fromX];
7903 if (piece >= EmptySquare) return;
7908 hop = (piece == WhiteKnight || piece == BlackKnight);
7911 if (appData.debugMode) {
7912 fprintf(debugFP, hop ? _("AnimateMove: piece %d hops from %d,%d to %d,%d \n") :
7913 _("AnimateMove: piece %d slides from %d,%d to %d,%d \n"),
7914 piece, fromX, fromY, toX, toY); }
7916 ScreenSquare(fromX, fromY, &start, &startColor);
7917 ScreenSquare(toX, toY, &finish, &endColor);
7920 /* Knight: make diagonal movement then straight */
7921 if (abs(toY - fromY) < abs(toX - fromX)) {
7922 mid.x = start.x + (finish.x - start.x) / 2;
7926 mid.y = start.y + (finish.y - start.y) / 2;
7929 mid.x = start.x + (finish.x - start.x) / 2;
7930 mid.y = start.y + (finish.y - start.y) / 2;
7933 /* Don't use as many frames for very short moves */
7934 if (abs(toY - fromY) + abs(toX - fromX) <= 2)
7935 Tween(&start, &mid, &finish, kFactor - 1, frames, &nFrames);
7937 Tween(&start, &mid, &finish, kFactor, frames, &nFrames);
7938 FrameSequence(&game, piece, startColor, &start, &finish, frames, nFrames);
7940 /* Be sure end square is redrawn */
7941 damage[toY][toX] = True;
7945 DragPieceBegin(x, y)
7948 int boardX, boardY, color;
7951 /* Are we animating? */
7952 if (!appData.animateDragging || appData.blindfold)
7955 /* Figure out which square we start in and the
7956 mouse position relative to top left corner. */
7957 BoardSquare(x, y, &boardX, &boardY);
7958 player.startBoardX = boardX;
7959 player.startBoardY = boardY;
7960 ScreenSquare(boardX, boardY, &corner, &color);
7961 player.startSquare = corner;
7962 player.startColor = color;
7964 /* Start from exactly where the piece is. This can be confusing
7965 if you start dragging far from the center of the square; most
7966 or all of the piece can be over a different square from the one
7967 the mouse pointer is in. */
7968 player.mouseDelta.x = x - corner.x;
7969 player.mouseDelta.y = y - corner.y;
7971 /* As soon as we start dragging, the piece will jump slightly to
7972 be centered over the mouse pointer. */
7973 player.mouseDelta.x = squareSize/2;
7974 player.mouseDelta.y = squareSize/2;
7976 /* Initialise animation */
7977 player.dragPiece = PieceForSquare(boardX, boardY);
7979 if (player.dragPiece >= 0 && player.dragPiece < EmptySquare) {
7980 player.dragActive = True;
7981 BeginAnimation(&player, player.dragPiece, color, &corner);
7982 /* Mark this square as needing to be redrawn. Note that
7983 we don't remove the piece though, since logically (ie
7984 as seen by opponent) the move hasn't been made yet. */
7985 if(boardX == BOARD_RGHT+1 && PieceForSquare(boardX-1, boardY) > 1 ||
7986 boardX == BOARD_LEFT-2 && PieceForSquare(boardX+1, boardY) > 1)
7987 // XCopyArea(xDisplay, xBoardWindow, player.saveBuf, player.blitGC,
7988 // corner.x, corner.y, squareSize, squareSize,
7989 // 0, 0); // [HGM] zh: unstack in stead of grab
7990 damage[boardY][boardX] = True;
7992 player.dragActive = False;
8002 /* Are we animating? */
8003 if (!appData.animateDragging || appData.blindfold)
8007 if (! player.dragActive)
8009 /* Move piece, maintaining same relative position
8010 of mouse within square */
8011 corner.x = x - player.mouseDelta.x;
8012 corner.y = y - player.mouseDelta.y;
8013 AnimationFrame(&player, &corner, player.dragPiece);
8015 if (appData.highlightDragging) {
8017 BoardSquare(x, y, &boardX, &boardY);
8018 SetHighlights(fromX, fromY, boardX, boardY);
8027 int boardX, boardY, color;
8030 /* Are we animating? */
8031 if (!appData.animateDragging || appData.blindfold)
8035 if (! player.dragActive)
8037 /* Last frame in sequence is square piece is
8038 placed on, which may not match mouse exactly. */
8039 BoardSquare(x, y, &boardX, &boardY);
8040 ScreenSquare(boardX, boardY, &corner, &color);
8041 EndAnimation(&player, &corner);
8043 /* Be sure end square is redrawn */
8044 damage[boardY][boardX] = True;
8046 /* This prevents weird things happening with fast successive
8047 clicks which on my Sun at least can cause motion events
8048 without corresponding press/release. */
8049 player.dragActive = False;
8052 /* Handle expose event while piece being dragged */
8057 if (!player.dragActive || appData.blindfold)
8060 /* What we're doing: logically, the move hasn't been made yet,
8061 so the piece is still in it's original square. But visually
8062 it's being dragged around the board. So we erase the square
8063 that the piece is on and draw it at the last known drag point. */
8064 BlankSquare(player.startSquare.x, player.startSquare.y,
8065 player.startColor, EmptySquare, xBoardWindow);
8066 AnimationFrame(&player, &player.prevFrame, player.dragPiece);
8067 damage[player.startBoardY][player.startBoardX] = TRUE;
8071 SetProgramStats( FrontEndProgramStats * stats )
8074 // [HGM] done, but perhaps backend should call this directly?
8075 EngineOutputUpdate( stats );