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 TestLegalityProc P((Widget w, XEvent *event, String *prms,
366 void AboutGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
367 void DebugProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
368 void NothingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
369 void Iconify P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
370 void DisplayMove P((int moveNumber));
371 void DisplayTitle P((char *title));
372 void ICSInitScript P((void));
373 int LoadGamePopUp P((FILE *f, int gameNumber, char *title));
374 void ErrorPopUp P((char *title, char *text, int modal));
375 void ErrorPopDown P((void));
376 static char *ExpandPathName P((char *path));
377 static void CreateAnimVars P((void));
378 void DragPieceBegin P((int x, int y));
379 static void DragPieceMove P((int x, int y));
380 void DragPieceEnd P((int x, int y));
381 static void DrawDragPiece P((void));
382 char *ModeToWidgetName P((GameMode mode));
383 void EngineOutputUpdate( FrontEndProgramStats * stats );
384 void ShuffleMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
385 void EngineMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
386 void UciMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
387 void TimeControlProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
388 void NewVariantProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
389 void FirstSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
390 void SecondSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
391 void ShufflePopDown P(());
392 void EnginePopDown P(());
393 void UciPopDown P(());
394 void TimeControlPopDown P(());
395 void NewVariantPopDown P(());
396 void SettingsPopDown P(());
397 void SetMenuEnables P((Enables *enab));
400 * XBoard depends on Xt R4 or higher
402 int xtVersion = XtSpecificationRelease;
407 Pixel lightSquareColor, darkSquareColor, whitePieceColor, blackPieceColor,
408 jailSquareColor, highlightSquareColor, premoveHighlightColor;
409 Pixel lowTimeWarningColor;
411 #define LINE_TYPE_NORMAL 0
412 #define LINE_TYPE_HIGHLIGHT 1
413 #define LINE_TYPE_PRE 2
416 GC lightSquareGC, darkSquareGC, jailSquareGC, wdPieceGC, wlPieceGC,
417 bdPieceGC, blPieceGC, wbPieceGC, bwPieceGC, coordGC,
418 wjPieceGC, bjPieceGC;
419 Pixmap iconPixmap, wIconPixmap, bIconPixmap, xMarkPixmap;
420 Widget shellWidget, layoutWidget, formWidget, boardWidget, messageWidget,
421 whiteTimerWidget, blackTimerWidget, titleWidget, widgetList[16],
422 commentShell, promotionShell, whitePieceMenu, blackPieceMenu, dropMenu,
423 menuBarWidget, buttonBarWidget, editShell, errorShell, analysisShell,
424 ICSInputShell, fileNameShell, askQuestionShell;
425 Font clockFontID, coordFontID, countFontID;
426 XFontStruct *clockFontStruct, *coordFontStruct, *countFontStruct;
427 XtAppContext appContext;
429 char *oldICSInteractionTitle;
433 char installDir[] = "."; // [HGM] UCI: needed for UCI; probably needs run-time initializtion
435 Position commentX = -1, commentY = -1;
436 Dimension commentW, commentH;
438 int squareSize, smallLayout = 0, tinyLayout = 0,
439 marginW, marginH, // [HGM] for run-time resizing
440 fromX = -1, fromY = -1, toX, toY, commentUp = False, analysisUp = False,
441 ICSInputBoxUp = False, askQuestionUp = False,
442 filenameUp = False, promotionUp = False, pmFromX = -1, pmFromY = -1,
443 editUp = False, errorUp = False, errorExitStatus = -1, lineGap;
444 Pixel timerForegroundPixel, timerBackgroundPixel;
445 Pixel buttonForegroundPixel, buttonBackgroundPixel;
446 char *chessDir, *programName, *programVersion,
447 *gameCopyFilename, *gamePasteFilename;
451 Pixmap pieceBitmap[2][(int)BlackPawn];
452 Pixmap pieceBitmap2[2][(int)BlackPawn+4]; /* [HGM] pieces */
453 Pixmap xpmPieceBitmap[4][(int)BlackPawn]; /* LL, LD, DL, DD actually used*/
454 Pixmap xpmPieceBitmap2[4][(int)BlackPawn+4]; /* LL, LD, DL, DD set to select from */
455 Pixmap xpmLightSquare, xpmDarkSquare, xpmJailSquare;
456 int useImages=0, useImageSqs;
457 XImage *ximPieceBitmap[4][(int)BlackPawn+4]; /* LL, LD, DL, DD */
458 Pixmap ximMaskPm[(int)BlackPawn]; /* clipmasks, used for XIM pieces */
459 Pixmap ximMaskPm2[(int)BlackPawn+4]; /* clipmasks, used for XIM pieces */
460 XImage *ximLightSquare, *ximDarkSquare;
463 #define pieceToSolid(piece) &pieceBitmap[SOLID][(piece) % (int)BlackPawn]
464 #define pieceToOutline(piece) &pieceBitmap[OUTLINE][(piece) % (int)BlackPawn]
466 #define White(piece) ((int)(piece) < (int)BlackPawn)
468 /* Variables for doing smooth animation. This whole thing
469 would be much easier if the board was double-buffered,
470 but that would require a fairly major rewrite. */
475 GC blitGC, pieceGC, outlineGC;
476 XPoint startSquare, prevFrame, mouseDelta;
480 int startBoardX, startBoardY;
483 /* There can be two pieces being animated at once: a player
484 can begin dragging a piece before the remote opponent has moved. */
486 static AnimState game, player;
488 /* Bitmaps for use as masks when drawing XPM pieces.
489 Need one for each black and white piece. */
490 static Pixmap xpmMask[BlackKing + 1];
492 /* This magic number is the number of intermediate frames used
493 in each half of the animation. For short moves it's reduced
494 by 1. The total number of frames will be factor * 2 + 1. */
497 SizeDefaults sizeDefaults[] = SIZE_DEFAULTS;
499 Enables icsEnables[] = {
500 { "menuFile.Mail Move", False },
501 { "menuFile.Reload CMail Message", False },
502 { "menuMode.Machine Black", False },
503 { "menuMode.Machine White", False },
504 { "menuMode.Analysis Mode", False },
505 { "menuMode.Analyze File", False },
506 { "menuMode.Two Machines", False },
508 { "menuHelp.Hint", False },
509 { "menuHelp.Book", False },
510 { "menuStep.Move Now", False },
511 { "menuOptions.Periodic Updates", False },
512 { "menuOptions.Hide Thinking", False },
513 { "menuOptions.Ponder Next Move", False },
518 Enables ncpEnables[] = {
519 { "menuFile.Mail Move", False },
520 { "menuFile.Reload CMail Message", False },
521 { "menuMode.Machine White", False },
522 { "menuMode.Machine Black", False },
523 { "menuMode.Analysis Mode", False },
524 { "menuMode.Analyze File", False },
525 { "menuMode.Two Machines", False },
526 { "menuMode.ICS Client", False },
527 { "menuMode.ICS Input Box", False },
529 { "menuStep.Revert", False },
530 { "menuStep.Move Now", False },
531 { "menuStep.Retract Move", False },
532 { "menuOptions.Auto Comment", False },
533 { "menuOptions.Auto Flag", False },
534 { "menuOptions.Auto Flip View", False },
535 { "menuOptions.Auto Observe", False },
536 { "menuOptions.Auto Raise Board", False },
537 { "menuOptions.Get Move List", False },
538 { "menuOptions.ICS Alarm", False },
539 { "menuOptions.Move Sound", False },
540 { "menuOptions.Quiet Play", False },
541 { "menuOptions.Hide Thinking", False },
542 { "menuOptions.Periodic Updates", False },
543 { "menuOptions.Ponder Next Move", False },
544 { "menuHelp.Hint", False },
545 { "menuHelp.Book", False },
549 Enables gnuEnables[] = {
550 { "menuMode.ICS Client", False },
551 { "menuMode.ICS Input Box", False },
552 { "menuAction.Accept", False },
553 { "menuAction.Decline", False },
554 { "menuAction.Rematch", False },
555 { "menuAction.Adjourn", False },
556 { "menuAction.Stop Examining", False },
557 { "menuAction.Stop Observing", False },
558 { "menuStep.Revert", False },
559 { "menuOptions.Auto Comment", False },
560 { "menuOptions.Auto Observe", False },
561 { "menuOptions.Auto Raise Board", False },
562 { "menuOptions.Get Move List", False },
563 { "menuOptions.Premove", False },
564 { "menuOptions.Quiet Play", False },
566 /* The next two options rely on SetCmailMode being called *after* */
567 /* SetGNUMode so that when GNU is being used to give hints these */
568 /* menu options are still available */
570 { "menuFile.Mail Move", False },
571 { "menuFile.Reload CMail Message", False },
575 Enables cmailEnables[] = {
577 { "menuAction.Call Flag", False },
578 { "menuAction.Draw", True },
579 { "menuAction.Adjourn", False },
580 { "menuAction.Abort", False },
581 { "menuAction.Stop Observing", False },
582 { "menuAction.Stop Examining", False },
583 { "menuFile.Mail Move", True },
584 { "menuFile.Reload CMail Message", True },
588 Enables trainingOnEnables[] = {
589 { "menuMode.Edit Comment", False },
590 { "menuMode.Pause", False },
591 { "menuStep.Forward", False },
592 { "menuStep.Backward", False },
593 { "menuStep.Forward to End", False },
594 { "menuStep.Back to Start", False },
595 { "menuStep.Move Now", False },
596 { "menuStep.Truncate Game", False },
600 Enables trainingOffEnables[] = {
601 { "menuMode.Edit Comment", True },
602 { "menuMode.Pause", True },
603 { "menuStep.Forward", True },
604 { "menuStep.Backward", True },
605 { "menuStep.Forward to End", True },
606 { "menuStep.Back to Start", True },
607 { "menuStep.Move Now", True },
608 { "menuStep.Truncate Game", True },
612 Enables machineThinkingEnables[] = {
613 { "menuFile.Load Game", False },
614 { "menuFile.Load Next Game", False },
615 { "menuFile.Load Previous Game", False },
616 { "menuFile.Reload Same Game", False },
617 { "menuFile.Paste Game", False },
618 { "menuFile.Load Position", False },
619 { "menuFile.Load Next Position", False },
620 { "menuFile.Load Previous Position", False },
621 { "menuFile.Reload Same Position", False },
622 { "menuFile.Paste Position", False },
623 { "menuMode.Machine White", False },
624 { "menuMode.Machine Black", False },
625 { "menuMode.Two Machines", False },
626 { "menuStep.Retract Move", False },
630 Enables userThinkingEnables[] = {
631 { "menuFile.Load Game", True },
632 { "menuFile.Load Next Game", True },
633 { "menuFile.Load Previous Game", True },
634 { "menuFile.Reload Same Game", True },
635 { "menuFile.Paste Game", True },
636 { "menuFile.Load Position", True },
637 { "menuFile.Load Next Position", True },
638 { "menuFile.Load Previous Position", True },
639 { "menuFile.Reload Same Position", True },
640 { "menuFile.Paste Position", True },
641 { "menuMode.Machine White", True },
642 { "menuMode.Machine Black", True },
643 { "menuMode.Two Machines", True },
644 { "menuStep.Retract Move", True },
650 MenuItem fileMenu[] = {
651 {N_("New Shuffle Game ..."), ShuffleMenuProc},
652 {N_("New Variant ..."), NewVariantProc}, // [HGM] variant: not functional yet
653 {"----", NothingProc},
654 {N_("Save Game"), SaveGameProc},
655 {"----", NothingProc},
656 {N_("Copy Game"), CopyGameProc},
657 {N_("Paste Game"), PasteGameProc},
658 {"----", NothingProc},
659 {N_("Load Position"), LoadPositionProc},
660 {N_("Load Next Position"), LoadNextPositionProc},
661 {N_("Load Previous Position"), LoadPrevPositionProc},
662 {N_("Reload Same Position"), ReloadPositionProc},
663 {N_("Save Position"), SavePositionProc},
664 {"----", NothingProc},
665 {N_("Copy Position"), CopyPositionProc},
666 {N_("Paste Position"), PastePositionProc},
667 {"----", NothingProc},
668 {N_("Mail Move"), MailMoveProc},
669 {N_("Reload CMail Message"), ReloadCmailMsgProc},
670 {"----", NothingProc},
674 MenuItem modeMenu[] = {
675 // {N_("Machine White"), MachineWhiteProc},
676 // {N_("Machine Black"), MachineBlackProc},
677 // {N_("Two Machines"), TwoMachinesProc},
678 {N_("Analysis Mode"), AnalyzeModeProc},
679 {N_("Analyze File"), AnalyzeFileProc },
680 // {N_("ICS Client"), IcsClientProc},
681 {N_("Edit Game"), EditGameProc},
682 {N_("Edit Position"), EditPositionProc},
683 {N_("Training"), TrainingProc},
684 {"----", NothingProc},
685 {N_("Show Engine Output"), EngineOutputProc},
686 {N_("Show Evaluation Graph"), NothingProc}, // [HGM] evalgr: not functional yet
687 {N_("Show Game List"), ShowGameListProc},
688 // {"Show Move History", HistoryShowProc}, // [HGM] hist: activate 4.2.7 code
689 {"----", NothingProc},
690 {N_("Edit Tags"), EditTagsProc},
691 {N_("Edit Comment"), EditCommentProc},
692 {N_("ICS Input Box"), IcsInputBoxProc},
696 MenuItem optionsMenu[] = {
697 // {N_("Flip View"), FlipViewProc},
698 // {"----", NothingProc},
699 {N_("Adjudications ..."), EngineMenuProc},
700 {N_("General Settings ..."), UciMenuProc},
701 {N_("Engine #1 Settings ..."), FirstSettingsProc},
702 {N_("Engine #2 Settings ..."), SecondSettingsProc},
703 {N_("Time Control ..."), TimeControlProc},
704 {"----", NothingProc},
705 {N_("Always Queen"), AlwaysQueenProc},
706 {N_("Animate Dragging"), AnimateDraggingProc},
707 {N_("Animate Moving"), AnimateMovingProc},
708 {N_("Auto Comment"), AutocommProc},
709 {N_("Auto Flag"), AutoflagProc},
710 {N_("Auto Flip View"), AutoflipProc},
711 {N_("Auto Observe"), AutobsProc},
712 {N_("Auto Raise Board"), AutoraiseProc},
713 {N_("Auto Save"), AutosaveProc},
714 {N_("Blindfold"), BlindfoldProc},
715 {N_("Flash Moves"), FlashMovesProc},
716 // {N_("Get Move List"), GetMoveListProc},
718 {N_("Highlight Dragging"), HighlightDraggingProc},
720 {N_("Highlight Last Move"), HighlightLastMoveProc},
721 {N_("Move Sound"), MoveSoundProc},
722 {N_("ICS Alarm"), IcsAlarmProc},
723 {N_("Old Save Style"), OldSaveStyleProc},
724 {N_("Periodic Updates"), PeriodicUpdatesProc},
725 {N_("Ponder Next Move"), PonderNextMoveProc},
726 {N_("Popup Exit Message"), PopupExitMessageProc},
727 {N_("Popup Move Errors"), PopupMoveErrorsProc},
728 {N_("Premove"), PremoveProc},
729 {N_("Quiet Play"), QuietPlayProc},
730 // {N_("Hide Thinking"), HideThinkingProc},
731 {N_("Test Legality"), TestLegalityProc},
736 {N_("File"), fileMenu},
737 {N_("Mode"), modeMenu},
738 {N_("Options"), optionsMenu},
742 #define PAUSE_BUTTON N_("P")
743 MenuItem buttonBar[] = {
744 // {"<<", ToStartProc},
745 // {"<", BackwardProc},
746 // {PAUSE_BUTTON, PauseProc},
747 // {">", ForwardProc},
748 // {">>", ToEndProc},
752 #define PIECE_MENU_SIZE 18
753 String pieceMenuStrings[2][PIECE_MENU_SIZE] = {
754 { N_("White"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
755 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
756 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
757 N_("Empty square"), N_("Clear board") },
758 { N_("Black"), "----", 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") }
763 /* must be in same order as PieceMenuStrings! */
764 ChessSquare pieceMenuTranslation[2][PIECE_MENU_SIZE] = {
765 { WhitePlay, (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
766 WhiteRook, WhiteQueen, WhiteKing, (ChessSquare) 0, WhiteAlfil,
767 WhiteCannon, WhiteAngel, WhiteMarshall, (ChessSquare) 0,
768 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
769 { BlackPlay, (ChessSquare) 0, BlackPawn, BlackKnight, BlackBishop,
770 BlackRook, BlackQueen, BlackKing, (ChessSquare) 0, BlackAlfil,
771 BlackCannon, BlackAngel, BlackMarshall, (ChessSquare) 0,
772 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
775 #define DROP_MENU_SIZE 6
776 String dropMenuStrings[DROP_MENU_SIZE] = {
777 "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"), N_("Queen")
779 /* must be in same order as PieceMenuStrings! */
780 ChessSquare dropMenuTranslation[DROP_MENU_SIZE] = {
781 (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
782 WhiteRook, WhiteQueen
790 DropMenuEnables dmEnables[] = {
799 { XtNborderWidth, 0 },
800 { XtNdefaultDistance, 0 },
804 { XtNborderWidth, 0 },
805 { XtNresizable, (XtArgVal) True },
809 { XtNborderWidth, 0 },
814 XtResource clientResources[] = {
815 { "whitePieceColor", "whitePieceColor", XtRString, sizeof(String),
816 XtOffset(AppDataPtr, whitePieceColor), XtRString,
818 { "blackPieceColor", "blackPieceColor", XtRString, sizeof(String),
819 XtOffset(AppDataPtr, blackPieceColor), XtRString,
821 { "lightSquareColor", "lightSquareColor", XtRString,
822 sizeof(String), XtOffset(AppDataPtr, lightSquareColor),
823 XtRString, LIGHT_SQUARE_COLOR },
824 { "darkSquareColor", "darkSquareColor", XtRString, sizeof(String),
825 XtOffset(AppDataPtr, darkSquareColor), XtRString,
827 { "highlightSquareColor", "highlightSquareColor", XtRString,
828 sizeof(String), XtOffset(AppDataPtr, highlightSquareColor),
829 XtRString, HIGHLIGHT_SQUARE_COLOR },
830 { "premoveHighlightColor", "premoveHighlightColor", XtRString,
831 sizeof(String), XtOffset(AppDataPtr, premoveHighlightColor),
832 XtRString, PREMOVE_HIGHLIGHT_COLOR },
833 { "movesPerSession", "movesPerSession", XtRInt, sizeof(int),
834 XtOffset(AppDataPtr, movesPerSession), XtRImmediate,
835 (XtPointer) MOVES_PER_SESSION },
836 { "timeIncrement", "timeIncrement", XtRInt, sizeof(int),
837 XtOffset(AppDataPtr, timeIncrement), XtRImmediate,
838 (XtPointer) TIME_INCREMENT },
839 { "initString", "initString", XtRString, sizeof(String),
840 XtOffset(AppDataPtr, initString), XtRString, INIT_STRING },
841 { "secondInitString", "secondInitString", XtRString, sizeof(String),
842 XtOffset(AppDataPtr, secondInitString), XtRString, INIT_STRING },
843 { "firstComputerString", "firstComputerString", XtRString,
844 sizeof(String), XtOffset(AppDataPtr, firstComputerString), XtRString,
846 { "secondComputerString", "secondComputerString", XtRString,
847 sizeof(String), XtOffset(AppDataPtr, secondComputerString), XtRString,
849 { "firstChessProgram", "firstChessProgram", XtRString,
850 sizeof(String), XtOffset(AppDataPtr, firstChessProgram),
851 XtRString, FIRST_CHESS_PROGRAM },
852 { "secondChessProgram", "secondChessProgram", XtRString,
853 sizeof(String), XtOffset(AppDataPtr, secondChessProgram),
854 XtRString, SECOND_CHESS_PROGRAM },
855 { "firstPlaysBlack", "firstPlaysBlack", XtRBoolean,
856 sizeof(Boolean), XtOffset(AppDataPtr, firstPlaysBlack),
857 XtRImmediate, (XtPointer) False },
858 { "noChessProgram", "noChessProgram", XtRBoolean,
859 sizeof(Boolean), XtOffset(AppDataPtr, noChessProgram),
860 XtRImmediate, (XtPointer) False },
861 { "firstHost", "firstHost", XtRString, sizeof(String),
862 XtOffset(AppDataPtr, firstHost), XtRString, FIRST_HOST },
863 { "secondHost", "secondHost", XtRString, sizeof(String),
864 XtOffset(AppDataPtr, secondHost), XtRString, SECOND_HOST },
865 { "firstDirectory", "firstDirectory", XtRString, sizeof(String),
866 XtOffset(AppDataPtr, firstDirectory), XtRString, "." },
867 { "secondDirectory", "secondDirectory", XtRString, sizeof(String),
868 XtOffset(AppDataPtr, secondDirectory), XtRString, "." },
869 { "bitmapDirectory", "bitmapDirectory", XtRString,
870 sizeof(String), XtOffset(AppDataPtr, bitmapDirectory),
872 { "remoteShell", "remoteShell", XtRString, sizeof(String),
873 XtOffset(AppDataPtr, remoteShell), XtRString, REMOTE_SHELL },
874 { "remoteUser", "remoteUser", XtRString, sizeof(String),
875 XtOffset(AppDataPtr, remoteUser), XtRString, "" },
876 { "timeDelay", "timeDelay", XtRFloat, sizeof(float),
877 XtOffset(AppDataPtr, timeDelay), XtRString,
878 (XtPointer) TIME_DELAY_QUOTE },
879 { "timeControl", "timeControl", XtRString, sizeof(String),
880 XtOffset(AppDataPtr, timeControl), XtRString,
881 (XtPointer) TIME_CONTROL },
882 { "internetChessServerMode", "internetChessServerMode",
883 XtRBoolean, sizeof(Boolean),
884 XtOffset(AppDataPtr, icsActive), XtRImmediate,
886 { "internetChessServerHost", "internetChessServerHost",
887 XtRString, sizeof(String),
888 XtOffset(AppDataPtr, icsHost),
889 XtRString, (XtPointer) ICS_HOST },
890 { "internetChessServerPort", "internetChessServerPort",
891 XtRString, sizeof(String),
892 XtOffset(AppDataPtr, icsPort), XtRString,
893 (XtPointer) ICS_PORT },
894 { "internetChessServerCommPort", "internetChessServerCommPort",
895 XtRString, sizeof(String),
896 XtOffset(AppDataPtr, icsCommPort), XtRString,
898 { "internetChessServerLogonScript", "internetChessServerLogonScript",
899 XtRString, sizeof(String),
900 XtOffset(AppDataPtr, icsLogon), XtRString,
902 { "internetChessServerHelper", "internetChessServerHelper",
903 XtRString, sizeof(String),
904 XtOffset(AppDataPtr, icsHelper), XtRString, "" },
905 { "internetChessServerInputBox", "internetChessServerInputBox",
906 XtRBoolean, sizeof(Boolean),
907 XtOffset(AppDataPtr, icsInputBox), XtRImmediate,
909 { "icsAlarm", "icsAlarm",
910 XtRBoolean, sizeof(Boolean),
911 XtOffset(AppDataPtr, icsAlarm), XtRImmediate,
913 { "icsAlarmTime", "icsAlarmTime",
915 XtOffset(AppDataPtr, icsAlarmTime), XtRImmediate,
917 { "useTelnet", "useTelnet", XtRBoolean, sizeof(Boolean),
918 XtOffset(AppDataPtr, useTelnet), XtRImmediate,
920 { "telnetProgram", "telnetProgram", XtRString, sizeof(String),
921 XtOffset(AppDataPtr, telnetProgram), XtRString, TELNET_PROGRAM },
922 { "gateway", "gateway", XtRString, sizeof(String),
923 XtOffset(AppDataPtr, gateway), XtRString, "" },
924 { "loadGameFile", "loadGameFile", XtRString, sizeof(String),
925 XtOffset(AppDataPtr, loadGameFile), XtRString, "" },
926 { "loadGameIndex", "loadGameIndex",
928 XtOffset(AppDataPtr, loadGameIndex), XtRImmediate,
930 { "saveGameFile", "saveGameFile", XtRString, sizeof(String),
931 XtOffset(AppDataPtr, saveGameFile), XtRString, "" },
932 { "autoRaiseBoard", "autoRaiseBoard", XtRBoolean,
933 sizeof(Boolean), XtOffset(AppDataPtr, autoRaiseBoard),
934 XtRImmediate, (XtPointer) True },
935 { "autoSaveGames", "autoSaveGames", XtRBoolean,
936 sizeof(Boolean), XtOffset(AppDataPtr, autoSaveGames),
937 XtRImmediate, (XtPointer) False },
938 { "blindfold", "blindfold", XtRBoolean,
939 sizeof(Boolean), XtOffset(AppDataPtr, blindfold),
940 XtRImmediate, (XtPointer) False },
941 { "loadPositionFile", "loadPositionFile", XtRString,
942 sizeof(String), XtOffset(AppDataPtr, loadPositionFile),
944 { "loadPositionIndex", "loadPositionIndex",
946 XtOffset(AppDataPtr, loadPositionIndex), XtRImmediate,
948 { "savePositionFile", "savePositionFile", XtRString,
949 sizeof(String), XtOffset(AppDataPtr, savePositionFile),
951 { "matchMode", "matchMode", XtRBoolean, sizeof(Boolean),
952 XtOffset(AppDataPtr, matchMode), XtRImmediate, (XtPointer) False },
953 { "matchGames", "matchGames", XtRInt, sizeof(int),
954 XtOffset(AppDataPtr, matchGames), XtRImmediate,
956 { "monoMode", "monoMode", XtRBoolean, sizeof(Boolean),
957 XtOffset(AppDataPtr, monoMode), XtRImmediate,
959 { "debugMode", "debugMode", XtRBoolean, sizeof(Boolean),
960 XtOffset(AppDataPtr, debugMode), XtRImmediate,
962 { "clockMode", "clockMode", XtRBoolean, sizeof(Boolean),
963 XtOffset(AppDataPtr, clockMode), XtRImmediate,
965 { "boardSize", "boardSize", XtRString, sizeof(String),
966 XtOffset(AppDataPtr, boardSize), XtRString, "" },
967 { "searchTime", "searchTime", XtRString, sizeof(String),
968 XtOffset(AppDataPtr, searchTime), XtRString,
970 { "searchDepth", "searchDepth", XtRInt, sizeof(int),
971 XtOffset(AppDataPtr, searchDepth), XtRImmediate,
973 { "showCoords", "showCoords", XtRBoolean, sizeof(Boolean),
974 XtOffset(AppDataPtr, showCoords), XtRImmediate,
976 { "showJail", "showJail", XtRInt, sizeof(int),
977 XtOffset(AppDataPtr, showJail), XtRImmediate,
979 { "showThinking", "showThinking", XtRBoolean, sizeof(Boolean),
980 XtOffset(AppDataPtr, showThinking), XtRImmediate,
982 { "ponderNextMove", "ponderNextMove", XtRBoolean, sizeof(Boolean),
983 XtOffset(AppDataPtr, ponderNextMove), XtRImmediate,
985 { "periodicUpdates", "periodicUpdates", XtRBoolean, sizeof(Boolean),
986 XtOffset(AppDataPtr, periodicUpdates), XtRImmediate,
988 { "clockFont", "clockFont", XtRString, sizeof(String),
989 XtOffset(AppDataPtr, clockFont), XtRString, CLOCK_FONT },
990 { "coordFont", "coordFont", XtRString, sizeof(String),
991 XtOffset(AppDataPtr, coordFont), XtRString, COORD_FONT },
992 { "font", "font", XtRString, sizeof(String),
993 XtOffset(AppDataPtr, font), XtRString, DEFAULT_FONT },
994 { "ringBellAfterMoves", "ringBellAfterMoves",
995 XtRBoolean, sizeof(Boolean),
996 XtOffset(AppDataPtr, ringBellAfterMoves),
997 XtRImmediate, (XtPointer) False },
998 { "autoCallFlag", "autoCallFlag", XtRBoolean,
999 sizeof(Boolean), XtOffset(AppDataPtr, autoCallFlag),
1000 XtRImmediate, (XtPointer) False },
1001 { "autoFlipView", "autoFlipView", XtRBoolean,
1002 sizeof(Boolean), XtOffset(AppDataPtr, autoFlipView),
1003 XtRImmediate, (XtPointer) True },
1004 { "autoObserve", "autoObserve", XtRBoolean,
1005 sizeof(Boolean), XtOffset(AppDataPtr, autoObserve),
1006 XtRImmediate, (XtPointer) False },
1007 { "autoComment", "autoComment", XtRBoolean,
1008 sizeof(Boolean), XtOffset(AppDataPtr, autoComment),
1009 XtRImmediate, (XtPointer) False },
1010 { "getMoveList", "getMoveList", XtRBoolean,
1011 sizeof(Boolean), XtOffset(AppDataPtr, getMoveList),
1012 XtRImmediate, (XtPointer) True },
1014 { "highlightDragging", "highlightDragging", XtRBoolean,
1015 sizeof(Boolean), XtOffset(AppDataPtr, highlightDragging),
1016 XtRImmediate, (XtPointer) False },
1018 { "highlightLastMove", "highlightLastMove", XtRBoolean,
1019 sizeof(Boolean), XtOffset(AppDataPtr, highlightLastMove),
1020 XtRImmediate, (XtPointer) False },
1021 { "premove", "premove", XtRBoolean,
1022 sizeof(Boolean), XtOffset(AppDataPtr, premove),
1023 XtRImmediate, (XtPointer) True },
1024 { "testLegality", "testLegality", XtRBoolean,
1025 sizeof(Boolean), XtOffset(AppDataPtr, testLegality),
1026 XtRImmediate, (XtPointer) True },
1027 { "flipView", "flipView", XtRBoolean,
1028 sizeof(Boolean), XtOffset(AppDataPtr, flipView),
1029 XtRImmediate, (XtPointer) False },
1030 { "cmail", "cmailGameName", XtRString, sizeof(String),
1031 XtOffset(AppDataPtr, cmailGameName), XtRString, "" },
1032 { "alwaysPromoteToQueen", "alwaysPromoteToQueen", XtRBoolean,
1033 sizeof(Boolean), XtOffset(AppDataPtr, alwaysPromoteToQueen),
1034 XtRImmediate, (XtPointer) False },
1035 { "oldSaveStyle", "oldSaveStyle", XtRBoolean,
1036 sizeof(Boolean), XtOffset(AppDataPtr, oldSaveStyle),
1037 XtRImmediate, (XtPointer) False },
1038 { "quietPlay", "quietPlay", XtRBoolean,
1039 sizeof(Boolean), XtOffset(AppDataPtr, quietPlay),
1040 XtRImmediate, (XtPointer) False },
1041 { "titleInWindow", "titleInWindow", XtRBoolean,
1042 sizeof(Boolean), XtOffset(AppDataPtr, titleInWindow),
1043 XtRImmediate, (XtPointer) False },
1044 { "localLineEditing", "localLineEditing", XtRBoolean,
1045 sizeof(Boolean), XtOffset(AppDataPtr, localLineEditing),
1046 XtRImmediate, (XtPointer) True }, /* not implemented, must be True */
1048 { "zippyTalk", "zippyTalk", XtRBoolean,
1049 sizeof(Boolean), XtOffset(AppDataPtr, zippyTalk),
1050 XtRImmediate, (XtPointer) ZIPPY_TALK },
1051 { "zippyPlay", "zippyPlay", XtRBoolean,
1052 sizeof(Boolean), XtOffset(AppDataPtr, zippyPlay),
1053 XtRImmediate, (XtPointer) ZIPPY_PLAY },
1054 { "zippyLines", "zippyLines", XtRString, sizeof(String),
1055 XtOffset(AppDataPtr, zippyLines), XtRString, ZIPPY_LINES },
1056 { "zippyPinhead", "zippyPinhead", XtRString, sizeof(String),
1057 XtOffset(AppDataPtr, zippyPinhead), XtRString, ZIPPY_PINHEAD },
1058 { "zippyPassword", "zippyPassword", XtRString, sizeof(String),
1059 XtOffset(AppDataPtr, zippyPassword), XtRString, ZIPPY_PASSWORD },
1060 { "zippyPassword2", "zippyPassword2", XtRString, sizeof(String),
1061 XtOffset(AppDataPtr, zippyPassword2), XtRString, ZIPPY_PASSWORD2 },
1062 { "zippyWrongPassword", "zippyWrongPassword", XtRString, sizeof(String),
1063 XtOffset(AppDataPtr, zippyWrongPassword), XtRString,
1064 ZIPPY_WRONG_PASSWORD },
1065 { "zippyAcceptOnly", "zippyAcceptOnly", XtRString, sizeof(String),
1066 XtOffset(AppDataPtr, zippyAcceptOnly), XtRString, ZIPPY_ACCEPT_ONLY },
1067 { "zippyUseI", "zippyUseI", XtRBoolean,
1068 sizeof(Boolean), XtOffset(AppDataPtr, zippyUseI),
1069 XtRImmediate, (XtPointer) ZIPPY_USE_I },
1070 { "zippyBughouse", "zippyBughouse", XtRInt,
1071 sizeof(int), XtOffset(AppDataPtr, zippyBughouse),
1072 XtRImmediate, (XtPointer) ZIPPY_BUGHOUSE },
1073 { "zippyNoplayCrafty", "zippyNoplayCrafty", XtRBoolean,
1074 sizeof(Boolean), XtOffset(AppDataPtr, zippyNoplayCrafty),
1075 XtRImmediate, (XtPointer) ZIPPY_NOPLAY_CRAFTY },
1076 { "zippyGameEnd", "zippyGameEnd", XtRString, sizeof(String),
1077 XtOffset(AppDataPtr, zippyGameEnd), XtRString, ZIPPY_GAME_END },
1078 { "zippyGameStart", "zippyGameStart", XtRString, sizeof(String),
1079 XtOffset(AppDataPtr, zippyGameStart), XtRString, ZIPPY_GAME_START },
1080 { "zippyAdjourn", "zippyAdjourn", XtRBoolean,
1081 sizeof(Boolean), XtOffset(AppDataPtr, zippyAdjourn),
1082 XtRImmediate, (XtPointer) ZIPPY_ADJOURN },
1083 { "zippyAbort", "zippyAbort", XtRBoolean,
1084 sizeof(Boolean), XtOffset(AppDataPtr, zippyAbort),
1085 XtRImmediate, (XtPointer) ZIPPY_ABORT },
1086 { "zippyVariants", "zippyVariants", XtRString, sizeof(String),
1087 XtOffset(AppDataPtr, zippyVariants), XtRString, ZIPPY_VARIANTS },
1088 { "zippyMaxGames", "zippyMaxGames", XtRInt, sizeof(int),
1089 XtOffset(AppDataPtr, zippyMaxGames), XtRImmediate,
1090 (XtPointer) ZIPPY_MAX_GAMES },
1091 { "zippyReplayTimeout", "zippyReplayTimeout", XtRInt, sizeof(int),
1092 XtOffset(AppDataPtr, zippyReplayTimeout), XtRImmediate,
1093 (XtPointer) ZIPPY_REPLAY_TIMEOUT },
1094 { "zippyShortGame", "zippyShortGame", XtRInt, sizeof(int),
1095 XtOffset(AppDataPtr, zippyShortGame), XtRImmediate,
1098 { "flashCount", "flashCount", XtRInt, sizeof(int),
1099 XtOffset(AppDataPtr, flashCount), XtRImmediate,
1100 (XtPointer) FLASH_COUNT },
1101 { "flashRate", "flashRate", XtRInt, sizeof(int),
1102 XtOffset(AppDataPtr, flashRate), XtRImmediate,
1103 (XtPointer) FLASH_RATE },
1104 { "pixmapDirectory", "pixmapDirectory", XtRString,
1105 sizeof(String), XtOffset(AppDataPtr, pixmapDirectory),
1107 { "msLoginDelay", "msLoginDelay", XtRInt, sizeof(int),
1108 XtOffset(AppDataPtr, msLoginDelay), XtRImmediate,
1109 (XtPointer) MS_LOGIN_DELAY },
1110 { "colorizeMessages", "colorizeMessages", XtRBoolean,
1111 sizeof(Boolean), XtOffset(AppDataPtr, colorize),
1112 XtRImmediate, (XtPointer) False },
1113 { "colorShout", "colorShout", XtRString,
1114 sizeof(String), XtOffset(AppDataPtr, colorShout),
1115 XtRString, COLOR_SHOUT },
1116 { "colorSShout", "colorSShout", XtRString,
1117 sizeof(String), XtOffset(AppDataPtr, colorSShout),
1118 XtRString, COLOR_SSHOUT },
1119 { "colorChannel1", "colorChannel1", XtRString,
1120 sizeof(String), XtOffset(AppDataPtr, colorChannel1),
1121 XtRString, COLOR_CHANNEL1 },
1122 { "colorChannel", "colorChannel", XtRString,
1123 sizeof(String), XtOffset(AppDataPtr, colorChannel),
1124 XtRString, COLOR_CHANNEL },
1125 { "colorKibitz", "colorKibitz", XtRString,
1126 sizeof(String), XtOffset(AppDataPtr, colorKibitz),
1127 XtRString, COLOR_KIBITZ },
1128 { "colorTell", "colorTell", XtRString,
1129 sizeof(String), XtOffset(AppDataPtr, colorTell),
1130 XtRString, COLOR_TELL },
1131 { "colorChallenge", "colorChallenge", XtRString,
1132 sizeof(String), XtOffset(AppDataPtr, colorChallenge),
1133 XtRString, COLOR_CHALLENGE },
1134 { "colorRequest", "colorRequest", XtRString,
1135 sizeof(String), XtOffset(AppDataPtr, colorRequest),
1136 XtRString, COLOR_REQUEST },
1137 { "colorSeek", "colorSeek", XtRString,
1138 sizeof(String), XtOffset(AppDataPtr, colorSeek),
1139 XtRString, COLOR_SEEK },
1140 { "colorNormal", "colorNormal", XtRString,
1141 sizeof(String), XtOffset(AppDataPtr, colorNormal),
1142 XtRString, COLOR_NORMAL },
1143 { "soundProgram", "soundProgram", XtRString,
1144 sizeof(String), XtOffset(AppDataPtr, soundProgram),
1145 XtRString, "play" },
1146 { "soundShout", "soundShout", XtRString,
1147 sizeof(String), XtOffset(AppDataPtr, soundShout),
1149 { "soundSShout", "soundSShout", XtRString,
1150 sizeof(String), XtOffset(AppDataPtr, soundSShout),
1152 { "soundChannel1", "soundChannel1", XtRString,
1153 sizeof(String), XtOffset(AppDataPtr, soundChannel1),
1155 { "soundChannel", "soundChannel", XtRString,
1156 sizeof(String), XtOffset(AppDataPtr, soundChannel),
1158 { "soundKibitz", "soundKibitz", XtRString,
1159 sizeof(String), XtOffset(AppDataPtr, soundKibitz),
1161 { "soundTell", "soundTell", XtRString,
1162 sizeof(String), XtOffset(AppDataPtr, soundTell),
1164 { "soundChallenge", "soundChallenge", XtRString,
1165 sizeof(String), XtOffset(AppDataPtr, soundChallenge),
1167 { "soundRequest", "soundRequest", XtRString,
1168 sizeof(String), XtOffset(AppDataPtr, soundRequest),
1170 { "soundSeek", "soundSeek", XtRString,
1171 sizeof(String), XtOffset(AppDataPtr, soundSeek),
1173 { "soundMove", "soundMove", XtRString,
1174 sizeof(String), XtOffset(AppDataPtr, soundMove),
1176 { "soundIcsWin", "soundIcsWin", XtRString,
1177 sizeof(String), XtOffset(AppDataPtr, soundIcsWin),
1179 { "soundIcsLoss", "soundIcsLoss", XtRString,
1180 sizeof(String), XtOffset(AppDataPtr, soundIcsLoss),
1182 { "soundIcsDraw", "soundIcsDraw", XtRString,
1183 sizeof(String), XtOffset(AppDataPtr, soundIcsDraw),
1185 { "soundIcsUnfinished", "soundIcsUnfinished", XtRString,
1186 sizeof(String), XtOffset(AppDataPtr, soundIcsUnfinished),
1188 { "soundIcsAlarm", "soundIcsAlarm", XtRString,
1189 sizeof(String), XtOffset(AppDataPtr, soundIcsAlarm),
1191 { "reuseFirst", "reuseFirst", XtRBoolean,
1192 sizeof(Boolean), XtOffset(AppDataPtr, reuseFirst),
1193 XtRImmediate, (XtPointer) True },
1194 { "reuseSecond", "reuseSecond", XtRBoolean,
1195 sizeof(Boolean), XtOffset(AppDataPtr, reuseSecond),
1196 XtRImmediate, (XtPointer) True },
1197 { "animateDragging", "animateDragging", XtRBoolean,
1198 sizeof(Boolean), XtOffset(AppDataPtr, animateDragging),
1199 XtRImmediate, (XtPointer) True },
1200 { "animateMoving", "animateMoving", XtRBoolean,
1201 sizeof(Boolean), XtOffset(AppDataPtr, animate),
1202 XtRImmediate, (XtPointer) True },
1203 { "animateSpeed", "animateSpeed", XtRInt,
1204 sizeof(int), XtOffset(AppDataPtr, animSpeed),
1205 XtRImmediate, (XtPointer)10 },
1206 { "popupExitMessage", "popupExitMessage", XtRBoolean,
1207 sizeof(Boolean), XtOffset(AppDataPtr, popupExitMessage),
1208 XtRImmediate, (XtPointer) True },
1209 { "popupMoveErrors", "popupMoveErrors", XtRBoolean,
1210 sizeof(Boolean), XtOffset(AppDataPtr, popupMoveErrors),
1211 XtRImmediate, (XtPointer) False },
1212 { "fontSizeTolerance", "fontSizeTolerance", XtRInt,
1213 sizeof(int), XtOffset(AppDataPtr, fontSizeTolerance),
1214 XtRImmediate, (XtPointer)4 },
1215 { "initialMode", "initialMode", XtRString,
1216 sizeof(String), XtOffset(AppDataPtr, initialMode),
1217 XtRImmediate, (XtPointer) "" },
1218 { "variant", "variant", XtRString,
1219 sizeof(String), XtOffset(AppDataPtr, variant),
1220 XtRImmediate, (XtPointer) "normal" },
1221 { "firstProtocolVersion", "firstProtocolVersion", XtRInt,
1222 sizeof(int), XtOffset(AppDataPtr, firstProtocolVersion),
1223 XtRImmediate, (XtPointer)PROTOVER },
1224 { "secondProtocolVersion", "secondProtocolVersion", XtRInt,
1225 sizeof(int), XtOffset(AppDataPtr, secondProtocolVersion),
1226 XtRImmediate, (XtPointer)PROTOVER },
1227 { "showButtonBar", "showButtonBar", XtRBoolean,
1228 sizeof(Boolean), XtOffset(AppDataPtr, showButtonBar),
1229 XtRImmediate, (XtPointer) True },
1230 { "lowTimeWarningColor", "lowTimeWarningColor", XtRString,
1231 sizeof(String), XtOffset(AppDataPtr, lowTimeWarningColor),
1232 XtRString, COLOR_LOWTIMEWARNING },
1233 { "lowTimeWarning", "lowTimeWarning", XtRBoolean,
1234 sizeof(Boolean), XtOffset(AppDataPtr, lowTimeWarning),
1235 XtRImmediate, (XtPointer) False },
1236 {"icsEngineAnalyze", "icsEngineAnalyze", XtRBoolean, /* [DM] icsEngineAnalyze */
1237 sizeof(Boolean), XtOffset(AppDataPtr, icsEngineAnalyze),
1238 XtRImmediate, (XtPointer) False },
1239 { "firstScoreAbs", "firstScoreAbs", XtRBoolean,
1240 sizeof(Boolean), XtOffset(AppDataPtr, firstScoreIsAbsolute),
1241 XtRImmediate, (XtPointer) False },
1242 { "secondScoreAbs", "secondScoreAbs", XtRBoolean,
1243 sizeof(Boolean), XtOffset(AppDataPtr, secondScoreIsAbsolute),
1244 XtRImmediate, (XtPointer) False },
1245 { "pgnExtendedInfo", "pgnExtendedInfo", XtRBoolean,
1246 sizeof(Boolean), XtOffset(AppDataPtr, saveExtendedInfoInPGN),
1247 XtRImmediate, (XtPointer) False },
1248 { "hideThinkingFromHuman", "hideThinkingFromHuman", XtRBoolean,
1249 sizeof(Boolean), XtOffset(AppDataPtr, hideThinkingFromHuman),
1250 XtRImmediate, (XtPointer) True },
1251 { "adjudicateLossThreshold", "adjudicateLossThreshold", XtRInt,
1252 sizeof(int), XtOffset(AppDataPtr, adjudicateLossThreshold),
1253 XtRImmediate, (XtPointer) 0},
1254 { "adjudicateDrawMoves", "adjudicateDrawMoves", XtRInt,
1255 sizeof(int), XtOffset(AppDataPtr, adjudicateDrawMoves),
1256 XtRImmediate, (XtPointer) 0},
1257 { "pgnEventHeader", "pgnEventHeader", XtRString,
1258 sizeof(String), XtOffset(AppDataPtr, pgnEventHeader),
1259 XtRImmediate, (XtPointer) "Computer Chess Game" },
1260 { "defaultFrcPosition", "defaultFrcPositon", XtRInt,
1261 sizeof(int), XtOffset(AppDataPtr, defaultFrcPosition),
1262 XtRImmediate, (XtPointer) -1},
1263 { "gameListTags", "gameListTags", XtRString,
1264 sizeof(String), XtOffset(AppDataPtr, gameListTags),
1265 XtRImmediate, (XtPointer) GLT_DEFAULT_TAGS },
1267 // [HGM] 4.3.xx options
1268 { "boardWidth", "boardWidth", XtRInt,
1269 sizeof(int), XtOffset(AppDataPtr, NrFiles),
1270 XtRImmediate, (XtPointer) -1},
1271 { "boardHeight", "boardHeight", XtRInt,
1272 sizeof(int), XtOffset(AppDataPtr, NrRanks),
1273 XtRImmediate, (XtPointer) -1},
1274 { "matchPause", "matchPause", XtRInt,
1275 sizeof(int), XtOffset(AppDataPtr, matchPause),
1276 XtRImmediate, (XtPointer) 10000},
1277 { "holdingsSize", "holdingsSize", XtRInt,
1278 sizeof(int), XtOffset(AppDataPtr, holdingsSize),
1279 XtRImmediate, (XtPointer) -1},
1280 { "flipBlack", "flipBlack", XtRBoolean,
1281 sizeof(Boolean), XtOffset(AppDataPtr, upsideDown),
1282 XtRImmediate, (XtPointer) False},
1283 { "allWhite", "allWhite", XtRBoolean,
1284 sizeof(Boolean), XtOffset(AppDataPtr, allWhite),
1285 XtRImmediate, (XtPointer) False},
1286 { "pieceToCharTable", "pieceToCharTable", XtRString,
1287 sizeof(String), XtOffset(AppDataPtr, pieceToCharTable),
1288 XtRImmediate, (XtPointer) 0},
1289 { "alphaRank", "alphaRank", XtRBoolean,
1290 sizeof(Boolean), XtOffset(AppDataPtr, alphaRank),
1291 XtRImmediate, (XtPointer) False},
1292 { "testClaims", "testClaims", XtRBoolean,
1293 sizeof(Boolean), XtOffset(AppDataPtr, testClaims),
1294 XtRImmediate, (XtPointer) True},
1295 { "checkMates", "checkMates", XtRBoolean,
1296 sizeof(Boolean), XtOffset(AppDataPtr, checkMates),
1297 XtRImmediate, (XtPointer) True},
1298 { "materialDraws", "materialDraws", XtRBoolean,
1299 sizeof(Boolean), XtOffset(AppDataPtr, materialDraws),
1300 XtRImmediate, (XtPointer) True},
1301 { "trivialDraws", "trivialDraws", XtRBoolean,
1302 sizeof(Boolean), XtOffset(AppDataPtr, trivialDraws),
1303 XtRImmediate, (XtPointer) False},
1304 { "ruleMoves", "ruleMoves", XtRInt,
1305 sizeof(int), XtOffset(AppDataPtr, ruleMoves),
1306 XtRImmediate, (XtPointer) 51},
1307 { "repeatsToDraw", "repeatsToDraw", XtRInt,
1308 sizeof(int), XtOffset(AppDataPtr, drawRepeats),
1309 XtRImmediate, (XtPointer) 6},
1310 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1311 sizeof(int), XtOffset(AppDataPtr, engineComments),
1312 XtRImmediate, (XtPointer) 1},
1313 { "userName", "userName", XtRString,
1314 sizeof(int), XtOffset(AppDataPtr, userName),
1315 XtRImmediate, (XtPointer) 0},
1316 { "autoKibitz", "autoKibitz", XtRBoolean,
1317 sizeof(Boolean), XtOffset(AppDataPtr, autoKibitz),
1318 XtRImmediate, (XtPointer) False},
1319 { "firstTimeOdds", "firstTimeOdds", XtRInt,
1320 sizeof(int), XtOffset(AppDataPtr, firstTimeOdds),
1321 XtRImmediate, (XtPointer) 1},
1322 { "secondTimeOdds", "secondTimeOdds", XtRInt,
1323 sizeof(int), XtOffset(AppDataPtr, secondTimeOdds),
1324 XtRImmediate, (XtPointer) 1},
1325 { "timeOddsMode", "timeOddsMode", XtRInt,
1326 sizeof(int), XtOffset(AppDataPtr, timeOddsMode),
1327 XtRImmediate, (XtPointer) 0},
1328 { "firstAccumulateTC", "firstAccumulateTC", XtRInt,
1329 sizeof(int), XtOffset(AppDataPtr, firstAccumulateTC),
1330 XtRImmediate, (XtPointer) 1},
1331 { "secondAccumulateTC", "secondAccumulateTC", XtRInt,
1332 sizeof(int), XtOffset(AppDataPtr, secondAccumulateTC),
1333 XtRImmediate, (XtPointer) 1},
1334 { "firstNPS", "firstNPS", XtRInt,
1335 sizeof(int), XtOffset(AppDataPtr, firstNPS),
1336 XtRImmediate, (XtPointer) -1},
1337 { "secondNPS", "secondNPS", XtRInt,
1338 sizeof(int), XtOffset(AppDataPtr, secondNPS),
1339 XtRImmediate, (XtPointer) -1},
1340 { "serverMoves", "serverMoves", XtRString,
1341 sizeof(String), XtOffset(AppDataPtr, serverMovesName),
1342 XtRImmediate, (XtPointer) 0},
1343 { "serverPause", "serverPause", XtRInt,
1344 sizeof(int), XtOffset(AppDataPtr, serverPause),
1345 XtRImmediate, (XtPointer) 0},
1346 { "suppressLoadMoves", "suppressLoadMoves", XtRBoolean,
1347 sizeof(Boolean), XtOffset(AppDataPtr, suppressLoadMoves),
1348 XtRImmediate, (XtPointer) False},
1349 { "userName", "userName", XtRString,
1350 sizeof(String), XtOffset(AppDataPtr, userName),
1351 XtRImmediate, (XtPointer) 0},
1352 { "egtFormats", "egtFormats", XtRString,
1353 sizeof(String), XtOffset(AppDataPtr, egtFormats),
1354 XtRImmediate, (XtPointer) 0},
1355 { "rewindIndex", "rewindIndex", XtRInt,
1356 sizeof(int), XtOffset(AppDataPtr, rewindIndex),
1357 XtRImmediate, (XtPointer) 0},
1358 { "sameColorGames", "sameColorGames", XtRInt,
1359 sizeof(int), XtOffset(AppDataPtr, sameColorGames),
1360 XtRImmediate, (XtPointer) 0},
1361 { "smpCores", "smpCores", XtRInt,
1362 sizeof(int), XtOffset(AppDataPtr, smpCores),
1363 XtRImmediate, (XtPointer) 1},
1364 { "niceEngines", "niceEngines", XtRInt,
1365 sizeof(int), XtOffset(AppDataPtr, niceEngines),
1366 XtRImmediate, (XtPointer) 0},
1367 { "nameOfDebugFile", "nameOfDebugFile", XtRString,
1368 sizeof(String), XtOffset(AppDataPtr, nameOfDebugFile),
1369 XtRImmediate, (XtPointer) "xboard.debug"},
1370 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1371 sizeof(int), XtOffset(AppDataPtr, engineComments),
1372 XtRImmediate, (XtPointer) 1},
1373 { "noGUI", "noGUI", XtRBoolean,
1374 sizeof(Boolean), XtOffset(AppDataPtr, noGUI),
1375 XtRImmediate, (XtPointer) 0},
1376 { "firstOptions", "firstOptions", XtRString,
1377 sizeof(String), XtOffset(AppDataPtr, firstOptions),
1378 XtRImmediate, (XtPointer) "" },
1379 { "secondOptions", "secondOptions", XtRString,
1380 sizeof(String), XtOffset(AppDataPtr, secondOptions),
1381 XtRImmediate, (XtPointer) "" },
1382 { "firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XtRString,
1383 sizeof(String), XtOffset(AppDataPtr, fenOverride1),
1384 XtRImmediate, (XtPointer) 0 },
1385 { "secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XtRString,
1386 sizeof(String), XtOffset(AppDataPtr, fenOverride2),
1387 XtRImmediate, (XtPointer) 0 },
1389 // [HGM] Winboard_x UCI options
1390 { "firstIsUCI", "firstIsUCI", XtRBoolean,
1391 sizeof(Boolean), XtOffset(AppDataPtr, firstIsUCI),
1392 XtRImmediate, (XtPointer) False},
1393 { "secondIsUCI", "secondIsUCI", XtRBoolean,
1394 sizeof(Boolean), XtOffset(AppDataPtr, secondIsUCI),
1395 XtRImmediate, (XtPointer) False},
1396 { "firstHasOwnBookUCI", "firstHasOwnBookUCI", XtRBoolean,
1397 sizeof(Boolean), XtOffset(AppDataPtr, firstHasOwnBookUCI),
1398 XtRImmediate, (XtPointer) True},
1399 { "secondHasOwnBookUCI", "secondHasOwnBookUCI", XtRBoolean,
1400 sizeof(Boolean), XtOffset(AppDataPtr, secondHasOwnBookUCI),
1401 XtRImmediate, (XtPointer) True},
1402 { "usePolyglotBook", "usePolyglotBook", XtRBoolean,
1403 sizeof(Boolean), XtOffset(AppDataPtr, usePolyglotBook),
1404 XtRImmediate, (XtPointer) False},
1405 { "defaultHashSize", "defaultHashSize", XtRInt,
1406 sizeof(int), XtOffset(AppDataPtr, defaultHashSize),
1407 XtRImmediate, (XtPointer) 64},
1408 { "defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XtRInt,
1409 sizeof(int), XtOffset(AppDataPtr, defaultCacheSizeEGTB),
1410 XtRImmediate, (XtPointer) 4},
1411 { "polyglotDir", "polyglotDir", XtRString,
1412 sizeof(String), XtOffset(AppDataPtr, polyglotDir),
1413 XtRImmediate, (XtPointer) "." },
1414 { "polyglotBook", "polyglotBook", XtRString,
1415 sizeof(String), XtOffset(AppDataPtr, polyglotBook),
1416 XtRImmediate, (XtPointer) "" },
1417 { "defaultPathEGTB", "defaultPathEGTB", XtRString,
1418 sizeof(String), XtOffset(AppDataPtr, defaultPathEGTB),
1419 XtRImmediate, (XtPointer) "/usr/local/share/egtb"},
1420 { "delayBeforeQuit", "delayBeforeQuit", XtRInt,
1421 sizeof(int), XtOffset(AppDataPtr, delayBeforeQuit),
1422 XtRImmediate, (XtPointer) 0},
1423 { "delayAfterQuit", "delayAfterQuit", XtRInt,
1424 sizeof(int), XtOffset(AppDataPtr, delayAfterQuit),
1425 XtRImmediate, (XtPointer) 0},
1426 { "keepAlive", "keepAlive", XtRInt,
1427 sizeof(int), XtOffset(AppDataPtr, keepAlive),
1428 XtRImmediate, (XtPointer) 0},
1429 { "forceIllegalMoves", "forceIllegalMoves", XtRBoolean,
1430 sizeof(Boolean), XtOffset(AppDataPtr, forceIllegal),
1431 XtRImmediate, (XtPointer) False},
1434 XrmOptionDescRec shellOptions[] = {
1435 { "-whitePieceColor", "whitePieceColor", XrmoptionSepArg, NULL },
1436 { "-blackPieceColor", "blackPieceColor", XrmoptionSepArg, NULL },
1437 { "-lightSquareColor", "lightSquareColor", XrmoptionSepArg, NULL },
1438 { "-darkSquareColor", "darkSquareColor", XrmoptionSepArg, NULL },
1439 { "-highlightSquareColor", "highlightSquareColor", XrmoptionSepArg, NULL },
1440 { "-premoveHighlightColor", "premoveHighlightColor", XrmoptionSepArg,NULL},
1441 { "-movesPerSession", "movesPerSession", XrmoptionSepArg, NULL },
1442 { "-mps", "movesPerSession", XrmoptionSepArg, NULL },
1443 { "-timeIncrement", "timeIncrement", XrmoptionSepArg, NULL },
1444 { "-inc", "timeIncrement", XrmoptionSepArg, NULL },
1445 { "-initString", "initString", XrmoptionSepArg, NULL },
1446 { "-firstInitString", "initString", XrmoptionSepArg, NULL },
1447 { "-secondInitString", "secondInitString", XrmoptionSepArg, NULL },
1448 { "-firstComputerString", "firstComputerString", XrmoptionSepArg, NULL },
1449 { "-secondComputerString", "secondComputerString", XrmoptionSepArg, NULL },
1450 { "-firstChessProgram", "firstChessProgram", XrmoptionSepArg, NULL },
1451 { "-fcp", "firstChessProgram", XrmoptionSepArg, NULL },
1452 { "-secondChessProgram", "secondChessProgram", XrmoptionSepArg, NULL },
1453 { "-scp", "secondChessProgram", XrmoptionSepArg, NULL },
1454 { "-firstPlaysBlack", "firstPlaysBlack", XrmoptionSepArg, NULL },
1455 { "-fb", "firstPlaysBlack", XrmoptionNoArg, "True" },
1456 { "-xfb", "firstPlaysBlack", XrmoptionNoArg, "False" },
1457 { "-noChessProgram", "noChessProgram", XrmoptionSepArg, NULL },
1458 { "-ncp", "noChessProgram", XrmoptionNoArg, "True" },
1459 { "-xncp", "noChessProgram", XrmoptionNoArg, "False" },
1460 { "-firstHost", "firstHost", XrmoptionSepArg, NULL },
1461 { "-fh", "firstHost", XrmoptionSepArg, NULL },
1462 { "-secondHost", "secondHost", XrmoptionSepArg, NULL },
1463 { "-sh", "secondHost", XrmoptionSepArg, NULL },
1464 { "-firstDirectory", "firstDirectory", XrmoptionSepArg, NULL },
1465 { "-fd", "firstDirectory", XrmoptionSepArg, NULL },
1466 { "-secondDirectory", "secondDirectory", XrmoptionSepArg, NULL },
1467 { "-sd", "secondDirectory", XrmoptionSepArg, NULL },
1468 { "-bitmapDirectory", "bitmapDirectory", XrmoptionSepArg, NULL },
1469 { "-bm", "bitmapDirectory", XrmoptionSepArg, NULL },
1470 { "-remoteShell", "remoteShell", XrmoptionSepArg, NULL },
1471 { "-rsh", "remoteShell", XrmoptionSepArg, NULL },
1472 { "-remoteUser", "remoteUser", XrmoptionSepArg, NULL },
1473 { "-ruser", "remoteUser", XrmoptionSepArg, NULL },
1474 { "-timeDelay", "timeDelay", XrmoptionSepArg, NULL },
1475 { "-td", "timeDelay", XrmoptionSepArg, NULL },
1476 { "-timeControl", "timeControl", XrmoptionSepArg, NULL },
1477 { "-tc", "timeControl", XrmoptionSepArg, NULL },
1478 { "-internetChessServerMode", "internetChessServerMode",
1479 XrmoptionSepArg, NULL },
1480 { "-ics", "internetChessServerMode", XrmoptionNoArg, "True" },
1481 { "-xics", "internetChessServerMode", XrmoptionNoArg, "False" },
1482 { "-internetChessServerHost", "internetChessServerHost",
1483 XrmoptionSepArg, NULL },
1484 { "-icshost", "internetChessServerHost", XrmoptionSepArg, NULL },
1485 { "-internetChessServerPort", "internetChessServerPort",
1486 XrmoptionSepArg, NULL },
1487 { "-icsport", "internetChessServerPort", XrmoptionSepArg, NULL },
1488 { "-internetChessServerCommPort", "internetChessServerCommPort",
1489 XrmoptionSepArg, NULL },
1490 { "-icscomm", "internetChessServerCommPort", XrmoptionSepArg, NULL },
1491 { "-internetChessServerLogonScript", "internetChessServerLogonScript",
1492 XrmoptionSepArg, NULL },
1493 { "-icslogon", "internetChessServerLogonScript", XrmoptionSepArg, NULL },
1494 { "-internetChessServerHelper", "internetChessServerHelper",
1495 XrmoptionSepArg, NULL },
1496 { "-icshelper", "internetChessServerHelper", XrmoptionSepArg, NULL },
1497 { "-internetChessServerInputBox", "internetChessServerInputBox",
1498 XrmoptionSepArg, NULL },
1499 { "-icsinput", "internetChessServerInputBox", XrmoptionNoArg, "True" },
1500 { "-xicsinput", "internetChessServerInputBox", XrmoptionNoArg, "False" },
1501 { "-icsAlarm", "icsAlarm", XrmoptionSepArg, NULL },
1502 { "-alarm", "icsAlarm", XrmoptionNoArg, "True" },
1503 { "-xalarm", "icsAlarm", XrmoptionNoArg, "False" },
1504 { "-icsAlarmTime", "icsAlarmTime", XrmoptionSepArg, NULL },
1505 { "-useTelnet", "useTelnet", XrmoptionSepArg, NULL },
1506 { "-telnet", "useTelnet", XrmoptionNoArg, "True" },
1507 { "-xtelnet", "useTelnet", XrmoptionNoArg, "False" },
1508 { "-telnetProgram", "telnetProgram", XrmoptionSepArg, NULL },
1509 { "-gateway", "gateway", XrmoptionSepArg, NULL },
1510 { "-loadGameFile", "loadGameFile", XrmoptionSepArg, NULL },
1511 { "-lgf", "loadGameFile", XrmoptionSepArg, NULL },
1512 { "-loadGameIndex", "loadGameIndex", XrmoptionSepArg, NULL },
1513 { "-lgi", "loadGameIndex", XrmoptionSepArg, NULL },
1514 { "-saveGameFile", "saveGameFile", XrmoptionSepArg, NULL },
1515 { "-sgf", "saveGameFile", XrmoptionSepArg, NULL },
1516 { "-autoSaveGames", "autoSaveGames", XrmoptionSepArg, NULL },
1517 { "-autosave", "autoSaveGames", XrmoptionNoArg, "True" },
1518 { "-xautosave", "autoSaveGames", XrmoptionNoArg, "False" },
1519 { "-autoRaiseBoard", "autoRaiseBoard", XrmoptionSepArg, NULL },
1520 { "-autoraise", "autoRaiseBoard", XrmoptionNoArg, "True" },
1521 { "-xautoraise", "autoRaiseBoard", XrmoptionNoArg, "False" },
1522 { "-blindfold", "blindfold", XrmoptionSepArg, NULL },
1523 { "-blind", "blindfold", XrmoptionNoArg, "True" },
1524 { "-xblind", "blindfold", XrmoptionNoArg, "False" },
1525 { "-loadPositionFile", "loadPositionFile", XrmoptionSepArg, NULL },
1526 { "-lpf", "loadPositionFile", XrmoptionSepArg, NULL },
1527 { "-loadPositionIndex", "loadPositionIndex", XrmoptionSepArg, NULL },
1528 { "-lpi", "loadPositionIndex", XrmoptionSepArg, NULL },
1529 { "-savePositionFile", "savePositionFile", XrmoptionSepArg, NULL },
1530 { "-spf", "savePositionFile", XrmoptionSepArg, NULL },
1531 { "-matchMode", "matchMode", XrmoptionSepArg, NULL },
1532 { "-mm", "matchMode", XrmoptionNoArg, "True" },
1533 { "-xmm", "matchMode", XrmoptionNoArg, "False" },
1534 { "-matchGames", "matchGames", XrmoptionSepArg, NULL },
1535 { "-mg", "matchGames", XrmoptionSepArg, NULL },
1536 { "-monoMode", "monoMode", XrmoptionSepArg, NULL },
1537 { "-mono", "monoMode", XrmoptionNoArg, "True" },
1538 { "-xmono", "monoMode", XrmoptionNoArg, "False" },
1539 { "-debugMode", "debugMode", XrmoptionSepArg, NULL },
1540 { "-debug", "debugMode", XrmoptionNoArg, "True" },
1541 { "-xdebug", "debugMode", XrmoptionNoArg, "False" },
1542 { "-clockMode", "clockMode", XrmoptionSepArg, NULL },
1543 { "-clock", "clockMode", XrmoptionNoArg, "True" },
1544 { "-xclock", "clockMode", XrmoptionNoArg, "False" },
1545 { "-boardSize", "boardSize", XrmoptionSepArg, NULL },
1546 { "-size", "boardSize", XrmoptionSepArg, NULL },
1547 { "-searchTime", "searchTime", XrmoptionSepArg, NULL },
1548 { "-st", "searchTime", XrmoptionSepArg, NULL },
1549 { "-searchDepth", "searchDepth", XrmoptionSepArg, NULL },
1550 { "-depth", "searchDepth", XrmoptionSepArg, NULL },
1551 { "-showCoords", "showCoords", XrmoptionSepArg, NULL },
1552 { "-coords", "showCoords", XrmoptionNoArg, "True" },
1553 { "-xcoords", "showCoords", XrmoptionNoArg, "False" },
1555 { "-showJail", "showJail", XrmoptionSepArg, NULL },
1556 { "-jail", "showJail", XrmoptionNoArg, "1" },
1557 { "-sidejail", "showJail", XrmoptionNoArg, "2" },
1558 { "-xjail", "showJail", XrmoptionNoArg, "0" },
1560 { "-showThinking", "showThinking", XrmoptionSepArg, NULL },
1561 { "-thinking", "showThinking", XrmoptionNoArg, "True" },
1562 { "-xthinking", "showThinking", XrmoptionNoArg, "False" },
1563 { "-ponderNextMove", "ponderNextMove", XrmoptionSepArg, NULL },
1564 { "-ponder", "ponderNextMove", XrmoptionNoArg, "True" },
1565 { "-xponder", "ponderNextMove", XrmoptionNoArg, "False" },
1566 { "-periodicUpdates", "periodicUpdates", XrmoptionSepArg, NULL },
1567 { "-periodic", "periodicUpdates", XrmoptionNoArg, "True" },
1568 { "-xperiodic", "periodicUpdates", XrmoptionNoArg, "False" },
1569 { "-clockFont", "clockFont", XrmoptionSepArg, NULL },
1570 { "-coordFont", "coordFont", XrmoptionSepArg, NULL },
1571 { "-font", "font", XrmoptionSepArg, NULL },
1572 { "-ringBellAfterMoves", "ringBellAfterMoves", XrmoptionSepArg, NULL },
1573 { "-bell", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1574 { "-xbell", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1575 { "-movesound", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1576 { "-xmovesound", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1577 { "-autoCallFlag", "autoCallFlag", XrmoptionSepArg, NULL },
1578 { "-autoflag", "autoCallFlag", XrmoptionNoArg, "True" },
1579 { "-xautoflag", "autoCallFlag", XrmoptionNoArg, "False" },
1580 { "-autoFlipView", "autoFlipView", XrmoptionSepArg, NULL },
1581 { "-autoflip", "autoFlipView", XrmoptionNoArg, "True" },
1582 { "-xautoflip", "autoFlipView", XrmoptionNoArg, "False" },
1583 { "-autoObserve", "autoObserve", XrmoptionSepArg, NULL },
1584 { "-autobs", "autoObserve", XrmoptionNoArg, "True" },
1585 { "-xautobs", "autoObserve", XrmoptionNoArg, "False" },
1586 { "-autoComment", "autoComment", XrmoptionSepArg, NULL },
1587 { "-autocomm", "autoComment", XrmoptionNoArg, "True" },
1588 { "-xautocomm", "autoComment", XrmoptionNoArg, "False" },
1589 { "-getMoveList", "getMoveList", XrmoptionSepArg, NULL },
1590 { "-moves", "getMoveList", XrmoptionNoArg, "True" },
1591 { "-xmoves", "getMoveList", XrmoptionNoArg, "False" },
1593 { "-highlightDragging", "highlightDragging", XrmoptionSepArg, NULL },
1594 { "-highdrag", "highlightDragging", XrmoptionNoArg, "True" },
1595 { "-xhighdrag", "highlightDragging", XrmoptionNoArg, "False" },
1597 { "-highlightLastMove", "highlightLastMove", XrmoptionSepArg, NULL },
1598 { "-highlight", "highlightLastMove", XrmoptionNoArg, "True" },
1599 { "-xhighlight", "highlightLastMove", XrmoptionNoArg, "False" },
1600 { "-premove", "premove", XrmoptionSepArg, NULL },
1601 { "-pre", "premove", XrmoptionNoArg, "True" },
1602 { "-xpre", "premove", XrmoptionNoArg, "False" },
1603 { "-testLegality", "testLegality", XrmoptionSepArg, NULL },
1604 { "-legal", "testLegality", XrmoptionNoArg, "True" },
1605 { "-xlegal", "testLegality", XrmoptionNoArg, "False" },
1606 { "-flipView", "flipView", XrmoptionSepArg, NULL },
1607 { "-flip", "flipView", XrmoptionNoArg, "True" },
1608 { "-xflip", "flipView", XrmoptionNoArg, "False" },
1609 { "-cmail", "cmailGameName", XrmoptionSepArg, NULL },
1610 { "-alwaysPromoteToQueen", "alwaysPromoteToQueen",
1611 XrmoptionSepArg, NULL },
1612 { "-queen", "alwaysPromoteToQueen", XrmoptionNoArg, "True" },
1613 { "-xqueen", "alwaysPromoteToQueen", XrmoptionNoArg, "False" },
1614 { "-oldSaveStyle", "oldSaveStyle", XrmoptionSepArg, NULL },
1615 { "-oldsave", "oldSaveStyle", XrmoptionNoArg, "True" },
1616 { "-xoldsave", "oldSaveStyle", XrmoptionNoArg, "False" },
1617 { "-quietPlay", "quietPlay", XrmoptionSepArg, NULL },
1618 { "-quiet", "quietPlay", XrmoptionNoArg, "True" },
1619 { "-xquiet", "quietPlay", XrmoptionNoArg, "False" },
1620 { "-titleInWindow", "titleInWindow", XrmoptionSepArg, NULL },
1621 { "-title", "titleInWindow", XrmoptionNoArg, "True" },
1622 { "-xtitle", "titleInWindow", XrmoptionNoArg, "False" },
1624 { "-zippyTalk", "zippyTalk", XrmoptionSepArg, NULL },
1625 { "-zt", "zippyTalk", XrmoptionNoArg, "True" },
1626 { "-xzt", "zippyTalk", XrmoptionNoArg, "False" },
1627 { "-zippyPlay", "zippyPlay", XrmoptionSepArg, NULL },
1628 { "-zp", "zippyPlay", XrmoptionNoArg, "True" },
1629 { "-xzp", "zippyPlay", XrmoptionNoArg, "False" },
1630 { "-zippyLines", "zippyLines", XrmoptionSepArg, NULL },
1631 { "-zippyPinhead", "zippyPinhead", XrmoptionSepArg, NULL },
1632 { "-zippyPassword", "zippyPassword", XrmoptionSepArg, NULL },
1633 { "-zippyPassword2", "zippyPassword2", XrmoptionSepArg, NULL },
1634 { "-zippyWrongPassword", "zippyWrongPassword", XrmoptionSepArg, NULL },
1635 { "-zippyAcceptOnly", "zippyAcceptOnly", XrmoptionSepArg, NULL },
1636 { "-zippyUseI", "zippyUseI", XrmoptionSepArg, NULL },
1637 { "-zui", "zippyUseI", XrmoptionNoArg, "True" },
1638 { "-xzui", "zippyUseI", XrmoptionNoArg, "False" },
1639 { "-zippyBughouse", "zippyBughouse", XrmoptionSepArg, NULL },
1640 { "-zippyNoplayCrafty", "zippyNoplayCrafty", XrmoptionSepArg, NULL },
1641 { "-znc", "zippyNoplayCrafty", XrmoptionNoArg, "True" },
1642 { "-xznc", "zippyNoplayCrafty", XrmoptionNoArg, "False" },
1643 { "-zippyGameEnd", "zippyGameEnd", XrmoptionSepArg, NULL },
1644 { "-zippyGameStart", "zippyGameStart", XrmoptionSepArg, NULL },
1645 { "-zippyAdjourn", "zippyAdjourn", XrmoptionSepArg, NULL },
1646 { "-zadj", "zippyAdjourn", XrmoptionNoArg, "True" },
1647 { "-xzadj", "zippyAdjourn", XrmoptionNoArg, "False" },
1648 { "-zippyAbort", "zippyAbort", XrmoptionSepArg, NULL },
1649 { "-zab", "zippyAbort", XrmoptionNoArg, "True" },
1650 { "-xzab", "zippyAbort", XrmoptionNoArg, "False" },
1651 { "-zippyVariants", "zippyVariants", XrmoptionSepArg, NULL },
1652 { "-zippyMaxGames", "zippyMaxGames", XrmoptionSepArg, NULL },
1653 { "-zippyReplayTimeout", "zippyReplayTimeout", XrmoptionSepArg, NULL },
1654 { "-zippyShortGame", "zippyShortGame", XrmoptionSepArg, NULL },
1656 { "-flashCount", "flashCount", XrmoptionSepArg, NULL },
1657 { "-flash", "flashCount", XrmoptionNoArg, "3" },
1658 { "-xflash", "flashCount", XrmoptionNoArg, "0" },
1659 { "-flashRate", "flashRate", XrmoptionSepArg, NULL },
1660 { "-pixmapDirectory", "pixmapDirectory", XrmoptionSepArg, NULL },
1661 { "-msLoginDelay", "msLoginDelay", XrmoptionSepArg, NULL },
1662 { "-pixmap", "pixmapDirectory", XrmoptionSepArg, NULL },
1663 { "-colorizeMessages", "colorizeMessages", XrmoptionSepArg, NULL },
1664 { "-colorize", "colorizeMessages", XrmoptionNoArg, "True" },
1665 { "-xcolorize", "colorizeMessages", XrmoptionNoArg, "False" },
1666 { "-colorShout", "colorShout", XrmoptionSepArg, NULL },
1667 { "-colorSShout", "colorSShout", XrmoptionSepArg, NULL },
1668 { "-colorCShout", "colorSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1669 { "-colorChannel1", "colorChannel1", XrmoptionSepArg, NULL },
1670 { "-colorChannel", "colorChannel", XrmoptionSepArg, NULL },
1671 { "-colorKibitz", "colorKibitz", XrmoptionSepArg, NULL },
1672 { "-colorTell", "colorTell", XrmoptionSepArg, NULL },
1673 { "-colorChallenge", "colorChallenge", XrmoptionSepArg, NULL },
1674 { "-colorRequest", "colorRequest", XrmoptionSepArg, NULL },
1675 { "-colorSeek", "colorSeek", XrmoptionSepArg, NULL },
1676 { "-colorNormal", "colorNormal", XrmoptionSepArg, NULL },
1677 { "-soundProgram", "soundProgram", XrmoptionSepArg, NULL },
1678 { "-soundShout", "soundShout", XrmoptionSepArg, NULL },
1679 { "-soundSShout", "soundSShout", XrmoptionSepArg, NULL },
1680 { "-soundCShout", "soundSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1681 { "-soundChannel1", "soundChannel1", XrmoptionSepArg, NULL },
1682 { "-soundChannel", "soundChannel", XrmoptionSepArg, NULL },
1683 { "-soundKibitz", "soundKibitz", XrmoptionSepArg, NULL },
1684 { "-soundTell", "soundTell", XrmoptionSepArg, NULL },
1685 { "-soundChallenge", "soundChallenge", XrmoptionSepArg, NULL },
1686 { "-soundRequest", "soundRequest", XrmoptionSepArg, NULL },
1687 { "-soundSeek", "soundSeek", XrmoptionSepArg, NULL },
1688 { "-soundMove", "soundMove", XrmoptionSepArg, NULL },
1689 { "-soundIcsWin", "soundIcsWin", XrmoptionSepArg, NULL },
1690 { "-soundIcsLoss", "soundIcsLoss", XrmoptionSepArg, NULL },
1691 { "-soundIcsDraw", "soundIcsDraw", XrmoptionSepArg, NULL },
1692 { "-soundIcsUnfinished", "soundIcsUnfinished", XrmoptionSepArg, NULL },
1693 { "-soundIcsAlarm", "soundIcsAlarm", XrmoptionSepArg, NULL },
1694 { "-reuseFirst", "reuseFirst", XrmoptionSepArg, NULL },
1695 { "-reuseChessPrograms", "reuseFirst", XrmoptionSepArg, NULL }, /*compat*/
1696 { "-reuse", "reuseFirst", XrmoptionNoArg, "True" },
1697 { "-xreuse", "reuseFirst", XrmoptionNoArg, "False" },
1698 { "-reuseSecond", "reuseSecond", XrmoptionSepArg, NULL },
1699 { "-reuse2", "reuseSecond", XrmoptionNoArg, "True" },
1700 { "-xreuse2", "reuseSecond", XrmoptionNoArg, "False" },
1701 { "-animateMoving", "animateMoving", XrmoptionSepArg, NULL },
1702 { "-animate", "animateMoving", XrmoptionNoArg, "True" },
1703 { "-xanimate", "animateMoving", XrmoptionNoArg, "False" },
1704 { "-animateDragging", "animateDragging", XrmoptionSepArg, NULL },
1705 { "-drag", "animateDragging", XrmoptionNoArg, "True" },
1706 { "-xdrag", "animateDragging", XrmoptionNoArg, "False" },
1707 { "-animateSpeed", "animateSpeed", XrmoptionSepArg, NULL },
1708 { "-popupExitMessage", "popupExitMessage", XrmoptionSepArg, NULL },
1709 { "-exit", "popupExitMessage", XrmoptionNoArg, "True" },
1710 { "-xexit", "popupExitMessage", XrmoptionNoArg, "False" },
1711 { "-popupMoveErrors", "popupMoveErrors", XrmoptionSepArg, NULL },
1712 { "-popup", "popupMoveErrors", XrmoptionNoArg, "True" },
1713 { "-xpopup", "popupMoveErrors", XrmoptionNoArg, "False" },
1714 { "-fontSizeTolerance", "fontSizeTolerance", XrmoptionSepArg, NULL },
1715 { "-initialMode", "initialMode", XrmoptionSepArg, NULL },
1716 { "-mode", "initialMode", XrmoptionSepArg, NULL },
1717 { "-variant", "variant", XrmoptionSepArg, NULL },
1718 { "-firstProtocolVersion", "firstProtocolVersion", XrmoptionSepArg, NULL },
1719 { "-secondProtocolVersion","secondProtocolVersion",XrmoptionSepArg, NULL },
1720 { "-showButtonBar", "showButtonBar", XrmoptionSepArg, NULL },
1721 { "-buttons", "showButtonBar", XrmoptionNoArg, "True" },
1722 { "-xbuttons", "showButtonBar", XrmoptionNoArg, "False" },
1723 { "-lowTimeWarningColor", "lowTimeWarningColor", XrmoptionSepArg, NULL },
1724 { "-lowTimeWarning", "lowTimeWarning", XrmoptionSepArg, NULL },
1725 /* [AS,HR] New features */
1726 { "-firstScoreAbs", "firstScoreAbs", XrmoptionSepArg, NULL },
1727 { "-secondScoreAbs", "secondScoreAbs", XrmoptionSepArg, NULL },
1728 { "-pgnExtendedInfo", "pgnExtendedInfo", XrmoptionSepArg, NULL },
1729 { "-hideThinkingFromHuman", "hideThinkingFromHuman", XrmoptionSepArg, NULL },
1730 { "-adjudicateLossThreshold", "adjudicateLossThreshold", XrmoptionSepArg, NULL },
1731 { "-adjudicateDrawMoves", "adjudicateDrawMoves", XrmoptionSepArg, NULL },
1732 { "-pgnEventHeader", "pgnEventHeader", XrmoptionSepArg, NULL },
1733 { "-firstIsUCI", "firstIsUCI", XrmoptionSepArg, NULL },
1734 { "-secondIsUCI", "secondIsUCI", XrmoptionSepArg, NULL },
1735 { "-fUCI", "firstIsUCI", XrmoptionNoArg, "True" },
1736 { "-sUCI", "secondIsUCI", XrmoptionNoArg, "True" },
1737 { "-firstHasOwnBookUCI", "firstHasOwnBookUCI", XrmoptionSepArg, NULL },
1738 { "-secondHasOwnBookUCI", "secondHasOwnBookUCI", XrmoptionSepArg, NULL },
1739 { "-fNoOwnBookUCI", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1740 { "-sNoOwnBookUCI", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1741 { "-firstXBook", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1742 { "-secondXBook", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1743 { "-polyglotDir", "polyglotDir", XrmoptionSepArg, NULL },
1744 { "-usePolyglotBook", "usePolyglotBook", XrmoptionSepArg, NULL },
1745 { "-polyglotBook", "polyglotBook", XrmoptionSepArg, NULL },
1746 { "-defaultHashSize", "defaultHashSize", XrmoptionSepArg, NULL },
1747 { "-defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XrmoptionSepArg, NULL },
1748 { "-defaultPathEGTB", "defaultPathEGTB", XrmoptionSepArg, NULL },
1749 { "-defaultFrcPosition", "defaultFrcPosition", XrmoptionSepArg, NULL },
1750 { "-gameListTags", "gameListTags", XrmoptionSepArg, NULL },
1751 // [HGM] I am sure AS added many more options, but we have to fish them out, from the list in winboard.c
1753 /* [HGM,HR] User-selectable board size */
1754 { "-boardWidth", "boardWidth", XrmoptionSepArg, NULL },
1755 { "-boardHeight", "boardHeight", XrmoptionSepArg, NULL },
1756 { "-matchPause", "matchPause", XrmoptionSepArg, NULL },
1758 /* [HGM] new arguments of 4.3.xx. All except first three are back-end options, which should work immediately */
1759 { "-holdingsSize", "holdingsSize", XrmoptionSepArg, NULL }, // requires extensive front-end changes to work
1760 { "-flipBlack", "flipBlack", XrmoptionSepArg, NULL }, // requires front-end changes to work
1761 { "-allWhite", "allWhite", XrmoptionSepArg, NULL }, // requires front-end changes to work
1762 { "-pieceToCharTable", "pieceToCharTable", XrmoptionSepArg, NULL },
1763 { "-alphaRank", "alphaRank", XrmoptionSepArg, NULL },
1764 { "-testClaims", "testClaims", XrmoptionSepArg, NULL },
1765 { "-checkMates", "checkMates", XrmoptionSepArg, NULL },
1766 { "-materialDraws", "materialDraws", XrmoptionSepArg, NULL },
1767 { "-trivialDraws", "trivialDraws", XrmoptionSepArg, NULL },
1768 { "-ruleMoves", "ruleMoves", XrmoptionSepArg, NULL },
1769 { "-repeatsToDraw", "repeatsToDraw", XrmoptionSepArg, NULL },
1770 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1771 { "-userName", "userName", XrmoptionSepArg, NULL },
1772 { "-autoKibitz", "autoKibitz", XrmoptionNoArg, "True" },
1773 { "-firstTimeOdds", "firstTimeOdds", XrmoptionSepArg, NULL },
1774 { "-secondTimeOdds", "secondTimeOdds", XrmoptionSepArg, NULL },
1775 { "-timeOddsMode", "timeOddsMode", XrmoptionSepArg, NULL },
1776 { "-firstAccumulateTC", "firstAccumulateTC", XrmoptionSepArg, NULL },
1777 { "-secondAccumulateTC", "secondAccumulateTC", XrmoptionSepArg, NULL },
1778 { "-firstNPS", "firstNPS", XrmoptionSepArg, NULL },
1779 { "-secondNPS", "secondNPS", XrmoptionSepArg, NULL },
1780 { "-serverMoves", "serverMoves", XrmoptionSepArg, NULL },
1781 { "-serverPause", "serverPause", XrmoptionSepArg, NULL },
1782 { "-suppressLoadMoves", "suppressLoadMoves", XrmoptionSepArg, NULL },
1783 { "-egtFormats", "egtFormats", XrmoptionSepArg, NULL },
1784 { "-userName", "userName", XrmoptionSepArg, NULL },
1785 { "-smpCores", "smpCores", XrmoptionSepArg, NULL },
1786 { "-sameColorGames", "sameColorGames", XrmoptionSepArg, NULL },
1787 { "-rewindIndex", "rewindIndex", XrmoptionSepArg, NULL },
1788 { "-niceEngines", "niceEngines", XrmoptionSepArg, NULL },
1789 { "-delayBeforeQuit", "delayBeforeQuit", XrmoptionSepArg, NULL },
1790 { "-delayAfterQuit", "delayAfterQuit", XrmoptionSepArg, NULL },
1791 { "-nameOfDebugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1792 { "-debugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1793 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1794 { "-noGUI", "noGUI", XrmoptionNoArg, "True" },
1795 { "-firstOptions", "firstOptions", XrmoptionSepArg, NULL },
1796 { "-secondOptions", "secondOptions", XrmoptionSepArg, NULL },
1797 { "-firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1798 { "-secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1799 { "-keepAlive", "keepAlive", XrmoptionSepArg, NULL },
1800 { "-forceIllegalMoves", "forceIllegalMoves", XrmoptionNoArg, "True" },
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));
2026 #define BoardSize int
2027 void InitDrawingSizes(BoardSize boardSize, int flags)
2028 { // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
2029 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2031 XtGeometryResult gres;
2034 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2035 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2037 timerWidth = (boardWidth - sep) / 2;
2039 if (appData.titleInWindow)
2044 w = boardWidth - 2*bor;
2048 w = boardWidth - w - sep - 2*bor - 2; // WIDTH_FUDGE
2052 if(!formWidget) return;
2055 * Inhibit shell resizing.
2058 // [HGM] pieces: tailor piece bitmaps to needs of specific variant
2061 for(i=0; i<4; i++) {
2063 for(p=0; p<=(int)WhiteKing; p++)
2064 xpmPieceBitmap[i][p] = xpmPieceBitmap2[i][p]; // defaults
2065 if(gameInfo.variant == VariantShogi) {
2066 xpmPieceBitmap[i][(int)WhiteCannon] = xpmPieceBitmap2[i][(int)WhiteKing+1];
2067 xpmPieceBitmap[i][(int)WhiteNightrider] = xpmPieceBitmap2[i][(int)WhiteKing+2];
2068 xpmPieceBitmap[i][(int)WhiteSilver] = xpmPieceBitmap2[i][(int)WhiteKing+3];
2069 xpmPieceBitmap[i][(int)WhiteGrasshopper] = xpmPieceBitmap2[i][(int)WhiteKing+4];
2070 xpmPieceBitmap[i][(int)WhiteQueen] = xpmPieceBitmap2[i][(int)WhiteLance];
2073 if(gameInfo.variant == VariantGothic) {
2074 xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteSilver];
2078 // [HGM] why are thee ximMasks used at all? the ximPieceBitmaps seem to be never used!
2079 for(p=0; p<=(int)WhiteKing; p++)
2080 ximMaskPm[p] = ximMaskPm2[p]; // defaults
2081 if(gameInfo.variant == VariantShogi) {
2082 ximMaskPm[(int)WhiteCannon] = ximMaskPm2[(int)WhiteKing+1];
2083 ximMaskPm[(int)WhiteNightrider] = ximMaskPm2[(int)WhiteKing+2];
2084 ximMaskPm[(int)WhiteSilver] = ximMaskPm2[(int)WhiteKing+3];
2085 ximMaskPm[(int)WhiteGrasshopper] = ximMaskPm2[(int)WhiteKing+4];
2086 ximMaskPm[(int)WhiteQueen] = ximMaskPm2[(int)WhiteLance];
2089 if(gameInfo.variant == VariantGothic) {
2090 ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[(int)WhiteSilver];
2096 for(i=0; i<2; i++) {
2098 for(p=0; p<=(int)WhiteKing; p++)
2099 pieceBitmap[i][p] = pieceBitmap2[i][p]; // defaults
2100 if(gameInfo.variant == VariantShogi) {
2101 pieceBitmap[i][(int)WhiteCannon] = pieceBitmap2[i][(int)WhiteKing+1];
2102 pieceBitmap[i][(int)WhiteNightrider] = pieceBitmap2[i][(int)WhiteKing+2];
2103 pieceBitmap[i][(int)WhiteSilver] = pieceBitmap2[i][(int)WhiteKing+3];
2104 pieceBitmap[i][(int)WhiteGrasshopper] = pieceBitmap2[i][(int)WhiteKing+4];
2105 pieceBitmap[i][(int)WhiteQueen] = pieceBitmap2[i][(int)WhiteLance];
2108 if(gameInfo.variant == VariantGothic) {
2109 pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteSilver];
2119 void EscapeExpand(char *p, char *q)
2120 { // [HGM] initstring: routine to shape up string arguments
2121 while(*p++ = *q++) if(p[-1] == '\\')
2123 case 'n': p[-1] = '\n'; break;
2124 case 'r': p[-1] = '\r'; break;
2125 case 't': p[-1] = '\t'; break;
2126 case '\\': p[-1] = '\\'; break;
2127 case 0: *p = 0; return;
2128 default: p[-1] = q[-1]; break;
2137 int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
2138 XSetWindowAttributes window_attributes;
2140 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2141 XrmValue vFrom, vTo;
2142 XtGeometryResult gres;
2145 int forceMono = False;
2149 // [HGM] before anything else, expand any indirection files amongst options
2150 char *argvCopy[1000]; // 1000 seems enough
2151 char newArgs[10000]; // holds actual characters
2154 srandom(time(0)); // [HGM] book: make random truly random
2157 for(i=0; i<argc; i++) {
2158 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2159 //fprintf(stderr, "arg %s\n", argv[i]);
2160 if(argv[i][0] != '@') argvCopy[j++] = argv[i]; else {
2162 FILE *f = fopen(argv[i]+1, "rb");
2163 if(f == NULL) { fprintf(stderr, _("ignore %s\n"), argv[i]); continue; } // do not expand non-existing
2164 argvCopy[j++] = newArgs + k; // get ready for first argument from file
2165 while((c = fgetc(f)) != EOF) { // each line of file inserts 1 argument in the list
2167 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2168 newArgs[k++] = 0; // terminate current arg
2169 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2170 argvCopy[j++] = newArgs + k; // get ready for next
2172 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2186 setbuf(stdout, NULL);
2187 setbuf(stderr, NULL);
2190 programName = strrchr(argv[0], '/');
2191 if (programName == NULL)
2192 programName = argv[0];
2197 XtSetLanguageProc(NULL, NULL, NULL);
2198 bindtextdomain(PACKAGE, LOCALEDIR);
2199 textdomain(PACKAGE);
2203 XtAppInitialize(&appContext, "XBoard", shellOptions,
2204 XtNumber(shellOptions),
2205 &argc, argv, xboardResources, NULL, 0);
2208 gtk_init (&argc, &argv);
2210 /* parse glade file to build widgets */
2212 builder = gtk_builder_new ();
2213 gtk_builder_add_from_file (builder, "gtk-interface.xml", NULL);
2215 /* test if everything worked ok */
2217 GUI_Window = GTK_WIDGET (gtk_builder_get_object (builder, "MainWindow"));
2218 if(!GUI_Window) printf("Error: gtk_builder didn't work!\n");
2220 GUI_History = GTK_WIDGET (gtk_builder_get_object (builder, "MoveHistory"));
2221 if(!GUI_History) printf("Error: gtk_builder didn't work!\n");
2223 GUI_Menubar = GTK_WIDGET (gtk_builder_get_object (builder, "MenuBar"));
2224 if(!GUI_Menubar) printf("Error: gtk_builder didn't work!\n");
2225 GUI_Timer = GTK_WIDGET (gtk_builder_get_object (builder, "Timer"));
2226 if(!GUI_Timer) printf("Error: gtk_builder didn't work!\n");
2227 GUI_Buttonbar = GTK_WIDGET (gtk_builder_get_object (builder, "ButtonBar"));
2228 if(!GUI_Buttonbar) printf("Error: gtk_builder didn't work!\n");
2229 GUI_Board = GTK_WIDGET (gtk_builder_get_object (builder, "Board"));
2230 if(!GUI_Board) printf("Error: gtk_builder didn't work!\n");
2232 GUI_Whiteclock = GTK_WIDGET (gtk_builder_get_object (builder, "WhiteClock"));
2233 if(!GUI_Whiteclock) printf("Error: gtk_builder didn't work!\n");
2235 GUI_Blackclock = GTK_WIDGET (gtk_builder_get_object (builder, "BlackClock"));
2236 if(!GUI_Blackclock) printf("Error: gtk_builder didn't work!\n");
2238 LIST_MoveHistory = GTK_LIST_STORE (gtk_builder_get_object (builder, "MoveHistoryStore"));
2239 if(!LIST_MoveHistory) printf("Error: gtk_builder didn't work!\n");
2242 gtk_builder_connect_signals (builder, NULL);
2244 // don't unref the builder, since we use it to get references to widgets
2245 // g_object_unref (G_OBJECT (builder));
2247 /* end parse glade file */
2251 fprintf(stderr, _("%s: unrecognized argument %s\n"),
2252 programName, argv[1]);
2254 fprintf(stderr, "Recognized options:\n");
2255 for(i = 0; i < XtNumber(shellOptions); i++)
2257 /* print first column */
2258 j = fprintf(stderr, " %s%s", shellOptions[i].option,
2259 (shellOptions[i].argKind == XrmoptionSepArg
2261 /* print second column and end line */
2262 if (++i < XtNumber(shellOptions))
2264 fprintf(stderr, "%*c%s%s\n", 40 - j, ' ',
2265 shellOptions[i].option,
2266 (shellOptions[i].argKind == XrmoptionSepArg
2271 fprintf(stderr, "\n");
2278 if (p == NULL) p = "/tmp";
2279 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
2280 gameCopyFilename = (char*) malloc(i);
2281 gamePasteFilename = (char*) malloc(i);
2282 snprintf(gameCopyFilename,i, "%s/.xboard%05uc.pgn", p, getpid());
2283 snprintf(gamePasteFilename,i, "%s/.xboard%05up.pgn", p, getpid());
2285 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
2286 clientResources, XtNumber(clientResources),
2289 { // [HGM] initstring: kludge to fix bad bug. expand '\n' characters in init string and computer string.
2290 static char buf[MSG_SIZ];
2291 EscapeExpand(buf, appData.initString);
2292 appData.initString = strdup(buf);
2293 EscapeExpand(buf, appData.secondInitString);
2294 appData.secondInitString = strdup(buf);
2295 EscapeExpand(buf, appData.firstComputerString);
2296 appData.firstComputerString = strdup(buf);
2297 EscapeExpand(buf, appData.secondComputerString);
2298 appData.secondComputerString = strdup(buf);
2301 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
2304 if (chdir(chessDir) != 0) {
2305 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
2311 if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) {
2312 /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */
2313 if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL) {
2314 printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile);
2317 setbuf(debugFP, NULL);
2320 /* [HGM,HR] make sure board size is acceptable */
2321 if(appData.NrFiles > BOARD_SIZE ||
2322 appData.NrRanks > BOARD_SIZE )
2323 DisplayFatalError(_("Recompile with BOARD_SIZE > 12, to support this size"), 0, 2);
2326 /* This feature does not work; animation needs a rewrite */
2327 appData.highlightDragging = FALSE;
2331 xDisplay = XtDisplay(shellWidget);
2332 xScreen = DefaultScreen(xDisplay);
2333 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
2335 gameInfo.variant = StringToVariant(appData.variant);
2336 InitPosition(FALSE);
2338 /* calc board size */
2339 if (isdigit(appData.boardSize[0]))
2341 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
2342 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
2343 &fontPxlSize, &smallLayout, &tinyLayout);
2346 fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
2347 programName, appData.boardSize);
2352 /* Find some defaults; use the nearest known size */
2353 SizeDefaults *szd, *nearest;
2354 int distance = 99999;
2355 nearest = szd = sizeDefaults;
2356 while (szd->name != NULL)
2358 if (abs(szd->squareSize - squareSize) < distance)
2361 distance = abs(szd->squareSize - squareSize);
2362 if (distance == 0) break;
2366 if (i < 2) lineGap = nearest->lineGap;
2367 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
2368 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
2369 if (i < 5) fontPxlSize = nearest->fontPxlSize;
2370 if (i < 6) smallLayout = nearest->smallLayout;
2371 if (i < 7) tinyLayout = nearest->tinyLayout;
2376 SizeDefaults *szd = sizeDefaults;
2377 if (*appData.boardSize == NULLCHAR)
2379 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize
2380 || DisplayHeight(xDisplay, xScreen) < szd->minScreenSize)
2384 if (szd->name == NULL) szd--;
2388 while (szd->name != NULL
2389 && StrCaseCmp(szd->name, appData.boardSize) != 0)
2391 if (szd->name == NULL)
2393 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
2394 programName, appData.boardSize);
2398 squareSize = szd->squareSize;
2399 lineGap = szd->lineGap;
2400 clockFontPxlSize = szd->clockFontPxlSize;
2401 coordFontPxlSize = szd->coordFontPxlSize;
2402 fontPxlSize = szd->fontPxlSize;
2403 smallLayout = szd->smallLayout;
2404 tinyLayout = szd->tinyLayout;
2406 /* end figuring out what size to use */
2408 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2409 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2412 * Determine what fonts to use.
2414 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
2415 clockFontID = XLoadFont(xDisplay, appData.clockFont);
2416 clockFontStruct = XQueryFont(xDisplay, clockFontID);
2417 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
2418 coordFontID = XLoadFont(xDisplay, appData.coordFont);
2419 coordFontStruct = XQueryFont(xDisplay, coordFontID);
2420 appData.font = FindFont(appData.font, fontPxlSize);
2421 countFontID = XLoadFont(xDisplay, appData.coordFont); // [HGM] holdings
2422 countFontStruct = XQueryFont(xDisplay, countFontID);
2423 // appData.font = FindFont(appData.font, fontPxlSize);
2425 xdb = XtDatabase(xDisplay);
2426 XrmPutStringResource(&xdb, "*font", appData.font);
2429 * Detect if there are not enough colors available and adapt.
2431 if (DefaultDepth(xDisplay, xScreen) <= 2) {
2432 appData.monoMode = True;
2435 if (!appData.monoMode) {
2436 vFrom.addr = (caddr_t) appData.lightSquareColor;
2437 vFrom.size = strlen(appData.lightSquareColor);
2438 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2439 if (vTo.addr == NULL) {
2440 appData.monoMode = True;
2443 lightSquareColor = *(Pixel *) vTo.addr;
2446 if (!appData.monoMode) {
2447 vFrom.addr = (caddr_t) appData.darkSquareColor;
2448 vFrom.size = strlen(appData.darkSquareColor);
2449 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2450 if (vTo.addr == NULL) {
2451 appData.monoMode = True;
2454 darkSquareColor = *(Pixel *) vTo.addr;
2457 if (!appData.monoMode) {
2458 vFrom.addr = (caddr_t) appData.whitePieceColor;
2459 vFrom.size = strlen(appData.whitePieceColor);
2460 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2461 if (vTo.addr == NULL) {
2462 appData.monoMode = True;
2465 whitePieceColor = *(Pixel *) vTo.addr;
2468 if (!appData.monoMode) {
2469 vFrom.addr = (caddr_t) appData.blackPieceColor;
2470 vFrom.size = strlen(appData.blackPieceColor);
2471 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2472 if (vTo.addr == NULL) {
2473 appData.monoMode = True;
2476 blackPieceColor = *(Pixel *) vTo.addr;
2480 if (!appData.monoMode) {
2481 vFrom.addr = (caddr_t) appData.highlightSquareColor;
2482 vFrom.size = strlen(appData.highlightSquareColor);
2483 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2484 if (vTo.addr == NULL) {
2485 appData.monoMode = True;
2488 highlightSquareColor = *(Pixel *) vTo.addr;
2492 if (!appData.monoMode) {
2493 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
2494 vFrom.size = strlen(appData.premoveHighlightColor);
2495 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2496 if (vTo.addr == NULL) {
2497 appData.monoMode = True;
2500 premoveHighlightColor = *(Pixel *) vTo.addr;
2505 fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2508 if (appData.bitmapDirectory == NULL ||
2509 appData.bitmapDirectory[0] == NULLCHAR)
2510 appData.bitmapDirectory = DEF_BITMAP_DIR;
2513 if (appData.lowTimeWarning && !appData.monoMode) {
2514 vFrom.addr = (caddr_t) appData.lowTimeWarningColor;
2515 vFrom.size = strlen(appData.lowTimeWarningColor);
2516 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2517 if (vTo.addr == NULL)
2518 appData.monoMode = True;
2520 lowTimeWarningColor = *(Pixel *) vTo.addr;
2523 if (appData.monoMode && appData.debugMode) {
2524 fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2525 (unsigned long) XWhitePixel(xDisplay, xScreen),
2526 (unsigned long) XBlackPixel(xDisplay, xScreen));
2529 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
2530 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
2531 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
2532 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
2533 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
2534 parse_cpair(ColorTell, appData.colorTell) < 0 ||
2535 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
2536 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
2537 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
2538 parse_cpair(ColorNormal, appData.colorNormal) < 0)
2540 if (appData.colorize) {
2542 _("%s: can't parse color names; disabling colorization\n"),
2545 appData.colorize = FALSE;
2547 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2548 textColors[ColorNone].attr = 0;
2550 // XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2556 layoutName = "tinyLayout";
2557 } else if (smallLayout) {
2558 layoutName = "smallLayout";
2560 layoutName = "normalLayout";
2563 if (appData.titleInWindow) {
2564 /* todo check what this appdata does */
2567 if (appData.showButtonBar) {
2568 /* TODO hide button bar if requested */
2572 if (appData.titleInWindow)
2577 if (appData.showButtonBar)
2584 if (appData.showButtonBar)
2594 /* set some checkboxes in the menu according to appData */
2596 if (appData.alwaysPromoteToQueen)
2597 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Always Queen")),TRUE);
2599 if (appData.animateDragging)
2600 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Animate Dragging")),TRUE);
2602 if (appData.animate)
2603 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Animate Moving")),TRUE);
2605 if (appData.autoComment)
2606 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Comment")),TRUE);
2608 if (appData.autoCallFlag)
2609 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Flag")),TRUE);
2611 if (appData.autoFlipView)
2612 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Flip View")),TRUE);
2614 if (appData.autoObserve)
2615 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Observe")),TRUE);
2617 if (appData.autoRaiseBoard)
2618 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Raise Board")),TRUE);
2620 if (appData.autoSaveGames)
2621 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Save")),TRUE);
2623 if (appData.saveGameFile[0] != NULLCHAR)
2625 /* Can't turn this off from menu */
2626 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Save")),TRUE);
2627 gtk_action_set_sensitive(GTK_ACTION (gtk_builder_get_object (builder, "menuOptions.Auto Save")),FALSE);
2630 if (appData.blindfold)
2631 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Blindfold")),TRUE);
2633 if (appData.flashCount > 0)
2634 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Flash Moves")),TRUE);
2636 if (appData.getMoveList)
2637 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Get Move List")),TRUE);
2640 if (appData.highlightDragging)
2641 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Highlight Dragging")),TRUE);
2644 if (appData.highlightLastMove)
2645 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Highlight Last Move")),TRUE);
2647 if (appData.icsAlarm)
2648 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.ICS Alarm")),TRUE);
2650 if (appData.ringBellAfterMoves)
2651 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Move Sound")),TRUE);
2653 if (appData.oldSaveStyle)
2654 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Old Save Style")),TRUE);
2656 if (appData.periodicUpdates)
2657 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Periodic Updates")),TRUE);
2659 if (appData.ponderNextMove)
2660 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Ponder Next Move")),TRUE);
2662 if (appData.popupExitMessage)
2663 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Popup Exit Message")),TRUE);
2665 if (appData.popupMoveErrors)
2666 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Popup Move Errors")),TRUE);
2668 if (appData.premove)
2669 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Premove")),TRUE);
2671 if (appData.quietPlay)
2672 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Quit Play")),TRUE);
2674 if (appData.showCoords)
2675 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Show Coords")),TRUE);
2677 if (appData.showThinking)
2678 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Show Thinking")),TRUE);
2680 if (appData.testLegality)
2681 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Test Legality")),TRUE);
2683 /* end setting check boxes */
2685 /* load square colors */
2686 SVGLightSquare = load_pixbuf("svg/LightSquare.svg",squareSize);
2687 SVGDarkSquare = load_pixbuf("svg/DarkSquare.svg",squareSize);
2688 SVGNeutralSquare = load_pixbuf("svg/NeutralSquare.svg",squareSize);
2690 /* use two icons to indicate if it is white's or black's turn */
2691 WhiteIcon = load_pixbuf("svg/icon_white.svg",0);
2692 BlackIcon = load_pixbuf("svg/icon_black.svg",0);
2693 WindowIcon = WhiteIcon;
2694 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
2697 /* realize window */
2698 gtk_widget_show (GUI_Window);
2700 /* recalc boardsize */
2705 if (appData.animate || appData.animateDragging)
2710 if (errorExitStatus == -1) {
2711 if (appData.icsActive) {
2712 /* We now wait until we see "login:" from the ICS before
2713 sending the logon script (problems with timestamp otherwise) */
2714 /*ICSInitScript();*/
2715 if (appData.icsInputBox) ICSInputBoxPopUp();
2718 signal(SIGINT, IntSigHandler);
2719 signal(SIGTERM, IntSigHandler);
2720 if (*appData.cmailGameName != NULLCHAR) {
2721 signal(SIGUSR1, CmailSigHandler);
2724 gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes()
2728 * Create a cursor for the board widget.
2729 * (This needs to be called after the window has been created to have access to board-window)
2732 BoardCursor = gdk_cursor_new(GDK_HAND2);
2733 gdk_window_set_cursor(GUI_Board->window, BoardCursor);
2734 gdk_cursor_destroy(BoardCursor);
2739 if (appData.debugMode) fclose(debugFP); // [DM] debug
2746 if (appData.icsActive && oldICSInteractionTitle != NULL) {
2747 DisplayIcsInteractionTitle(oldICSInteractionTitle);
2749 unlink(gameCopyFilename);
2750 unlink(gamePasteFilename);
2761 CmailSigHandler(sig)
2767 signal(SIGUSR1, SIG_IGN); /* suspend handler */
2769 /* Activate call-back function CmailSigHandlerCallBack() */
2770 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
2772 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
2776 CmailSigHandlerCallBack(isr, closure, message, count, error)
2784 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
2786 /**** end signal code ****/
2796 f = fopen(appData.icsLogon, "r");
2802 strcat(buf, appData.icsLogon);
2803 f = fopen(buf, "r");
2807 ProcessICSInitScript(f);
2814 EditCommentPopDown();
2820 SetMenuEnables(enab)
2825 if (!builder) return;
2826 while (enab->name != NULL) {
2827 o = gtk_builder_get_object(builder, enab->name);
2828 if(GTK_IS_WIDGET(o))
2829 gtk_widget_set_sensitive(GTK_WIDGET (o),enab->value);
2832 if(GTK_IS_ACTION(o))
2833 gtk_action_set_sensitive(GTK_ACTION (o),enab->value);
2835 DisplayError(enab->name, 0);
2843 SetMenuEnables(icsEnables);
2846 if (appData.zippyPlay && !appData.noChessProgram) /* [DM] icsEngineAnalyze */
2847 {}; // XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
2854 SetMenuEnables(ncpEnables);
2860 SetMenuEnables(gnuEnables);
2866 SetMenuEnables(cmailEnables);
2872 SetMenuEnables(trainingOnEnables);
2873 if (appData.showButtonBar) {
2874 // XtSetSensitive(buttonBarWidget, False);
2880 SetTrainingModeOff()
2882 SetMenuEnables(trainingOffEnables);
2883 if (appData.showButtonBar) {
2884 // XtSetSensitive(buttonBarWidget, True);
2889 SetUserThinkingEnables()
2891 if (appData.noChessProgram) return;
2892 SetMenuEnables(userThinkingEnables);
2896 SetMachineThinkingEnables()
2898 if (appData.noChessProgram) return;
2899 SetMenuEnables(machineThinkingEnables);
2901 case MachinePlaysBlack:
2902 case MachinePlaysWhite:
2903 case TwoMachinesPlay:
2904 // XtSetSensitive(XtNameToWidget(menuBarWidget,
2905 // ModeToWidgetName(gameMode)), True);
2912 #define Abs(n) ((n)<0 ? -(n) : (n))
2915 * Find a font that matches "pattern" that is as close as
2916 * possible to the targetPxlSize. Prefer fonts that are k
2917 * pixels smaller to fonts that are k pixels larger. The
2918 * pattern must be in the X Consortium standard format,
2919 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
2920 * The return value should be freed with XtFree when no
2923 char *FindFont(pattern, targetPxlSize)
2927 char **fonts, *p, *best, *scalable, *scalableTail;
2928 int i, j, nfonts, minerr, err, pxlSize;
2931 char **missing_list;
2933 char *def_string, *base_fnt_lst, strInt[3];
2935 XFontStruct **fnt_list;
2937 base_fnt_lst = calloc(1, strlen(pattern) + 3);
2938 sprintf(strInt, "%d", targetPxlSize);
2939 p = strstr(pattern, "--");
2940 strncpy(base_fnt_lst, pattern, p - pattern + 2);
2941 strcat(base_fnt_lst, strInt);
2942 strcat(base_fnt_lst, strchr(p + 2, '-'));
2944 if ((fntSet = XCreateFontSet(xDisplay,
2948 &def_string)) == NULL) {
2950 fprintf(stderr, _("Unable to create font set.\n"));
2954 nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
2956 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
2958 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
2959 programName, pattern);
2967 for (i=0; i<nfonts; i++) {
2970 if (*p != '-') continue;
2972 if (*p == NULLCHAR) break;
2973 if (*p++ == '-') j++;
2975 if (j < 7) continue;
2978 scalable = fonts[i];
2981 err = pxlSize - targetPxlSize;
2982 if (Abs(err) < Abs(minerr) ||
2983 (minerr > 0 && err < 0 && -err == minerr)) {
2989 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
2990 /* If the error is too big and there is a scalable font,
2991 use the scalable font. */
2992 int headlen = scalableTail - scalable;
2993 p = (char *) XtMalloc(strlen(scalable) + 10);
2994 while (isdigit(*scalableTail)) scalableTail++;
2995 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
2997 p = (char *) XtMalloc(strlen(best) + 1);
3000 if (appData.debugMode) {
3001 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
3002 pattern, targetPxlSize, p);
3005 if (missing_count > 0)
3006 XFreeStringList(missing_list);
3007 XFreeFontSet(xDisplay, fntSet);
3009 XFreeFontNames(fonts);
3016 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
3017 | GCBackground | GCFunction | GCPlaneMask;
3018 XGCValues gc_values;
3021 gc_values.plane_mask = AllPlanes;
3022 gc_values.line_width = lineGap;
3023 gc_values.line_style = LineSolid;
3024 gc_values.function = GXcopy;
3026 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3027 gc_values.background = XWhitePixel(xDisplay, xScreen);
3028 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
3029 XSetFont(xDisplay, coordGC, coordFontID);
3031 if (appData.monoMode) {
3032 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3033 gc_values.background = XBlackPixel(xDisplay, xScreen);
3034 lightSquareGC = wbPieceGC
3035 = XtGetGC(shellWidget, value_mask, &gc_values);
3037 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3038 gc_values.background = XWhitePixel(xDisplay, xScreen);
3039 darkSquareGC = bwPieceGC
3040 = XtGetGC(shellWidget, value_mask, &gc_values);
3042 if (DefaultDepth(xDisplay, xScreen) == 1) {
3043 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3044 gc_values.function = GXcopyInverted;
3045 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3046 gc_values.function = GXcopy;
3047 if (XBlackPixel(xDisplay, xScreen) == 1) {
3048 bwPieceGC = darkSquareGC;
3049 wbPieceGC = copyInvertedGC;
3051 bwPieceGC = copyInvertedGC;
3052 wbPieceGC = lightSquareGC;
3056 gc_values.foreground = lightSquareColor;
3057 gc_values.background = darkSquareColor;
3058 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3060 gc_values.foreground = darkSquareColor;
3061 gc_values.background = lightSquareColor;
3062 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3064 gc_values.foreground = jailSquareColor;
3065 gc_values.background = jailSquareColor;
3066 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3068 gc_values.foreground = whitePieceColor;
3069 gc_values.background = darkSquareColor;
3070 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3072 gc_values.foreground = whitePieceColor;
3073 gc_values.background = lightSquareColor;
3074 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3076 gc_values.foreground = whitePieceColor;
3077 gc_values.background = jailSquareColor;
3078 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3080 gc_values.foreground = blackPieceColor;
3081 gc_values.background = darkSquareColor;
3082 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3084 gc_values.foreground = blackPieceColor;
3085 gc_values.background = lightSquareColor;
3086 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3088 gc_values.foreground = blackPieceColor;
3089 gc_values.background = jailSquareColor;
3090 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3099 for(i=0;i<MAXPIECES;i++)
3103 g_free(SVGpieces[i]);
3110 SVGLightSquare = load_pixbuf("svg/LightSquare.svg",squareSize);
3111 SVGDarkSquare = load_pixbuf("svg/DarkSquare.svg",squareSize);
3112 SVGNeutralSquare = load_pixbuf("svg/NeutralSquare.svg",squareSize);
3115 /* get some defaults going */
3116 for(i=WhitePawn; i<DemotePiece+1; i++)
3117 SVGpieces[i] = load_pixbuf("svg/NeutralSquare.svg",squareSize);
3119 SVGpieces[WhitePawn] = load_pixbuf("svg/WhitePawn.svg",squareSize);
3120 SVGpieces[WhiteKnight] = load_pixbuf("svg/WhiteKnight.svg",squareSize);
3121 SVGpieces[WhiteBishop] = load_pixbuf("svg/WhiteBishop.svg",squareSize);
3122 SVGpieces[WhiteRook] = load_pixbuf("svg/WhiteRook.svg",squareSize);
3123 SVGpieces[WhiteQueen] = load_pixbuf("svg/WhiteQueen.svg",squareSize);
3124 SVGpieces[WhiteKing] = load_pixbuf("svg/WhiteKing.svg",squareSize);
3126 SVGpieces[BlackPawn] = load_pixbuf("svg/BlackPawn.svg",squareSize);
3127 SVGpieces[BlackKnight] = load_pixbuf("svg/BlackKnight.svg",squareSize);
3128 SVGpieces[BlackBishop] = load_pixbuf("svg/BlackBishop.svg",squareSize);
3129 SVGpieces[BlackRook] = load_pixbuf("svg/BlackRook.svg",squareSize);
3130 SVGpieces[BlackQueen] = load_pixbuf("svg/BlackQueen.svg",squareSize);
3131 SVGpieces[BlackKing] = load_pixbuf("svg/BlackKing.svg",squareSize);
3137 static void MenuBarSelect(w, addr, index)
3142 XtActionProc proc = (XtActionProc) addr;
3144 (proc)(NULL, NULL, NULL, NULL);
3147 void CreateMenuBarPopup(parent, name, mb)
3157 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3160 XtSetArg(args[j], XtNleftMargin, 20); j++;
3161 XtSetArg(args[j], XtNrightMargin, 20); j++;
3163 while (mi->string != NULL) {
3164 if (strcmp(mi->string, "----") == 0) {
3165 entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
3168 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string)));
3169 entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass,
3171 XtAddCallback(entry, XtNcallback,
3172 (XtCallbackProc) MenuBarSelect,
3173 (caddr_t) mi->proc);
3179 Widget CreateMenuBar(mb)
3183 Widget anchor, menuBar;
3185 char menuName[MSG_SIZ];
3188 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3189 XtSetArg(args[j], XtNvSpace, 0); j++;
3190 XtSetArg(args[j], XtNborderWidth, 0); j++;
3191 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
3192 formWidget, args, j);
3194 while (mb->name != NULL) {
3195 strcpy(menuName, "menu");
3196 strcat(menuName, mb->name);
3198 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
3201 shortName[0] = _(mb->name)[0];
3202 shortName[1] = NULLCHAR;
3203 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
3206 XtSetArg(args[j], XtNlabel, XtNewString(_(mb->name))); j++;
3209 XtSetArg(args[j], XtNborderWidth, 0); j++;
3210 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
3212 CreateMenuBarPopup(menuBar, menuName, mb);
3218 Widget CreateButtonBar(mi)
3222 Widget button, buttonBar;
3226 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3228 XtSetArg(args[j], XtNhSpace, 0); j++;
3230 XtSetArg(args[j], XtNborderWidth, 0); j++;
3231 XtSetArg(args[j], XtNvSpace, 0); j++;
3232 buttonBar = XtCreateWidget("buttonBar", boxWidgetClass,
3233 formWidget, args, j);
3235 while (mi->string != NULL) {
3238 XtSetArg(args[j], XtNinternalWidth, 2); j++;
3239 XtSetArg(args[j], XtNborderWidth, 0); j++;
3241 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string))); j++;
3242 button = XtCreateManagedWidget(mi->string, commandWidgetClass,
3243 buttonBar, args, j);
3244 XtAddCallback(button, XtNcallback,
3245 (XtCallbackProc) MenuBarSelect,
3246 (caddr_t) mi->proc);
3253 CreatePieceMenu(name, color)
3260 ChessSquare selection;
3262 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3263 boardWidget, args, 0);
3265 for (i = 0; i < PIECE_MENU_SIZE; i++) {
3266 String item = pieceMenuStrings[color][i];
3268 if (strcmp(item, "----") == 0) {
3269 entry = XtCreateManagedWidget(item, smeLineObjectClass,
3272 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3273 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3275 selection = pieceMenuTranslation[color][i];
3276 XtAddCallback(entry, XtNcallback,
3277 (XtCallbackProc) PieceMenuSelect,
3278 (caddr_t) selection);
3279 if (selection == WhitePawn || selection == BlackPawn) {
3280 XtSetArg(args[0], XtNpopupOnEntry, entry);
3281 XtSetValues(menu, args, 1);
3294 ChessSquare selection;
3296 // whitePieceMenu = CreatePieceMenu("menuW", 0);
3297 // blackPieceMenu = CreatePieceMenu("menuB", 1);
3299 // XtRegisterGrabAction(PieceMenuPopup, True,
3300 // (unsigned)(ButtonPressMask|ButtonReleaseMask),
3301 // GrabModeAsync, GrabModeAsync);
3303 // XtSetArg(args[0], XtNlabel, _("Drop"));
3304 // dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
3305 // boardWidget, args, 1);
3306 // for (i = 0; i < DROP_MENU_SIZE; i++) {
3307 // String item = dropMenuStrings[i];
3309 // if (strcmp(item, "----") == 0) {
3310 // entry = XtCreateManagedWidget(item, smeLineObjectClass,
3311 // dropMenu, NULL, 0);
3313 // XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3314 // entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3315 // dropMenu, args, 1);
3316 // selection = dropMenuTranslation[i];
3317 // XtAddCallback(entry, XtNcallback,
3318 // (XtCallbackProc) DropMenuSelect,
3319 // (caddr_t) selection);
3324 void SetupDropMenu()
3332 for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
3333 entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
3334 p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
3335 dmEnables[i].piece);
3336 XtSetSensitive(entry, p != NULL || !appData.testLegality
3337 /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
3338 && !appData.icsActive));
3340 while (p && *p++ == dmEnables[i].piece) count++;
3341 snprintf(label, sizeof(label), "%s %d", dmEnables[i].widget, count);
3343 XtSetArg(args[j], XtNlabel, label); j++;
3344 XtSetValues(entry, args, j);
3348 void PieceMenuPopup(w, event, params, num_params)
3352 Cardinal *num_params;
3355 if (event->type != ButtonPress) return;
3356 if (errorUp) ErrorPopDown();
3360 whichMenu = params[0];
3362 case IcsPlayingWhite:
3363 case IcsPlayingBlack:
3365 case MachinePlaysWhite:
3366 case MachinePlaysBlack:
3367 if (appData.testLegality &&
3368 gameInfo.variant != VariantBughouse &&
3369 gameInfo.variant != VariantCrazyhouse) return;
3371 whichMenu = "menuD";
3377 if (((pmFromX = EventToSquare(event->xbutton.x, BOARD_WIDTH)) < 0) ||
3378 ((pmFromY = EventToSquare(event->xbutton.y, BOARD_HEIGHT)) < 0)) {
3379 pmFromX = pmFromY = -1;
3383 pmFromX = BOARD_WIDTH - 1 - pmFromX;
3385 pmFromY = BOARD_HEIGHT - 1 - pmFromY;
3387 XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
3390 static void PieceMenuSelect(w, piece, junk)
3395 if (pmFromX < 0 || pmFromY < 0) return;
3396 EditPositionMenuEvent(piece, pmFromX, pmFromY);
3399 static void DropMenuSelect(w, piece, junk)
3404 if (pmFromX < 0 || pmFromY < 0) return;
3405 DropMenuEvent(piece, pmFromX, pmFromY);
3408 void WhiteClock(w, event, prms, nprms)
3414 if (gameMode == EditPosition || gameMode == IcsExamining) {
3415 SetWhiteToPlayEvent();
3416 } else if (gameMode == IcsPlayingBlack || gameMode == MachinePlaysWhite) {
3421 void BlackClock(w, event, prms, nprms)
3427 if (gameMode == EditPosition || gameMode == IcsExamining) {
3428 SetBlackToPlayEvent();
3429 } else if (gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) {
3436 * If the user selects on a border boundary, return -1; if off the board,
3437 * return -2. Otherwise map the event coordinate to the square.
3439 int EventToSquare(x, limit)
3447 if ((x % (squareSize + lineGap)) >= squareSize)
3449 x /= (squareSize + lineGap);
3455 static void do_flash_delay(msec)
3461 static void drawHighlight(file, rank, line_type)
3462 int file, rank, line_type;
3467 if (lineGap == 0 || appData.blindfold) return;
3471 x = lineGap/2 + ((BOARD_WIDTH-1)-file) *
3472 (squareSize + lineGap);
3473 y = lineGap/2 + rank * (squareSize + lineGap);
3477 x = lineGap/2 + file * (squareSize + lineGap);
3478 y = lineGap/2 + ((BOARD_HEIGHT-1)-rank) *
3479 (squareSize + lineGap);
3483 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3485 /* draw the highlight */
3486 cairo_move_to (cr, x, y);
3487 cairo_rel_line_to (cr, 0,squareSize+lineGap);
3488 cairo_rel_line_to (cr, squareSize+lineGap,0);
3489 cairo_rel_line_to (cr, 0,-squareSize-lineGap);
3490 cairo_close_path (cr);
3492 cairo_set_line_width (cr, lineGap);
3495 /* TODO: use appdata colors */
3496 case LINE_TYPE_HIGHLIGHT:
3497 cairo_set_source_rgba (cr, 1, 1, 0, 1.0);
3500 cairo_set_source_rgba (cr, 1, 0, 0, 1.0);
3502 case LINE_TYPE_NORMAL:
3504 cairo_set_source_rgba (cr, 0, 1, 0, 1.0);
3515 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
3516 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
3519 SetHighlights(fromX, fromY, toX, toY)
3520 int fromX, fromY, toX, toY;
3522 if (hi1X != fromX || hi1Y != fromY)
3524 if (hi1X >= 0 && hi1Y >= 0)
3526 drawHighlight(hi1X, hi1Y, LINE_TYPE_NORMAL);
3528 if (fromX >= 0 && fromY >= 0)
3530 drawHighlight(fromX, fromY, LINE_TYPE_HIGHLIGHT);
3533 if (hi2X != toX || hi2Y != toY)
3535 if (hi2X >= 0 && hi2Y >= 0)
3537 drawHighlight(hi2X, hi2Y, LINE_TYPE_NORMAL);
3539 if (toX >= 0 && toY >= 0)
3541 drawHighlight(toX, toY, LINE_TYPE_HIGHLIGHT);
3555 SetHighlights(-1, -1, -1, -1);
3560 SetPremoveHighlights(fromX, fromY, toX, toY)
3561 int fromX, fromY, toX, toY;
3563 if (pm1X != fromX || pm1Y != fromY)
3565 if (pm1X >= 0 && pm1Y >= 0)
3567 drawHighlight(pm1X, pm1Y, LINE_TYPE_NORMAL);
3569 if (fromX >= 0 && fromY >= 0)
3571 drawHighlight(fromX, fromY, LINE_TYPE_PRE);
3574 if (pm2X != toX || pm2Y != toY)
3576 if (pm2X >= 0 && pm2Y >= 0)
3578 drawHighlight(pm2X, pm2Y, LINE_TYPE_NORMAL);
3580 if (toX >= 0 && toY >= 0)
3582 drawHighlight(toX, toY, LINE_TYPE_PRE);
3595 ClearPremoveHighlights()
3597 SetPremoveHighlights(-1, -1, -1, -1);
3600 static void BlankSquare(x, y, color, piece, dest)
3613 pb = SVGLightSquare;
3615 case 2: /* neutral */
3617 pb = SVGNeutralSquare;
3620 gdk_draw_pixbuf(GDK_WINDOW(GUI_Board->window),NULL,pb,0,0,x,y,-1,-1, GDK_RGB_DITHER_NORMAL, 0, 0);
3624 static void DrawPiece(piece, square_color, x, y, dest)
3626 int square_color, x, y;
3629 /* redraw background, since piece might be transparent in some areas */
3630 BlankSquare(x,y,square_color,piece,dest);
3633 gdk_draw_pixbuf(GDK_WINDOW(GUI_Board->window),NULL,
3634 GDK_PIXBUF(SVGpieces[piece]),0,0,x,y,-1,-1,
3635 GDK_RGB_DITHER_NORMAL, 0, 0);
3639 /* [HR] determine square color depending on chess variant. */
3640 static int SquareColor(row, column)
3645 if (gameInfo.variant == VariantXiangqi) {
3646 if (column >= 3 && column <= 5 && row >= 0 && row <= 2) {
3648 } else if (column >= 3 && column <= 5 && row >= 7 && row <= 9) {
3650 } else if (row <= 4) {
3656 square_color = ((column + row) % 2) == 1;
3659 /* [hgm] holdings: next line makes all holdings squares light */
3660 if(column < BOARD_LEFT || column >= BOARD_RGHT) square_color = 1;
3662 return square_color;
3665 void DrawSquare(row, column, piece, do_flash)
3666 int row, column, do_flash;
3669 int square_color, x, y;
3674 /* Calculate delay in milliseconds (2-delays per complete flash) */
3675 flash_delay = 500 / appData.flashRate;
3677 /* calculate x and y coordinates from row and column */
3680 x = lineGap + ((BOARD_WIDTH-1)-column) *
3681 (squareSize + lineGap);
3682 y = lineGap + row * (squareSize + lineGap);
3686 x = lineGap + column * (squareSize + lineGap);
3687 y = lineGap + ((BOARD_HEIGHT-1)-row) *
3688 (squareSize + lineGap);
3691 square_color = SquareColor(row, column);
3693 // [HGM] holdings: blank out area between board and holdings
3694 if ( column == BOARD_LEFT-1 || column == BOARD_RGHT
3695 || (column == BOARD_LEFT-2 && row < BOARD_HEIGHT-gameInfo.holdingsSize)
3696 || (column == BOARD_RGHT+1 && row >= gameInfo.holdingsSize) )
3698 BlankSquare(x, y, 2, EmptySquare, xBoardWindow);
3700 // [HGM] print piece counts next to holdings
3701 string[1] = NULLCHAR;
3704 cairo_text_extents_t extents;
3709 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3711 string[0] = '0' + piece;
3713 /* TODO this has to go into the font-selection */
3714 cairo_select_font_face (cr, "Sans",
3715 CAIRO_FONT_SLANT_NORMAL,
3716 CAIRO_FONT_WEIGHT_NORMAL);
3718 cairo_set_font_size (cr, 12.0);
3719 cairo_text_extents (cr, string, &extents);
3721 if (column == (flipView ? BOARD_LEFT-1 : BOARD_RGHT) )
3723 xpos= x + squareSize - extents.width - 2;
3724 ypos= y + extents.y_bearing + 1;
3726 if (column == (flipView ? BOARD_RGHT : BOARD_LEFT-1) && piece > 1)
3729 ypos = y + extents.y_bearing + 1;
3732 /* TODO mono mode? */
3733 cairo_move_to (cr, xpos, ypos);
3734 cairo_text_path (cr, string);
3735 cairo_set_source_rgb (cr, 1.0, 1.0, 1);
3736 cairo_fill_preserve (cr);
3737 cairo_set_source_rgb (cr, 0, 0, 0);
3738 cairo_set_line_width (cr, 0.1);
3747 /* square on the board */
3748 if (piece == EmptySquare || appData.blindfold)
3750 BlankSquare(x, y, square_color, piece, xBoardWindow);
3754 if (do_flash && appData.flashCount > 0)
3756 for (i=0; i<appData.flashCount; ++i)
3759 DrawPiece(piece, square_color, x, y, xBoardWindow);
3760 do_flash_delay(flash_delay);
3762 BlankSquare(x, y, square_color, piece, xBoardWindow);
3763 do_flash_delay(flash_delay);
3766 DrawPiece(piece, square_color, x, y, xBoardWindow);
3770 /* show coordinates if necessary */
3771 if(appData.showCoords)
3773 cairo_text_extents_t extents;
3777 /* TODO this has to go into the font-selection */
3778 cairo_select_font_face (cr, "Sans",
3779 CAIRO_FONT_SLANT_NORMAL,
3780 CAIRO_FONT_WEIGHT_NORMAL);
3781 cairo_set_font_size (cr, 12.0);
3783 string[1] = NULLCHAR;
3786 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3788 if (row == (flipView ? BOARD_HEIGHT-1 : 0) &&
3789 column >= BOARD_LEFT && column < BOARD_RGHT)
3791 string[0] = 'a' + column - BOARD_LEFT;
3792 cairo_text_extents (cr, string, &extents);
3794 xpos = x + squareSize - extents.width - 2;
3795 ypos = y + squareSize - extents.height - extents.y_bearing - 1;
3797 if (appData.monoMode)
3804 cairo_move_to (cr, xpos, ypos);
3805 cairo_text_path (cr, string);
3806 cairo_set_source_rgb (cr, 0.0, 0.0, 0);
3807 cairo_fill_preserve (cr);
3808 cairo_set_source_rgb (cr, 0, 1.0, 0);
3809 cairo_set_line_width (cr, 0.1);
3812 if ( column == (flipView ? BOARD_RGHT-1 : BOARD_LEFT))
3815 string[0] = ONE + row;
3816 cairo_text_extents (cr, string, &extents);
3819 ypos = y + extents.height + 1;
3821 if (appData.monoMode)
3828 cairo_move_to (cr, xpos, ypos);
3829 cairo_text_path (cr, string);
3830 cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
3831 cairo_fill_preserve (cr);
3832 cairo_set_source_rgb (cr, 0, 0, 1.0);
3833 cairo_set_line_width (cr, 0.1);
3845 /* Returns 1 if there are "too many" differences between b1 and b2
3846 (i.e. more than 1 move was made) */
3847 static int too_many_diffs(b1, b2)
3853 for (i=0; i<BOARD_HEIGHT; ++i) {
3854 for (j=0; j<BOARD_WIDTH; ++j) {
3855 if (b1[i][j] != b2[i][j]) {
3856 if (++c > 4) /* Castling causes 4 diffs */
3865 /* Matrix describing castling maneuvers */
3866 /* Row, ColRookFrom, ColKingFrom, ColRookTo, ColKingTo */
3867 static int castling_matrix[4][5] = {
3868 { 0, 0, 4, 3, 2 }, /* 0-0-0, white */
3869 { 0, 7, 4, 5, 6 }, /* 0-0, white */
3870 { 7, 0, 4, 3, 2 }, /* 0-0-0, black */
3871 { 7, 7, 4, 5, 6 } /* 0-0, black */
3874 /* Checks whether castling occurred. If it did, *rrow and *rcol
3875 are set to the destination (row,col) of the rook that moved.
3877 Returns 1 if castling occurred, 0 if not.
3879 Note: Only handles a max of 1 castling move, so be sure
3880 to call too_many_diffs() first.
3882 static int check_castle_draw(newb, oldb, rrow, rcol)
3889 /* For each type of castling... */
3890 for (i=0; i<4; ++i) {
3891 r = castling_matrix[i];
3893 /* Check the 4 squares involved in the castling move */
3895 for (j=1; j<=4; ++j) {
3896 if (newb[r[0]][r[j]] == oldb[r[0]][r[j]]) {
3903 /* All 4 changed, so it must be a castling move */
3912 static int damage[BOARD_SIZE][BOARD_SIZE];
3915 * event handler for redrawing the board
3917 void DrawPosition( repaint, board)
3918 /*Boolean*/int repaint;
3922 static int lastFlipView = 0;
3923 static int lastBoardValid = 0;
3924 static Board lastBoard;
3927 if (board == NULL) {
3928 if (!lastBoardValid) return;
3931 if (!lastBoardValid || lastFlipView != flipView) {
3932 // XtSetArg(args[0], XtNleftBitmap, (flipView ? xMarkPixmap : None));
3933 // XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flip View"),
3938 * It would be simpler to clear the window with XClearWindow()
3939 * but this causes a very distracting flicker.
3942 if (!repaint && lastBoardValid && lastFlipView == flipView)
3944 /* If too much changes (begin observing new game, etc.), don't
3946 do_flash = too_many_diffs(board, lastBoard) ? 0 : 1;
3948 /* Special check for castling so we don't flash both the king
3949 and the rook (just flash the king). */
3952 if (check_castle_draw(board, lastBoard, &rrow, &rcol))
3954 /* Draw rook with NO flashing. King will be drawn flashing later */
3955 DrawSquare(rrow, rcol, board[rrow][rcol], 0);
3956 lastBoard[rrow][rcol] = board[rrow][rcol];
3960 /* First pass -- Draw (newly) empty squares and repair damage.
3961 This prevents you from having a piece show up twice while it
3962 is flashing on its new square */
3963 for (i = 0; i < BOARD_HEIGHT; i++)
3964 for (j = 0; j < BOARD_WIDTH; j++)
3965 if ((board[i][j] != lastBoard[i][j] && board[i][j] == EmptySquare)
3968 DrawSquare(i, j, board[i][j], 0);
3969 damage[i][j] = False;
3972 /* Second pass -- Draw piece(s) in new position and flash them */
3973 for (i = 0; i < BOARD_HEIGHT; i++)
3974 for (j = 0; j < BOARD_WIDTH; j++)
3975 if (board[i][j] != lastBoard[i][j])
3977 DrawSquare(i, j, board[i][j], do_flash);
3989 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3991 cairo_set_line_width (cr, lineGap);
3993 /* TODO: use appdata colors */
3994 cairo_set_source_rgba (cr, 0, 1, 0, 1.0);
3998 for (i = 0; i < BOARD_HEIGHT + 1; i++)
4001 x2 = lineGap + BOARD_WIDTH * (squareSize + lineGap);
4002 y1 = y2 = lineGap / 2 + (i * (squareSize + lineGap));
4004 cairo_move_to (cr, x1, y1);
4005 cairo_rel_line_to (cr, x2,0);
4009 for (j = 0; j < BOARD_WIDTH + 1; j++)
4012 y2 = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
4013 x1 = x2 = lineGap / 2 + (j * (squareSize + lineGap));
4015 cairo_move_to (cr, x1, y1);
4016 cairo_rel_line_to (cr, 0, y2);
4025 for (i = 0; i < BOARD_HEIGHT; i++)
4026 for (j = 0; j < BOARD_WIDTH; j++)
4028 DrawSquare(i, j, board[i][j], 0);
4029 damage[i][j] = False;
4033 CopyBoard(lastBoard, board);
4035 lastFlipView = flipView;
4037 /* Draw highlights */
4038 if (pm1X >= 0 && pm1Y >= 0)
4040 drawHighlight(pm1X, pm1Y, LINE_TYPE_PRE);
4042 if (pm2X >= 0 && pm2Y >= 0)
4044 drawHighlight(pm2X, pm2Y, LINE_TYPE_PRE);
4046 if (hi1X >= 0 && hi1Y >= 0)
4048 drawHighlight(hi1X, hi1Y, LINE_TYPE_HIGHLIGHT);
4050 if (hi2X >= 0 && hi2Y >= 0)
4052 drawHighlight(hi2X, hi2Y, LINE_TYPE_HIGHLIGHT);
4055 /* If piece being dragged around board, must redraw that too */
4062 * event handler for parsing user moves
4064 // [HGM] This routine will need quite some reworking. Although the backend still supports the old
4065 // way of doing things, by calling UserMoveEvent() to test the legality of the move and then perform
4066 // it at the end, and doing all kind of preliminary tests here (e.g. to weed out self-captures), it
4067 // should be made to use the new way, of calling UserMoveTest early to determine the legality of the
4068 // move, (which will weed out the illegal selfcaptures and moves into the holdings, and flag promotions),
4069 // and at the end FinishMove() to perform the move after optional promotion popups.
4070 // For now I patched it to allow self-capture with King, and suppress clicks between board and holdings.
4071 void HandleUserMove(w, event, prms, nprms)
4078 Boolean saveAnimate;
4079 static int second = 0, promotionChoice = 0;
4082 if (w != boardWidget || errorExitStatus != -1) return;
4084 x = EventToSquare(event->xbutton.x, BOARD_WIDTH);
4085 y = EventToSquare(event->xbutton.y, BOARD_HEIGHT);
4086 if (!flipView && y >= 0) {
4087 y = BOARD_HEIGHT - 1 - y;
4089 if (flipView && x >= 0) {
4090 x = BOARD_WIDTH - 1 - x;
4093 if(promotionChoice) { // we are waiting for a click to indicate promotion piece
4094 if(event->type == ButtonRelease) return; // ignore upclick of click-click destination
4095 promotionChoice = FALSE; // only one chance: if click not OK it is interpreted as cancel
4096 if(appData.debugMode) fprintf(debugFP, "promotion click, x=%d, y=%d\n", x, y);
4097 if(gameInfo.holdingsWidth &&
4098 (WhiteOnMove(currentMove)
4099 ? x == BOARD_WIDTH-1 && y < gameInfo.holdingsSize && y > 0
4100 : x == 0 && y >= BOARD_HEIGHT - gameInfo.holdingsSize && y < BOARD_HEIGHT-1) ) {
4101 // click in right holdings, for determining promotion piece
4102 ChessSquare p = boards[currentMove][y][x];
4103 if(appData.debugMode) fprintf(debugFP, "square contains %d\n", (int)p);
4104 if(p != EmptySquare) {
4105 FinishMove(NormalMove, fromX, fromY, toX, toY, ToLower(PieceToChar(p)));
4110 DrawPosition(FALSE, boards[currentMove]);
4113 if (event->type == ButtonPress) ErrorPopDown();
4116 if (event->type == ButtonPress) {
4117 // XtPopdown(promotionShell);
4118 // XtDestroyWidget(promotionShell);
4119 promotionUp = False;
4127 /* [HGM] holdings: next 5 lines: ignore all clicks between board and holdings */
4128 if(event->type == ButtonPress
4129 && ( x == BOARD_LEFT-1 ||
4131 (x == BOARD_LEFT-2 && y < BOARD_HEIGHT-gameInfo.holdingsSize ) ||
4132 (x == BOARD_RGHT+1 && y >= gameInfo.holdingsSize)) )
4136 if (event->type == ButtonPress) {
4137 /* First square, prepare to drag */
4138 if (OKToStartUserMove(x, y)) {
4142 DragPieceBegin(event->xbutton.x, event->xbutton.y);
4143 if (appData.highlightDragging) {
4144 SetHighlights(x, y, -1, -1);
4152 if (event->type == ButtonRelease && x == fromX && y == fromY) {
4153 /* Click on single square in stead of drag-drop */
4154 DragPieceEnd(event->xbutton.x, event->xbutton.y);
4155 if (appData.animateDragging) {
4156 /* Undo animation damage if any */
4157 DrawPosition(FALSE, NULL);
4160 /* Second up/down in same square; just abort move */
4165 ClearPremoveHighlights();
4167 /* First upclick in same square; start click-click mode */
4168 SetHighlights(x, y, -1, -1);
4173 moveType = UserMoveTest(fromX, fromY, x, y, NULLCHAR, event->type == ButtonRelease);
4175 if (moveType == Comment) { // kludge for indicating capture-own on Press
4176 /* Clicked again on same color piece -- changed his mind */
4177 /* note that re-clicking same square always hits same color piece */
4178 second = (x == fromX && y == fromY);
4179 if (appData.highlightDragging) {
4180 SetHighlights(x, y, -1, -1);
4184 if (OKToStartUserMove(x, y)) {
4187 DragPieceBegin(event->xbutton.x, event->xbutton.y);
4192 if(moveType == AmbiguousMove) { // kludge to indicate edit-position move
4195 DragPieceEnd(event->xbutton.x, event->xbutton.y);
4196 DrawPosition(FALSE, boards[currentMove]);
4200 /* Complete move; (x,y) is now different from (fromX, fromY) on both Press and Release */
4203 saveAnimate = appData.animate;
4204 if (event->type == ButtonPress) {
4205 /* Finish clickclick move */
4206 if (appData.animate || appData.highlightLastMove) {
4207 SetHighlights(fromX, fromY, toX, toY);
4212 /* Finish drag move */
4213 if (appData.highlightLastMove) {
4214 SetHighlights(fromX, fromY, toX, toY);
4218 DragPieceEnd(event->xbutton.x, event->xbutton.y);
4219 /* Don't animate move and drag both */
4220 appData.animate = FALSE;
4222 if (moveType == WhitePromotionKnight || moveType == BlackPromotionKnight ||
4223 (moveType == WhitePromotionQueen || moveType == BlackPromotionQueen) &&
4224 appData.alwaysPromoteToQueen) { // promotion, but no choice
4225 FinishMove(moveType, fromX, fromY, toX, toY, 'q');
4227 if (moveType == WhitePromotionQueen || moveType == BlackPromotionQueen ) {
4228 SetHighlights(fromX, fromY, toX, toY);
4229 if(gameInfo.variant == VariantSuper || gameInfo.variant == VariantGreat) {
4230 // [HGM] super: promotion to captured piece selected from holdings
4231 ChessSquare p = boards[currentMove][fromY][fromX], q = boards[currentMove][toY][toX];
4232 promotionChoice = TRUE;
4233 // kludge follows to temporarily execute move on display, without promoting yet
4234 boards[currentMove][fromY][fromX] = EmptySquare; // move Pawn to 8th rank
4235 boards[currentMove][toY][toX] = p;
4236 DrawPosition(FALSE, boards[currentMove]);
4237 boards[currentMove][fromY][fromX] = p; // take back, but display stays
4238 boards[currentMove][toY][toX] = q;
4239 DisplayMessage("Click in holdings to choose piece", "");
4243 goto skipClearingFrom; // the skipped stuff is done asynchronously by PromotionCallback
4245 if(moveType != ImpossibleMove) { // valid move, but no promotion
4246 FinishMove(moveType, fromX, fromY, toX, toY, NULLCHAR);
4247 } else { // invalid move; could have set premove
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*/
4312 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
4313 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
4314 XtSetArg(args[j], XtNautoFill, True); j++;
4315 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
4317 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
4321 XtSetArg(args[j], XtNfromVert, edit); j++;
4322 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4323 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4324 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4325 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4327 XtCreateManagedWidget(_("ok"), commandWidgetClass, form, args, j);
4328 XtAddCallback(b_ok, XtNcallback, callback, (XtPointer) 0);
4331 XtSetArg(args[j], XtNfromVert, edit); j++;
4332 XtSetArg(args[j], XtNfromHoriz, b_ok); j++;
4333 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4334 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4335 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4336 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4338 XtCreateManagedWidget(_("cancel"), commandWidgetClass, form, args, j);
4339 XtAddCallback(b_cancel, XtNcallback, callback, (XtPointer) 0);
4342 XtSetArg(args[j], XtNfromVert, edit); j++;
4343 XtSetArg(args[j], XtNfromHoriz, b_cancel); j++;
4344 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4345 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4346 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4347 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4349 XtCreateManagedWidget(_("clear"), commandWidgetClass, form, args, j);
4350 XtAddCallback(b_clear, XtNcallback, callback, (XtPointer) 0);
4353 XtSetArg(args[j], XtNfromVert, edit); j++;
4354 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4355 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4356 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4357 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4359 XtCreateManagedWidget(_("close"), commandWidgetClass, form, args, j);
4360 XtAddCallback(b_close, XtNcallback, callback, (XtPointer) 0);
4363 XtSetArg(args[j], XtNfromVert, edit); j++;
4364 XtSetArg(args[j], XtNfromHoriz, b_close); j++;
4365 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4366 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4367 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4368 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4370 XtCreateManagedWidget(_("edit"), commandWidgetClass, form, args, j);
4371 XtAddCallback(b_edit, XtNcallback, callback, (XtPointer) 0);
4374 XtRealizeWidget(shell);
4376 if (commentX == -1) {
4379 Dimension pw_height;
4380 Dimension ew_height;
4383 XtSetArg(args[j], XtNheight, &ew_height); j++;
4384 XtGetValues(edit, args, j);
4387 XtSetArg(args[j], XtNheight, &pw_height); j++;
4388 XtGetValues(shell, args, j);
4389 commentH = pw_height + (lines - 1) * ew_height;
4390 commentW = bw_width - 16;
4392 XSync(xDisplay, False);
4394 /* This code seems to tickle an X bug if it is executed too soon
4395 after xboard starts up. The coordinates get transformed as if
4396 the main window was positioned at (0, 0).
4398 XtTranslateCoords(shellWidget,
4399 (bw_width - commentW) / 2, 0 - commentH / 2,
4400 &commentX, &commentY);
4402 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
4403 RootWindowOfScreen(XtScreen(shellWidget)),
4404 (bw_width - commentW) / 2, 0 - commentH / 2,
4409 if (commentY < 0) commentY = 0; /*avoid positioning top offscreen*/
4412 XtSetArg(args[j], XtNheight, commentH); j++;
4413 XtSetArg(args[j], XtNwidth, commentW); j++;
4414 XtSetArg(args[j], XtNx, commentX); j++;
4415 XtSetArg(args[j], XtNy, commentY); j++;
4416 XtSetValues(shell, args, j);
4417 XtSetKeyboardFocus(shell, edit);
4422 /* Used for analysis window and ICS input window */
4423 Widget MiscCreate(name, text, mutable, callback, lines)
4425 int /*Boolean*/ mutable;
4426 XtCallbackProc callback;
4430 Widget shell, layout, form, edit;
4432 Dimension bw_width, pw_height, ew_height, w, h;
4438 XtSetArg(args[j], XtNresizable, True); j++;
4441 XtCreatePopupShell(name, topLevelShellWidgetClass,
4442 shellWidget, args, j);
4445 XtCreatePopupShell(name, transientShellWidgetClass,
4446 shellWidget, args, j);
4449 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
4450 layoutArgs, XtNumber(layoutArgs));
4452 XtCreateManagedWidget("form", formWidgetClass, layout,
4453 formArgs, XtNumber(formArgs));
4457 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
4458 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
4460 XtSetArg(args[j], XtNstring, text); j++;
4461 XtSetArg(args[j], XtNtop, XtChainTop); j++;
4462 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4463 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4464 XtSetArg(args[j], XtNright, XtChainRight); j++;
4465 XtSetArg(args[j], XtNresizable, True); j++;
4466 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
4467 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
4468 XtSetArg(args[j], XtNautoFill, True); j++;
4469 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
4471 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
4473 XtRealizeWidget(shell);
4476 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4477 XtGetValues(boardWidget, args, j);
4480 XtSetArg(args[j], XtNheight, &ew_height); j++;
4481 XtGetValues(edit, args, j);
4484 XtSetArg(args[j], XtNheight, &pw_height); j++;
4485 XtGetValues(shell, args, j);
4486 h = pw_height + (lines - 1) * ew_height;
4489 XSync(xDisplay, False);
4491 /* This code seems to tickle an X bug if it is executed too soon
4492 after xboard starts up. The coordinates get transformed as if
4493 the main window was positioned at (0, 0).
4495 XtTranslateCoords(shellWidget, (bw_width - w) / 2, 0 - h / 2, &x, &y);
4497 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
4498 RootWindowOfScreen(XtScreen(shellWidget)),
4499 (bw_width - w) / 2, 0 - h / 2, &xx, &yy, &junk);
4503 if (y < 0) y = 0; /*avoid positioning top offscreen*/
4506 XtSetArg(args[j], XtNheight, h); j++;
4507 XtSetArg(args[j], XtNwidth, w); j++;
4508 XtSetArg(args[j], XtNx, x); j++;
4509 XtSetArg(args[j], XtNy, y); j++;
4510 XtSetValues(shell, args, j);
4516 static int savedIndex; /* gross that this is global */
4518 void EditCommentPopUp(index, title, text)
4527 if (text == NULL) text = "";
4529 if (editShell == NULL) {
4531 CommentCreate(title, text, True, EditCommentCallback, 4);
4532 XtRealizeWidget(editShell);
4533 CatchDeleteWindow(editShell, "EditCommentPopDown");
4535 edit = XtNameToWidget(editShell, "*form.text");
4537 XtSetArg(args[j], XtNstring, text); j++;
4538 XtSetValues(edit, args, j);
4540 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4541 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4542 XtSetValues(editShell, args, j);
4545 XtPopup(editShell, XtGrabNone);
4549 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
4550 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
4554 void EditCommentCallback(w, client_data, call_data)
4556 XtPointer client_data, call_data;
4564 XtSetArg(args[j], XtNlabel, &name); j++;
4565 XtGetValues(w, args, j);
4567 if (strcmp(name, _("ok")) == 0) {
4568 edit = XtNameToWidget(editShell, "*form.text");
4570 XtSetArg(args[j], XtNstring, &val); j++;
4571 XtGetValues(edit, args, j);
4572 ReplaceComment(savedIndex, val);
4573 EditCommentPopDown();
4574 } else if (strcmp(name, _("cancel")) == 0) {
4575 EditCommentPopDown();
4576 } else if (strcmp(name, _("clear")) == 0) {
4577 edit = XtNameToWidget(editShell, "*form.text");
4578 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
4579 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
4583 void EditCommentPopDown()
4588 if (!editUp) return;
4590 XtSetArg(args[j], XtNx, &commentX); j++;
4591 XtSetArg(args[j], XtNy, &commentY); j++;
4592 XtSetArg(args[j], XtNheight, &commentH); j++;
4593 XtSetArg(args[j], XtNwidth, &commentW); j++;
4594 XtGetValues(editShell, args, j);
4595 XtPopdown(editShell);
4598 XtSetArg(args[j], XtNleftBitmap, None); j++;
4599 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
4603 void ICSInputBoxPopUp()
4608 char *title = _("ICS Input");
4611 if (ICSInputShell == NULL) {
4612 ICSInputShell = MiscCreate(title, "", True, NULL, 1);
4613 tr = XtParseTranslationTable(ICSInputTranslations);
4614 edit = XtNameToWidget(ICSInputShell, "*form.text");
4615 XtOverrideTranslations(edit, tr);
4616 XtRealizeWidget(ICSInputShell);
4617 CatchDeleteWindow(ICSInputShell, "ICSInputBoxPopDown");
4620 edit = XtNameToWidget(ICSInputShell, "*form.text");
4622 XtSetArg(args[j], XtNstring, ""); j++;
4623 XtSetValues(edit, args, j);
4625 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4626 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4627 XtSetValues(ICSInputShell, args, j);
4630 XtPopup(ICSInputShell, XtGrabNone);
4631 XtSetKeyboardFocus(ICSInputShell, edit);
4633 ICSInputBoxUp = True;
4635 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
4636 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
4640 void ICSInputSendText()
4647 edit = XtNameToWidget(ICSInputShell, "*form.text");
4649 XtSetArg(args[j], XtNstring, &val); j++;
4650 XtGetValues(edit, args, j);
4651 SendMultiLineToICS(val);
4652 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
4653 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
4656 void ICSInputBoxPopDown()
4661 if (!ICSInputBoxUp) return;
4663 XtPopdown(ICSInputShell);
4664 ICSInputBoxUp = False;
4666 XtSetArg(args[j], XtNleftBitmap, None); j++;
4667 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
4671 void CommentPopUp(title, text)
4678 if (commentShell == NULL) {
4680 CommentCreate(title, text, False, CommentCallback, 4);
4681 XtRealizeWidget(commentShell);
4682 CatchDeleteWindow(commentShell, "CommentPopDown");
4684 edit = XtNameToWidget(commentShell, "*form.text");
4686 XtSetArg(args[j], XtNstring, text); j++;
4687 XtSetValues(edit, args, j);
4689 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4690 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4691 XtSetValues(commentShell, args, j);
4694 XtPopup(commentShell, XtGrabNone);
4695 XSync(xDisplay, False);
4700 void AnalysisPopUp(title, text)
4707 if (analysisShell == NULL) {
4708 analysisShell = MiscCreate(title, text, False, NULL, 4);
4709 XtRealizeWidget(analysisShell);
4710 CatchDeleteWindow(analysisShell, "AnalysisPopDown");
4713 edit = XtNameToWidget(analysisShell, "*form.text");
4715 XtSetArg(args[j], XtNstring, text); j++;
4716 XtSetValues(edit, args, j);
4718 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4719 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4720 XtSetValues(analysisShell, args, j);
4724 XtPopup(analysisShell, XtGrabNone);
4726 XSync(xDisplay, False);
4731 void CommentCallback(w, client_data, call_data)
4733 XtPointer client_data, call_data;
4740 XtSetArg(args[j], XtNlabel, &name); j++;
4741 XtGetValues(w, args, j);
4743 if (strcmp(name, _("close")) == 0) {
4745 } else if (strcmp(name, _("edit")) == 0) {
4752 void CommentPopDown()
4757 if (!commentUp) return;
4759 XtSetArg(args[j], XtNx, &commentX); j++;
4760 XtSetArg(args[j], XtNy, &commentY); j++;
4761 XtSetArg(args[j], XtNwidth, &commentW); j++;
4762 XtSetArg(args[j], XtNheight, &commentH); j++;
4763 XtGetValues(commentShell, args, j);
4764 XtPopdown(commentShell);
4765 XSync(xDisplay, False);
4769 void AnalysisPopDown()
4771 if (!analysisUp) return;
4772 XtPopdown(analysisShell);
4773 XSync(xDisplay, False);
4775 if (appData.icsEngineAnalyze) ExitAnalyzeMode(); /* [DM] icsEngineAnalyze */
4779 void FileNamePopUp(label, def, proc, openMode)
4786 Widget popup, layout, dialog, edit;
4792 fileProc = proc; /* I can't see a way not */
4793 fileOpenMode = openMode; /* to use globals here */
4796 XtSetArg(args[i], XtNresizable, True); i++;
4797 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
4798 XtSetArg(args[i], XtNtitle, XtNewString(_("File name prompt"))); i++;
4799 fileNameShell = popup =
4800 XtCreatePopupShell("File name prompt", transientShellWidgetClass,
4801 shellWidget, args, i);
4804 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
4805 layoutArgs, XtNumber(layoutArgs));
4808 XtSetArg(args[i], XtNlabel, label); i++;
4809 XtSetArg(args[i], XtNvalue, def); i++;
4810 XtSetArg(args[i], XtNborderWidth, 0); i++;
4811 dialog = XtCreateManagedWidget("fileName", dialogWidgetClass,
4814 XawDialogAddButton(dialog, _("ok"), FileNameCallback, (XtPointer) dialog);
4815 XawDialogAddButton(dialog, _("cancel"), FileNameCallback,
4816 (XtPointer) dialog);
4818 XtRealizeWidget(popup);
4819 CatchDeleteWindow(popup, "FileNamePopDown");
4821 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
4822 &x, &y, &win_x, &win_y, &mask);
4824 XtSetArg(args[0], XtNx, x - 10);
4825 XtSetArg(args[1], XtNy, y - 30);
4826 XtSetValues(popup, args, 2);
4828 XtPopup(popup, XtGrabExclusive);
4831 edit = XtNameToWidget(dialog, "*value");
4832 XtSetKeyboardFocus(popup, edit);
4835 void FileNamePopDown()
4837 if (!filenameUp) return;
4838 XtPopdown(fileNameShell);
4839 XtDestroyWidget(fileNameShell);
4844 void FileNameCallback(w, client_data, call_data)
4846 XtPointer client_data, call_data;
4851 XtSetArg(args[0], XtNlabel, &name);
4852 XtGetValues(w, args, 1);
4854 if (strcmp(name, _("cancel")) == 0) {
4859 FileNameAction(w, NULL, NULL, NULL);
4862 void FileNameAction(w, event, prms, nprms)
4874 name = XawDialogGetValueString(w = XtParent(w));
4876 if ((name != NULL) && (*name != NULLCHAR)) {
4878 XtPopdown(w = XtParent(XtParent(w)));
4882 p = strrchr(buf, ' ');
4889 fullname = ExpandPathName(buf);
4891 ErrorPopUp(_("Error"), _("Can't open file"), FALSE);
4894 f = fopen(fullname, fileOpenMode);
4896 DisplayError(_("Failed to open file"), errno);
4898 (void) (*fileProc)(f, index, buf);
4905 XtPopdown(w = XtParent(XtParent(w)));
4911 void PromotionPopUp()
4914 Widget dialog, layout;
4916 Dimension bw_width, pw_width;
4920 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4921 XtGetValues(boardWidget, args, j);
4924 XtSetArg(args[j], XtNresizable, True); j++;
4925 XtSetArg(args[j], XtNtitle, XtNewString(_("Promotion"))); j++;
4927 XtCreatePopupShell("Promotion", transientShellWidgetClass,
4928 shellWidget, args, j);
4930 XtCreateManagedWidget(layoutName, formWidgetClass, promotionShell,
4931 layoutArgs, XtNumber(layoutArgs));
4934 XtSetArg(args[j], XtNlabel, _("Promote to what?")); j++;
4935 XtSetArg(args[j], XtNborderWidth, 0); j++;
4936 dialog = XtCreateManagedWidget("promotion", dialogWidgetClass,
4939 if(gameInfo.variant != VariantShogi) {
4940 XawDialogAddButton(dialog, _("Queen"), PromotionCallback,
4941 (XtPointer) dialog);
4942 XawDialogAddButton(dialog, _("Rook"), PromotionCallback,
4943 (XtPointer) dialog);
4944 XawDialogAddButton(dialog, _("Bishop"), PromotionCallback,
4945 (XtPointer) dialog);
4946 XawDialogAddButton(dialog, _("Knight"), PromotionCallback,
4947 (XtPointer) dialog);
4948 if (!appData.testLegality || gameInfo.variant == VariantSuicide ||
4949 gameInfo.variant == VariantGiveaway) {
4950 XawDialogAddButton(dialog, _("King"), PromotionCallback,
4951 (XtPointer) dialog);
4953 if(gameInfo.variant == VariantCapablanca ||
4954 gameInfo.variant == VariantGothic ||
4955 gameInfo.variant == VariantCapaRandom) {
4956 XawDialogAddButton(dialog, _("Archbishop"), PromotionCallback,
4957 (XtPointer) dialog);
4958 XawDialogAddButton(dialog, _("Chancellor"), PromotionCallback,
4959 (XtPointer) dialog);
4961 } else // [HGM] shogi
4963 XawDialogAddButton(dialog, _("Promote"), PromotionCallback,
4964 (XtPointer) dialog);
4965 XawDialogAddButton(dialog, _("Defer"), PromotionCallback,
4966 (XtPointer) dialog);
4968 XawDialogAddButton(dialog, _("cancel"), PromotionCallback,
4969 (XtPointer) dialog);
4971 XtRealizeWidget(promotionShell);
4972 CatchDeleteWindow(promotionShell, "PromotionPopDown");
4975 XtSetArg(args[j], XtNwidth, &pw_width); j++;
4976 XtGetValues(promotionShell, args, j);
4978 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
4979 lineGap + squareSize/3 +
4980 ((toY == BOARD_HEIGHT-1) ^ (flipView) ?
4981 0 : 6*(squareSize + lineGap)), &x, &y);
4984 XtSetArg(args[j], XtNx, x); j++;
4985 XtSetArg(args[j], XtNy, y); j++;
4986 XtSetValues(promotionShell, args, j);
4988 XtPopup(promotionShell, XtGrabNone);
4993 void PromotionPopDown()
4995 if (!promotionUp) return;
4996 XtPopdown(promotionShell);
4997 XtDestroyWidget(promotionShell);
4998 promotionUp = False;
5001 void PromotionCallback(w, client_data, call_data)
5003 XtPointer client_data, call_data;
5009 XtSetArg(args[0], XtNlabel, &name);
5010 XtGetValues(w, args, 1);
5014 if (fromX == -1) return;
5016 if (strcmp(name, _("cancel")) == 0) {
5020 } else if (strcmp(name, _("Knight")) == 0) {
5022 } else if (strcmp(name, _("Promote")) == 0) {
5024 } else if (strcmp(name, _("Defer")) == 0) {
5027 promoChar = ToLower(name[0]);
5030 FinishMove(NormalMove, fromX, fromY, toX, toY, promoChar);
5032 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
5033 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
5038 void ErrorCallback(w, client_data, call_data)
5040 XtPointer client_data, call_data;
5043 XtPopdown(w = XtParent(XtParent(XtParent(w))));
5045 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5051 if (!errorUp) return;
5055 gtk_widget_destroy(GTK_WIDGET(GUI_Error));
5057 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5062 void ErrorPopUp(title, label, modal)
5063 char *title, *label;
5066 GUI_Error = gtk_message_dialog_new(GTK_WINDOW(GUI_Window),
5067 GTK_DIALOG_DESTROY_WITH_PARENT,
5072 gtk_window_set_title(GTK_WINDOW(GUI_Error),(gchar *) title);
5075 gtk_dialog_run(GTK_DIALOG(GUI_Error));
5076 gtk_widget_destroy(GTK_WIDGET(GUI_Error));
5080 g_signal_connect_swapped (GUI_Error, "response",
5081 G_CALLBACK (ErrorPopDownProc),
5084 gtk_widget_show(GTK_WIDGET(GUI_Error));
5090 /* Disable all user input other than deleting the window */
5091 static int frozen = 0;
5095 /* Grab by a widget that doesn't accept input */
5096 // XtAddGrab(messageWidget, TRUE, FALSE);
5100 /* Undo a FreezeUI */
5103 if (!frozen) return;
5104 // XtRemoveGrab(messageWidget);
5108 char *ModeToWidgetName(mode)
5112 case BeginningOfGame:
5113 if (appData.icsActive)
5114 return "menuMode.ICS Client";
5115 else if (appData.noChessProgram ||
5116 *appData.cmailGameName != NULLCHAR)
5117 return "menuMode.Edit Game";
5119 return "menuMode.Machine Black";
5120 case MachinePlaysBlack:
5121 return "menuMode.Machine Black";
5122 case MachinePlaysWhite:
5123 return "menuMode.Machine White";
5125 return "menuMode.Analysis Mode";
5127 return "menuMode.Analyze File";
5128 case TwoMachinesPlay:
5129 return "menuMode.Two Machines";
5131 return "menuMode.Edit Game";
5132 case PlayFromGameFile:
5133 return "menuFile.Load Game";
5135 return "menuMode.Edit Position";
5137 return "menuMode.Training";
5138 case IcsPlayingWhite:
5139 case IcsPlayingBlack:
5143 return "menuMode.ICS Client";
5150 void ModeHighlight()
5152 static int oldPausing = FALSE;
5153 static GameMode oldmode = (GameMode) -1;
5156 // todo this toggling of the pause button doesn't seem to work?
5157 // e.g. select pause from buttonbar doesn't activate menumode.pause
5159 // if (!boardWidget || !XtIsRealized(boardWidget)) return;
5161 if (pausing != oldPausing) {
5162 oldPausing = pausing;
5163 gtk_button_set_relief(GTK_BUTTON (gtk_builder_get_object (builder, "menuMode.Pause")),pausing?GTK_RELIEF_NORMAL:GTK_RELIEF_NONE);
5164 /* toggle background color in showbuttonbar */
5165 if (appData.showButtonBar) {
5167 gtk_button_pressed(GTK_BUTTON (gtk_builder_get_object (builder, "buttonbar.Pause")));
5169 gtk_button_released(GTK_BUTTON (gtk_builder_get_object (builder, "buttonbar.Pause")));
5174 wname = ModeToWidgetName(oldmode);
5176 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, wname)),True);
5180 /* Maybe all the enables should be handled here, not just this one */
5181 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuMode.Training")),
5182 gameMode == Training || gameMode == PlayFromGameFile);
5187 * Button/menu procedures
5190 int LoadGamePopUp(f, gameNumber, title)
5195 cmailMsgLoaded = FALSE;
5197 if (gameNumber == 0)
5199 int error = GameListBuild(f);
5203 DisplayError(_("Cannot build game list"), error);
5205 else if (!ListEmpty(&gameList)
5206 && ((ListGame *) gameList.tailPred)->number > 1)
5208 GameListPopUp(f, title);
5216 return LoadGame(f, gameNumber, title, FALSE);
5220 void LoadNextPositionProc(w, event, prms, nprms)
5229 void LoadPrevPositionProc(w, event, prms, nprms)
5238 void ReloadPositionProc(w, event, prms, nprms)
5247 void LoadPositionProc(w, event, prms, nprms)
5253 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
5256 FileNamePopUp(_("Load position file name?"), "", LoadPosition, "rb");
5259 void SaveGameProc(w, event, prms, nprms)
5265 FileNamePopUp(_("Save game file name?"),
5266 DefaultFileName(appData.oldSaveStyle ? "game" : "pgn"),
5270 void SavePositionProc(w, event, prms, nprms)
5276 FileNamePopUp(_("Save position file name?"),
5277 DefaultFileName(appData.oldSaveStyle ? "pos" : "fen"),
5281 void ReloadCmailMsgProc(w, event, prms, nprms)
5287 ReloadCmailMsgEvent(FALSE);
5290 void MailMoveProc(w, event, prms, nprms)
5299 /* this variable is shared between CopyPositionProc and SendPositionSelection */
5300 static char *selected_fen_position=NULL;
5303 SendPositionSelection(Widget w, Atom *selection, Atom *target,
5304 Atom *type_return, XtPointer *value_return,
5305 unsigned long *length_return, int *format_return)
5307 char *selection_tmp;
5309 if (!selected_fen_position) return False; /* should never happen */
5310 if (*target == XA_STRING){
5311 /* note: since no XtSelectionDoneProc was registered, Xt will
5312 * automatically call XtFree on the value returned. So have to
5313 * make a copy of it allocated with XtMalloc */
5314 selection_tmp= XtMalloc(strlen(selected_fen_position)+16);
5315 strcpy(selection_tmp, selected_fen_position);
5317 *value_return=selection_tmp;
5318 *length_return=strlen(selection_tmp);
5319 *type_return=XA_STRING;
5320 *format_return = 8; /* bits per byte */
5327 /* note: when called from menu all parameters are NULL, so no clue what the
5328 * Widget which was clicked on was, or what the click event was
5330 void CopyPositionProc(w, event, prms, nprms)
5338 if (selected_fen_position) free(selected_fen_position);
5339 selected_fen_position = (char *)PositionToFEN(currentMove, NULL);
5340 if (!selected_fen_position) return;
5341 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
5343 SendPositionSelection,
5344 NULL/* lose_ownership_proc */ ,
5345 NULL/* transfer_done_proc */);
5347 free(selected_fen_position);
5348 selected_fen_position=NULL;
5352 /* function called when the data to Paste is ready */
5354 PastePositionCB(Widget w, XtPointer client_data, Atom *selection,
5355 Atom *type, XtPointer value, unsigned long *len, int *format)
5358 if (value==NULL || *len==0) return; /* nothing had been selected to copy */
5359 fenstr[*len]='\0'; /* normally this string is terminated, but be safe */
5360 EditPositionPasteFEN(fenstr);
5364 /* called when Paste Position button is pressed,
5365 * all parameters will be NULL */
5366 void PastePositionProc(w, event, prms, nprms)
5372 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
5373 /* (XtSelectionCallbackProc) */ PastePositionCB,
5374 NULL, /* client_data passed to PastePositionCB */
5376 /* better to use the time field from the event that triggered the
5377 * call to this function, but that isn't trivial to get
5385 SendGameSelection(Widget w, Atom *selection, Atom *target,
5386 Atom *type_return, XtPointer *value_return,
5387 unsigned long *length_return, int *format_return)
5389 char *selection_tmp;
5391 if (*target == XA_STRING){
5392 FILE* f = fopen(gameCopyFilename, "r");
5395 if (f == NULL) return False;
5399 selection_tmp = XtMalloc(len + 1);
5400 count = fread(selection_tmp, 1, len, f);
5402 XtFree(selection_tmp);
5405 selection_tmp[len] = NULLCHAR;
5406 *value_return = selection_tmp;
5407 *length_return = len;
5408 *type_return = XA_STRING;
5409 *format_return = 8; /* bits per byte */
5416 /* note: when called from menu all parameters are NULL, so no clue what the
5417 * Widget which was clicked on was, or what the click event was
5419 void CopyGameProc(w, event, prms, nprms)
5427 ret = SaveGameToFile(gameCopyFilename, FALSE);
5430 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
5433 NULL/* lose_ownership_proc */ ,
5434 NULL/* transfer_done_proc */);
5437 /* function called when the data to Paste is ready */
5439 PasteGameCB(Widget w, XtPointer client_data, Atom *selection,
5440 Atom *type, XtPointer value, unsigned long *len, int *format)
5443 if (value == NULL || *len == 0) {
5444 return; /* nothing had been selected to copy */
5446 f = fopen(gamePasteFilename, "w");
5448 DisplayError(_("Can't open temp file"), errno);
5451 fwrite(value, 1, *len, f);
5454 LoadGameFromFile(gamePasteFilename, 0, gamePasteFilename, TRUE);
5457 /* called when Paste Game button is pressed,
5458 * all parameters will be NULL */
5459 void PasteGameProc(w, event, prms, nprms)
5465 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
5466 /* (XtSelectionCallbackProc) */ PasteGameCB,
5467 NULL, /* client_data passed to PasteGameCB */
5469 /* better to use the time field from the event that triggered the
5470 * call to this function, but that isn't trivial to get
5480 SaveGameProc(NULL, NULL, NULL, NULL);
5483 void AnalyzeModeProc(w, event, prms, nprms)
5491 if (!first.analysisSupport) {
5492 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
5493 DisplayError(buf, 0);
5496 /* [DM] icsEngineAnalyze [HGM] This is horrible code; reverse the gameMode and isEngineAnalyze tests! */
5497 if (appData.icsActive) {
5498 if (gameMode != IcsObserving) {
5499 sprintf(buf,_("You are not observing a game"));
5500 DisplayError(buf, 0);
5502 if (appData.icsEngineAnalyze) {
5503 if (appData.debugMode)
5504 fprintf(debugFP, _("Found unexpected active ICS engine analyze \n"));
5510 /* if enable, use want disable icsEngineAnalyze */
5511 if (appData.icsEngineAnalyze) {
5516 appData.icsEngineAnalyze = TRUE;
5517 if (appData.debugMode)
5518 fprintf(debugFP, _("ICS engine analyze starting... \n"));
5520 if (!appData.showThinking)
5521 ShowThinkingProc(NULL,NULL);
5526 void AnalyzeFileProc(w, event, prms, nprms)
5532 if (!first.analysisSupport) {
5534 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
5535 DisplayError(buf, 0);
5540 if (!appData.showThinking)
5541 ShowThinkingProc(NULL,NULL);
5544 FileNamePopUp(_("File to analyze"), "", LoadGamePopUp, "rb");
5545 AnalysisPeriodicEvent(1);
5549 void EditGameProc(w, event, prms, nprms)
5558 void EditPositionProc(w, event, prms, nprms)
5564 EditPositionEvent();
5567 void TrainingProc(w, event, prms, nprms)
5576 void EditCommentProc(w, event, prms, nprms)
5583 EditCommentPopDown();
5589 void IcsInputBoxProc(w, event, prms, nprms)
5595 if (ICSInputBoxUp) {
5596 ICSInputBoxPopDown();
5603 void EnterKeyProc(w, event, prms, nprms)
5609 if (ICSInputBoxUp == True)
5613 void AlwaysQueenProc(w, event, prms, nprms)
5621 appData.alwaysPromoteToQueen = !appData.alwaysPromoteToQueen;
5623 if (appData.alwaysPromoteToQueen) {
5624 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5626 XtSetArg(args[0], XtNleftBitmap, None);
5628 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
5632 void AnimateDraggingProc(w, event, prms, nprms)
5640 appData.animateDragging = !appData.animateDragging;
5642 if (appData.animateDragging) {
5643 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5646 XtSetArg(args[0], XtNleftBitmap, None);
5648 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Dragging"),
5652 void AnimateMovingProc(w, event, prms, nprms)
5660 appData.animate = !appData.animate;
5662 if (appData.animate) {
5663 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5666 XtSetArg(args[0], XtNleftBitmap, None);
5668 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
5672 void AutocommProc(w, event, prms, nprms)
5680 appData.autoComment = !appData.autoComment;
5682 if (appData.autoComment) {
5683 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5685 XtSetArg(args[0], XtNleftBitmap, None);
5687 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
5692 void AutoflagProc(w, event, prms, nprms)
5700 appData.autoCallFlag = !appData.autoCallFlag;
5702 if (appData.autoCallFlag) {
5703 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5705 XtSetArg(args[0], XtNleftBitmap, None);
5707 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
5711 void AutoflipProc(w, event, prms, nprms)
5719 appData.autoFlipView = !appData.autoFlipView;
5721 if (appData.autoFlipView) {
5722 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5724 XtSetArg(args[0], XtNleftBitmap, None);
5726 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flip View"),
5730 void AutobsProc(w, event, prms, nprms)
5738 appData.autoObserve = !appData.autoObserve;
5740 if (appData.autoObserve) {
5741 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5743 XtSetArg(args[0], XtNleftBitmap, None);
5745 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
5749 void AutoraiseProc(w, event, prms, nprms)
5757 appData.autoRaiseBoard = !appData.autoRaiseBoard;
5759 if (appData.autoRaiseBoard) {
5760 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5762 XtSetArg(args[0], XtNleftBitmap, None);
5764 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Raise Board"),
5768 void AutosaveProc(w, event, prms, nprms)
5776 appData.autoSaveGames = !appData.autoSaveGames;
5778 if (appData.autoSaveGames) {
5779 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5781 XtSetArg(args[0], XtNleftBitmap, None);
5783 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
5787 void BlindfoldProc(w, event, prms, nprms)
5795 appData.blindfold = !appData.blindfold;
5797 if (appData.blindfold) {
5798 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5800 XtSetArg(args[0], XtNleftBitmap, None);
5802 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Blindfold"),
5805 DrawPosition(True, NULL);
5808 void TestLegalityProc(w, event, prms, nprms)
5816 appData.testLegality = !appData.testLegality;
5818 if (appData.testLegality) {
5819 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5821 XtSetArg(args[0], XtNleftBitmap, None);
5823 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Test Legality"),
5828 void FlashMovesProc(w, event, prms, nprms)
5836 if (appData.flashCount == 0) {
5837 appData.flashCount = 3;
5839 appData.flashCount = -appData.flashCount;
5842 if (appData.flashCount > 0) {
5843 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5845 XtSetArg(args[0], XtNleftBitmap, None);
5847 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flash Moves"),
5852 void HighlightDraggingProc(w, event, prms, nprms)
5860 appData.highlightDragging = !appData.highlightDragging;
5862 if (appData.highlightDragging) {
5863 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5865 XtSetArg(args[0], XtNleftBitmap, None);
5867 XtSetValues(XtNameToWidget(menuBarWidget,
5868 "menuOptions.Highlight Dragging"), args, 1);
5872 void HighlightLastMoveProc(w, event, prms, nprms)
5880 appData.highlightLastMove = !appData.highlightLastMove;
5882 if (appData.highlightLastMove) {
5883 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5885 XtSetArg(args[0], XtNleftBitmap, None);
5887 XtSetValues(XtNameToWidget(menuBarWidget,
5888 "menuOptions.Highlight Last Move"), args, 1);
5891 void IcsAlarmProc(w, event, prms, nprms)
5899 appData.icsAlarm = !appData.icsAlarm;
5901 if (appData.icsAlarm) {
5902 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5904 XtSetArg(args[0], XtNleftBitmap, None);
5906 XtSetValues(XtNameToWidget(menuBarWidget,
5907 "menuOptions.ICS Alarm"), args, 1);
5910 void MoveSoundProc(w, event, prms, nprms)
5918 appData.ringBellAfterMoves = !appData.ringBellAfterMoves;
5920 if (appData.ringBellAfterMoves) {
5921 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5923 XtSetArg(args[0], XtNleftBitmap, None);
5925 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
5930 void OldSaveStyleProc(w, event, prms, nprms)
5938 appData.oldSaveStyle = !appData.oldSaveStyle;
5940 if (appData.oldSaveStyle) {
5941 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5943 XtSetArg(args[0], XtNleftBitmap, None);
5945 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Old Save Style"),
5949 void PeriodicUpdatesProc(w, event, prms, nprms)
5957 PeriodicUpdatesEvent(!appData.periodicUpdates);
5959 if (appData.periodicUpdates) {
5960 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5962 XtSetArg(args[0], XtNleftBitmap, None);
5964 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Periodic Updates"),
5968 void PonderNextMoveProc(w, event, prms, nprms)
5976 PonderNextMoveEvent(!appData.ponderNextMove);
5978 if (appData.ponderNextMove) {
5979 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5981 XtSetArg(args[0], XtNleftBitmap, None);
5983 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Ponder Next Move"),
5987 void PopupExitMessageProc(w, event, prms, nprms)
5995 appData.popupExitMessage = !appData.popupExitMessage;
5997 if (appData.popupExitMessage) {
5998 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6000 XtSetArg(args[0], XtNleftBitmap, None);
6002 XtSetValues(XtNameToWidget(menuBarWidget,
6003 "menuOptions.Popup Exit Message"), args, 1);
6006 void PopupMoveErrorsProc(w, event, prms, nprms)
6014 appData.popupMoveErrors = !appData.popupMoveErrors;
6016 if (appData.popupMoveErrors) {
6017 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6019 XtSetArg(args[0], XtNleftBitmap, None);
6021 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Popup Move Errors"),
6025 void PremoveProc(w, event, prms, nprms)
6033 appData.premove = !appData.premove;
6035 if (appData.premove) {
6036 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6038 XtSetArg(args[0], XtNleftBitmap, None);
6040 XtSetValues(XtNameToWidget(menuBarWidget,
6041 "menuOptions.Premove"), args, 1);
6044 void QuietPlayProc(w, event, prms, nprms)
6052 appData.quietPlay = !appData.quietPlay;
6054 if (appData.quietPlay) {
6055 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6057 XtSetArg(args[0], XtNleftBitmap, None);
6059 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Quiet Play"),
6063 void DebugProc(w, event, prms, nprms)
6069 appData.debugMode = !appData.debugMode;
6072 void AboutGameProc(w, event, prms, nprms)
6081 void NothingProc(w, event, prms, nprms)
6090 void Iconify(w, event, prms, nprms)
6099 XtSetArg(args[0], XtNiconic, True);
6100 XtSetValues(shellWidget, args, 1);
6103 void DisplayMessage(message, extMessage)
6104 gchar *message, *extMessage;
6111 snprintf(buf, sizeof(buf), "%s %s", message, extMessage);
6114 message = extMessage;
6117 gtk_label_set_text( GTK_LABEL(gtk_builder_get_object (builder, "Messages")),message);
6122 void DisplayTitle(text)
6125 gchar title[MSG_SIZ];
6127 if (text == NULL) text = "";
6129 if (appData.titleInWindow)
6134 if (*text != NULLCHAR)
6136 strcpy(title, text);
6138 else if (appData.icsActive)
6140 snprintf(title, sizeof(title), "%s: %s", programName, appData.icsHost);
6142 else if (appData.cmailGameName[0] != NULLCHAR)
6144 snprintf(title,sizeof(title), "%s: %s", programName, "CMail");
6146 // [HGM] license: This stuff should really be done in back-end, but WinBoard already had a pop-up for it
6148 else if (gameInfo.variant == VariantGothic)
6150 strcpy(title, GOTHIC);
6154 else if (gameInfo.variant == VariantFalcon)
6156 strcpy(title, FALCON);
6159 else if (appData.noChessProgram)
6161 strcpy(title, programName);
6165 snprintf(title,sizeof(title), "%s: %s", programName, first.tidy);
6167 gtk_window_set_title(GTK_WINDOW(GUI_Window),title);
6173 void DisplayError(message, error)
6180 if (appData.debugMode || appData.matchMode) {
6181 fprintf(stderr, "%s: %s\n", programName, message);
6184 if (appData.debugMode || appData.matchMode) {
6185 fprintf(stderr, "%s: %s: %s\n",
6186 programName, message, strerror(error));
6188 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
6191 ErrorPopUp(_("Error"), message, FALSE);
6195 void DisplayMoveError(message)
6200 DrawPosition(FALSE, NULL);
6201 if (appData.debugMode || appData.matchMode) {
6202 fprintf(stderr, "%s: %s\n", programName, message);
6204 if (appData.popupMoveErrors) {
6205 ErrorPopUp(_("Error"), message, FALSE);
6207 DisplayMessage(message, "");
6212 void DisplayFatalError(message, error, status)
6218 errorExitStatus = status;
6220 fprintf(stderr, "%s: %s\n", programName, message);
6222 fprintf(stderr, "%s: %s: %s\n",
6223 programName, message, strerror(error));
6224 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
6227 if (appData.popupExitMessage && boardWidget && XtIsRealized(boardWidget)) {
6228 ErrorPopUp(status ? _("Fatal Error") : _("Exiting"), message, TRUE);
6234 void DisplayInformation(message)
6238 ErrorPopUp(_("Information"), message, TRUE);
6241 void DisplayNote(message)
6245 ErrorPopUp(_("Note"), message, FALSE);
6249 NullXErrorCheck(dpy, error_event)
6251 XErrorEvent *error_event;
6256 void DisplayIcsInteractionTitle(message)
6259 if (oldICSInteractionTitle == NULL) {
6260 /* Magic to find the old window title, adapted from vim */
6261 char *wina = getenv("WINDOWID");
6263 Window win = (Window) atoi(wina);
6264 Window root, parent, *children;
6265 unsigned int nchildren;
6266 int (*oldHandler)() = XSetErrorHandler(NullXErrorCheck);
6268 if (XFetchName(xDisplay, win, &oldICSInteractionTitle)) break;
6269 if (!XQueryTree(xDisplay, win, &root, &parent,
6270 &children, &nchildren)) break;
6271 if (children) XFree((void *)children);
6272 if (parent == root || parent == 0) break;
6275 XSetErrorHandler(oldHandler);
6277 if (oldICSInteractionTitle == NULL) {
6278 oldICSInteractionTitle = "xterm";
6281 printf("\033]0;%s\007", message);
6285 char pendingReplyPrefix[MSG_SIZ];
6286 ProcRef pendingReplyPR;
6288 void AskQuestionProc(w, event, prms, nprms)
6295 fprintf(stderr, _("AskQuestionProc needed 4 parameters, got %d\n"),
6299 AskQuestionEvent(prms[0], prms[1], prms[2], prms[3]);
6302 void AskQuestionPopDown()
6304 if (!askQuestionUp) return;
6305 XtPopdown(askQuestionShell);
6306 XtDestroyWidget(askQuestionShell);
6307 askQuestionUp = False;
6310 void AskQuestionReplyAction(w, event, prms, nprms)
6320 reply = XawDialogGetValueString(w = XtParent(w));
6321 strcpy(buf, pendingReplyPrefix);
6322 if (*buf) strcat(buf, " ");
6325 OutputToProcess(pendingReplyPR, buf, strlen(buf), &err);
6326 AskQuestionPopDown();
6328 if (err) DisplayFatalError(_("Error writing to chess program"), err, 0);
6331 void AskQuestionCallback(w, client_data, call_data)
6333 XtPointer client_data, call_data;
6338 XtSetArg(args[0], XtNlabel, &name);
6339 XtGetValues(w, args, 1);
6341 if (strcmp(name, _("cancel")) == 0) {
6342 AskQuestionPopDown();
6344 AskQuestionReplyAction(w, NULL, NULL, NULL);
6348 void AskQuestion(title, question, replyPrefix, pr)
6349 char *title, *question, *replyPrefix;
6353 Widget popup, layout, dialog, edit;
6359 strcpy(pendingReplyPrefix, replyPrefix);
6360 pendingReplyPR = pr;
6363 XtSetArg(args[i], XtNresizable, True); i++;
6364 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
6365 askQuestionShell = popup =
6366 XtCreatePopupShell(title, transientShellWidgetClass,
6367 shellWidget, args, i);
6370 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
6371 layoutArgs, XtNumber(layoutArgs));
6374 XtSetArg(args[i], XtNlabel, question); i++;
6375 XtSetArg(args[i], XtNvalue, ""); i++;
6376 XtSetArg(args[i], XtNborderWidth, 0); i++;
6377 dialog = XtCreateManagedWidget("question", dialogWidgetClass,
6380 XawDialogAddButton(dialog, _("enter"), AskQuestionCallback,
6381 (XtPointer) dialog);
6382 XawDialogAddButton(dialog, _("cancel"), AskQuestionCallback,
6383 (XtPointer) dialog);
6385 XtRealizeWidget(popup);
6386 CatchDeleteWindow(popup, "AskQuestionPopDown");
6388 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
6389 &x, &y, &win_x, &win_y, &mask);
6391 XtSetArg(args[0], XtNx, x - 10);
6392 XtSetArg(args[1], XtNy, y - 30);
6393 XtSetValues(popup, args, 2);
6395 XtPopup(popup, XtGrabExclusive);
6396 askQuestionUp = True;
6398 edit = XtNameToWidget(dialog, "*value");
6399 XtSetKeyboardFocus(popup, edit);
6407 if (*name == NULLCHAR) {
6409 } else if (strcmp(name, "$") == 0) {
6410 putc(BELLCHAR, stderr);
6413 snprintf(buf, sizeof(buf), "%s '%s' &", appData.soundProgram, name);
6421 PlaySound(appData.soundMove);
6427 PlaySound(appData.soundIcsWin);
6433 PlaySound(appData.soundIcsLoss);
6439 PlaySound(appData.soundIcsDraw);
6443 PlayIcsUnfinishedSound()
6445 PlaySound(appData.soundIcsUnfinished);
6451 PlaySound(appData.soundIcsAlarm);
6457 system("stty echo");
6463 system("stty -echo");
6467 Colorize(cc, continuation)
6472 int count, outCount, error;
6474 if (textColors[(int)cc].bg > 0) {
6475 if (textColors[(int)cc].fg > 0) {
6476 sprintf(buf, "\033[0;%d;%d;%dm", textColors[(int)cc].attr,
6477 textColors[(int)cc].fg, textColors[(int)cc].bg);
6479 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
6480 textColors[(int)cc].bg);
6483 if (textColors[(int)cc].fg > 0) {
6484 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
6485 textColors[(int)cc].fg);
6487 sprintf(buf, "\033[0;%dm", textColors[(int)cc].attr);
6490 count = strlen(buf);
6491 outCount = OutputToProcess(NoProc, buf, count, &error);
6492 if (outCount < count) {
6493 DisplayFatalError(_("Error writing to display"), error, 1);
6496 if (continuation) return;
6499 PlaySound(appData.soundShout);
6502 PlaySound(appData.soundSShout);
6505 PlaySound(appData.soundChannel1);
6508 PlaySound(appData.soundChannel);
6511 PlaySound(appData.soundKibitz);
6514 PlaySound(appData.soundTell);
6516 case ColorChallenge:
6517 PlaySound(appData.soundChallenge);
6520 PlaySound(appData.soundRequest);
6523 PlaySound(appData.soundSeek);
6534 return getpwuid(getuid())->pw_name;
6537 static char *ExpandPathName(path)
6540 static char static_buf[2000];
6541 char *d, *s, buf[2000];
6547 while (*s && isspace(*s))
6556 if (*(s+1) == '/') {
6557 strcpy(d, getpwuid(getuid())->pw_dir);
6562 *strchr(buf, '/') = 0;
6563 pwd = getpwnam(buf);
6566 fprintf(stderr, _("ERROR: Unknown user %s (in path %s)\n"),
6570 strcpy(d, pwd->pw_dir);
6571 strcat(d, strchr(s+1, '/'));
6582 static char host_name[MSG_SIZ];
6584 #if HAVE_GETHOSTNAME
6585 gethostname(host_name, MSG_SIZ);
6587 #else /* not HAVE_GETHOSTNAME */
6588 # if HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H
6589 sysinfo(SI_HOSTNAME, host_name, MSG_SIZ);
6591 # else /* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
6593 # endif/* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
6594 #endif /* not HAVE_GETHOSTNAME */
6597 guint delayedEventTimerTag = 0;
6598 DelayedEventCallback delayedEventCallback = 0;
6601 FireDelayedEvent(data)
6605 g_source_remove(delayedEventTimerTag);
6606 delayedEventTimerTag = 0;
6609 delayedEventCallback();
6615 ScheduleDelayedEvent(cb, millisec)
6616 DelayedEventCallback cb; guint millisec;
6618 if(delayedEventTimerTag && delayedEventCallback == cb)
6619 // [HGM] alive: replace, rather than add or flush identical event
6620 g_source_remove(delayedEventTimerTag);
6621 delayedEventCallback = cb;
6622 delayedEventTimerTag = g_timeout_add(millisec,(GSourceFunc) FireDelayedEvent, NULL);
6626 DelayedEventCallback
6629 if (delayedEventTimerTag)
6631 return delayedEventCallback;
6640 CancelDelayedEvent()
6642 if (delayedEventTimerTag)
6644 g_source_remove(delayedEventTimerTag);
6645 delayedEventTimerTag = 0;
6651 guint loadGameTimerTag = 0;
6653 int LoadGameTimerRunning()
6655 return loadGameTimerTag != 0;
6658 int StopLoadGameTimer()
6660 if (loadGameTimerTag != 0) {
6661 g_source_remove(loadGameTimerTag);
6662 loadGameTimerTag = 0;
6670 LoadGameTimerCallback(data)
6674 g_source_remove(loadGameTimerTag);
6675 loadGameTimerTag = 0;
6682 StartLoadGameTimer(millisec)
6686 g_timeout_add( millisec, (GSourceFunc) LoadGameTimerCallback, NULL);
6690 guint analysisClockTag = 0;
6693 AnalysisClockCallback(data)
6696 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile
6697 || appData.icsEngineAnalyze)
6699 AnalysisPeriodicEvent(0);
6700 return 1; /* keep on going */
6702 return 0; /* stop timer */
6706 StartAnalysisClock()
6709 g_timeout_add( 2000,(GSourceFunc) AnalysisClockCallback, NULL);
6713 guint clockTimerTag = 0;
6715 int ClockTimerRunning()
6717 return clockTimerTag != 0;
6720 int StopClockTimer()
6722 if (clockTimerTag != 0)
6724 g_source_remove(clockTimerTag);
6735 ClockTimerCallback(data)
6739 g_source_remove(clockTimerTag);
6747 StartClockTimer(millisec)
6750 clockTimerTag = g_timeout_add(millisec,(GSourceFunc) ClockTimerCallback,NULL);
6755 DisplayTimerLabel(w, color, timer, highlight)
6764 if (appData.clockMode) {
6765 sprintf(buf, "%s: %s", color, TimeString(timer));
6767 sprintf(buf, "%s ", color);
6769 gtk_label_set_text(GTK_LABEL(w),buf);
6771 /* check for low time warning */
6772 // Pixel foregroundOrWarningColor = timerForegroundPixel;
6775 // appData.lowTimeWarning &&
6776 // (timer / 1000) < appData.icsAlarmTime)
6777 // foregroundOrWarningColor = lowTimeWarningColor;
6779 // if (appData.clockMode) {
6780 // sprintf(buf, "%s: %s", color, TimeString(timer));
6781 // XtSetArg(args[0], XtNlabel, buf);
6783 // sprintf(buf, "%s ", color);
6784 // XtSetArg(args[0], XtNlabel, buf);
6789 // XtSetArg(args[1], XtNbackground, foregroundOrWarningColor);
6790 // XtSetArg(args[2], XtNforeground, timerBackgroundPixel);
6792 // XtSetArg(args[1], XtNbackground, timerBackgroundPixel);
6793 // XtSetArg(args[2], XtNforeground, foregroundOrWarningColor);
6796 // XtSetValues(w, args, 3);
6801 DisplayWhiteClock(timeRemaining, highlight)
6805 if(appData.noGUI) return;
6807 DisplayTimerLabel(GUI_Whiteclock, _("White"), timeRemaining, highlight);
6808 if (highlight && WindowIcon == BlackIcon)
6810 WindowIcon = WhiteIcon;
6811 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
6816 DisplayBlackClock(timeRemaining, highlight)
6820 if(appData.noGUI) return;
6822 DisplayTimerLabel(GUI_Blackclock, _("Black"), timeRemaining, highlight);
6823 if (highlight && WindowIcon == WhiteIcon)
6825 WindowIcon = BlackIcon;
6826 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
6844 int StartChildProcess(cmdLine, dir, pr)
6851 int to_prog[2], from_prog[2];
6855 if (appData.debugMode) {
6856 fprintf(stderr, "StartChildProcess (dir=\"%s\") %s\n",dir, cmdLine);
6859 /* We do NOT feed the cmdLine to the shell; we just
6860 parse it into blank-separated arguments in the
6861 most simple-minded way possible.
6864 strcpy(buf, cmdLine);
6869 if (p == NULL) break;
6874 SetUpChildIO(to_prog, from_prog);
6876 if ((pid = fork()) == 0) {
6878 // [HGM] PSWBTM: made order resistant against case where fd of created pipe was 0 or 1
6879 close(to_prog[1]); // first close the unused pipe ends
6880 close(from_prog[0]);
6881 dup2(to_prog[0], 0); // to_prog was created first, nd is the only one to use 0 or 1
6882 dup2(from_prog[1], 1);
6883 if(to_prog[0] >= 2) close(to_prog[0]); // if 0 or 1, the dup2 already cosed the original
6884 close(from_prog[1]); // and closing again loses one of the pipes!
6885 if(fileno(stderr) >= 2) // better safe than sorry...
6886 dup2(1, fileno(stderr)); /* force stderr to the pipe */
6888 if (dir[0] != NULLCHAR && chdir(dir) != 0) {
6893 nice(appData.niceEngines); // [HGM] nice: adjust priority of engine proc
6895 execvp(argv[0], argv);
6897 /* If we get here, exec failed */
6902 /* Parent process */
6904 close(from_prog[1]);
6906 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
6909 cp->fdFrom = from_prog[0];
6910 cp->fdTo = to_prog[1];
6915 // [HGM] kill: implement the 'hard killing' of AS's Winboard_x
6916 static RETSIGTYPE AlarmCallBack(int n)
6922 DestroyChildProcess(pr, signalType)
6926 ChildProc *cp = (ChildProc *) pr;
6928 if (cp->kind != CPReal) return;
6930 if (signalType == 10) { // [HGM] kill: if it does not terminate in 3 sec, kill
6931 signal(SIGALRM, AlarmCallBack);
6933 if(wait((int *) 0) == -1) { // process does not terminate on its own accord
6934 kill(cp->pid, SIGKILL); // kill it forcefully
6935 wait((int *) 0); // and wait again
6939 kill(cp->pid, signalType == 9 ? SIGKILL : SIGTERM); // [HGM] kill: use hard kill if so requested
6941 /* Process is exiting either because of the kill or because of
6942 a quit command sent by the backend; either way, wait for it to die.
6951 InterruptChildProcess(pr)
6954 ChildProc *cp = (ChildProc *) pr;
6956 if (cp->kind != CPReal) return;
6957 (void) kill(cp->pid, SIGINT); /* stop it thinking */
6960 int OpenTelnet(host, port, pr)
6965 char cmdLine[MSG_SIZ];
6967 if (port[0] == NULLCHAR) {
6968 snprintf(cmdLine, sizeof(cmdLine), "%s %s", appData.telnetProgram, host);
6970 snprintf(cmdLine, sizeof(cmdLine), "%s %s %s", appData.telnetProgram, host, port);
6972 return StartChildProcess(cmdLine, "", pr);
6975 int OpenTCP(host, port, pr)
6981 DisplayFatalError(_("Socket support is not configured in"), 0, 2);
6982 #else /* !OMIT_SOCKETS */
6984 struct sockaddr_in sa;
6986 unsigned short uport;
6989 if ((s = socket(AF_INET, SOCK_STREAM, 6)) < 0) {
6993 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
6994 sa.sin_family = AF_INET;
6995 sa.sin_addr.s_addr = INADDR_ANY;
6996 uport = (unsigned short) 0;
6997 sa.sin_port = htons(uport);
6998 if (bind(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)) < 0) {
7002 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
7003 if (!(hp = gethostbyname(host))) {
7005 if (sscanf(host, "%d.%d.%d.%d", &b0, &b1, &b2, &b3) == 4) {
7006 hp = (struct hostent *) calloc(1, sizeof(struct hostent));
7007 hp->h_addrtype = AF_INET;
7009 hp->h_addr_list = (char **) calloc(2, sizeof(char *));
7010 hp->h_addr_list[0] = (char *) malloc(4);
7011 hp->h_addr_list[0][0] = b0;
7012 hp->h_addr_list[0][1] = b1;
7013 hp->h_addr_list[0][2] = b2;
7014 hp->h_addr_list[0][3] = b3;
7019 sa.sin_family = hp->h_addrtype;
7020 uport = (unsigned short) atoi(port);
7021 sa.sin_port = htons(uport);
7022 memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);
7024 if (connect(s, (struct sockaddr *) &sa,
7025 sizeof(struct sockaddr_in)) < 0) {
7029 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7036 #endif /* !OMIT_SOCKETS */
7041 int OpenCommPort(name, pr)
7048 fd = open(name, 2, 0);
7049 if (fd < 0) return errno;
7051 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7061 int OpenLoopback(pr)
7067 SetUpChildIO(to, from);
7069 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7072 cp->fdFrom = to[0]; /* note not from[0]; we are doing a loopback */
7079 int OpenRcmd(host, user, cmd, pr)
7080 char *host, *user, *cmd;
7083 DisplayFatalError(_("internal rcmd not implemented for Unix"), 0, 1);
7087 #define INPUT_SOURCE_BUF_SIZE 8192
7096 char buf[INPUT_SOURCE_BUF_SIZE];
7101 DoInputCallback(io,cond,data)
7106 /* read input from one of the input source (for example a chess program, ICS, etc).
7107 * and call a function that will handle the input
7110 int count; /* how many bytes did we read */
7114 /* All information (callback function, file descriptor, etc) is
7115 * saved in an InputSource structure
7117 InputSource *is = (InputSource *) data;
7121 count = read(is->fd, is->unused,
7122 INPUT_SOURCE_BUF_SIZE - (is->unused - is->buf));
7126 (is->func)(is, is->closure, is->buf, count, count ? errno : 0);
7129 is->unused += count;
7131 /* break input into lines and call the callback function on each
7134 while (p < is->unused)
7136 q = memchr(p, '\n', is->unused - p);
7137 if (q == NULL) break;
7139 (is->func)(is, is->closure, p, q - p, 0);
7142 /* remember not yet used part of the buffer */
7144 while (p < is->unused)
7152 /* read maximum length of input buffer and send the whole buffer
7153 * to the callback function
7155 count = read(is->fd, is->buf, INPUT_SOURCE_BUF_SIZE);
7160 (is->func)(is, is->closure, is->buf, count, error);
7166 InputSourceRef AddInputSource(pr, lineByLine, func, closure)
7173 GIOChannel *channel;
7174 ChildProc *cp = (ChildProc *) pr;
7176 is = (InputSource *) calloc(1, sizeof(InputSource));
7177 is->lineByLine = lineByLine;
7181 is->fd = fileno(stdin);
7183 is->kind = cp->kind;
7184 is->fd = cp->fdFrom;
7187 is->unused = is->buf;
7191 // is->xid = XtAppAddInput(appContext, is->fd,
7192 // (XtPointer) (XtInputReadMask),
7193 // (XtInputCallbackProc) DoInputCallback,
7197 /* TODO: will this work on windows?*/
7198 printf("DEBUG: fd=%d %d\n",is->fd,is);
7200 channel = g_io_channel_unix_new(is->fd);
7201 g_io_channel_set_close_on_unref (channel, TRUE);
7202 is->sid = g_io_add_watch(channel, G_IO_IN,(GIOFunc) DoInputCallback, is);
7203 is->closure = closure;
7204 return (InputSourceRef) is;
7208 RemoveInputSource(isr)
7211 InputSource *is = (InputSource *) isr;
7213 if (is->sid == 0) return;
7214 g_source_remove(is->sid);
7219 int OutputToProcess(pr, message, count, outError)
7225 ChildProc *cp = (ChildProc *) pr;
7229 outCount = fwrite(message, 1, count, stdout);
7231 outCount = write(cp->fdTo, message, count);
7241 /* Output message to process, with "ms" milliseconds of delay
7242 between each character. This is needed when sending the logon
7243 script to ICC, which for some reason doesn't like the
7244 instantaneous send. */
7245 int OutputToProcessDelayed(pr, message, count, outError, msdelay)
7252 ChildProc *cp = (ChildProc *) pr;
7257 r = write(cp->fdTo, message++, 1);
7270 /**** Animation code by Hugh Fisher, DCS, ANU.
7272 Known problem: if a window overlapping the board is
7273 moved away while a piece is being animated underneath,
7274 the newly exposed area won't be updated properly.
7275 I can live with this.
7277 Known problem: if you look carefully at the animation
7278 of pieces in mono mode, they are being drawn as solid
7279 shapes without interior detail while moving. Fixing
7280 this would be a major complication for minimal return.
7283 /* Masks for XPM pieces. Black and white pieces can have
7284 different shapes, but in the interest of retaining my
7285 sanity pieces must have the same outline on both light
7286 and dark squares, and all pieces must use the same
7287 background square colors/images. */
7289 static int xpmDone = 0;
7292 CreateAnimMasks (pieceDepth)
7299 unsigned long plane;
7302 /* just return for gtk at the moment */
7305 /* Need a bitmap just to get a GC with right depth */
7306 buf = XCreatePixmap(xDisplay, xBoardWindow,
7308 values.foreground = 1;
7309 values.background = 0;
7310 /* Don't use XtGetGC, not read only */
7311 maskGC = XCreateGC(xDisplay, buf,
7312 GCForeground | GCBackground, &values);
7313 XFreePixmap(xDisplay, buf);
7315 buf = XCreatePixmap(xDisplay, xBoardWindow,
7316 squareSize, squareSize, pieceDepth);
7317 values.foreground = XBlackPixel(xDisplay, xScreen);
7318 values.background = XWhitePixel(xDisplay, xScreen);
7319 bufGC = XCreateGC(xDisplay, buf,
7320 GCForeground | GCBackground, &values);
7322 for (piece = WhitePawn; piece <= BlackKing; piece++) {
7323 /* Begin with empty mask */
7324 if(!xpmDone) // [HGM] pieces: keep using existing
7325 xpmMask[piece] = XCreatePixmap(xDisplay, xBoardWindow,
7326 squareSize, squareSize, 1);
7327 XSetFunction(xDisplay, maskGC, GXclear);
7328 XFillRectangle(xDisplay, xpmMask[piece], maskGC,
7329 0, 0, squareSize, squareSize);
7331 /* Take a copy of the piece */
7336 XSetFunction(xDisplay, bufGC, GXcopy);
7337 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn],
7339 0, 0, squareSize, squareSize, 0, 0);
7341 /* XOR the background (light) over the piece */
7342 XSetFunction(xDisplay, bufGC, GXxor);
7344 XCopyArea(xDisplay, xpmLightSquare, buf, bufGC,
7345 0, 0, squareSize, squareSize, 0, 0);
7347 XSetForeground(xDisplay, bufGC, lightSquareColor);
7348 XFillRectangle(xDisplay, buf, bufGC, 0, 0, squareSize, squareSize);
7351 /* We now have an inverted piece image with the background
7352 erased. Construct mask by just selecting all the non-zero
7353 pixels - no need to reconstruct the original image. */
7354 XSetFunction(xDisplay, maskGC, GXor);
7356 /* Might be quicker to download an XImage and create bitmap
7357 data from it rather than this N copies per piece, but it
7358 only takes a fraction of a second and there is a much
7359 longer delay for loading the pieces. */
7360 for (n = 0; n < pieceDepth; n ++) {
7361 XCopyPlane(xDisplay, buf, xpmMask[piece], maskGC,
7362 0, 0, squareSize, squareSize,
7368 XFreePixmap(xDisplay, buf);
7369 XFreeGC(xDisplay, bufGC);
7370 XFreeGC(xDisplay, maskGC);
7374 InitAnimState (anim, info)
7376 XWindowAttributes * info;
7381 /* Each buffer is square size, same depth as window */
7382 // anim->saveBuf = XCreatePixmap(xDisplay, xBoardWindow,
7383 // squareSize, squareSize, info->depth);
7384 // anim->newBuf = XCreatePixmap(xDisplay, xBoardWindow,
7385 // squareSize, squareSize, info->depth);
7387 // /* Create a plain GC for blitting */
7388 // mask = GCForeground | GCBackground | GCFunction |
7389 // GCPlaneMask | GCGraphicsExposures;
7390 // values.foreground = XBlackPixel(xDisplay, xScreen);
7391 // values.background = XWhitePixel(xDisplay, xScreen);
7392 // values.function = GXcopy;
7393 // values.plane_mask = AllPlanes;
7394 // values.graphics_exposures = False;
7395 // anim->blitGC = XCreateGC(xDisplay, xBoardWindow, mask, &values);
7397 // /* Piece will be copied from an existing context at
7398 // the start of each new animation/drag. */
7399 // anim->pieceGC = XCreateGC(xDisplay, xBoardWindow, 0, &values);
7401 // /* Outline will be a read-only copy of an existing */
7402 // anim->outlineGC = None;
7408 static VariantClass old = (VariantClass) -1; // [HGM] pieces: redo every time variant changes
7409 XWindowAttributes info;
7411 /* for gtk at the moment just ... */
7414 if (xpmDone && gameInfo.variant == old) return;
7415 if(xpmDone) old = gameInfo.variant; // first time pieces might not be created yet
7416 // XGetWindowAttributes(xDisplay, xBoardWindow, &info);
7418 // InitAnimState(&game, &info);
7419 // InitAnimState(&player, &info);
7421 /* For XPM pieces, we need bitmaps to use as masks. */
7423 // CreateAnimMasks(info.depth);
7429 static Boolean frameWaiting;
7431 static RETSIGTYPE FrameAlarm (sig)
7434 frameWaiting = False;
7435 /* In case System-V style signals. Needed?? */
7436 signal(SIGALRM, FrameAlarm);
7443 struct itimerval delay;
7445 XSync(xDisplay, False);
7448 frameWaiting = True;
7449 signal(SIGALRM, FrameAlarm);
7450 delay.it_interval.tv_sec =
7451 delay.it_value.tv_sec = time / 1000;
7452 delay.it_interval.tv_usec =
7453 delay.it_value.tv_usec = (time % 1000) * 1000;
7454 setitimer(ITIMER_REAL, &delay, NULL);
7455 while (frameWaiting) pause();
7456 delay.it_interval.tv_sec = delay.it_value.tv_sec = 0;
7457 delay.it_interval.tv_usec = delay.it_value.tv_usec = 0;
7458 setitimer(ITIMER_REAL, &delay, NULL);
7468 // XSync(xDisplay, False);
7470 usleep(time * 1000);
7475 /* Convert board position to corner of screen rect and color */
7478 ScreenSquare(column, row, pt, color)
7479 int column; int row; XPoint * pt; int * color;
7482 pt->x = lineGap + ((BOARD_WIDTH-1)-column) * (squareSize + lineGap);
7483 pt->y = lineGap + row * (squareSize + lineGap);
7485 pt->x = lineGap + column * (squareSize + lineGap);
7486 pt->y = lineGap + ((BOARD_HEIGHT-1)-row) * (squareSize + lineGap);
7488 *color = SquareColor(row, column);
7491 /* Convert window coords to square */
7494 BoardSquare(x, y, column, row)
7495 int x; int y; int * column; int * row;
7497 *column = EventToSquare(x, BOARD_WIDTH);
7498 if (flipView && *column >= 0)
7499 *column = BOARD_WIDTH - 1 - *column;
7500 *row = EventToSquare(y, BOARD_HEIGHT);
7501 if (!flipView && *row >= 0)
7502 *row = BOARD_HEIGHT - 1 - *row;
7507 #undef Max /* just in case */
7509 #define Max(a, b) ((a) > (b) ? (a) : (b))
7510 #define Min(a, b) ((a) < (b) ? (a) : (b))
7513 SetRect(rect, x, y, width, height)
7514 XRectangle * rect; int x; int y; int width; int height;
7518 rect->width = width;
7519 rect->height = height;
7522 /* Test if two frames overlap. If they do, return
7523 intersection rect within old and location of
7524 that rect within new. */
7527 Intersect(old, new, size, area, pt)
7528 XPoint * old; XPoint * new;
7529 int size; XRectangle * area; XPoint * pt;
7531 if (old->x > new->x + size || new->x > old->x + size ||
7532 old->y > new->y + size || new->y > old->y + size) {
7535 SetRect(area, Max(new->x - old->x, 0), Max(new->y - old->y, 0),
7536 size - abs(old->x - new->x), size - abs(old->y - new->y));
7537 pt->x = Max(old->x - new->x, 0);
7538 pt->y = Max(old->y - new->y, 0);
7543 /* For two overlapping frames, return the rect(s)
7544 in the old that do not intersect with the new. */
7547 CalcUpdateRects(old, new, size, update, nUpdates)
7548 XPoint * old; XPoint * new; int size;
7549 XRectangle update[]; int * nUpdates;
7553 /* If old = new (shouldn't happen) then nothing to draw */
7554 if (old->x == new->x && old->y == new->y) {
7558 /* Work out what bits overlap. Since we know the rects
7559 are the same size we don't need a full intersect calc. */
7561 /* Top or bottom edge? */
7562 if (new->y > old->y) {
7563 SetRect(&(update[count]), old->x, old->y, size, new->y - old->y);
7565 } else if (old->y > new->y) {
7566 SetRect(&(update[count]), old->x, old->y + size - (old->y - new->y),
7567 size, old->y - new->y);
7570 /* Left or right edge - don't overlap any update calculated above. */
7571 if (new->x > old->x) {
7572 SetRect(&(update[count]), old->x, Max(new->y, old->y),
7573 new->x - old->x, size - abs(new->y - old->y));
7575 } else if (old->x > new->x) {
7576 SetRect(&(update[count]), new->x + size, Max(new->y, old->y),
7577 old->x - new->x, size - abs(new->y - old->y));
7584 /* Generate a series of frame coords from start->mid->finish.
7585 The movement rate doubles until the half way point is
7586 reached, then halves back down to the final destination,
7587 which gives a nice slow in/out effect. The algorithmn
7588 may seem to generate too many intermediates for short
7589 moves, but remember that the purpose is to attract the
7590 viewers attention to the piece about to be moved and
7591 then to where it ends up. Too few frames would be less
7595 Tween(start, mid, finish, factor, frames, nFrames)
7596 XPoint * start; XPoint * mid;
7597 XPoint * finish; int factor;
7598 XPoint frames[]; int * nFrames;
7600 int fraction, n, count;
7604 /* Slow in, stepping 1/16th, then 1/8th, ... */
7606 for (n = 0; n < factor; n++)
7608 for (n = 0; n < factor; n++) {
7609 frames[count].x = start->x + (mid->x - start->x) / fraction;
7610 frames[count].y = start->y + (mid->y - start->y) / fraction;
7612 fraction = fraction / 2;
7616 frames[count] = *mid;
7619 /* Slow out, stepping 1/2, then 1/4, ... */
7621 for (n = 0; n < factor; n++) {
7622 frames[count].x = finish->x - (finish->x - mid->x) / fraction;
7623 frames[count].y = finish->y - (finish->y - mid->y) / fraction;
7625 fraction = fraction * 2;
7630 /* Draw a piece on the screen without disturbing what's there */
7633 SelectGCMask(piece, clip, outline, mask)
7634 ChessSquare piece; GC * clip; GC * outline; Pixmap * mask;
7638 /* Bitmap for piece being moved. */
7639 if (appData.monoMode) {
7640 *mask = *pieceToSolid(piece);
7641 } else if (useImages) {
7643 *mask = xpmMask[piece];
7645 *mask = ximMaskPm[piece];
7648 *mask = *pieceToSolid(piece);
7651 /* GC for piece being moved. Square color doesn't matter, but
7652 since it gets modified we make a copy of the original. */
7654 if (appData.monoMode)
7659 if (appData.monoMode)
7664 // XCopyGC(xDisplay, source, 0xFFFFFFFF, *clip);
7666 /* Outline only used in mono mode and is not modified */
7668 *outline = bwPieceGC;
7670 *outline = wbPieceGC;
7674 OverlayPiece(piece, clip, outline, dest)
7675 ChessSquare piece; GC clip; GC outline; Drawable dest;
7680 /* Draw solid rectangle which will be clipped to shape of piece */
7681 // XFillRectangle(xDisplay, dest, clip,
7682 // 0, 0, squareSize, squareSize)
7684 if (appData.monoMode)
7685 /* Also draw outline in contrasting color for black
7686 on black / white on white cases */
7687 // XCopyPlane(xDisplay, *pieceToOutline(piece), dest, outline,
7688 // 0, 0, squareSize, squareSize, 0, 0, 1)
7691 /* Copy the piece */
7696 // XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
7698 // 0, 0, squareSize, squareSize,
7703 /* Animate the movement of a single piece */
7706 BeginAnimation(anim, piece, startColor, start)
7714 /* The old buffer is initialised with the start square (empty) */
7715 BlankSquare(0, 0, startColor, EmptySquare, anim->saveBuf);
7716 anim->prevFrame = *start;
7718 /* The piece will be drawn using its own bitmap as a matte */
7719 // SelectGCMask(piece, &anim->pieceGC, &anim->outlineGC, &mask);
7720 // XSetClipMask(xDisplay, anim->pieceGC, mask);
7724 AnimationFrame(anim, frame, piece)
7729 XRectangle updates[4];
7734 /* Save what we are about to draw into the new buffer */
7735 // XCopyArea(xDisplay, xBoardWindow, anim->newBuf, anim->blitGC,
7736 // frame->x, frame->y, squareSize, squareSize,
7739 /* Erase bits of the previous frame */
7740 if (Intersect(&anim->prevFrame, frame, squareSize, &overlap, &pt)) {
7741 /* Where the new frame overlapped the previous,
7742 the contents in newBuf are wrong. */
7743 // XCopyArea(xDisplay, anim->saveBuf, anim->newBuf, anim->blitGC,
7744 // overlap.x, overlap.y,
7745 // overlap.width, overlap.height,
7747 /* Repaint the areas in the old that don't overlap new */
7748 CalcUpdateRects(&anim->prevFrame, frame, squareSize, updates, &count);
7749 for (i = 0; i < count; i++)
7750 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
7751 // updates[i].x - anim->prevFrame.x,
7752 // updates[i].y - anim->prevFrame.y,
7753 // updates[i].width, updates[i].height,
7754 // updates[i].x, updates[i].y)
7757 /* Easy when no overlap */
7758 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
7759 // 0, 0, squareSize, squareSize,
7760 // anim->prevFrame.x, anim->prevFrame.y);
7763 /* Save this frame for next time round */
7764 // XCopyArea(xDisplay, anim->newBuf, anim->saveBuf, anim->blitGC,
7765 // 0, 0, squareSize, squareSize,
7767 anim->prevFrame = *frame;
7769 /* Draw piece over original screen contents, not current,
7770 and copy entire rect. Wipes out overlapping piece images. */
7771 OverlayPiece(piece, anim->pieceGC, anim->outlineGC, anim->newBuf);
7772 // XCopyArea(xDisplay, anim->newBuf, xBoardWindow, anim->blitGC,
7773 // 0, 0, squareSize, squareSize,
7774 // frame->x, frame->y);
7778 EndAnimation (anim, finish)
7782 XRectangle updates[4];
7787 /* The main code will redraw the final square, so we
7788 only need to erase the bits that don't overlap. */
7789 if (Intersect(&anim->prevFrame, finish, squareSize, &overlap, &pt)) {
7790 CalcUpdateRects(&anim->prevFrame, finish, squareSize, updates, &count);
7791 for (i = 0; i < count; i++)
7792 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
7793 // updates[i].x - anim->prevFrame.x,
7794 // updates[i].y - anim->prevFrame.y,
7795 // updates[i].width, updates[i].height,
7796 // updates[i].x, updates[i].y)
7799 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
7800 // 0, 0, squareSize, squareSize,
7801 // anim->prevFrame.x, anim->prevFrame.y);
7806 FrameSequence(anim, piece, startColor, start, finish, frames, nFrames)
7808 ChessSquare piece; int startColor;
7809 XPoint * start; XPoint * finish;
7810 XPoint frames[]; int nFrames;
7814 BeginAnimation(anim, piece, startColor, start);
7815 for (n = 0; n < nFrames; n++) {
7816 AnimationFrame(anim, &(frames[n]), piece);
7817 FrameDelay(appData.animSpeed);
7819 EndAnimation(anim, finish);
7822 /* Main control logic for deciding what to animate and how */
7825 AnimateMove(board, fromX, fromY, toX, toY)
7834 XPoint start, finish, mid;
7835 XPoint frames[kFactor * 2 + 1];
7836 int nFrames, startColor, endColor;
7838 /* Are we animating? */
7839 if (!appData.animate || appData.blindfold)
7842 if(board[toY][toX] == WhiteRook && board[fromY][fromX] == WhiteKing ||
7843 board[toY][toX] == BlackRook && board[fromY][fromX] == BlackKing)
7844 return; // [HGM] FRC: no animtion of FRC castlings, as to-square is not true to-square
7846 if (fromY < 0 || fromX < 0 || toX < 0 || toY < 0) return;
7847 piece = board[fromY][fromX];
7848 if (piece >= EmptySquare) return;
7853 hop = (piece == WhiteKnight || piece == BlackKnight);
7856 if (appData.debugMode) {
7857 fprintf(debugFP, hop ? _("AnimateMove: piece %d hops from %d,%d to %d,%d \n") :
7858 _("AnimateMove: piece %d slides from %d,%d to %d,%d \n"),
7859 piece, fromX, fromY, toX, toY); }
7861 ScreenSquare(fromX, fromY, &start, &startColor);
7862 ScreenSquare(toX, toY, &finish, &endColor);
7865 /* Knight: make diagonal movement then straight */
7866 if (abs(toY - fromY) < abs(toX - fromX)) {
7867 mid.x = start.x + (finish.x - start.x) / 2;
7871 mid.y = start.y + (finish.y - start.y) / 2;
7874 mid.x = start.x + (finish.x - start.x) / 2;
7875 mid.y = start.y + (finish.y - start.y) / 2;
7878 /* Don't use as many frames for very short moves */
7879 if (abs(toY - fromY) + abs(toX - fromX) <= 2)
7880 Tween(&start, &mid, &finish, kFactor - 1, frames, &nFrames);
7882 Tween(&start, &mid, &finish, kFactor, frames, &nFrames);
7883 FrameSequence(&game, piece, startColor, &start, &finish, frames, nFrames);
7885 /* Be sure end square is redrawn */
7886 damage[toY][toX] = True;
7890 DragPieceBegin(x, y)
7893 int boardX, boardY, color;
7896 /* Are we animating? */
7897 if (!appData.animateDragging || appData.blindfold)
7900 /* Figure out which square we start in and the
7901 mouse position relative to top left corner. */
7902 BoardSquare(x, y, &boardX, &boardY);
7903 player.startBoardX = boardX;
7904 player.startBoardY = boardY;
7905 ScreenSquare(boardX, boardY, &corner, &color);
7906 player.startSquare = corner;
7907 player.startColor = color;
7908 /* As soon as we start dragging, the piece will jump slightly to
7909 be centered over the mouse pointer. */
7910 player.mouseDelta.x = squareSize/2;
7911 player.mouseDelta.y = squareSize/2;
7912 /* Initialise animation */
7913 player.dragPiece = PieceForSquare(boardX, boardY);
7915 if (player.dragPiece >= 0 && player.dragPiece < EmptySquare) {
7916 player.dragActive = True;
7917 BeginAnimation(&player, player.dragPiece, color, &corner);
7918 /* Mark this square as needing to be redrawn. Note that
7919 we don't remove the piece though, since logically (ie
7920 as seen by opponent) the move hasn't been made yet. */
7921 if(boardX == BOARD_RGHT+1 && PieceForSquare(boardX-1, boardY) > 1 ||
7922 boardX == BOARD_LEFT-2 && PieceForSquare(boardX+1, boardY) > 1)
7923 // XCopyArea(xDisplay, xBoardWindow, player.saveBuf, player.blitGC,
7924 // corner.x, corner.y, squareSize, squareSize,
7925 // 0, 0); // [HGM] zh: unstack in stead of grab
7926 damage[boardY][boardX] = True;
7928 player.dragActive = False;
7938 /* Are we animating? */
7939 if (!appData.animateDragging || appData.blindfold)
7943 if (! player.dragActive)
7945 /* Move piece, maintaining same relative position
7946 of mouse within square */
7947 corner.x = x - player.mouseDelta.x;
7948 corner.y = y - player.mouseDelta.y;
7949 AnimationFrame(&player, &corner, player.dragPiece);
7951 if (appData.highlightDragging) {
7953 BoardSquare(x, y, &boardX, &boardY);
7954 SetHighlights(fromX, fromY, boardX, boardY);
7963 int boardX, boardY, color;
7966 /* Are we animating? */
7967 if (!appData.animateDragging || appData.blindfold)
7971 if (! player.dragActive)
7973 /* Last frame in sequence is square piece is
7974 placed on, which may not match mouse exactly. */
7975 BoardSquare(x, y, &boardX, &boardY);
7976 ScreenSquare(boardX, boardY, &corner, &color);
7977 EndAnimation(&player, &corner);
7979 /* Be sure end square is redrawn */
7980 damage[boardY][boardX] = True;
7982 /* This prevents weird things happening with fast successive
7983 clicks which on my Sun at least can cause motion events
7984 without corresponding press/release. */
7985 player.dragActive = False;
7988 /* Handle expose event while piece being dragged */
7993 if (!player.dragActive || appData.blindfold)
7996 /* What we're doing: logically, the move hasn't been made yet,
7997 so the piece is still in it's original square. But visually
7998 it's being dragged around the board. So we erase the square
7999 that the piece is on and draw it at the last known drag point. */
8000 BlankSquare(player.startSquare.x, player.startSquare.y,
8001 player.startColor, EmptySquare, xBoardWindow);
8002 AnimationFrame(&player, &player.prevFrame, player.dragPiece);
8003 damage[player.startBoardY][player.startBoardX] = TRUE;
8007 SetProgramStats( FrontEndProgramStats * stats )
8010 // [HGM] done, but perhaps backend should call this directly?
8011 EngineOutputUpdate( stats );