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 * gtk set properties of widgets
2575 /* set board size */
2576 gtk_widget_set_size_request(GTK_WIDGET(GUI_Board),
2577 boardWidth,boardHeight);
2579 /* end gtk set properties of widgets */
2581 if (appData.titleInWindow)
2586 if (appData.showButtonBar)
2593 if (appData.showButtonBar)
2603 /* set some checkboxes in the menu according to appData */
2605 if (appData.alwaysPromoteToQueen)
2606 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Always Queen")),TRUE);
2608 if (appData.animateDragging)
2609 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Animate Dragging")),TRUE);
2611 if (appData.animate)
2612 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Animate Moving")),TRUE);
2614 if (appData.autoComment)
2615 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Comment")),TRUE);
2617 if (appData.autoCallFlag)
2618 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Flag")),TRUE);
2620 if (appData.autoFlipView)
2621 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Flip View")),TRUE);
2623 if (appData.autoObserve)
2624 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Observe")),TRUE);
2626 if (appData.autoRaiseBoard)
2627 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Raise Board")),TRUE);
2629 if (appData.autoSaveGames)
2630 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Save")),TRUE);
2632 if (appData.saveGameFile[0] != NULLCHAR)
2634 /* Can't turn this off from menu */
2635 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Save")),TRUE);
2636 gtk_action_set_sensitive(GTK_ACTION (gtk_builder_get_object (builder, "menuOptions.Auto Save")),FALSE);
2639 if (appData.blindfold)
2640 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Blindfold")),TRUE);
2642 if (appData.flashCount > 0)
2643 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Flash Moves")),TRUE);
2645 if (appData.getMoveList)
2646 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Get Move List")),TRUE);
2649 if (appData.highlightDragging)
2650 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Highlight Dragging")),TRUE);
2653 if (appData.highlightLastMove)
2654 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Highlight Last Move")),TRUE);
2656 if (appData.icsAlarm)
2657 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.ICS Alarm")),TRUE);
2659 if (appData.ringBellAfterMoves)
2660 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Move Sound")),TRUE);
2662 if (appData.oldSaveStyle)
2663 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Old Save Style")),TRUE);
2665 if (appData.periodicUpdates)
2666 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Periodic Updates")),TRUE);
2668 if (appData.ponderNextMove)
2669 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Ponder Next Move")),TRUE);
2671 if (appData.popupExitMessage)
2672 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Popup Exit Message")),TRUE);
2674 if (appData.popupMoveErrors)
2675 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Popup Move Errors")),TRUE);
2677 if (appData.premove)
2678 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Premove")),TRUE);
2680 if (appData.quietPlay)
2681 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Quit Play")),TRUE);
2683 if (appData.showCoords)
2684 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Show Coords")),TRUE);
2686 if (appData.showThinking)
2687 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Show Thinking")),TRUE);
2689 if (appData.testLegality)
2690 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Test Legality")),TRUE);
2692 /* end setting check boxes */
2694 /* load square colors */
2695 SVGLightSquare = load_pixbuf("svg/LightSquare.svg",squareSize);
2696 SVGDarkSquare = load_pixbuf("svg/DarkSquare.svg",squareSize);
2697 SVGNeutralSquare = load_pixbuf("svg/NeutralSquare.svg",squareSize);
2699 /* use two icons to indicate if it is white's or black's turn */
2700 WhiteIcon = load_pixbuf("svg/icon_white.svg",0);
2701 BlackIcon = load_pixbuf("svg/icon_black.svg",0);
2702 WindowIcon = WhiteIcon;
2703 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
2706 /* realize window */
2707 gtk_widget_show (GUI_Window);
2709 /* do resizing to a fixed aspect ratio */
2712 int totalh=boardHeight;
2715 gtk_widget_size_request(GTK_WIDGET(GUI_Menubar), &w);
2718 gtk_widget_size_request(GTK_WIDGET(GUI_Timer), &w);
2721 gtk_widget_size_request(GTK_WIDGET(GUI_Buttonbar), &w);
2724 ratio = (totalh)/(boardWidth) ;
2725 GUI_SetAspectRatio(ratio);
2732 if (appData.animate || appData.animateDragging)
2737 if (errorExitStatus == -1) {
2738 if (appData.icsActive) {
2739 /* We now wait until we see "login:" from the ICS before
2740 sending the logon script (problems with timestamp otherwise) */
2741 /*ICSInitScript();*/
2742 if (appData.icsInputBox) ICSInputBoxPopUp();
2745 signal(SIGINT, IntSigHandler);
2746 signal(SIGTERM, IntSigHandler);
2747 if (*appData.cmailGameName != NULLCHAR) {
2748 signal(SIGUSR1, CmailSigHandler);
2751 gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes()
2755 * Create a cursor for the board widget.
2756 * (This needs to be called after the window has been created to have access to board-window)
2759 BoardCursor = gdk_cursor_new(GDK_HAND2);
2760 gdk_window_set_cursor(GUI_Board->window, BoardCursor);
2761 gdk_cursor_destroy(BoardCursor);
2766 if (appData.debugMode) fclose(debugFP); // [DM] debug
2773 if (appData.icsActive && oldICSInteractionTitle != NULL) {
2774 DisplayIcsInteractionTitle(oldICSInteractionTitle);
2776 unlink(gameCopyFilename);
2777 unlink(gamePasteFilename);
2788 CmailSigHandler(sig)
2794 signal(SIGUSR1, SIG_IGN); /* suspend handler */
2796 /* Activate call-back function CmailSigHandlerCallBack() */
2797 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
2799 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
2803 CmailSigHandlerCallBack(isr, closure, message, count, error)
2811 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
2813 /**** end signal code ****/
2823 f = fopen(appData.icsLogon, "r");
2829 strcat(buf, appData.icsLogon);
2830 f = fopen(buf, "r");
2834 ProcessICSInitScript(f);
2841 EditCommentPopDown();
2847 SetMenuEnables(enab)
2852 if (!builder) return;
2853 while (enab->name != NULL) {
2854 o = gtk_builder_get_object(builder, enab->name);
2855 if(GTK_IS_WIDGET(o))
2856 gtk_widget_set_sensitive(GTK_WIDGET (o),enab->value);
2859 if(GTK_IS_ACTION(o))
2860 gtk_action_set_sensitive(GTK_ACTION (o),enab->value);
2862 DisplayError(enab->name, 0);
2870 SetMenuEnables(icsEnables);
2873 if (appData.zippyPlay && !appData.noChessProgram) /* [DM] icsEngineAnalyze */
2874 {}; // XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
2881 SetMenuEnables(ncpEnables);
2887 SetMenuEnables(gnuEnables);
2893 SetMenuEnables(cmailEnables);
2899 SetMenuEnables(trainingOnEnables);
2900 if (appData.showButtonBar) {
2901 // XtSetSensitive(buttonBarWidget, False);
2907 SetTrainingModeOff()
2909 SetMenuEnables(trainingOffEnables);
2910 if (appData.showButtonBar) {
2911 // XtSetSensitive(buttonBarWidget, True);
2916 SetUserThinkingEnables()
2918 if (appData.noChessProgram) return;
2919 SetMenuEnables(userThinkingEnables);
2923 SetMachineThinkingEnables()
2925 if (appData.noChessProgram) return;
2926 SetMenuEnables(machineThinkingEnables);
2928 case MachinePlaysBlack:
2929 case MachinePlaysWhite:
2930 case TwoMachinesPlay:
2931 // XtSetSensitive(XtNameToWidget(menuBarWidget,
2932 // ModeToWidgetName(gameMode)), True);
2939 #define Abs(n) ((n)<0 ? -(n) : (n))
2942 * Find a font that matches "pattern" that is as close as
2943 * possible to the targetPxlSize. Prefer fonts that are k
2944 * pixels smaller to fonts that are k pixels larger. The
2945 * pattern must be in the X Consortium standard format,
2946 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
2947 * The return value should be freed with XtFree when no
2950 char *FindFont(pattern, targetPxlSize)
2954 char **fonts, *p, *best, *scalable, *scalableTail;
2955 int i, j, nfonts, minerr, err, pxlSize;
2958 char **missing_list;
2960 char *def_string, *base_fnt_lst, strInt[3];
2962 XFontStruct **fnt_list;
2964 base_fnt_lst = calloc(1, strlen(pattern) + 3);
2965 sprintf(strInt, "%d", targetPxlSize);
2966 p = strstr(pattern, "--");
2967 strncpy(base_fnt_lst, pattern, p - pattern + 2);
2968 strcat(base_fnt_lst, strInt);
2969 strcat(base_fnt_lst, strchr(p + 2, '-'));
2971 if ((fntSet = XCreateFontSet(xDisplay,
2975 &def_string)) == NULL) {
2977 fprintf(stderr, _("Unable to create font set.\n"));
2981 nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
2983 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
2985 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
2986 programName, pattern);
2994 for (i=0; i<nfonts; i++) {
2997 if (*p != '-') continue;
2999 if (*p == NULLCHAR) break;
3000 if (*p++ == '-') j++;
3002 if (j < 7) continue;
3005 scalable = fonts[i];
3008 err = pxlSize - targetPxlSize;
3009 if (Abs(err) < Abs(minerr) ||
3010 (minerr > 0 && err < 0 && -err == minerr)) {
3016 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
3017 /* If the error is too big and there is a scalable font,
3018 use the scalable font. */
3019 int headlen = scalableTail - scalable;
3020 p = (char *) XtMalloc(strlen(scalable) + 10);
3021 while (isdigit(*scalableTail)) scalableTail++;
3022 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
3024 p = (char *) XtMalloc(strlen(best) + 1);
3027 if (appData.debugMode) {
3028 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
3029 pattern, targetPxlSize, p);
3032 if (missing_count > 0)
3033 XFreeStringList(missing_list);
3034 XFreeFontSet(xDisplay, fntSet);
3036 XFreeFontNames(fonts);
3043 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
3044 | GCBackground | GCFunction | GCPlaneMask;
3045 XGCValues gc_values;
3048 gc_values.plane_mask = AllPlanes;
3049 gc_values.line_width = lineGap;
3050 gc_values.line_style = LineSolid;
3051 gc_values.function = GXcopy;
3053 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3054 gc_values.background = XWhitePixel(xDisplay, xScreen);
3055 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
3056 XSetFont(xDisplay, coordGC, coordFontID);
3058 if (appData.monoMode) {
3059 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3060 gc_values.background = XBlackPixel(xDisplay, xScreen);
3061 lightSquareGC = wbPieceGC
3062 = XtGetGC(shellWidget, value_mask, &gc_values);
3064 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3065 gc_values.background = XWhitePixel(xDisplay, xScreen);
3066 darkSquareGC = bwPieceGC
3067 = XtGetGC(shellWidget, value_mask, &gc_values);
3069 if (DefaultDepth(xDisplay, xScreen) == 1) {
3070 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3071 gc_values.function = GXcopyInverted;
3072 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3073 gc_values.function = GXcopy;
3074 if (XBlackPixel(xDisplay, xScreen) == 1) {
3075 bwPieceGC = darkSquareGC;
3076 wbPieceGC = copyInvertedGC;
3078 bwPieceGC = copyInvertedGC;
3079 wbPieceGC = lightSquareGC;
3083 gc_values.foreground = lightSquareColor;
3084 gc_values.background = darkSquareColor;
3085 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3087 gc_values.foreground = darkSquareColor;
3088 gc_values.background = lightSquareColor;
3089 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3091 gc_values.foreground = jailSquareColor;
3092 gc_values.background = jailSquareColor;
3093 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3095 gc_values.foreground = whitePieceColor;
3096 gc_values.background = darkSquareColor;
3097 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3099 gc_values.foreground = whitePieceColor;
3100 gc_values.background = lightSquareColor;
3101 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3103 gc_values.foreground = whitePieceColor;
3104 gc_values.background = jailSquareColor;
3105 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3107 gc_values.foreground = blackPieceColor;
3108 gc_values.background = darkSquareColor;
3109 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3111 gc_values.foreground = blackPieceColor;
3112 gc_values.background = lightSquareColor;
3113 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3115 gc_values.foreground = blackPieceColor;
3116 gc_values.background = jailSquareColor;
3117 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3124 WhitePawn, WhiteKnight, WhiteBishop, WhiteRook, WhiteQueen, WhiteKing,
3125 BlackPawn, BlackKnight, BlackBishop, BlackRook, BlackQueen, BlackKing,
3129 /* get some defaults going */
3130 for(i=WhitePawn; i<DemotePiece+1; i++)
3131 SVGpieces[i] = load_pixbuf("svg/NeutralSquare.svg",squareSize);
3134 SVGpieces[WhitePawn] = load_pixbuf("svg/WhitePawn.svg",squareSize);
3135 SVGpieces[WhiteKnight] = load_pixbuf("svg/WhiteKnight.svg",squareSize);
3136 SVGpieces[WhiteBishop] = load_pixbuf("svg/WhiteBishop.svg",squareSize);
3137 SVGpieces[WhiteRook] = load_pixbuf("svg/WhiteRook.svg",squareSize);
3138 SVGpieces[WhiteQueen] = load_pixbuf("svg/WhiteQueen.svg",squareSize);
3139 SVGpieces[WhiteKing] = load_pixbuf("svg/WhiteKing.svg",squareSize);
3141 SVGpieces[BlackPawn] = load_pixbuf("svg/BlackPawn.svg",squareSize);
3142 SVGpieces[BlackKnight] = load_pixbuf("svg/BlackKnight.svg",squareSize);
3143 SVGpieces[BlackBishop] = load_pixbuf("svg/BlackBishop.svg",squareSize);
3144 SVGpieces[BlackRook] = load_pixbuf("svg/BlackRook.svg",squareSize);
3145 SVGpieces[BlackQueen] = load_pixbuf("svg/BlackQueen.svg",squareSize);
3146 SVGpieces[BlackKing] = load_pixbuf("svg/BlackKing.svg",squareSize);
3152 static void MenuBarSelect(w, addr, index)
3157 XtActionProc proc = (XtActionProc) addr;
3159 (proc)(NULL, NULL, NULL, NULL);
3162 void CreateMenuBarPopup(parent, name, mb)
3172 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3175 XtSetArg(args[j], XtNleftMargin, 20); j++;
3176 XtSetArg(args[j], XtNrightMargin, 20); j++;
3178 while (mi->string != NULL) {
3179 if (strcmp(mi->string, "----") == 0) {
3180 entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
3183 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string)));
3184 entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass,
3186 XtAddCallback(entry, XtNcallback,
3187 (XtCallbackProc) MenuBarSelect,
3188 (caddr_t) mi->proc);
3194 Widget CreateMenuBar(mb)
3198 Widget anchor, menuBar;
3200 char menuName[MSG_SIZ];
3203 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3204 XtSetArg(args[j], XtNvSpace, 0); j++;
3205 XtSetArg(args[j], XtNborderWidth, 0); j++;
3206 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
3207 formWidget, args, j);
3209 while (mb->name != NULL) {
3210 strcpy(menuName, "menu");
3211 strcat(menuName, mb->name);
3213 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
3216 shortName[0] = _(mb->name)[0];
3217 shortName[1] = NULLCHAR;
3218 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
3221 XtSetArg(args[j], XtNlabel, XtNewString(_(mb->name))); j++;
3224 XtSetArg(args[j], XtNborderWidth, 0); j++;
3225 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
3227 CreateMenuBarPopup(menuBar, menuName, mb);
3233 Widget CreateButtonBar(mi)
3237 Widget button, buttonBar;
3241 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3243 XtSetArg(args[j], XtNhSpace, 0); j++;
3245 XtSetArg(args[j], XtNborderWidth, 0); j++;
3246 XtSetArg(args[j], XtNvSpace, 0); j++;
3247 buttonBar = XtCreateWidget("buttonBar", boxWidgetClass,
3248 formWidget, args, j);
3250 while (mi->string != NULL) {
3253 XtSetArg(args[j], XtNinternalWidth, 2); j++;
3254 XtSetArg(args[j], XtNborderWidth, 0); j++;
3256 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string))); j++;
3257 button = XtCreateManagedWidget(mi->string, commandWidgetClass,
3258 buttonBar, args, j);
3259 XtAddCallback(button, XtNcallback,
3260 (XtCallbackProc) MenuBarSelect,
3261 (caddr_t) mi->proc);
3268 CreatePieceMenu(name, color)
3275 ChessSquare selection;
3277 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3278 boardWidget, args, 0);
3280 for (i = 0; i < PIECE_MENU_SIZE; i++) {
3281 String item = pieceMenuStrings[color][i];
3283 if (strcmp(item, "----") == 0) {
3284 entry = XtCreateManagedWidget(item, smeLineObjectClass,
3287 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3288 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3290 selection = pieceMenuTranslation[color][i];
3291 XtAddCallback(entry, XtNcallback,
3292 (XtCallbackProc) PieceMenuSelect,
3293 (caddr_t) selection);
3294 if (selection == WhitePawn || selection == BlackPawn) {
3295 XtSetArg(args[0], XtNpopupOnEntry, entry);
3296 XtSetValues(menu, args, 1);
3309 ChessSquare selection;
3311 // whitePieceMenu = CreatePieceMenu("menuW", 0);
3312 // blackPieceMenu = CreatePieceMenu("menuB", 1);
3314 // XtRegisterGrabAction(PieceMenuPopup, True,
3315 // (unsigned)(ButtonPressMask|ButtonReleaseMask),
3316 // GrabModeAsync, GrabModeAsync);
3318 // XtSetArg(args[0], XtNlabel, _("Drop"));
3319 // dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
3320 // boardWidget, args, 1);
3321 // for (i = 0; i < DROP_MENU_SIZE; i++) {
3322 // String item = dropMenuStrings[i];
3324 // if (strcmp(item, "----") == 0) {
3325 // entry = XtCreateManagedWidget(item, smeLineObjectClass,
3326 // dropMenu, NULL, 0);
3328 // XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3329 // entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3330 // dropMenu, args, 1);
3331 // selection = dropMenuTranslation[i];
3332 // XtAddCallback(entry, XtNcallback,
3333 // (XtCallbackProc) DropMenuSelect,
3334 // (caddr_t) selection);
3339 void SetupDropMenu()
3347 for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
3348 entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
3349 p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
3350 dmEnables[i].piece);
3351 XtSetSensitive(entry, p != NULL || !appData.testLegality
3352 /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
3353 && !appData.icsActive));
3355 while (p && *p++ == dmEnables[i].piece) count++;
3356 snprintf(label, sizeof(label), "%s %d", dmEnables[i].widget, count);
3358 XtSetArg(args[j], XtNlabel, label); j++;
3359 XtSetValues(entry, args, j);
3363 void PieceMenuPopup(w, event, params, num_params)
3367 Cardinal *num_params;
3370 if (event->type != ButtonPress) return;
3371 if (errorUp) ErrorPopDown();
3375 whichMenu = params[0];
3377 case IcsPlayingWhite:
3378 case IcsPlayingBlack:
3380 case MachinePlaysWhite:
3381 case MachinePlaysBlack:
3382 if (appData.testLegality &&
3383 gameInfo.variant != VariantBughouse &&
3384 gameInfo.variant != VariantCrazyhouse) return;
3386 whichMenu = "menuD";
3392 if (((pmFromX = EventToSquare(event->xbutton.x, BOARD_WIDTH)) < 0) ||
3393 ((pmFromY = EventToSquare(event->xbutton.y, BOARD_HEIGHT)) < 0)) {
3394 pmFromX = pmFromY = -1;
3398 pmFromX = BOARD_WIDTH - 1 - pmFromX;
3400 pmFromY = BOARD_HEIGHT - 1 - pmFromY;
3402 XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
3405 static void PieceMenuSelect(w, piece, junk)
3410 if (pmFromX < 0 || pmFromY < 0) return;
3411 EditPositionMenuEvent(piece, pmFromX, pmFromY);
3414 static void DropMenuSelect(w, piece, junk)
3419 if (pmFromX < 0 || pmFromY < 0) return;
3420 DropMenuEvent(piece, pmFromX, pmFromY);
3423 void WhiteClock(w, event, prms, nprms)
3429 if (gameMode == EditPosition || gameMode == IcsExamining) {
3430 SetWhiteToPlayEvent();
3431 } else if (gameMode == IcsPlayingBlack || gameMode == MachinePlaysWhite) {
3436 void BlackClock(w, event, prms, nprms)
3442 if (gameMode == EditPosition || gameMode == IcsExamining) {
3443 SetBlackToPlayEvent();
3444 } else if (gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) {
3451 * If the user selects on a border boundary, return -1; if off the board,
3452 * return -2. Otherwise map the event coordinate to the square.
3454 int EventToSquare(x, limit)
3462 if ((x % (squareSize + lineGap)) >= squareSize)
3464 x /= (squareSize + lineGap);
3470 static void do_flash_delay(msec)
3476 static void drawHighlight(file, rank, line_type)
3477 int file, rank, line_type;
3482 if (lineGap == 0 || appData.blindfold) return;
3486 x = lineGap/2 + ((BOARD_WIDTH-1)-file) *
3487 (squareSize + lineGap);
3488 y = lineGap/2 + rank * (squareSize + lineGap);
3492 x = lineGap/2 + file * (squareSize + lineGap);
3493 y = lineGap/2 + ((BOARD_HEIGHT-1)-rank) *
3494 (squareSize + lineGap);
3498 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3500 /* draw the highlight */
3501 cairo_move_to (cr, x, y);
3502 cairo_rel_line_to (cr, 0,squareSize+lineGap);
3503 cairo_rel_line_to (cr, squareSize+lineGap,0);
3504 cairo_rel_line_to (cr, 0,-squareSize-lineGap);
3505 cairo_close_path (cr);
3507 cairo_set_line_width (cr, lineGap);
3510 /* TODO: use appdata colors */
3511 case LINE_TYPE_HIGHLIGHT:
3512 cairo_set_source_rgba (cr, 1, 1, 0, 1.0);
3515 cairo_set_source_rgba (cr, 1, 0, 0, 1.0);
3517 case LINE_TYPE_NORMAL:
3519 cairo_set_source_rgba (cr, 0, 1, 0, 1.0);
3530 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
3531 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
3534 SetHighlights(fromX, fromY, toX, toY)
3535 int fromX, fromY, toX, toY;
3537 if (hi1X != fromX || hi1Y != fromY)
3539 if (hi1X >= 0 && hi1Y >= 0)
3541 drawHighlight(hi1X, hi1Y, LINE_TYPE_NORMAL);
3543 if (fromX >= 0 && fromY >= 0)
3545 drawHighlight(fromX, fromY, LINE_TYPE_HIGHLIGHT);
3548 if (hi2X != toX || hi2Y != toY)
3550 if (hi2X >= 0 && hi2Y >= 0)
3552 drawHighlight(hi2X, hi2Y, LINE_TYPE_NORMAL);
3554 if (toX >= 0 && toY >= 0)
3556 drawHighlight(toX, toY, LINE_TYPE_HIGHLIGHT);
3570 SetHighlights(-1, -1, -1, -1);
3575 SetPremoveHighlights(fromX, fromY, toX, toY)
3576 int fromX, fromY, toX, toY;
3578 if (pm1X != fromX || pm1Y != fromY)
3580 if (pm1X >= 0 && pm1Y >= 0)
3582 drawHighlight(pm1X, pm1Y, LINE_TYPE_NORMAL);
3584 if (fromX >= 0 && fromY >= 0)
3586 drawHighlight(fromX, fromY, LINE_TYPE_PRE);
3589 if (pm2X != toX || pm2Y != toY)
3591 if (pm2X >= 0 && pm2Y >= 0)
3593 drawHighlight(pm2X, pm2Y, LINE_TYPE_NORMAL);
3595 if (toX >= 0 && toY >= 0)
3597 drawHighlight(toX, toY, LINE_TYPE_PRE);
3610 ClearPremoveHighlights()
3612 SetPremoveHighlights(-1, -1, -1, -1);
3615 static void BlankSquare(x, y, color, piece, dest)
3628 pb = SVGLightSquare;
3630 case 2: /* neutral */
3632 pb = SVGNeutralSquare;
3635 gdk_draw_pixbuf(GDK_WINDOW(GUI_Board->window),NULL,pb,0,0,x,y,-1,-1, GDK_RGB_DITHER_NORMAL, 0, 0);
3639 static void DrawPiece(piece, square_color, x, y, dest)
3641 int square_color, x, y;
3644 /* redraw background, since piece might be transparent in some areas */
3645 BlankSquare(x,y,square_color,piece,dest);
3648 gdk_draw_pixbuf(GDK_WINDOW(GUI_Board->window),NULL,
3649 GDK_PIXBUF(SVGpieces[piece]),0,0,x,y,-1,-1,
3650 GDK_RGB_DITHER_NORMAL, 0, 0);
3654 /* [HR] determine square color depending on chess variant. */
3655 static int SquareColor(row, column)
3660 if (gameInfo.variant == VariantXiangqi) {
3661 if (column >= 3 && column <= 5 && row >= 0 && row <= 2) {
3663 } else if (column >= 3 && column <= 5 && row >= 7 && row <= 9) {
3665 } else if (row <= 4) {
3671 square_color = ((column + row) % 2) == 1;
3674 /* [hgm] holdings: next line makes all holdings squares light */
3675 if(column < BOARD_LEFT || column >= BOARD_RGHT) square_color = 1;
3677 return square_color;
3680 void DrawSquare(row, column, piece, do_flash)
3681 int row, column, do_flash;
3684 int square_color, x, y;
3689 /* Calculate delay in milliseconds (2-delays per complete flash) */
3690 flash_delay = 500 / appData.flashRate;
3692 /* calculate x and y coordinates from row and column */
3695 x = lineGap + ((BOARD_WIDTH-1)-column) *
3696 (squareSize + lineGap);
3697 y = lineGap + row * (squareSize + lineGap);
3701 x = lineGap + column * (squareSize + lineGap);
3702 y = lineGap + ((BOARD_HEIGHT-1)-row) *
3703 (squareSize + lineGap);
3706 square_color = SquareColor(row, column);
3708 // [HGM] holdings: blank out area between board and holdings
3709 if ( column == BOARD_LEFT-1 || column == BOARD_RGHT
3710 || (column == BOARD_LEFT-2 && row < BOARD_HEIGHT-gameInfo.holdingsSize)
3711 || (column == BOARD_RGHT+1 && row >= gameInfo.holdingsSize) )
3713 BlankSquare(x, y, 2, EmptySquare, xBoardWindow);
3715 // [HGM] print piece counts next to holdings
3716 string[1] = NULLCHAR;
3719 cairo_text_extents_t extents;
3724 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3726 string[0] = '0' + piece;
3728 /* TODO this has to go into the font-selection */
3729 cairo_select_font_face (cr, "Sans",
3730 CAIRO_FONT_SLANT_NORMAL,
3731 CAIRO_FONT_WEIGHT_NORMAL);
3733 cairo_set_font_size (cr, 12.0);
3734 cairo_text_extents (cr, string, &extents);
3736 if (column == (flipView ? BOARD_LEFT-1 : BOARD_RGHT) )
3738 xpos= x + squareSize - extents.width - 2;
3739 ypos= y + extents.y_bearing + 1;
3741 if (column == (flipView ? BOARD_RGHT : BOARD_LEFT-1) && piece > 1)
3744 ypos = y + extents.y_bearing + 1;
3747 /* TODO mono mode? */
3748 cairo_move_to (cr, xpos, ypos);
3749 cairo_text_path (cr, string);
3750 cairo_set_source_rgb (cr, 1.0, 1.0, 1);
3751 cairo_fill_preserve (cr);
3752 cairo_set_source_rgb (cr, 0, 0, 0);
3753 cairo_set_line_width (cr, 0.1);
3762 /* square on the board */
3763 if (piece == EmptySquare || appData.blindfold)
3765 BlankSquare(x, y, square_color, piece, xBoardWindow);
3769 if (do_flash && appData.flashCount > 0)
3771 for (i=0; i<appData.flashCount; ++i)
3774 DrawPiece(piece, square_color, x, y, xBoardWindow);
3775 do_flash_delay(flash_delay);
3777 BlankSquare(x, y, square_color, piece, xBoardWindow);
3778 do_flash_delay(flash_delay);
3781 DrawPiece(piece, square_color, x, y, xBoardWindow);
3785 /* show coordinates if necessary */
3786 if(appData.showCoords)
3788 cairo_text_extents_t extents;
3792 /* TODO this has to go into the font-selection */
3793 cairo_select_font_face (cr, "Sans",
3794 CAIRO_FONT_SLANT_NORMAL,
3795 CAIRO_FONT_WEIGHT_NORMAL);
3796 cairo_set_font_size (cr, 12.0);
3798 string[1] = NULLCHAR;
3801 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3803 if (row == (flipView ? BOARD_HEIGHT-1 : 0) &&
3804 column >= BOARD_LEFT && column < BOARD_RGHT)
3806 string[0] = 'a' + column - BOARD_LEFT;
3807 cairo_text_extents (cr, string, &extents);
3809 xpos = x + squareSize - extents.width - 2;
3810 ypos = y + squareSize - extents.height - extents.y_bearing - 1;
3812 if (appData.monoMode)
3819 cairo_move_to (cr, xpos, ypos);
3820 cairo_text_path (cr, string);
3821 cairo_set_source_rgb (cr, 0.0, 0.0, 0);
3822 cairo_fill_preserve (cr);
3823 cairo_set_source_rgb (cr, 0, 1.0, 0);
3824 cairo_set_line_width (cr, 0.1);
3827 if ( column == (flipView ? BOARD_RGHT-1 : BOARD_LEFT))
3830 string[0] = ONE + row;
3831 cairo_text_extents (cr, string, &extents);
3834 ypos = y + extents.height + 1;
3836 if (appData.monoMode)
3843 cairo_move_to (cr, xpos, ypos);
3844 cairo_text_path (cr, string);
3845 cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
3846 cairo_fill_preserve (cr);
3847 cairo_set_source_rgb (cr, 0, 0, 1.0);
3848 cairo_set_line_width (cr, 0.1);
3860 /* Returns 1 if there are "too many" differences between b1 and b2
3861 (i.e. more than 1 move was made) */
3862 static int too_many_diffs(b1, b2)
3868 for (i=0; i<BOARD_HEIGHT; ++i) {
3869 for (j=0; j<BOARD_WIDTH; ++j) {
3870 if (b1[i][j] != b2[i][j]) {
3871 if (++c > 4) /* Castling causes 4 diffs */
3880 /* Matrix describing castling maneuvers */
3881 /* Row, ColRookFrom, ColKingFrom, ColRookTo, ColKingTo */
3882 static int castling_matrix[4][5] = {
3883 { 0, 0, 4, 3, 2 }, /* 0-0-0, white */
3884 { 0, 7, 4, 5, 6 }, /* 0-0, white */
3885 { 7, 0, 4, 3, 2 }, /* 0-0-0, black */
3886 { 7, 7, 4, 5, 6 } /* 0-0, black */
3889 /* Checks whether castling occurred. If it did, *rrow and *rcol
3890 are set to the destination (row,col) of the rook that moved.
3892 Returns 1 if castling occurred, 0 if not.
3894 Note: Only handles a max of 1 castling move, so be sure
3895 to call too_many_diffs() first.
3897 static int check_castle_draw(newb, oldb, rrow, rcol)
3904 /* For each type of castling... */
3905 for (i=0; i<4; ++i) {
3906 r = castling_matrix[i];
3908 /* Check the 4 squares involved in the castling move */
3910 for (j=1; j<=4; ++j) {
3911 if (newb[r[0]][r[j]] == oldb[r[0]][r[j]]) {
3918 /* All 4 changed, so it must be a castling move */
3927 static int damage[BOARD_SIZE][BOARD_SIZE];
3930 * event handler for redrawing the board
3932 void DrawPosition( repaint, board)
3933 /*Boolean*/int repaint;
3937 static int lastFlipView = 0;
3938 static int lastBoardValid = 0;
3939 static Board lastBoard;
3942 if (board == NULL) {
3943 if (!lastBoardValid) return;
3946 if (!lastBoardValid || lastFlipView != flipView) {
3947 // XtSetArg(args[0], XtNleftBitmap, (flipView ? xMarkPixmap : None));
3948 // XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flip View"),
3953 * It would be simpler to clear the window with XClearWindow()
3954 * but this causes a very distracting flicker.
3957 if (!repaint && lastBoardValid && lastFlipView == flipView)
3959 /* If too much changes (begin observing new game, etc.), don't
3961 do_flash = too_many_diffs(board, lastBoard) ? 0 : 1;
3963 /* Special check for castling so we don't flash both the king
3964 and the rook (just flash the king). */
3967 if (check_castle_draw(board, lastBoard, &rrow, &rcol))
3969 /* Draw rook with NO flashing. King will be drawn flashing later */
3970 DrawSquare(rrow, rcol, board[rrow][rcol], 0);
3971 lastBoard[rrow][rcol] = board[rrow][rcol];
3975 /* First pass -- Draw (newly) empty squares and repair damage.
3976 This prevents you from having a piece show up twice while it
3977 is flashing on its new square */
3978 for (i = 0; i < BOARD_HEIGHT; i++)
3979 for (j = 0; j < BOARD_WIDTH; j++)
3980 if ((board[i][j] != lastBoard[i][j] && board[i][j] == EmptySquare)
3983 DrawSquare(i, j, board[i][j], 0);
3984 damage[i][j] = False;
3987 /* Second pass -- Draw piece(s) in new position and flash them */
3988 for (i = 0; i < BOARD_HEIGHT; i++)
3989 for (j = 0; j < BOARD_WIDTH; j++)
3990 if (board[i][j] != lastBoard[i][j])
3992 DrawSquare(i, j, board[i][j], do_flash);
4004 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
4006 cairo_set_line_width (cr, lineGap);
4008 /* TODO: use appdata colors */
4009 cairo_set_source_rgba (cr, 0, 1, 0, 1.0);
4013 for (i = 0; i < BOARD_HEIGHT + 1; i++)
4016 x2 = lineGap + BOARD_WIDTH * (squareSize + lineGap);
4017 y1 = y2 = lineGap / 2 + (i * (squareSize + lineGap));
4019 cairo_move_to (cr, x1, y1);
4020 cairo_rel_line_to (cr, x2,0);
4024 for (j = 0; j < BOARD_WIDTH + 1; j++)
4027 y2 = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
4028 x1 = x2 = lineGap / 2 + (j * (squareSize + lineGap));
4030 cairo_move_to (cr, x1, y1);
4031 cairo_rel_line_to (cr, 0, y2);
4040 for (i = 0; i < BOARD_HEIGHT; i++)
4041 for (j = 0; j < BOARD_WIDTH; j++)
4043 DrawSquare(i, j, board[i][j], 0);
4044 damage[i][j] = False;
4048 CopyBoard(lastBoard, board);
4050 lastFlipView = flipView;
4052 /* Draw highlights */
4053 if (pm1X >= 0 && pm1Y >= 0)
4055 drawHighlight(pm1X, pm1Y, LINE_TYPE_PRE);
4057 if (pm2X >= 0 && pm2Y >= 0)
4059 drawHighlight(pm2X, pm2Y, LINE_TYPE_PRE);
4061 if (hi1X >= 0 && hi1Y >= 0)
4063 drawHighlight(hi1X, hi1Y, LINE_TYPE_HIGHLIGHT);
4065 if (hi2X >= 0 && hi2Y >= 0)
4067 drawHighlight(hi2X, hi2Y, LINE_TYPE_HIGHLIGHT);
4070 /* If piece being dragged around board, must redraw that too */
4077 * event handler for parsing user moves
4079 // [HGM] This routine will need quite some reworking. Although the backend still supports the old
4080 // way of doing things, by calling UserMoveEvent() to test the legality of the move and then perform
4081 // it at the end, and doing all kind of preliminary tests here (e.g. to weed out self-captures), it
4082 // should be made to use the new way, of calling UserMoveTest early to determine the legality of the
4083 // move, (which will weed out the illegal selfcaptures and moves into the holdings, and flag promotions),
4084 // and at the end FinishMove() to perform the move after optional promotion popups.
4085 // For now I patched it to allow self-capture with King, and suppress clicks between board and holdings.
4086 void HandleUserMove(w, event, prms, nprms)
4093 Boolean saveAnimate;
4094 static int second = 0, promotionChoice = 0;
4097 if (w != boardWidget || errorExitStatus != -1) return;
4099 x = EventToSquare(event->xbutton.x, BOARD_WIDTH);
4100 y = EventToSquare(event->xbutton.y, BOARD_HEIGHT);
4101 if (!flipView && y >= 0) {
4102 y = BOARD_HEIGHT - 1 - y;
4104 if (flipView && x >= 0) {
4105 x = BOARD_WIDTH - 1 - x;
4108 if(promotionChoice) { // we are waiting for a click to indicate promotion piece
4109 if(event->type == ButtonRelease) return; // ignore upclick of click-click destination
4110 promotionChoice = FALSE; // only one chance: if click not OK it is interpreted as cancel
4111 if(appData.debugMode) fprintf(debugFP, "promotion click, x=%d, y=%d\n", x, y);
4112 if(gameInfo.holdingsWidth &&
4113 (WhiteOnMove(currentMove)
4114 ? x == BOARD_WIDTH-1 && y < gameInfo.holdingsSize && y > 0
4115 : x == 0 && y >= BOARD_HEIGHT - gameInfo.holdingsSize && y < BOARD_HEIGHT-1) ) {
4116 // click in right holdings, for determining promotion piece
4117 ChessSquare p = boards[currentMove][y][x];
4118 if(appData.debugMode) fprintf(debugFP, "square contains %d\n", (int)p);
4119 if(p != EmptySquare) {
4120 FinishMove(NormalMove, fromX, fromY, toX, toY, ToLower(PieceToChar(p)));
4125 DrawPosition(FALSE, boards[currentMove]);
4128 if (event->type == ButtonPress) ErrorPopDown();
4131 if (event->type == ButtonPress) {
4132 // XtPopdown(promotionShell);
4133 // XtDestroyWidget(promotionShell);
4134 promotionUp = False;
4142 /* [HGM] holdings: next 5 lines: ignore all clicks between board and holdings */
4143 if(event->type == ButtonPress
4144 && ( x == BOARD_LEFT-1 ||
4146 (x == BOARD_LEFT-2 && y < BOARD_HEIGHT-gameInfo.holdingsSize ) ||
4147 (x == BOARD_RGHT+1 && y >= gameInfo.holdingsSize)) )
4151 if (event->type == ButtonPress) {
4152 /* First square, prepare to drag */
4153 if (OKToStartUserMove(x, y)) {
4157 DragPieceBegin(event->xbutton.x, event->xbutton.y);
4158 if (appData.highlightDragging) {
4159 SetHighlights(x, y, -1, -1);
4167 if (event->type == ButtonRelease && x == fromX && y == fromY) {
4168 /* Click on single square in stead of drag-drop */
4169 DragPieceEnd(event->xbutton.x, event->xbutton.y);
4170 if (appData.animateDragging) {
4171 /* Undo animation damage if any */
4172 DrawPosition(FALSE, NULL);
4175 /* Second up/down in same square; just abort move */
4180 ClearPremoveHighlights();
4182 /* First upclick in same square; start click-click mode */
4183 SetHighlights(x, y, -1, -1);
4188 moveType = UserMoveTest(fromX, fromY, x, y, NULLCHAR, event->type == ButtonRelease);
4190 if (moveType == Comment) { // kludge for indicating capture-own on Press
4191 /* Clicked again on same color piece -- changed his mind */
4192 /* note that re-clicking same square always hits same color piece */
4193 second = (x == fromX && y == fromY);
4194 if (appData.highlightDragging) {
4195 SetHighlights(x, y, -1, -1);
4199 if (OKToStartUserMove(x, y)) {
4202 DragPieceBegin(event->xbutton.x, event->xbutton.y);
4207 if(moveType == AmbiguousMove) { // kludge to indicate edit-position move
4210 DragPieceEnd(event->xbutton.x, event->xbutton.y);
4211 DrawPosition(FALSE, boards[currentMove]);
4215 /* Complete move; (x,y) is now different from (fromX, fromY) on both Press and Release */
4218 saveAnimate = appData.animate;
4219 if (event->type == ButtonPress) {
4220 /* Finish clickclick move */
4221 if (appData.animate || appData.highlightLastMove) {
4222 SetHighlights(fromX, fromY, toX, toY);
4227 /* Finish drag move */
4228 if (appData.highlightLastMove) {
4229 SetHighlights(fromX, fromY, toX, toY);
4233 DragPieceEnd(event->xbutton.x, event->xbutton.y);
4234 /* Don't animate move and drag both */
4235 appData.animate = FALSE;
4237 if (moveType == WhitePromotionKnight || moveType == BlackPromotionKnight ||
4238 (moveType == WhitePromotionQueen || moveType == BlackPromotionQueen) &&
4239 appData.alwaysPromoteToQueen) { // promotion, but no choice
4240 FinishMove(moveType, fromX, fromY, toX, toY, 'q');
4242 if (moveType == WhitePromotionQueen || moveType == BlackPromotionQueen ) {
4243 SetHighlights(fromX, fromY, toX, toY);
4244 if(gameInfo.variant == VariantSuper || gameInfo.variant == VariantGreat) {
4245 // [HGM] super: promotion to captured piece selected from holdings
4246 ChessSquare p = boards[currentMove][fromY][fromX], q = boards[currentMove][toY][toX];
4247 promotionChoice = TRUE;
4248 // kludge follows to temporarily execute move on display, without promoting yet
4249 boards[currentMove][fromY][fromX] = EmptySquare; // move Pawn to 8th rank
4250 boards[currentMove][toY][toX] = p;
4251 DrawPosition(FALSE, boards[currentMove]);
4252 boards[currentMove][fromY][fromX] = p; // take back, but display stays
4253 boards[currentMove][toY][toX] = q;
4254 DisplayMessage("Click in holdings to choose piece", "");
4258 goto skipClearingFrom; // the skipped stuff is done asynchronously by PromotionCallback
4260 if(moveType != ImpossibleMove) { // valid move, but no promotion
4261 FinishMove(moveType, fromX, fromY, toX, toY, NULLCHAR);
4262 } else { // invalid move; could have set premove
4265 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
4266 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
4269 appData.animate = saveAnimate;
4270 if (appData.animate || appData.animateDragging) {
4271 /* Undo animation damage if needed */
4272 DrawPosition(FALSE, NULL);
4276 void AnimateUserMove (Widget w, XEvent * event,
4277 String * params, Cardinal * nParams)
4279 DragPieceMove(event->xmotion.x, event->xmotion.y);
4282 Widget CommentCreate(name, text, mutable, callback, lines)
4284 int /*Boolean*/ mutable;
4285 XtCallbackProc callback;
4289 Widget shell, layout, form, edit, b_ok, b_cancel, b_clear, b_close, b_edit;
4294 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4295 XtGetValues(boardWidget, args, j);
4298 XtSetArg(args[j], XtNresizable, True); j++;
4301 XtCreatePopupShell(name, topLevelShellWidgetClass,
4302 shellWidget, args, j);
4305 XtCreatePopupShell(name, transientShellWidgetClass,
4306 shellWidget, args, j);
4309 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
4310 layoutArgs, XtNumber(layoutArgs));
4312 XtCreateManagedWidget("form", formWidgetClass, layout,
4313 formArgs, XtNumber(formArgs));
4317 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
4318 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
4320 XtSetArg(args[j], XtNstring, text); j++;
4321 XtSetArg(args[j], XtNtop, XtChainTop); j++;
4322 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4323 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4324 XtSetArg(args[j], XtNright, XtChainRight); j++;
4325 XtSetArg(args[j], XtNresizable, True); j++;
4326 XtSetArg(args[j], XtNwidth, bw_width); j++; /*force wider than buttons*/
4327 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
4328 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
4329 XtSetArg(args[j], XtNautoFill, True); j++;
4330 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
4332 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
4336 XtSetArg(args[j], XtNfromVert, edit); j++;
4337 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4338 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4339 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4340 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4342 XtCreateManagedWidget(_("ok"), commandWidgetClass, form, args, j);
4343 XtAddCallback(b_ok, XtNcallback, callback, (XtPointer) 0);
4346 XtSetArg(args[j], XtNfromVert, edit); j++;
4347 XtSetArg(args[j], XtNfromHoriz, b_ok); j++;
4348 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4349 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4350 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4351 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4353 XtCreateManagedWidget(_("cancel"), commandWidgetClass, form, args, j);
4354 XtAddCallback(b_cancel, XtNcallback, callback, (XtPointer) 0);
4357 XtSetArg(args[j], XtNfromVert, edit); j++;
4358 XtSetArg(args[j], XtNfromHoriz, b_cancel); j++;
4359 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4360 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4361 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4362 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4364 XtCreateManagedWidget(_("clear"), commandWidgetClass, form, args, j);
4365 XtAddCallback(b_clear, XtNcallback, callback, (XtPointer) 0);
4368 XtSetArg(args[j], XtNfromVert, edit); j++;
4369 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4370 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4371 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4372 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4374 XtCreateManagedWidget(_("close"), commandWidgetClass, form, args, j);
4375 XtAddCallback(b_close, XtNcallback, callback, (XtPointer) 0);
4378 XtSetArg(args[j], XtNfromVert, edit); j++;
4379 XtSetArg(args[j], XtNfromHoriz, b_close); j++;
4380 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4381 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4382 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4383 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4385 XtCreateManagedWidget(_("edit"), commandWidgetClass, form, args, j);
4386 XtAddCallback(b_edit, XtNcallback, callback, (XtPointer) 0);
4389 XtRealizeWidget(shell);
4391 if (commentX == -1) {
4394 Dimension pw_height;
4395 Dimension ew_height;
4398 XtSetArg(args[j], XtNheight, &ew_height); j++;
4399 XtGetValues(edit, args, j);
4402 XtSetArg(args[j], XtNheight, &pw_height); j++;
4403 XtGetValues(shell, args, j);
4404 commentH = pw_height + (lines - 1) * ew_height;
4405 commentW = bw_width - 16;
4407 XSync(xDisplay, False);
4409 /* This code seems to tickle an X bug if it is executed too soon
4410 after xboard starts up. The coordinates get transformed as if
4411 the main window was positioned at (0, 0).
4413 XtTranslateCoords(shellWidget,
4414 (bw_width - commentW) / 2, 0 - commentH / 2,
4415 &commentX, &commentY);
4417 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
4418 RootWindowOfScreen(XtScreen(shellWidget)),
4419 (bw_width - commentW) / 2, 0 - commentH / 2,
4424 if (commentY < 0) commentY = 0; /*avoid positioning top offscreen*/
4427 XtSetArg(args[j], XtNheight, commentH); j++;
4428 XtSetArg(args[j], XtNwidth, commentW); j++;
4429 XtSetArg(args[j], XtNx, commentX); j++;
4430 XtSetArg(args[j], XtNy, commentY); j++;
4431 XtSetValues(shell, args, j);
4432 XtSetKeyboardFocus(shell, edit);
4437 /* Used for analysis window and ICS input window */
4438 Widget MiscCreate(name, text, mutable, callback, lines)
4440 int /*Boolean*/ mutable;
4441 XtCallbackProc callback;
4445 Widget shell, layout, form, edit;
4447 Dimension bw_width, pw_height, ew_height, w, h;
4453 XtSetArg(args[j], XtNresizable, True); j++;
4456 XtCreatePopupShell(name, topLevelShellWidgetClass,
4457 shellWidget, args, j);
4460 XtCreatePopupShell(name, transientShellWidgetClass,
4461 shellWidget, args, j);
4464 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
4465 layoutArgs, XtNumber(layoutArgs));
4467 XtCreateManagedWidget("form", formWidgetClass, layout,
4468 formArgs, XtNumber(formArgs));
4472 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
4473 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
4475 XtSetArg(args[j], XtNstring, text); j++;
4476 XtSetArg(args[j], XtNtop, XtChainTop); j++;
4477 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4478 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4479 XtSetArg(args[j], XtNright, XtChainRight); j++;
4480 XtSetArg(args[j], XtNresizable, True); j++;
4481 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
4482 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
4483 XtSetArg(args[j], XtNautoFill, True); j++;
4484 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
4486 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
4488 XtRealizeWidget(shell);
4491 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4492 XtGetValues(boardWidget, args, j);
4495 XtSetArg(args[j], XtNheight, &ew_height); j++;
4496 XtGetValues(edit, args, j);
4499 XtSetArg(args[j], XtNheight, &pw_height); j++;
4500 XtGetValues(shell, args, j);
4501 h = pw_height + (lines - 1) * ew_height;
4504 XSync(xDisplay, False);
4506 /* This code seems to tickle an X bug if it is executed too soon
4507 after xboard starts up. The coordinates get transformed as if
4508 the main window was positioned at (0, 0).
4510 XtTranslateCoords(shellWidget, (bw_width - w) / 2, 0 - h / 2, &x, &y);
4512 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
4513 RootWindowOfScreen(XtScreen(shellWidget)),
4514 (bw_width - w) / 2, 0 - h / 2, &xx, &yy, &junk);
4518 if (y < 0) y = 0; /*avoid positioning top offscreen*/
4521 XtSetArg(args[j], XtNheight, h); j++;
4522 XtSetArg(args[j], XtNwidth, w); j++;
4523 XtSetArg(args[j], XtNx, x); j++;
4524 XtSetArg(args[j], XtNy, y); j++;
4525 XtSetValues(shell, args, j);
4531 static int savedIndex; /* gross that this is global */
4533 void EditCommentPopUp(index, title, text)
4542 if (text == NULL) text = "";
4544 if (editShell == NULL) {
4546 CommentCreate(title, text, True, EditCommentCallback, 4);
4547 XtRealizeWidget(editShell);
4548 CatchDeleteWindow(editShell, "EditCommentPopDown");
4550 edit = XtNameToWidget(editShell, "*form.text");
4552 XtSetArg(args[j], XtNstring, text); j++;
4553 XtSetValues(edit, args, j);
4555 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4556 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4557 XtSetValues(editShell, args, j);
4560 XtPopup(editShell, XtGrabNone);
4564 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
4565 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
4569 void EditCommentCallback(w, client_data, call_data)
4571 XtPointer client_data, call_data;
4579 XtSetArg(args[j], XtNlabel, &name); j++;
4580 XtGetValues(w, args, j);
4582 if (strcmp(name, _("ok")) == 0) {
4583 edit = XtNameToWidget(editShell, "*form.text");
4585 XtSetArg(args[j], XtNstring, &val); j++;
4586 XtGetValues(edit, args, j);
4587 ReplaceComment(savedIndex, val);
4588 EditCommentPopDown();
4589 } else if (strcmp(name, _("cancel")) == 0) {
4590 EditCommentPopDown();
4591 } else if (strcmp(name, _("clear")) == 0) {
4592 edit = XtNameToWidget(editShell, "*form.text");
4593 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
4594 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
4598 void EditCommentPopDown()
4603 if (!editUp) return;
4605 XtSetArg(args[j], XtNx, &commentX); j++;
4606 XtSetArg(args[j], XtNy, &commentY); j++;
4607 XtSetArg(args[j], XtNheight, &commentH); j++;
4608 XtSetArg(args[j], XtNwidth, &commentW); j++;
4609 XtGetValues(editShell, args, j);
4610 XtPopdown(editShell);
4613 XtSetArg(args[j], XtNleftBitmap, None); j++;
4614 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
4618 void ICSInputBoxPopUp()
4623 char *title = _("ICS Input");
4626 if (ICSInputShell == NULL) {
4627 ICSInputShell = MiscCreate(title, "", True, NULL, 1);
4628 tr = XtParseTranslationTable(ICSInputTranslations);
4629 edit = XtNameToWidget(ICSInputShell, "*form.text");
4630 XtOverrideTranslations(edit, tr);
4631 XtRealizeWidget(ICSInputShell);
4632 CatchDeleteWindow(ICSInputShell, "ICSInputBoxPopDown");
4635 edit = XtNameToWidget(ICSInputShell, "*form.text");
4637 XtSetArg(args[j], XtNstring, ""); j++;
4638 XtSetValues(edit, args, j);
4640 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4641 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4642 XtSetValues(ICSInputShell, args, j);
4645 XtPopup(ICSInputShell, XtGrabNone);
4646 XtSetKeyboardFocus(ICSInputShell, edit);
4648 ICSInputBoxUp = True;
4650 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
4651 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
4655 void ICSInputSendText()
4662 edit = XtNameToWidget(ICSInputShell, "*form.text");
4664 XtSetArg(args[j], XtNstring, &val); j++;
4665 XtGetValues(edit, args, j);
4666 SendMultiLineToICS(val);
4667 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
4668 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
4671 void ICSInputBoxPopDown()
4676 if (!ICSInputBoxUp) return;
4678 XtPopdown(ICSInputShell);
4679 ICSInputBoxUp = False;
4681 XtSetArg(args[j], XtNleftBitmap, None); j++;
4682 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
4686 void CommentPopUp(title, text)
4693 if (commentShell == NULL) {
4695 CommentCreate(title, text, False, CommentCallback, 4);
4696 XtRealizeWidget(commentShell);
4697 CatchDeleteWindow(commentShell, "CommentPopDown");
4699 edit = XtNameToWidget(commentShell, "*form.text");
4701 XtSetArg(args[j], XtNstring, text); j++;
4702 XtSetValues(edit, args, j);
4704 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4705 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4706 XtSetValues(commentShell, args, j);
4709 XtPopup(commentShell, XtGrabNone);
4710 XSync(xDisplay, False);
4715 void AnalysisPopUp(title, text)
4722 if (analysisShell == NULL) {
4723 analysisShell = MiscCreate(title, text, False, NULL, 4);
4724 XtRealizeWidget(analysisShell);
4725 CatchDeleteWindow(analysisShell, "AnalysisPopDown");
4728 edit = XtNameToWidget(analysisShell, "*form.text");
4730 XtSetArg(args[j], XtNstring, text); j++;
4731 XtSetValues(edit, args, j);
4733 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4734 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4735 XtSetValues(analysisShell, args, j);
4739 XtPopup(analysisShell, XtGrabNone);
4741 XSync(xDisplay, False);
4746 void CommentCallback(w, client_data, call_data)
4748 XtPointer client_data, call_data;
4755 XtSetArg(args[j], XtNlabel, &name); j++;
4756 XtGetValues(w, args, j);
4758 if (strcmp(name, _("close")) == 0) {
4760 } else if (strcmp(name, _("edit")) == 0) {
4767 void CommentPopDown()
4772 if (!commentUp) return;
4774 XtSetArg(args[j], XtNx, &commentX); j++;
4775 XtSetArg(args[j], XtNy, &commentY); j++;
4776 XtSetArg(args[j], XtNwidth, &commentW); j++;
4777 XtSetArg(args[j], XtNheight, &commentH); j++;
4778 XtGetValues(commentShell, args, j);
4779 XtPopdown(commentShell);
4780 XSync(xDisplay, False);
4784 void AnalysisPopDown()
4786 if (!analysisUp) return;
4787 XtPopdown(analysisShell);
4788 XSync(xDisplay, False);
4790 if (appData.icsEngineAnalyze) ExitAnalyzeMode(); /* [DM] icsEngineAnalyze */
4794 void FileNamePopUp(label, def, proc, openMode)
4801 Widget popup, layout, dialog, edit;
4807 fileProc = proc; /* I can't see a way not */
4808 fileOpenMode = openMode; /* to use globals here */
4811 XtSetArg(args[i], XtNresizable, True); i++;
4812 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
4813 XtSetArg(args[i], XtNtitle, XtNewString(_("File name prompt"))); i++;
4814 fileNameShell = popup =
4815 XtCreatePopupShell("File name prompt", transientShellWidgetClass,
4816 shellWidget, args, i);
4819 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
4820 layoutArgs, XtNumber(layoutArgs));
4823 XtSetArg(args[i], XtNlabel, label); i++;
4824 XtSetArg(args[i], XtNvalue, def); i++;
4825 XtSetArg(args[i], XtNborderWidth, 0); i++;
4826 dialog = XtCreateManagedWidget("fileName", dialogWidgetClass,
4829 XawDialogAddButton(dialog, _("ok"), FileNameCallback, (XtPointer) dialog);
4830 XawDialogAddButton(dialog, _("cancel"), FileNameCallback,
4831 (XtPointer) dialog);
4833 XtRealizeWidget(popup);
4834 CatchDeleteWindow(popup, "FileNamePopDown");
4836 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
4837 &x, &y, &win_x, &win_y, &mask);
4839 XtSetArg(args[0], XtNx, x - 10);
4840 XtSetArg(args[1], XtNy, y - 30);
4841 XtSetValues(popup, args, 2);
4843 XtPopup(popup, XtGrabExclusive);
4846 edit = XtNameToWidget(dialog, "*value");
4847 XtSetKeyboardFocus(popup, edit);
4850 void FileNamePopDown()
4852 if (!filenameUp) return;
4853 XtPopdown(fileNameShell);
4854 XtDestroyWidget(fileNameShell);
4859 void FileNameCallback(w, client_data, call_data)
4861 XtPointer client_data, call_data;
4866 XtSetArg(args[0], XtNlabel, &name);
4867 XtGetValues(w, args, 1);
4869 if (strcmp(name, _("cancel")) == 0) {
4874 FileNameAction(w, NULL, NULL, NULL);
4877 void FileNameAction(w, event, prms, nprms)
4889 name = XawDialogGetValueString(w = XtParent(w));
4891 if ((name != NULL) && (*name != NULLCHAR)) {
4893 XtPopdown(w = XtParent(XtParent(w)));
4897 p = strrchr(buf, ' ');
4904 fullname = ExpandPathName(buf);
4906 ErrorPopUp(_("Error"), _("Can't open file"), FALSE);
4909 f = fopen(fullname, fileOpenMode);
4911 DisplayError(_("Failed to open file"), errno);
4913 (void) (*fileProc)(f, index, buf);
4920 XtPopdown(w = XtParent(XtParent(w)));
4926 void PromotionPopUp()
4929 Widget dialog, layout;
4931 Dimension bw_width, pw_width;
4935 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4936 XtGetValues(boardWidget, args, j);
4939 XtSetArg(args[j], XtNresizable, True); j++;
4940 XtSetArg(args[j], XtNtitle, XtNewString(_("Promotion"))); j++;
4942 XtCreatePopupShell("Promotion", transientShellWidgetClass,
4943 shellWidget, args, j);
4945 XtCreateManagedWidget(layoutName, formWidgetClass, promotionShell,
4946 layoutArgs, XtNumber(layoutArgs));
4949 XtSetArg(args[j], XtNlabel, _("Promote to what?")); j++;
4950 XtSetArg(args[j], XtNborderWidth, 0); j++;
4951 dialog = XtCreateManagedWidget("promotion", dialogWidgetClass,
4954 if(gameInfo.variant != VariantShogi) {
4955 XawDialogAddButton(dialog, _("Queen"), PromotionCallback,
4956 (XtPointer) dialog);
4957 XawDialogAddButton(dialog, _("Rook"), PromotionCallback,
4958 (XtPointer) dialog);
4959 XawDialogAddButton(dialog, _("Bishop"), PromotionCallback,
4960 (XtPointer) dialog);
4961 XawDialogAddButton(dialog, _("Knight"), PromotionCallback,
4962 (XtPointer) dialog);
4963 if (!appData.testLegality || gameInfo.variant == VariantSuicide ||
4964 gameInfo.variant == VariantGiveaway) {
4965 XawDialogAddButton(dialog, _("King"), PromotionCallback,
4966 (XtPointer) dialog);
4968 if(gameInfo.variant == VariantCapablanca ||
4969 gameInfo.variant == VariantGothic ||
4970 gameInfo.variant == VariantCapaRandom) {
4971 XawDialogAddButton(dialog, _("Archbishop"), PromotionCallback,
4972 (XtPointer) dialog);
4973 XawDialogAddButton(dialog, _("Chancellor"), PromotionCallback,
4974 (XtPointer) dialog);
4976 } else // [HGM] shogi
4978 XawDialogAddButton(dialog, _("Promote"), PromotionCallback,
4979 (XtPointer) dialog);
4980 XawDialogAddButton(dialog, _("Defer"), PromotionCallback,
4981 (XtPointer) dialog);
4983 XawDialogAddButton(dialog, _("cancel"), PromotionCallback,
4984 (XtPointer) dialog);
4986 XtRealizeWidget(promotionShell);
4987 CatchDeleteWindow(promotionShell, "PromotionPopDown");
4990 XtSetArg(args[j], XtNwidth, &pw_width); j++;
4991 XtGetValues(promotionShell, args, j);
4993 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
4994 lineGap + squareSize/3 +
4995 ((toY == BOARD_HEIGHT-1) ^ (flipView) ?
4996 0 : 6*(squareSize + lineGap)), &x, &y);
4999 XtSetArg(args[j], XtNx, x); j++;
5000 XtSetArg(args[j], XtNy, y); j++;
5001 XtSetValues(promotionShell, args, j);
5003 XtPopup(promotionShell, XtGrabNone);
5008 void PromotionPopDown()
5010 if (!promotionUp) return;
5011 XtPopdown(promotionShell);
5012 XtDestroyWidget(promotionShell);
5013 promotionUp = False;
5016 void PromotionCallback(w, client_data, call_data)
5018 XtPointer client_data, call_data;
5024 XtSetArg(args[0], XtNlabel, &name);
5025 XtGetValues(w, args, 1);
5029 if (fromX == -1) return;
5031 if (strcmp(name, _("cancel")) == 0) {
5035 } else if (strcmp(name, _("Knight")) == 0) {
5037 } else if (strcmp(name, _("Promote")) == 0) {
5039 } else if (strcmp(name, _("Defer")) == 0) {
5042 promoChar = ToLower(name[0]);
5045 FinishMove(NormalMove, fromX, fromY, toX, toY, promoChar);
5047 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
5048 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
5053 void ErrorCallback(w, client_data, call_data)
5055 XtPointer client_data, call_data;
5058 XtPopdown(w = XtParent(XtParent(XtParent(w))));
5060 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5066 if (!errorUp) return;
5070 gtk_widget_destroy(GTK_WIDGET(GUI_Error));
5072 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5077 void ErrorPopUp(title, label, modal)
5078 char *title, *label;
5081 GUI_Error = gtk_message_dialog_new(GTK_WINDOW(GUI_Window),
5082 GTK_DIALOG_DESTROY_WITH_PARENT,
5087 gtk_window_set_title(GTK_WINDOW(GUI_Error),(gchar *) title);
5090 gtk_dialog_run(GTK_DIALOG(GUI_Error));
5091 gtk_widget_destroy(GTK_WIDGET(GUI_Error));
5095 g_signal_connect_swapped (GUI_Error, "response",
5096 G_CALLBACK (ErrorPopDownProc),
5099 gtk_widget_show(GTK_WIDGET(GUI_Error));
5105 /* Disable all user input other than deleting the window */
5106 static int frozen = 0;
5110 /* Grab by a widget that doesn't accept input */
5111 // XtAddGrab(messageWidget, TRUE, FALSE);
5115 /* Undo a FreezeUI */
5118 if (!frozen) return;
5119 // XtRemoveGrab(messageWidget);
5123 char *ModeToWidgetName(mode)
5127 case BeginningOfGame:
5128 if (appData.icsActive)
5129 return "menuMode.ICS Client";
5130 else if (appData.noChessProgram ||
5131 *appData.cmailGameName != NULLCHAR)
5132 return "menuMode.Edit Game";
5134 return "menuMode.Machine Black";
5135 case MachinePlaysBlack:
5136 return "menuMode.Machine Black";
5137 case MachinePlaysWhite:
5138 return "menuMode.Machine White";
5140 return "menuMode.Analysis Mode";
5142 return "menuMode.Analyze File";
5143 case TwoMachinesPlay:
5144 return "menuMode.Two Machines";
5146 return "menuMode.Edit Game";
5147 case PlayFromGameFile:
5148 return "menuFile.Load Game";
5150 return "menuMode.Edit Position";
5152 return "menuMode.Training";
5153 case IcsPlayingWhite:
5154 case IcsPlayingBlack:
5158 return "menuMode.ICS Client";
5165 void ModeHighlight()
5167 static int oldPausing = FALSE;
5168 static GameMode oldmode = (GameMode) -1;
5171 // todo this toggling of the pause button doesn't seem to work?
5172 // e.g. select pause from buttonbar doesn't activate menumode.pause
5174 // if (!boardWidget || !XtIsRealized(boardWidget)) return;
5176 if (pausing != oldPausing) {
5177 oldPausing = pausing;
5178 gtk_button_set_relief(GTK_BUTTON (gtk_builder_get_object (builder, "menuMode.Pause")),pausing?GTK_RELIEF_NORMAL:GTK_RELIEF_NONE);
5179 /* toggle background color in showbuttonbar */
5180 if (appData.showButtonBar) {
5182 gtk_button_pressed(GTK_BUTTON (gtk_builder_get_object (builder, "buttonbar.Pause")));
5184 gtk_button_released(GTK_BUTTON (gtk_builder_get_object (builder, "buttonbar.Pause")));
5189 wname = ModeToWidgetName(oldmode);
5191 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, wname)),True);
5195 /* Maybe all the enables should be handled here, not just this one */
5196 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuMode.Training")),
5197 gameMode == Training || gameMode == PlayFromGameFile);
5202 * Button/menu procedures
5205 int LoadGamePopUp(f, gameNumber, title)
5210 cmailMsgLoaded = FALSE;
5212 if (gameNumber == 0)
5214 int error = GameListBuild(f);
5218 DisplayError(_("Cannot build game list"), error);
5220 else if (!ListEmpty(&gameList)
5221 && ((ListGame *) gameList.tailPred)->number > 1)
5223 GameListPopUp(f, title);
5231 return LoadGame(f, gameNumber, title, FALSE);
5235 void LoadNextPositionProc(w, event, prms, nprms)
5244 void LoadPrevPositionProc(w, event, prms, nprms)
5253 void ReloadPositionProc(w, event, prms, nprms)
5262 void LoadPositionProc(w, event, prms, nprms)
5268 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
5271 FileNamePopUp(_("Load position file name?"), "", LoadPosition, "rb");
5274 void SaveGameProc(w, event, prms, nprms)
5280 FileNamePopUp(_("Save game file name?"),
5281 DefaultFileName(appData.oldSaveStyle ? "game" : "pgn"),
5285 void SavePositionProc(w, event, prms, nprms)
5291 FileNamePopUp(_("Save position file name?"),
5292 DefaultFileName(appData.oldSaveStyle ? "pos" : "fen"),
5296 void ReloadCmailMsgProc(w, event, prms, nprms)
5302 ReloadCmailMsgEvent(FALSE);
5305 void MailMoveProc(w, event, prms, nprms)
5314 /* this variable is shared between CopyPositionProc and SendPositionSelection */
5315 static char *selected_fen_position=NULL;
5318 SendPositionSelection(Widget w, Atom *selection, Atom *target,
5319 Atom *type_return, XtPointer *value_return,
5320 unsigned long *length_return, int *format_return)
5322 char *selection_tmp;
5324 if (!selected_fen_position) return False; /* should never happen */
5325 if (*target == XA_STRING){
5326 /* note: since no XtSelectionDoneProc was registered, Xt will
5327 * automatically call XtFree on the value returned. So have to
5328 * make a copy of it allocated with XtMalloc */
5329 selection_tmp= XtMalloc(strlen(selected_fen_position)+16);
5330 strcpy(selection_tmp, selected_fen_position);
5332 *value_return=selection_tmp;
5333 *length_return=strlen(selection_tmp);
5334 *type_return=XA_STRING;
5335 *format_return = 8; /* bits per byte */
5342 /* note: when called from menu all parameters are NULL, so no clue what the
5343 * Widget which was clicked on was, or what the click event was
5345 void CopyPositionProc(w, event, prms, nprms)
5353 if (selected_fen_position) free(selected_fen_position);
5354 selected_fen_position = (char *)PositionToFEN(currentMove, NULL);
5355 if (!selected_fen_position) return;
5356 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
5358 SendPositionSelection,
5359 NULL/* lose_ownership_proc */ ,
5360 NULL/* transfer_done_proc */);
5362 free(selected_fen_position);
5363 selected_fen_position=NULL;
5367 /* function called when the data to Paste is ready */
5369 PastePositionCB(Widget w, XtPointer client_data, Atom *selection,
5370 Atom *type, XtPointer value, unsigned long *len, int *format)
5373 if (value==NULL || *len==0) return; /* nothing had been selected to copy */
5374 fenstr[*len]='\0'; /* normally this string is terminated, but be safe */
5375 EditPositionPasteFEN(fenstr);
5379 /* called when Paste Position button is pressed,
5380 * all parameters will be NULL */
5381 void PastePositionProc(w, event, prms, nprms)
5387 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
5388 /* (XtSelectionCallbackProc) */ PastePositionCB,
5389 NULL, /* client_data passed to PastePositionCB */
5391 /* better to use the time field from the event that triggered the
5392 * call to this function, but that isn't trivial to get
5400 SendGameSelection(Widget w, Atom *selection, Atom *target,
5401 Atom *type_return, XtPointer *value_return,
5402 unsigned long *length_return, int *format_return)
5404 char *selection_tmp;
5406 if (*target == XA_STRING){
5407 FILE* f = fopen(gameCopyFilename, "r");
5410 if (f == NULL) return False;
5414 selection_tmp = XtMalloc(len + 1);
5415 count = fread(selection_tmp, 1, len, f);
5417 XtFree(selection_tmp);
5420 selection_tmp[len] = NULLCHAR;
5421 *value_return = selection_tmp;
5422 *length_return = len;
5423 *type_return = XA_STRING;
5424 *format_return = 8; /* bits per byte */
5431 /* note: when called from menu all parameters are NULL, so no clue what the
5432 * Widget which was clicked on was, or what the click event was
5434 void CopyGameProc(w, event, prms, nprms)
5442 ret = SaveGameToFile(gameCopyFilename, FALSE);
5445 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
5448 NULL/* lose_ownership_proc */ ,
5449 NULL/* transfer_done_proc */);
5452 /* function called when the data to Paste is ready */
5454 PasteGameCB(Widget w, XtPointer client_data, Atom *selection,
5455 Atom *type, XtPointer value, unsigned long *len, int *format)
5458 if (value == NULL || *len == 0) {
5459 return; /* nothing had been selected to copy */
5461 f = fopen(gamePasteFilename, "w");
5463 DisplayError(_("Can't open temp file"), errno);
5466 fwrite(value, 1, *len, f);
5469 LoadGameFromFile(gamePasteFilename, 0, gamePasteFilename, TRUE);
5472 /* called when Paste Game button is pressed,
5473 * all parameters will be NULL */
5474 void PasteGameProc(w, event, prms, nprms)
5480 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
5481 /* (XtSelectionCallbackProc) */ PasteGameCB,
5482 NULL, /* client_data passed to PasteGameCB */
5484 /* better to use the time field from the event that triggered the
5485 * call to this function, but that isn't trivial to get
5495 SaveGameProc(NULL, NULL, NULL, NULL);
5498 void AnalyzeModeProc(w, event, prms, nprms)
5506 if (!first.analysisSupport) {
5507 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
5508 DisplayError(buf, 0);
5511 /* [DM] icsEngineAnalyze [HGM] This is horrible code; reverse the gameMode and isEngineAnalyze tests! */
5512 if (appData.icsActive) {
5513 if (gameMode != IcsObserving) {
5514 sprintf(buf,_("You are not observing a game"));
5515 DisplayError(buf, 0);
5517 if (appData.icsEngineAnalyze) {
5518 if (appData.debugMode)
5519 fprintf(debugFP, _("Found unexpected active ICS engine analyze \n"));
5525 /* if enable, use want disable icsEngineAnalyze */
5526 if (appData.icsEngineAnalyze) {
5531 appData.icsEngineAnalyze = TRUE;
5532 if (appData.debugMode)
5533 fprintf(debugFP, _("ICS engine analyze starting... \n"));
5535 if (!appData.showThinking)
5536 ShowThinkingProc(NULL,NULL);
5541 void AnalyzeFileProc(w, event, prms, nprms)
5547 if (!first.analysisSupport) {
5549 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
5550 DisplayError(buf, 0);
5555 if (!appData.showThinking)
5556 ShowThinkingProc(NULL,NULL);
5559 FileNamePopUp(_("File to analyze"), "", LoadGamePopUp, "rb");
5560 AnalysisPeriodicEvent(1);
5564 void EditGameProc(w, event, prms, nprms)
5573 void EditPositionProc(w, event, prms, nprms)
5579 EditPositionEvent();
5582 void TrainingProc(w, event, prms, nprms)
5591 void EditCommentProc(w, event, prms, nprms)
5598 EditCommentPopDown();
5604 void IcsInputBoxProc(w, event, prms, nprms)
5610 if (ICSInputBoxUp) {
5611 ICSInputBoxPopDown();
5618 void EnterKeyProc(w, event, prms, nprms)
5624 if (ICSInputBoxUp == True)
5628 void AlwaysQueenProc(w, event, prms, nprms)
5636 appData.alwaysPromoteToQueen = !appData.alwaysPromoteToQueen;
5638 if (appData.alwaysPromoteToQueen) {
5639 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5641 XtSetArg(args[0], XtNleftBitmap, None);
5643 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
5647 void AnimateDraggingProc(w, event, prms, nprms)
5655 appData.animateDragging = !appData.animateDragging;
5657 if (appData.animateDragging) {
5658 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5661 XtSetArg(args[0], XtNleftBitmap, None);
5663 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Dragging"),
5667 void AnimateMovingProc(w, event, prms, nprms)
5675 appData.animate = !appData.animate;
5677 if (appData.animate) {
5678 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5681 XtSetArg(args[0], XtNleftBitmap, None);
5683 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
5687 void AutocommProc(w, event, prms, nprms)
5695 appData.autoComment = !appData.autoComment;
5697 if (appData.autoComment) {
5698 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5700 XtSetArg(args[0], XtNleftBitmap, None);
5702 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
5707 void AutoflagProc(w, event, prms, nprms)
5715 appData.autoCallFlag = !appData.autoCallFlag;
5717 if (appData.autoCallFlag) {
5718 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5720 XtSetArg(args[0], XtNleftBitmap, None);
5722 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
5726 void AutoflipProc(w, event, prms, nprms)
5734 appData.autoFlipView = !appData.autoFlipView;
5736 if (appData.autoFlipView) {
5737 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5739 XtSetArg(args[0], XtNleftBitmap, None);
5741 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flip View"),
5745 void AutobsProc(w, event, prms, nprms)
5753 appData.autoObserve = !appData.autoObserve;
5755 if (appData.autoObserve) {
5756 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5758 XtSetArg(args[0], XtNleftBitmap, None);
5760 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
5764 void AutoraiseProc(w, event, prms, nprms)
5772 appData.autoRaiseBoard = !appData.autoRaiseBoard;
5774 if (appData.autoRaiseBoard) {
5775 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5777 XtSetArg(args[0], XtNleftBitmap, None);
5779 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Raise Board"),
5783 void AutosaveProc(w, event, prms, nprms)
5791 appData.autoSaveGames = !appData.autoSaveGames;
5793 if (appData.autoSaveGames) {
5794 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5796 XtSetArg(args[0], XtNleftBitmap, None);
5798 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
5802 void BlindfoldProc(w, event, prms, nprms)
5810 appData.blindfold = !appData.blindfold;
5812 if (appData.blindfold) {
5813 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5815 XtSetArg(args[0], XtNleftBitmap, None);
5817 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Blindfold"),
5820 DrawPosition(True, NULL);
5823 void TestLegalityProc(w, event, prms, nprms)
5831 appData.testLegality = !appData.testLegality;
5833 if (appData.testLegality) {
5834 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5836 XtSetArg(args[0], XtNleftBitmap, None);
5838 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Test Legality"),
5843 void FlashMovesProc(w, event, prms, nprms)
5851 if (appData.flashCount == 0) {
5852 appData.flashCount = 3;
5854 appData.flashCount = -appData.flashCount;
5857 if (appData.flashCount > 0) {
5858 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5860 XtSetArg(args[0], XtNleftBitmap, None);
5862 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flash Moves"),
5867 void HighlightDraggingProc(w, event, prms, nprms)
5875 appData.highlightDragging = !appData.highlightDragging;
5877 if (appData.highlightDragging) {
5878 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5880 XtSetArg(args[0], XtNleftBitmap, None);
5882 XtSetValues(XtNameToWidget(menuBarWidget,
5883 "menuOptions.Highlight Dragging"), args, 1);
5887 void HighlightLastMoveProc(w, event, prms, nprms)
5895 appData.highlightLastMove = !appData.highlightLastMove;
5897 if (appData.highlightLastMove) {
5898 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5900 XtSetArg(args[0], XtNleftBitmap, None);
5902 XtSetValues(XtNameToWidget(menuBarWidget,
5903 "menuOptions.Highlight Last Move"), args, 1);
5906 void IcsAlarmProc(w, event, prms, nprms)
5914 appData.icsAlarm = !appData.icsAlarm;
5916 if (appData.icsAlarm) {
5917 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5919 XtSetArg(args[0], XtNleftBitmap, None);
5921 XtSetValues(XtNameToWidget(menuBarWidget,
5922 "menuOptions.ICS Alarm"), args, 1);
5925 void MoveSoundProc(w, event, prms, nprms)
5933 appData.ringBellAfterMoves = !appData.ringBellAfterMoves;
5935 if (appData.ringBellAfterMoves) {
5936 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5938 XtSetArg(args[0], XtNleftBitmap, None);
5940 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
5945 void OldSaveStyleProc(w, event, prms, nprms)
5953 appData.oldSaveStyle = !appData.oldSaveStyle;
5955 if (appData.oldSaveStyle) {
5956 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5958 XtSetArg(args[0], XtNleftBitmap, None);
5960 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Old Save Style"),
5964 void PeriodicUpdatesProc(w, event, prms, nprms)
5972 PeriodicUpdatesEvent(!appData.periodicUpdates);
5974 if (appData.periodicUpdates) {
5975 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5977 XtSetArg(args[0], XtNleftBitmap, None);
5979 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Periodic Updates"),
5983 void PonderNextMoveProc(w, event, prms, nprms)
5991 PonderNextMoveEvent(!appData.ponderNextMove);
5993 if (appData.ponderNextMove) {
5994 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5996 XtSetArg(args[0], XtNleftBitmap, None);
5998 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Ponder Next Move"),
6002 void PopupExitMessageProc(w, event, prms, nprms)
6010 appData.popupExitMessage = !appData.popupExitMessage;
6012 if (appData.popupExitMessage) {
6013 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6015 XtSetArg(args[0], XtNleftBitmap, None);
6017 XtSetValues(XtNameToWidget(menuBarWidget,
6018 "menuOptions.Popup Exit Message"), args, 1);
6021 void PopupMoveErrorsProc(w, event, prms, nprms)
6029 appData.popupMoveErrors = !appData.popupMoveErrors;
6031 if (appData.popupMoveErrors) {
6032 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6034 XtSetArg(args[0], XtNleftBitmap, None);
6036 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Popup Move Errors"),
6040 void PremoveProc(w, event, prms, nprms)
6048 appData.premove = !appData.premove;
6050 if (appData.premove) {
6051 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6053 XtSetArg(args[0], XtNleftBitmap, None);
6055 XtSetValues(XtNameToWidget(menuBarWidget,
6056 "menuOptions.Premove"), args, 1);
6059 void QuietPlayProc(w, event, prms, nprms)
6067 appData.quietPlay = !appData.quietPlay;
6069 if (appData.quietPlay) {
6070 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6072 XtSetArg(args[0], XtNleftBitmap, None);
6074 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Quiet Play"),
6078 void DebugProc(w, event, prms, nprms)
6084 appData.debugMode = !appData.debugMode;
6087 void AboutGameProc(w, event, prms, nprms)
6096 void NothingProc(w, event, prms, nprms)
6105 void Iconify(w, event, prms, nprms)
6114 XtSetArg(args[0], XtNiconic, True);
6115 XtSetValues(shellWidget, args, 1);
6118 void DisplayMessage(message, extMessage)
6119 gchar *message, *extMessage;
6126 snprintf(buf, sizeof(buf), "%s %s", message, extMessage);
6129 message = extMessage;
6132 gtk_label_set_text( GTK_LABEL(gtk_builder_get_object (builder, "Messages")),message);
6137 void DisplayTitle(text)
6140 gchar title[MSG_SIZ];
6142 if (text == NULL) text = "";
6144 if (appData.titleInWindow)
6149 if (*text != NULLCHAR)
6151 strcpy(title, text);
6153 else if (appData.icsActive)
6155 snprintf(title, sizeof(title), "%s: %s", programName, appData.icsHost);
6157 else if (appData.cmailGameName[0] != NULLCHAR)
6159 snprintf(title,sizeof(title), "%s: %s", programName, "CMail");
6161 // [HGM] license: This stuff should really be done in back-end, but WinBoard already had a pop-up for it
6163 else if (gameInfo.variant == VariantGothic)
6165 strcpy(title, GOTHIC);
6169 else if (gameInfo.variant == VariantFalcon)
6171 strcpy(title, FALCON);
6174 else if (appData.noChessProgram)
6176 strcpy(title, programName);
6180 snprintf(title,sizeof(title), "%s: %s", programName, first.tidy);
6182 gtk_window_set_title(GTK_WINDOW(GUI_Window),title);
6188 void DisplayError(message, error)
6195 if (appData.debugMode || appData.matchMode) {
6196 fprintf(stderr, "%s: %s\n", programName, message);
6199 if (appData.debugMode || appData.matchMode) {
6200 fprintf(stderr, "%s: %s: %s\n",
6201 programName, message, strerror(error));
6203 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
6206 ErrorPopUp(_("Error"), message, FALSE);
6210 void DisplayMoveError(message)
6215 DrawPosition(FALSE, NULL);
6216 if (appData.debugMode || appData.matchMode) {
6217 fprintf(stderr, "%s: %s\n", programName, message);
6219 if (appData.popupMoveErrors) {
6220 ErrorPopUp(_("Error"), message, FALSE);
6222 DisplayMessage(message, "");
6227 void DisplayFatalError(message, error, status)
6233 errorExitStatus = status;
6235 fprintf(stderr, "%s: %s\n", programName, message);
6237 fprintf(stderr, "%s: %s: %s\n",
6238 programName, message, strerror(error));
6239 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
6242 if (appData.popupExitMessage && boardWidget && XtIsRealized(boardWidget)) {
6243 ErrorPopUp(status ? _("Fatal Error") : _("Exiting"), message, TRUE);
6249 void DisplayInformation(message)
6253 ErrorPopUp(_("Information"), message, TRUE);
6256 void DisplayNote(message)
6260 ErrorPopUp(_("Note"), message, FALSE);
6264 NullXErrorCheck(dpy, error_event)
6266 XErrorEvent *error_event;
6271 void DisplayIcsInteractionTitle(message)
6274 if (oldICSInteractionTitle == NULL) {
6275 /* Magic to find the old window title, adapted from vim */
6276 char *wina = getenv("WINDOWID");
6278 Window win = (Window) atoi(wina);
6279 Window root, parent, *children;
6280 unsigned int nchildren;
6281 int (*oldHandler)() = XSetErrorHandler(NullXErrorCheck);
6283 if (XFetchName(xDisplay, win, &oldICSInteractionTitle)) break;
6284 if (!XQueryTree(xDisplay, win, &root, &parent,
6285 &children, &nchildren)) break;
6286 if (children) XFree((void *)children);
6287 if (parent == root || parent == 0) break;
6290 XSetErrorHandler(oldHandler);
6292 if (oldICSInteractionTitle == NULL) {
6293 oldICSInteractionTitle = "xterm";
6296 printf("\033]0;%s\007", message);
6300 char pendingReplyPrefix[MSG_SIZ];
6301 ProcRef pendingReplyPR;
6303 void AskQuestionProc(w, event, prms, nprms)
6310 fprintf(stderr, _("AskQuestionProc needed 4 parameters, got %d\n"),
6314 AskQuestionEvent(prms[0], prms[1], prms[2], prms[3]);
6317 void AskQuestionPopDown()
6319 if (!askQuestionUp) return;
6320 XtPopdown(askQuestionShell);
6321 XtDestroyWidget(askQuestionShell);
6322 askQuestionUp = False;
6325 void AskQuestionReplyAction(w, event, prms, nprms)
6335 reply = XawDialogGetValueString(w = XtParent(w));
6336 strcpy(buf, pendingReplyPrefix);
6337 if (*buf) strcat(buf, " ");
6340 OutputToProcess(pendingReplyPR, buf, strlen(buf), &err);
6341 AskQuestionPopDown();
6343 if (err) DisplayFatalError(_("Error writing to chess program"), err, 0);
6346 void AskQuestionCallback(w, client_data, call_data)
6348 XtPointer client_data, call_data;
6353 XtSetArg(args[0], XtNlabel, &name);
6354 XtGetValues(w, args, 1);
6356 if (strcmp(name, _("cancel")) == 0) {
6357 AskQuestionPopDown();
6359 AskQuestionReplyAction(w, NULL, NULL, NULL);
6363 void AskQuestion(title, question, replyPrefix, pr)
6364 char *title, *question, *replyPrefix;
6368 Widget popup, layout, dialog, edit;
6374 strcpy(pendingReplyPrefix, replyPrefix);
6375 pendingReplyPR = pr;
6378 XtSetArg(args[i], XtNresizable, True); i++;
6379 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
6380 askQuestionShell = popup =
6381 XtCreatePopupShell(title, transientShellWidgetClass,
6382 shellWidget, args, i);
6385 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
6386 layoutArgs, XtNumber(layoutArgs));
6389 XtSetArg(args[i], XtNlabel, question); i++;
6390 XtSetArg(args[i], XtNvalue, ""); i++;
6391 XtSetArg(args[i], XtNborderWidth, 0); i++;
6392 dialog = XtCreateManagedWidget("question", dialogWidgetClass,
6395 XawDialogAddButton(dialog, _("enter"), AskQuestionCallback,
6396 (XtPointer) dialog);
6397 XawDialogAddButton(dialog, _("cancel"), AskQuestionCallback,
6398 (XtPointer) dialog);
6400 XtRealizeWidget(popup);
6401 CatchDeleteWindow(popup, "AskQuestionPopDown");
6403 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
6404 &x, &y, &win_x, &win_y, &mask);
6406 XtSetArg(args[0], XtNx, x - 10);
6407 XtSetArg(args[1], XtNy, y - 30);
6408 XtSetValues(popup, args, 2);
6410 XtPopup(popup, XtGrabExclusive);
6411 askQuestionUp = True;
6413 edit = XtNameToWidget(dialog, "*value");
6414 XtSetKeyboardFocus(popup, edit);
6422 if (*name == NULLCHAR) {
6424 } else if (strcmp(name, "$") == 0) {
6425 putc(BELLCHAR, stderr);
6428 snprintf(buf, sizeof(buf), "%s '%s' &", appData.soundProgram, name);
6436 PlaySound(appData.soundMove);
6442 PlaySound(appData.soundIcsWin);
6448 PlaySound(appData.soundIcsLoss);
6454 PlaySound(appData.soundIcsDraw);
6458 PlayIcsUnfinishedSound()
6460 PlaySound(appData.soundIcsUnfinished);
6466 PlaySound(appData.soundIcsAlarm);
6472 system("stty echo");
6478 system("stty -echo");
6482 Colorize(cc, continuation)
6487 int count, outCount, error;
6489 if (textColors[(int)cc].bg > 0) {
6490 if (textColors[(int)cc].fg > 0) {
6491 sprintf(buf, "\033[0;%d;%d;%dm", textColors[(int)cc].attr,
6492 textColors[(int)cc].fg, textColors[(int)cc].bg);
6494 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
6495 textColors[(int)cc].bg);
6498 if (textColors[(int)cc].fg > 0) {
6499 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
6500 textColors[(int)cc].fg);
6502 sprintf(buf, "\033[0;%dm", textColors[(int)cc].attr);
6505 count = strlen(buf);
6506 outCount = OutputToProcess(NoProc, buf, count, &error);
6507 if (outCount < count) {
6508 DisplayFatalError(_("Error writing to display"), error, 1);
6511 if (continuation) return;
6514 PlaySound(appData.soundShout);
6517 PlaySound(appData.soundSShout);
6520 PlaySound(appData.soundChannel1);
6523 PlaySound(appData.soundChannel);
6526 PlaySound(appData.soundKibitz);
6529 PlaySound(appData.soundTell);
6531 case ColorChallenge:
6532 PlaySound(appData.soundChallenge);
6535 PlaySound(appData.soundRequest);
6538 PlaySound(appData.soundSeek);
6549 return getpwuid(getuid())->pw_name;
6552 static char *ExpandPathName(path)
6555 static char static_buf[2000];
6556 char *d, *s, buf[2000];
6562 while (*s && isspace(*s))
6571 if (*(s+1) == '/') {
6572 strcpy(d, getpwuid(getuid())->pw_dir);
6577 *strchr(buf, '/') = 0;
6578 pwd = getpwnam(buf);
6581 fprintf(stderr, _("ERROR: Unknown user %s (in path %s)\n"),
6585 strcpy(d, pwd->pw_dir);
6586 strcat(d, strchr(s+1, '/'));
6597 static char host_name[MSG_SIZ];
6599 #if HAVE_GETHOSTNAME
6600 gethostname(host_name, MSG_SIZ);
6602 #else /* not HAVE_GETHOSTNAME */
6603 # if HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H
6604 sysinfo(SI_HOSTNAME, host_name, MSG_SIZ);
6606 # else /* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
6608 # endif/* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
6609 #endif /* not HAVE_GETHOSTNAME */
6612 guint delayedEventTimerTag = 0;
6613 DelayedEventCallback delayedEventCallback = 0;
6616 FireDelayedEvent(data)
6620 g_source_remove(delayedEventTimerTag);
6621 delayedEventTimerTag = 0;
6624 delayedEventCallback();
6630 ScheduleDelayedEvent(cb, millisec)
6631 DelayedEventCallback cb; guint millisec;
6633 if(delayedEventTimerTag && delayedEventCallback == cb)
6634 // [HGM] alive: replace, rather than add or flush identical event
6635 g_source_remove(delayedEventTimerTag);
6636 delayedEventCallback = cb;
6637 delayedEventTimerTag = g_timeout_add(millisec,(GSourceFunc) FireDelayedEvent, NULL);
6641 DelayedEventCallback
6644 if (delayedEventTimerTag)
6646 return delayedEventCallback;
6655 CancelDelayedEvent()
6657 if (delayedEventTimerTag)
6659 g_source_remove(delayedEventTimerTag);
6660 delayedEventTimerTag = 0;
6666 guint loadGameTimerTag = 0;
6668 int LoadGameTimerRunning()
6670 return loadGameTimerTag != 0;
6673 int StopLoadGameTimer()
6675 if (loadGameTimerTag != 0) {
6676 g_source_remove(loadGameTimerTag);
6677 loadGameTimerTag = 0;
6685 LoadGameTimerCallback(data)
6689 g_source_remove(loadGameTimerTag);
6690 loadGameTimerTag = 0;
6697 StartLoadGameTimer(millisec)
6701 g_timeout_add( millisec, (GSourceFunc) LoadGameTimerCallback, NULL);
6705 guint analysisClockTag = 0;
6708 AnalysisClockCallback(data)
6711 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile
6712 || appData.icsEngineAnalyze)
6714 AnalysisPeriodicEvent(0);
6715 return 1; /* keep on going */
6717 return 0; /* stop timer */
6721 StartAnalysisClock()
6724 g_timeout_add( 2000,(GSourceFunc) AnalysisClockCallback, NULL);
6728 guint clockTimerTag = 0;
6730 int ClockTimerRunning()
6732 return clockTimerTag != 0;
6735 int StopClockTimer()
6737 if (clockTimerTag != 0)
6739 g_source_remove(clockTimerTag);
6750 ClockTimerCallback(data)
6754 g_source_remove(clockTimerTag);
6762 StartClockTimer(millisec)
6765 clockTimerTag = g_timeout_add(millisec,(GSourceFunc) ClockTimerCallback,NULL);
6770 DisplayTimerLabel(w, color, timer, highlight)
6779 if (appData.clockMode) {
6780 sprintf(buf, "%s: %s", color, TimeString(timer));
6782 sprintf(buf, "%s ", color);
6784 gtk_label_set_text(GTK_LABEL(w),buf);
6786 /* check for low time warning */
6787 // Pixel foregroundOrWarningColor = timerForegroundPixel;
6790 // appData.lowTimeWarning &&
6791 // (timer / 1000) < appData.icsAlarmTime)
6792 // foregroundOrWarningColor = lowTimeWarningColor;
6794 // if (appData.clockMode) {
6795 // sprintf(buf, "%s: %s", color, TimeString(timer));
6796 // XtSetArg(args[0], XtNlabel, buf);
6798 // sprintf(buf, "%s ", color);
6799 // XtSetArg(args[0], XtNlabel, buf);
6804 // XtSetArg(args[1], XtNbackground, foregroundOrWarningColor);
6805 // XtSetArg(args[2], XtNforeground, timerBackgroundPixel);
6807 // XtSetArg(args[1], XtNbackground, timerBackgroundPixel);
6808 // XtSetArg(args[2], XtNforeground, foregroundOrWarningColor);
6811 // XtSetValues(w, args, 3);
6816 DisplayWhiteClock(timeRemaining, highlight)
6820 if(appData.noGUI) return;
6822 DisplayTimerLabel(GUI_Whiteclock, _("White"), timeRemaining, highlight);
6823 if (highlight && WindowIcon == BlackIcon)
6825 WindowIcon = WhiteIcon;
6826 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
6831 DisplayBlackClock(timeRemaining, highlight)
6835 if(appData.noGUI) return;
6837 DisplayTimerLabel(GUI_Blackclock, _("Black"), timeRemaining, highlight);
6838 if (highlight && WindowIcon == WhiteIcon)
6840 WindowIcon = BlackIcon;
6841 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
6859 int StartChildProcess(cmdLine, dir, pr)
6866 int to_prog[2], from_prog[2];
6870 if (appData.debugMode) {
6871 fprintf(stderr, "StartChildProcess (dir=\"%s\") %s\n",dir, cmdLine);
6874 /* We do NOT feed the cmdLine to the shell; we just
6875 parse it into blank-separated arguments in the
6876 most simple-minded way possible.
6879 strcpy(buf, cmdLine);
6884 if (p == NULL) break;
6889 SetUpChildIO(to_prog, from_prog);
6891 if ((pid = fork()) == 0) {
6893 // [HGM] PSWBTM: made order resistant against case where fd of created pipe was 0 or 1
6894 close(to_prog[1]); // first close the unused pipe ends
6895 close(from_prog[0]);
6896 dup2(to_prog[0], 0); // to_prog was created first, nd is the only one to use 0 or 1
6897 dup2(from_prog[1], 1);
6898 if(to_prog[0] >= 2) close(to_prog[0]); // if 0 or 1, the dup2 already cosed the original
6899 close(from_prog[1]); // and closing again loses one of the pipes!
6900 if(fileno(stderr) >= 2) // better safe than sorry...
6901 dup2(1, fileno(stderr)); /* force stderr to the pipe */
6903 if (dir[0] != NULLCHAR && chdir(dir) != 0) {
6908 nice(appData.niceEngines); // [HGM] nice: adjust priority of engine proc
6910 execvp(argv[0], argv);
6912 /* If we get here, exec failed */
6917 /* Parent process */
6919 close(from_prog[1]);
6921 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
6924 cp->fdFrom = from_prog[0];
6925 cp->fdTo = to_prog[1];
6930 // [HGM] kill: implement the 'hard killing' of AS's Winboard_x
6931 static RETSIGTYPE AlarmCallBack(int n)
6937 DestroyChildProcess(pr, signalType)
6941 ChildProc *cp = (ChildProc *) pr;
6943 if (cp->kind != CPReal) return;
6945 if (signalType == 10) { // [HGM] kill: if it does not terminate in 3 sec, kill
6946 signal(SIGALRM, AlarmCallBack);
6948 if(wait((int *) 0) == -1) { // process does not terminate on its own accord
6949 kill(cp->pid, SIGKILL); // kill it forcefully
6950 wait((int *) 0); // and wait again
6954 kill(cp->pid, signalType == 9 ? SIGKILL : SIGTERM); // [HGM] kill: use hard kill if so requested
6956 /* Process is exiting either because of the kill or because of
6957 a quit command sent by the backend; either way, wait for it to die.
6966 InterruptChildProcess(pr)
6969 ChildProc *cp = (ChildProc *) pr;
6971 if (cp->kind != CPReal) return;
6972 (void) kill(cp->pid, SIGINT); /* stop it thinking */
6975 int OpenTelnet(host, port, pr)
6980 char cmdLine[MSG_SIZ];
6982 if (port[0] == NULLCHAR) {
6983 snprintf(cmdLine, sizeof(cmdLine), "%s %s", appData.telnetProgram, host);
6985 snprintf(cmdLine, sizeof(cmdLine), "%s %s %s", appData.telnetProgram, host, port);
6987 return StartChildProcess(cmdLine, "", pr);
6990 int OpenTCP(host, port, pr)
6996 DisplayFatalError(_("Socket support is not configured in"), 0, 2);
6997 #else /* !OMIT_SOCKETS */
6999 struct sockaddr_in sa;
7001 unsigned short uport;
7004 if ((s = socket(AF_INET, SOCK_STREAM, 6)) < 0) {
7008 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
7009 sa.sin_family = AF_INET;
7010 sa.sin_addr.s_addr = INADDR_ANY;
7011 uport = (unsigned short) 0;
7012 sa.sin_port = htons(uport);
7013 if (bind(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)) < 0) {
7017 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
7018 if (!(hp = gethostbyname(host))) {
7020 if (sscanf(host, "%d.%d.%d.%d", &b0, &b1, &b2, &b3) == 4) {
7021 hp = (struct hostent *) calloc(1, sizeof(struct hostent));
7022 hp->h_addrtype = AF_INET;
7024 hp->h_addr_list = (char **) calloc(2, sizeof(char *));
7025 hp->h_addr_list[0] = (char *) malloc(4);
7026 hp->h_addr_list[0][0] = b0;
7027 hp->h_addr_list[0][1] = b1;
7028 hp->h_addr_list[0][2] = b2;
7029 hp->h_addr_list[0][3] = b3;
7034 sa.sin_family = hp->h_addrtype;
7035 uport = (unsigned short) atoi(port);
7036 sa.sin_port = htons(uport);
7037 memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);
7039 if (connect(s, (struct sockaddr *) &sa,
7040 sizeof(struct sockaddr_in)) < 0) {
7044 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7051 #endif /* !OMIT_SOCKETS */
7056 int OpenCommPort(name, pr)
7063 fd = open(name, 2, 0);
7064 if (fd < 0) return errno;
7066 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7076 int OpenLoopback(pr)
7082 SetUpChildIO(to, from);
7084 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7087 cp->fdFrom = to[0]; /* note not from[0]; we are doing a loopback */
7094 int OpenRcmd(host, user, cmd, pr)
7095 char *host, *user, *cmd;
7098 DisplayFatalError(_("internal rcmd not implemented for Unix"), 0, 1);
7102 #define INPUT_SOURCE_BUF_SIZE 8192
7111 char buf[INPUT_SOURCE_BUF_SIZE];
7116 DoInputCallback(io,cond,data)
7121 /* read input from one of the input source (for example a chess program, ICS, etc).
7122 * and call a function that will handle the input
7125 int count; /* how many bytes did we read */
7129 /* All information (callback function, file descriptor, etc) is
7130 * saved in an InputSource structure
7132 InputSource *is = (InputSource *) data;
7136 count = read(is->fd, is->unused,
7137 INPUT_SOURCE_BUF_SIZE - (is->unused - is->buf));
7141 (is->func)(is, is->closure, is->buf, count, count ? errno : 0);
7144 is->unused += count;
7146 /* break input into lines and call the callback function on each
7149 while (p < is->unused)
7151 q = memchr(p, '\n', is->unused - p);
7152 if (q == NULL) break;
7154 (is->func)(is, is->closure, p, q - p, 0);
7157 /* remember not yet used part of the buffer */
7159 while (p < is->unused)
7167 /* read maximum length of input buffer and send the whole buffer
7168 * to the callback function
7170 count = read(is->fd, is->buf, INPUT_SOURCE_BUF_SIZE);
7175 (is->func)(is, is->closure, is->buf, count, error);
7181 InputSourceRef AddInputSource(pr, lineByLine, func, closure)
7188 GIOChannel *channel;
7189 ChildProc *cp = (ChildProc *) pr;
7191 is = (InputSource *) calloc(1, sizeof(InputSource));
7192 is->lineByLine = lineByLine;
7196 is->fd = fileno(stdin);
7198 is->kind = cp->kind;
7199 is->fd = cp->fdFrom;
7202 is->unused = is->buf;
7206 // is->xid = XtAppAddInput(appContext, is->fd,
7207 // (XtPointer) (XtInputReadMask),
7208 // (XtInputCallbackProc) DoInputCallback,
7212 /* TODO: will this work on windows?*/
7213 printf("DEBUG: fd=%d %d\n",is->fd,is);
7215 channel = g_io_channel_unix_new(is->fd);
7216 g_io_channel_set_close_on_unref (channel, TRUE);
7217 is->sid = g_io_add_watch(channel, G_IO_IN,(GIOFunc) DoInputCallback, is);
7218 is->closure = closure;
7219 return (InputSourceRef) is;
7223 RemoveInputSource(isr)
7226 InputSource *is = (InputSource *) isr;
7228 if (is->sid == 0) return;
7229 g_source_remove(is->sid);
7234 int OutputToProcess(pr, message, count, outError)
7240 ChildProc *cp = (ChildProc *) pr;
7244 outCount = fwrite(message, 1, count, stdout);
7246 outCount = write(cp->fdTo, message, count);
7256 /* Output message to process, with "ms" milliseconds of delay
7257 between each character. This is needed when sending the logon
7258 script to ICC, which for some reason doesn't like the
7259 instantaneous send. */
7260 int OutputToProcessDelayed(pr, message, count, outError, msdelay)
7267 ChildProc *cp = (ChildProc *) pr;
7272 r = write(cp->fdTo, message++, 1);
7285 /**** Animation code by Hugh Fisher, DCS, ANU.
7287 Known problem: if a window overlapping the board is
7288 moved away while a piece is being animated underneath,
7289 the newly exposed area won't be updated properly.
7290 I can live with this.
7292 Known problem: if you look carefully at the animation
7293 of pieces in mono mode, they are being drawn as solid
7294 shapes without interior detail while moving. Fixing
7295 this would be a major complication for minimal return.
7298 /* Masks for XPM pieces. Black and white pieces can have
7299 different shapes, but in the interest of retaining my
7300 sanity pieces must have the same outline on both light
7301 and dark squares, and all pieces must use the same
7302 background square colors/images. */
7304 static int xpmDone = 0;
7307 CreateAnimMasks (pieceDepth)
7314 unsigned long plane;
7317 /* just return for gtk at the moment */
7320 /* Need a bitmap just to get a GC with right depth */
7321 buf = XCreatePixmap(xDisplay, xBoardWindow,
7323 values.foreground = 1;
7324 values.background = 0;
7325 /* Don't use XtGetGC, not read only */
7326 maskGC = XCreateGC(xDisplay, buf,
7327 GCForeground | GCBackground, &values);
7328 XFreePixmap(xDisplay, buf);
7330 buf = XCreatePixmap(xDisplay, xBoardWindow,
7331 squareSize, squareSize, pieceDepth);
7332 values.foreground = XBlackPixel(xDisplay, xScreen);
7333 values.background = XWhitePixel(xDisplay, xScreen);
7334 bufGC = XCreateGC(xDisplay, buf,
7335 GCForeground | GCBackground, &values);
7337 for (piece = WhitePawn; piece <= BlackKing; piece++) {
7338 /* Begin with empty mask */
7339 if(!xpmDone) // [HGM] pieces: keep using existing
7340 xpmMask[piece] = XCreatePixmap(xDisplay, xBoardWindow,
7341 squareSize, squareSize, 1);
7342 XSetFunction(xDisplay, maskGC, GXclear);
7343 XFillRectangle(xDisplay, xpmMask[piece], maskGC,
7344 0, 0, squareSize, squareSize);
7346 /* Take a copy of the piece */
7351 XSetFunction(xDisplay, bufGC, GXcopy);
7352 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn],
7354 0, 0, squareSize, squareSize, 0, 0);
7356 /* XOR the background (light) over the piece */
7357 XSetFunction(xDisplay, bufGC, GXxor);
7359 XCopyArea(xDisplay, xpmLightSquare, buf, bufGC,
7360 0, 0, squareSize, squareSize, 0, 0);
7362 XSetForeground(xDisplay, bufGC, lightSquareColor);
7363 XFillRectangle(xDisplay, buf, bufGC, 0, 0, squareSize, squareSize);
7366 /* We now have an inverted piece image with the background
7367 erased. Construct mask by just selecting all the non-zero
7368 pixels - no need to reconstruct the original image. */
7369 XSetFunction(xDisplay, maskGC, GXor);
7371 /* Might be quicker to download an XImage and create bitmap
7372 data from it rather than this N copies per piece, but it
7373 only takes a fraction of a second and there is a much
7374 longer delay for loading the pieces. */
7375 for (n = 0; n < pieceDepth; n ++) {
7376 XCopyPlane(xDisplay, buf, xpmMask[piece], maskGC,
7377 0, 0, squareSize, squareSize,
7383 XFreePixmap(xDisplay, buf);
7384 XFreeGC(xDisplay, bufGC);
7385 XFreeGC(xDisplay, maskGC);
7389 InitAnimState (anim, info)
7391 XWindowAttributes * info;
7396 /* Each buffer is square size, same depth as window */
7397 // anim->saveBuf = XCreatePixmap(xDisplay, xBoardWindow,
7398 // squareSize, squareSize, info->depth);
7399 // anim->newBuf = XCreatePixmap(xDisplay, xBoardWindow,
7400 // squareSize, squareSize, info->depth);
7402 // /* Create a plain GC for blitting */
7403 // mask = GCForeground | GCBackground | GCFunction |
7404 // GCPlaneMask | GCGraphicsExposures;
7405 // values.foreground = XBlackPixel(xDisplay, xScreen);
7406 // values.background = XWhitePixel(xDisplay, xScreen);
7407 // values.function = GXcopy;
7408 // values.plane_mask = AllPlanes;
7409 // values.graphics_exposures = False;
7410 // anim->blitGC = XCreateGC(xDisplay, xBoardWindow, mask, &values);
7412 // /* Piece will be copied from an existing context at
7413 // the start of each new animation/drag. */
7414 // anim->pieceGC = XCreateGC(xDisplay, xBoardWindow, 0, &values);
7416 // /* Outline will be a read-only copy of an existing */
7417 // anim->outlineGC = None;
7423 static VariantClass old = (VariantClass) -1; // [HGM] pieces: redo every time variant changes
7424 XWindowAttributes info;
7426 /* for gtk at the moment just ... */
7429 if (xpmDone && gameInfo.variant == old) return;
7430 if(xpmDone) old = gameInfo.variant; // first time pieces might not be created yet
7431 // XGetWindowAttributes(xDisplay, xBoardWindow, &info);
7433 // InitAnimState(&game, &info);
7434 // InitAnimState(&player, &info);
7436 /* For XPM pieces, we need bitmaps to use as masks. */
7438 // CreateAnimMasks(info.depth);
7444 static Boolean frameWaiting;
7446 static RETSIGTYPE FrameAlarm (sig)
7449 frameWaiting = False;
7450 /* In case System-V style signals. Needed?? */
7451 signal(SIGALRM, FrameAlarm);
7458 struct itimerval delay;
7460 XSync(xDisplay, False);
7463 frameWaiting = True;
7464 signal(SIGALRM, FrameAlarm);
7465 delay.it_interval.tv_sec =
7466 delay.it_value.tv_sec = time / 1000;
7467 delay.it_interval.tv_usec =
7468 delay.it_value.tv_usec = (time % 1000) * 1000;
7469 setitimer(ITIMER_REAL, &delay, NULL);
7470 while (frameWaiting) pause();
7471 delay.it_interval.tv_sec = delay.it_value.tv_sec = 0;
7472 delay.it_interval.tv_usec = delay.it_value.tv_usec = 0;
7473 setitimer(ITIMER_REAL, &delay, NULL);
7483 // XSync(xDisplay, False);
7485 usleep(time * 1000);
7490 /* Convert board position to corner of screen rect and color */
7493 ScreenSquare(column, row, pt, color)
7494 int column; int row; XPoint * pt; int * color;
7497 pt->x = lineGap + ((BOARD_WIDTH-1)-column) * (squareSize + lineGap);
7498 pt->y = lineGap + row * (squareSize + lineGap);
7500 pt->x = lineGap + column * (squareSize + lineGap);
7501 pt->y = lineGap + ((BOARD_HEIGHT-1)-row) * (squareSize + lineGap);
7503 *color = SquareColor(row, column);
7506 /* Convert window coords to square */
7509 BoardSquare(x, y, column, row)
7510 int x; int y; int * column; int * row;
7512 *column = EventToSquare(x, BOARD_WIDTH);
7513 if (flipView && *column >= 0)
7514 *column = BOARD_WIDTH - 1 - *column;
7515 *row = EventToSquare(y, BOARD_HEIGHT);
7516 if (!flipView && *row >= 0)
7517 *row = BOARD_HEIGHT - 1 - *row;
7522 #undef Max /* just in case */
7524 #define Max(a, b) ((a) > (b) ? (a) : (b))
7525 #define Min(a, b) ((a) < (b) ? (a) : (b))
7528 SetRect(rect, x, y, width, height)
7529 XRectangle * rect; int x; int y; int width; int height;
7533 rect->width = width;
7534 rect->height = height;
7537 /* Test if two frames overlap. If they do, return
7538 intersection rect within old and location of
7539 that rect within new. */
7542 Intersect(old, new, size, area, pt)
7543 XPoint * old; XPoint * new;
7544 int size; XRectangle * area; XPoint * pt;
7546 if (old->x > new->x + size || new->x > old->x + size ||
7547 old->y > new->y + size || new->y > old->y + size) {
7550 SetRect(area, Max(new->x - old->x, 0), Max(new->y - old->y, 0),
7551 size - abs(old->x - new->x), size - abs(old->y - new->y));
7552 pt->x = Max(old->x - new->x, 0);
7553 pt->y = Max(old->y - new->y, 0);
7558 /* For two overlapping frames, return the rect(s)
7559 in the old that do not intersect with the new. */
7562 CalcUpdateRects(old, new, size, update, nUpdates)
7563 XPoint * old; XPoint * new; int size;
7564 XRectangle update[]; int * nUpdates;
7568 /* If old = new (shouldn't happen) then nothing to draw */
7569 if (old->x == new->x && old->y == new->y) {
7573 /* Work out what bits overlap. Since we know the rects
7574 are the same size we don't need a full intersect calc. */
7576 /* Top or bottom edge? */
7577 if (new->y > old->y) {
7578 SetRect(&(update[count]), old->x, old->y, size, new->y - old->y);
7580 } else if (old->y > new->y) {
7581 SetRect(&(update[count]), old->x, old->y + size - (old->y - new->y),
7582 size, old->y - new->y);
7585 /* Left or right edge - don't overlap any update calculated above. */
7586 if (new->x > old->x) {
7587 SetRect(&(update[count]), old->x, Max(new->y, old->y),
7588 new->x - old->x, size - abs(new->y - old->y));
7590 } else if (old->x > new->x) {
7591 SetRect(&(update[count]), new->x + size, Max(new->y, old->y),
7592 old->x - new->x, size - abs(new->y - old->y));
7599 /* Generate a series of frame coords from start->mid->finish.
7600 The movement rate doubles until the half way point is
7601 reached, then halves back down to the final destination,
7602 which gives a nice slow in/out effect. The algorithmn
7603 may seem to generate too many intermediates for short
7604 moves, but remember that the purpose is to attract the
7605 viewers attention to the piece about to be moved and
7606 then to where it ends up. Too few frames would be less
7610 Tween(start, mid, finish, factor, frames, nFrames)
7611 XPoint * start; XPoint * mid;
7612 XPoint * finish; int factor;
7613 XPoint frames[]; int * nFrames;
7615 int fraction, n, count;
7619 /* Slow in, stepping 1/16th, then 1/8th, ... */
7621 for (n = 0; n < factor; n++)
7623 for (n = 0; n < factor; n++) {
7624 frames[count].x = start->x + (mid->x - start->x) / fraction;
7625 frames[count].y = start->y + (mid->y - start->y) / fraction;
7627 fraction = fraction / 2;
7631 frames[count] = *mid;
7634 /* Slow out, stepping 1/2, then 1/4, ... */
7636 for (n = 0; n < factor; n++) {
7637 frames[count].x = finish->x - (finish->x - mid->x) / fraction;
7638 frames[count].y = finish->y - (finish->y - mid->y) / fraction;
7640 fraction = fraction * 2;
7645 /* Draw a piece on the screen without disturbing what's there */
7648 SelectGCMask(piece, clip, outline, mask)
7649 ChessSquare piece; GC * clip; GC * outline; Pixmap * mask;
7653 /* Bitmap for piece being moved. */
7654 if (appData.monoMode) {
7655 *mask = *pieceToSolid(piece);
7656 } else if (useImages) {
7658 *mask = xpmMask[piece];
7660 *mask = ximMaskPm[piece];
7663 *mask = *pieceToSolid(piece);
7666 /* GC for piece being moved. Square color doesn't matter, but
7667 since it gets modified we make a copy of the original. */
7669 if (appData.monoMode)
7674 if (appData.monoMode)
7679 // XCopyGC(xDisplay, source, 0xFFFFFFFF, *clip);
7681 /* Outline only used in mono mode and is not modified */
7683 *outline = bwPieceGC;
7685 *outline = wbPieceGC;
7689 OverlayPiece(piece, clip, outline, dest)
7690 ChessSquare piece; GC clip; GC outline; Drawable dest;
7695 /* Draw solid rectangle which will be clipped to shape of piece */
7696 // XFillRectangle(xDisplay, dest, clip,
7697 // 0, 0, squareSize, squareSize)
7699 if (appData.monoMode)
7700 /* Also draw outline in contrasting color for black
7701 on black / white on white cases */
7702 // XCopyPlane(xDisplay, *pieceToOutline(piece), dest, outline,
7703 // 0, 0, squareSize, squareSize, 0, 0, 1)
7706 /* Copy the piece */
7711 // XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
7713 // 0, 0, squareSize, squareSize,
7718 /* Animate the movement of a single piece */
7721 BeginAnimation(anim, piece, startColor, start)
7729 /* The old buffer is initialised with the start square (empty) */
7730 BlankSquare(0, 0, startColor, EmptySquare, anim->saveBuf);
7731 anim->prevFrame = *start;
7733 /* The piece will be drawn using its own bitmap as a matte */
7734 // SelectGCMask(piece, &anim->pieceGC, &anim->outlineGC, &mask);
7735 // XSetClipMask(xDisplay, anim->pieceGC, mask);
7739 AnimationFrame(anim, frame, piece)
7744 XRectangle updates[4];
7749 /* Save what we are about to draw into the new buffer */
7750 // XCopyArea(xDisplay, xBoardWindow, anim->newBuf, anim->blitGC,
7751 // frame->x, frame->y, squareSize, squareSize,
7754 /* Erase bits of the previous frame */
7755 if (Intersect(&anim->prevFrame, frame, squareSize, &overlap, &pt)) {
7756 /* Where the new frame overlapped the previous,
7757 the contents in newBuf are wrong. */
7758 // XCopyArea(xDisplay, anim->saveBuf, anim->newBuf, anim->blitGC,
7759 // overlap.x, overlap.y,
7760 // overlap.width, overlap.height,
7762 /* Repaint the areas in the old that don't overlap new */
7763 CalcUpdateRects(&anim->prevFrame, frame, squareSize, updates, &count);
7764 for (i = 0; i < count; i++)
7765 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
7766 // updates[i].x - anim->prevFrame.x,
7767 // updates[i].y - anim->prevFrame.y,
7768 // updates[i].width, updates[i].height,
7769 // updates[i].x, updates[i].y)
7772 /* Easy when no overlap */
7773 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
7774 // 0, 0, squareSize, squareSize,
7775 // anim->prevFrame.x, anim->prevFrame.y);
7778 /* Save this frame for next time round */
7779 // XCopyArea(xDisplay, anim->newBuf, anim->saveBuf, anim->blitGC,
7780 // 0, 0, squareSize, squareSize,
7782 anim->prevFrame = *frame;
7784 /* Draw piece over original screen contents, not current,
7785 and copy entire rect. Wipes out overlapping piece images. */
7786 OverlayPiece(piece, anim->pieceGC, anim->outlineGC, anim->newBuf);
7787 // XCopyArea(xDisplay, anim->newBuf, xBoardWindow, anim->blitGC,
7788 // 0, 0, squareSize, squareSize,
7789 // frame->x, frame->y);
7793 EndAnimation (anim, finish)
7797 XRectangle updates[4];
7802 /* The main code will redraw the final square, so we
7803 only need to erase the bits that don't overlap. */
7804 if (Intersect(&anim->prevFrame, finish, squareSize, &overlap, &pt)) {
7805 CalcUpdateRects(&anim->prevFrame, finish, squareSize, updates, &count);
7806 for (i = 0; i < count; i++)
7807 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
7808 // updates[i].x - anim->prevFrame.x,
7809 // updates[i].y - anim->prevFrame.y,
7810 // updates[i].width, updates[i].height,
7811 // updates[i].x, updates[i].y)
7814 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
7815 // 0, 0, squareSize, squareSize,
7816 // anim->prevFrame.x, anim->prevFrame.y);
7821 FrameSequence(anim, piece, startColor, start, finish, frames, nFrames)
7823 ChessSquare piece; int startColor;
7824 XPoint * start; XPoint * finish;
7825 XPoint frames[]; int nFrames;
7829 BeginAnimation(anim, piece, startColor, start);
7830 for (n = 0; n < nFrames; n++) {
7831 AnimationFrame(anim, &(frames[n]), piece);
7832 FrameDelay(appData.animSpeed);
7834 EndAnimation(anim, finish);
7837 /* Main control logic for deciding what to animate and how */
7840 AnimateMove(board, fromX, fromY, toX, toY)
7849 XPoint start, finish, mid;
7850 XPoint frames[kFactor * 2 + 1];
7851 int nFrames, startColor, endColor;
7853 /* Are we animating? */
7854 if (!appData.animate || appData.blindfold)
7857 if(board[toY][toX] == WhiteRook && board[fromY][fromX] == WhiteKing ||
7858 board[toY][toX] == BlackRook && board[fromY][fromX] == BlackKing)
7859 return; // [HGM] FRC: no animtion of FRC castlings, as to-square is not true to-square
7861 if (fromY < 0 || fromX < 0 || toX < 0 || toY < 0) return;
7862 piece = board[fromY][fromX];
7863 if (piece >= EmptySquare) return;
7868 hop = (piece == WhiteKnight || piece == BlackKnight);
7871 if (appData.debugMode) {
7872 fprintf(debugFP, hop ? _("AnimateMove: piece %d hops from %d,%d to %d,%d \n") :
7873 _("AnimateMove: piece %d slides from %d,%d to %d,%d \n"),
7874 piece, fromX, fromY, toX, toY); }
7876 ScreenSquare(fromX, fromY, &start, &startColor);
7877 ScreenSquare(toX, toY, &finish, &endColor);
7880 /* Knight: make diagonal movement then straight */
7881 if (abs(toY - fromY) < abs(toX - fromX)) {
7882 mid.x = start.x + (finish.x - start.x) / 2;
7886 mid.y = start.y + (finish.y - start.y) / 2;
7889 mid.x = start.x + (finish.x - start.x) / 2;
7890 mid.y = start.y + (finish.y - start.y) / 2;
7893 /* Don't use as many frames for very short moves */
7894 if (abs(toY - fromY) + abs(toX - fromX) <= 2)
7895 Tween(&start, &mid, &finish, kFactor - 1, frames, &nFrames);
7897 Tween(&start, &mid, &finish, kFactor, frames, &nFrames);
7898 FrameSequence(&game, piece, startColor, &start, &finish, frames, nFrames);
7900 /* Be sure end square is redrawn */
7901 damage[toY][toX] = True;
7905 DragPieceBegin(x, y)
7908 int boardX, boardY, color;
7911 /* Are we animating? */
7912 if (!appData.animateDragging || appData.blindfold)
7915 /* Figure out which square we start in and the
7916 mouse position relative to top left corner. */
7917 BoardSquare(x, y, &boardX, &boardY);
7918 player.startBoardX = boardX;
7919 player.startBoardY = boardY;
7920 ScreenSquare(boardX, boardY, &corner, &color);
7921 player.startSquare = corner;
7922 player.startColor = color;
7923 /* As soon as we start dragging, the piece will jump slightly to
7924 be centered over the mouse pointer. */
7925 player.mouseDelta.x = squareSize/2;
7926 player.mouseDelta.y = squareSize/2;
7927 /* Initialise animation */
7928 player.dragPiece = PieceForSquare(boardX, boardY);
7930 if (player.dragPiece >= 0 && player.dragPiece < EmptySquare) {
7931 player.dragActive = True;
7932 BeginAnimation(&player, player.dragPiece, color, &corner);
7933 /* Mark this square as needing to be redrawn. Note that
7934 we don't remove the piece though, since logically (ie
7935 as seen by opponent) the move hasn't been made yet. */
7936 if(boardX == BOARD_RGHT+1 && PieceForSquare(boardX-1, boardY) > 1 ||
7937 boardX == BOARD_LEFT-2 && PieceForSquare(boardX+1, boardY) > 1)
7938 // XCopyArea(xDisplay, xBoardWindow, player.saveBuf, player.blitGC,
7939 // corner.x, corner.y, squareSize, squareSize,
7940 // 0, 0); // [HGM] zh: unstack in stead of grab
7941 damage[boardY][boardX] = True;
7943 player.dragActive = False;
7953 /* Are we animating? */
7954 if (!appData.animateDragging || appData.blindfold)
7958 if (! player.dragActive)
7960 /* Move piece, maintaining same relative position
7961 of mouse within square */
7962 corner.x = x - player.mouseDelta.x;
7963 corner.y = y - player.mouseDelta.y;
7964 AnimationFrame(&player, &corner, player.dragPiece);
7966 if (appData.highlightDragging) {
7968 BoardSquare(x, y, &boardX, &boardY);
7969 SetHighlights(fromX, fromY, boardX, boardY);
7978 int boardX, boardY, color;
7981 /* Are we animating? */
7982 if (!appData.animateDragging || appData.blindfold)
7986 if (! player.dragActive)
7988 /* Last frame in sequence is square piece is
7989 placed on, which may not match mouse exactly. */
7990 BoardSquare(x, y, &boardX, &boardY);
7991 ScreenSquare(boardX, boardY, &corner, &color);
7992 EndAnimation(&player, &corner);
7994 /* Be sure end square is redrawn */
7995 damage[boardY][boardX] = True;
7997 /* This prevents weird things happening with fast successive
7998 clicks which on my Sun at least can cause motion events
7999 without corresponding press/release. */
8000 player.dragActive = False;
8003 /* Handle expose event while piece being dragged */
8008 if (!player.dragActive || appData.blindfold)
8011 /* What we're doing: logically, the move hasn't been made yet,
8012 so the piece is still in it's original square. But visually
8013 it's being dragged around the board. So we erase the square
8014 that the piece is on and draw it at the last known drag point. */
8015 BlankSquare(player.startSquare.x, player.startSquare.y,
8016 player.startColor, EmptySquare, xBoardWindow);
8017 AnimationFrame(&player, &player.prevFrame, player.dragPiece);
8018 damage[player.startBoardY][player.startBoardX] = TRUE;
8022 SetProgramStats( FrontEndProgramStats * stats )
8025 // [HGM] done, but perhaps backend should call this directly?
8026 EngineOutputUpdate( stats );