2 * xboard.c -- X front end for XBoard
4 * Copyright 1991 by Digital Equipment Corporation, Maynard,
7 * Enhancements Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006,
8 * 2007, 2008, 2009 Free Software Foundation, Inc.
10 * The following terms apply to Digital Equipment Corporation's copyright
12 * ------------------------------------------------------------------------
15 * Permission to use, copy, modify, and distribute this software and its
16 * documentation for any purpose and without fee is hereby granted,
17 * provided that the above copyright notice appear in all copies and that
18 * both that copyright notice and this permission notice appear in
19 * supporting documentation, and that the name of Digital not be
20 * used in advertising or publicity pertaining to distribution of the
21 * software without specific, written prior permission.
23 * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
24 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
25 * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
26 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
27 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
28 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
30 * ------------------------------------------------------------------------
32 * The following terms apply to the enhanced version of XBoard
33 * distributed by the Free Software Foundation:
34 * ------------------------------------------------------------------------
36 * GNU XBoard is free software: you can redistribute it and/or modify
37 * it under the terms of the GNU General Public License as published by
38 * the Free Software Foundation, either version 3 of the License, or (at
39 * your option) any later version.
41 * GNU XBoard is distributed in the hope that it will be useful, but
42 * WITHOUT ANY WARRANTY; without even the implied warranty of
43 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
44 * General Public License for more details.
46 * You should have received a copy of the GNU General Public License
47 * along with this program. If not, see http://www.gnu.org/licenses/. *
49 *------------------------------------------------------------------------
50 ** See the file ChangeLog for a revision history. */
58 #include <sys/types.h>
63 # if HAVE_SYS_SOCKET_H
64 # include <sys/socket.h>
65 # include <netinet/in.h>
67 # else /* not HAVE_SYS_SOCKET_H */
68 # if HAVE_LAN_SOCKET_H
69 # include <lan/socket.h>
71 # include <lan/netdb.h>
72 # else /* not HAVE_LAN_SOCKET_H */
73 # define OMIT_SOCKETS 1
74 # endif /* not HAVE_LAN_SOCKET_H */
75 # endif /* not HAVE_SYS_SOCKET_H */
76 #endif /* !OMIT_SOCKETS */
81 #else /* not STDC_HEADERS */
82 extern char *getenv();
85 # else /* not HAVE_STRING_H */
87 # endif /* not HAVE_STRING_H */
88 #endif /* not STDC_HEADERS */
91 # include <sys/fcntl.h>
92 #else /* not HAVE_SYS_FCNTL_H */
95 # endif /* HAVE_FCNTL_H */
96 #endif /* not HAVE_SYS_FCNTL_H */
98 #if HAVE_SYS_SYSTEMINFO_H
99 # include <sys/systeminfo.h>
100 #endif /* HAVE_SYS_SYSTEMINFO_H */
102 #if TIME_WITH_SYS_TIME
103 # include <sys/time.h>
107 # include <sys/time.h>
118 # include <sys/wait.h>
123 # define NAMLEN(dirent) strlen((dirent)->d_name)
124 # define HAVE_DIR_STRUCT
126 # define dirent direct
127 # define NAMLEN(dirent) (dirent)->d_namlen
129 # include <sys/ndir.h>
130 # define HAVE_DIR_STRUCT
133 # include <sys/dir.h>
134 # define HAVE_DIR_STRUCT
138 # define HAVE_DIR_STRUCT
142 #include <X11/Intrinsic.h>
143 #include <X11/StringDefs.h>
144 #include <X11/Shell.h>
145 #include <X11/cursorfont.h>
146 #include <X11/Xatom.h>
148 #include <X11/Xaw3d/Dialog.h>
149 #include <X11/Xaw3d/Form.h>
150 #include <X11/Xaw3d/List.h>
151 #include <X11/Xaw3d/Label.h>
152 #include <X11/Xaw3d/SimpleMenu.h>
153 #include <X11/Xaw3d/SmeBSB.h>
154 #include <X11/Xaw3d/SmeLine.h>
155 #include <X11/Xaw3d/Box.h>
156 #include <X11/Xaw3d/MenuButton.h>
157 #include <X11/Xaw3d/Text.h>
158 #include <X11/Xaw3d/AsciiText.h>
160 #include <X11/Xaw/Dialog.h>
161 #include <X11/Xaw/Form.h>
162 #include <X11/Xaw/List.h>
163 #include <X11/Xaw/Label.h>
164 #include <X11/Xaw/SimpleMenu.h>
165 #include <X11/Xaw/SmeBSB.h>
166 #include <X11/Xaw/SmeLine.h>
167 #include <X11/Xaw/Box.h>
168 #include <X11/Xaw/MenuButton.h>
169 #include <X11/Xaw/Text.h>
170 #include <X11/Xaw/AsciiText.h>
173 // [HGM] bitmaps: put before incuding the bitmaps / pixmaps, to know how many piece types there are.
178 #include "pixmaps/pixmaps.h"
179 #define IMAGE_EXT "xpm"
181 #define IMAGE_EXT "xim"
182 #include "bitmaps/bitmaps.h"
187 #include <gdk-pixbuf/gdk-pixbuf.h>
189 #include "bitmaps/icon_white.bm"
190 #include "bitmaps/icon_black.bm"
191 #include "bitmaps/checkmark.bm"
193 #include "frontend.h"
198 #include "xgamelist.h"
199 #include "xhistory.h"
200 #include "xedittags.h"
202 #include "callback.h"
203 #include "interface.h"
205 // must be moved to xengineoutput.h
207 void EngineOutputProc P((Widget w, XEvent *event,
208 String *prms, Cardinal *nprms));
210 void EngineOutputPopDown();
217 #define usleep(t) _sleep2(((t)+500)/1000)
221 # define _(s) gettext (s)
222 # define N_(s) gettext_noop (s)
245 int main P((int argc, char **argv));
246 RETSIGTYPE CmailSigHandler P((int sig));
247 RETSIGTYPE IntSigHandler P((int sig));
248 void CreateGCs P((void));
249 void CreateXIMPieces P((void));
250 void CreateXPMPieces P((void));
251 void CreatePieces P((void));
252 void CreatePieceMenus P((void));
253 Widget CreateMenuBar P((Menu *mb));
254 Widget CreateButtonBar P ((MenuItem *mi));
255 char *FindFont P((char *pattern, int targetPxlSize));
256 void PieceMenuPopup P((Widget w, XEvent *event,
257 String *params, Cardinal *num_params));
258 static void PieceMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
259 static void DropMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
260 int EventToSquare P((int x, int limit));
261 void DrawSquare P((int row, int column, ChessSquare piece, int do_flash));
262 void HandleUserMove P((Widget w, XEvent *event,
263 String *prms, Cardinal *nprms));
264 void AnimateUserMove P((Widget w, XEvent * event,
265 String * params, Cardinal * nParams));
266 void WhiteClock P((Widget w, XEvent *event,
267 String *prms, Cardinal *nprms));
268 void BlackClock P((Widget w, XEvent *event,
269 String *prms, Cardinal *nprms));
270 void CommentPopUp P((char *title, char *label));
271 void CommentPopDown P((void));
272 void CommentCallback P((Widget w, XtPointer client_data,
273 XtPointer call_data));
274 void ICSInputBoxPopUp P((void));
275 void ICSInputBoxPopDown P((void));
276 void FileNamePopUp P((char *label, char *def,
277 FileProc proc, char *openMode));
278 void FileNamePopDown P((void));
279 void FileNameCallback P((Widget w, XtPointer client_data,
280 XtPointer call_data));
281 void FileNameAction P((Widget w, XEvent *event,
282 String *prms, Cardinal *nprms));
283 void AskQuestionReplyAction P((Widget w, XEvent *event,
284 String *prms, Cardinal *nprms));
285 void AskQuestionProc P((Widget w, XEvent *event,
286 String *prms, Cardinal *nprms));
287 void AskQuestionPopDown P((void));
288 void PromotionPopUp P((void));
289 void PromotionPopDown P((void));
290 void PromotionCallback P((Widget w, XtPointer client_data,
291 XtPointer call_data));
292 void EditCommentPopDown P((void));
293 void EditCommentCallback P((Widget w, XtPointer client_data,
294 XtPointer call_data));
295 void SelectCommand P((Widget w, XtPointer client_data, XtPointer call_data));
296 void LoadPositionProc P((Widget w, XEvent *event,
297 String *prms, Cardinal *nprms));
298 void LoadNextPositionProc P((Widget w, XEvent *event, String *prms,
300 void LoadPrevPositionProc P((Widget w, XEvent *event, String *prms,
302 void ReloadPositionProc P((Widget w, XEvent *event, String *prms,
304 void CopyPositionProc P((Widget w, XEvent *event, String *prms,
306 void PastePositionProc P((Widget w, XEvent *event, String *prms,
308 void CopyGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
309 void PasteGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
310 void SaveGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
311 void SavePositionProc P((Widget w, XEvent *event,
312 String *prms, Cardinal *nprms));
313 void MailMoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
314 void ReloadCmailMsgProc P((Widget w, XEvent *event, String *prms,
316 void AnalyzeModeProc P((Widget w, XEvent *event,
317 String *prms, Cardinal *nprms));
318 void AnalyzeFileProc P((Widget w, XEvent *event,
319 String *prms, Cardinal *nprms));
320 void EditGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
321 void EditPositionProc P((Widget w, XEvent *event,
322 String *prms, Cardinal *nprms));
323 void TrainingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
324 void EditCommentProc P((Widget w, XEvent *event,
325 String *prms, Cardinal *nprms));
326 void IcsInputBoxProc P((Widget w, XEvent *event,
327 String *prms, Cardinal *nprms));
328 void EnterKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
329 void AlwaysQueenProc P((Widget w, XEvent *event, String *prms,
331 void AnimateDraggingProc P((Widget w, XEvent *event, String *prms,
333 void AnimateMovingProc P((Widget w, XEvent *event, String *prms,
335 void AutocommProc P((Widget w, XEvent *event, String *prms,
337 void AutoflagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
338 void AutoflipProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
339 void AutobsProc P((Widget w, XEvent *event, String *prms,
341 void AutoraiseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
342 void AutosaveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
343 void BlindfoldProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
344 void FlashMovesProc P((Widget w, XEvent *event, String *prms,
346 void HighlightDraggingProc P((Widget w, XEvent *event, String *prms,
348 void HighlightLastMoveProc P((Widget w, XEvent *event, String *prms,
350 void MoveSoundProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
351 void IcsAlarmProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
352 void OldSaveStyleProc P((Widget w, XEvent *event, String *prms,
354 void PeriodicUpdatesProc P((Widget w, XEvent *event, String *prms,
356 void PonderNextMoveProc P((Widget w, XEvent *event, String *prms,
358 void PopupMoveErrorsProc P((Widget w, XEvent *event, String *prms,
360 void PopupExitMessageProc P((Widget w, XEvent *event, String *prms,
362 void PremoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
363 void QuietPlayProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
364 void ShowThinkingProc P((Widget w, XEvent *event, String *prms,
366 void HideThinkingProc P((Widget w, XEvent *event, String *prms,
368 void TestLegalityProc P((Widget w, XEvent *event, String *prms,
370 void AboutGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
371 void DebugProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
372 void NothingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
373 void Iconify P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
374 void DisplayMove P((int moveNumber));
375 void DisplayTitle P((char *title));
376 void ICSInitScript P((void));
377 int LoadGamePopUp P((FILE *f, int gameNumber, char *title));
378 void ErrorPopUp P((char *title, char *text, int modal));
379 void ErrorPopDown P((void));
380 static char *ExpandPathName P((char *path));
381 static void CreateAnimVars P((void));
382 void DragPieceBegin P((int x, int y));
383 static void DragPieceMove P((int x, int y));
384 void DragPieceEnd P((int x, int y));
385 static void DrawDragPiece P((void));
386 char *ModeToWidgetName P((GameMode mode));
387 void EngineOutputUpdate( FrontEndProgramStats * stats );
388 void ShuffleMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
389 void EngineMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
390 void UciMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
391 void TimeControlProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
392 void NewVariantProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
393 void FirstSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
394 void SecondSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
395 void ShufflePopDown P(());
396 void EnginePopDown P(());
397 void UciPopDown P(());
398 void TimeControlPopDown P(());
399 void NewVariantPopDown P(());
400 void SettingsPopDown P(());
401 void SetMenuEnables P((Enables *enab));
404 * XBoard depends on Xt R4 or higher
406 int xtVersion = XtSpecificationRelease;
411 Pixel lightSquareColor, darkSquareColor, whitePieceColor, blackPieceColor,
412 jailSquareColor, highlightSquareColor, premoveHighlightColor;
413 Pixel lowTimeWarningColor;
415 #define LINE_TYPE_NORMAL 0
416 #define LINE_TYPE_HIGHLIGHT 1
417 #define LINE_TYPE_PRE 2
420 GC lightSquareGC, darkSquareGC, jailSquareGC, wdPieceGC, wlPieceGC,
421 bdPieceGC, blPieceGC, wbPieceGC, bwPieceGC, coordGC,
422 wjPieceGC, bjPieceGC;
423 Pixmap iconPixmap, wIconPixmap, bIconPixmap, xMarkPixmap;
424 Widget shellWidget, layoutWidget, formWidget, boardWidget, messageWidget,
425 whiteTimerWidget, blackTimerWidget, titleWidget, widgetList[16],
426 commentShell, promotionShell, whitePieceMenu, blackPieceMenu, dropMenu,
427 menuBarWidget, buttonBarWidget, editShell, errorShell, analysisShell,
428 ICSInputShell, fileNameShell, askQuestionShell;
429 Font clockFontID, coordFontID, countFontID;
430 XFontStruct *clockFontStruct, *coordFontStruct, *countFontStruct;
431 XtAppContext appContext;
433 char *oldICSInteractionTitle;
437 char installDir[] = "."; // [HGM] UCI: needed for UCI; probably needs run-time initializtion
439 Position commentX = -1, commentY = -1;
440 Dimension commentW, commentH;
442 int squareSize, smallLayout = 0, tinyLayout = 0,
443 marginW, marginH, // [HGM] for run-time resizing
444 fromX = -1, fromY = -1, toX, toY, commentUp = False, analysisUp = False,
445 ICSInputBoxUp = False, askQuestionUp = False,
446 filenameUp = False, promotionUp = False, pmFromX = -1, pmFromY = -1,
447 editUp = False, errorUp = False, errorExitStatus = -1, lineGap;
448 Pixel timerForegroundPixel, timerBackgroundPixel;
449 Pixel buttonForegroundPixel, buttonBackgroundPixel;
450 char *chessDir, *programName, *programVersion,
451 *gameCopyFilename, *gamePasteFilename;
455 Pixmap pieceBitmap[2][(int)BlackPawn];
456 Pixmap pieceBitmap2[2][(int)BlackPawn+4]; /* [HGM] pieces */
457 Pixmap xpmPieceBitmap[4][(int)BlackPawn]; /* LL, LD, DL, DD actually used*/
458 Pixmap xpmPieceBitmap2[4][(int)BlackPawn+4]; /* LL, LD, DL, DD set to select from */
459 Pixmap xpmLightSquare, xpmDarkSquare, xpmJailSquare;
460 int useImages=0, useImageSqs;
461 XImage *ximPieceBitmap[4][(int)BlackPawn+4]; /* LL, LD, DL, DD */
462 Pixmap ximMaskPm[(int)BlackPawn]; /* clipmasks, used for XIM pieces */
463 Pixmap ximMaskPm2[(int)BlackPawn+4]; /* clipmasks, used for XIM pieces */
464 XImage *ximLightSquare, *ximDarkSquare;
467 #define pieceToSolid(piece) &pieceBitmap[SOLID][(piece) % (int)BlackPawn]
468 #define pieceToOutline(piece) &pieceBitmap[OUTLINE][(piece) % (int)BlackPawn]
470 #define White(piece) ((int)(piece) < (int)BlackPawn)
472 /* Variables for doing smooth animation. This whole thing
473 would be much easier if the board was double-buffered,
474 but that would require a fairly major rewrite. */
479 GC blitGC, pieceGC, outlineGC;
480 XPoint startSquare, prevFrame, mouseDelta;
484 int startBoardX, startBoardY;
487 /* There can be two pieces being animated at once: a player
488 can begin dragging a piece before the remote opponent has moved. */
490 static AnimState game, player;
492 /* Bitmaps for use as masks when drawing XPM pieces.
493 Need one for each black and white piece. */
494 static Pixmap xpmMask[BlackKing + 1];
496 /* This magic number is the number of intermediate frames used
497 in each half of the animation. For short moves it's reduced
498 by 1. The total number of frames will be factor * 2 + 1. */
501 SizeDefaults sizeDefaults[] = SIZE_DEFAULTS;
503 Enables icsEnables[] = {
504 { "menuFile.Mail Move", False },
505 { "menuFile.Reload CMail Message", False },
506 { "menuMode.Machine Black", False },
507 { "menuMode.Machine White", False },
508 { "menuMode.Analysis Mode", False },
509 { "menuMode.Analyze File", False },
510 { "menuMode.Two Machines", False },
512 { "menuHelp.Hint", False },
513 { "menuHelp.Book", False },
514 { "menuStep.Move Now", False },
515 { "menuOptions.Periodic Updates", False },
516 { "menuOptions.Hide Thinking", False },
517 { "menuOptions.Ponder Next Move", False },
522 Enables ncpEnables[] = {
523 { "menuFile.Mail Move", False },
524 { "menuFile.Reload CMail Message", False },
525 { "menuMode.Machine White", False },
526 { "menuMode.Machine Black", False },
527 { "menuMode.Analysis Mode", False },
528 { "menuMode.Analyze File", False },
529 { "menuMode.Two Machines", False },
530 { "menuMode.ICS Client", False },
531 { "menuMode.ICS Input Box", False },
533 { "menuStep.Revert", False },
534 { "menuStep.Move Now", False },
535 { "menuStep.Retract Move", False },
536 { "menuOptions.Auto Comment", False },
537 { "menuOptions.Auto Flag", False },
538 { "menuOptions.Auto Flip View", False },
539 { "menuOptions.Auto Observe", False },
540 { "menuOptions.Auto Raise Board", False },
541 { "menuOptions.Get Move List", False },
542 { "menuOptions.ICS Alarm", False },
543 { "menuOptions.Move Sound", False },
544 { "menuOptions.Quiet Play", False },
545 { "menuOptions.Hide Thinking", False },
546 { "menuOptions.Periodic Updates", False },
547 { "menuOptions.Ponder Next Move", False },
548 { "menuHelp.Hint", False },
549 { "menuHelp.Book", False },
553 Enables gnuEnables[] = {
554 { "menuMode.ICS Client", False },
555 { "menuMode.ICS Input Box", False },
556 { "menuAction.Accept", False },
557 { "menuAction.Decline", False },
558 { "menuAction.Rematch", False },
559 { "menuAction.Adjourn", False },
560 { "menuAction.Stop Examining", False },
561 { "menuAction.Stop Observing", False },
562 { "menuStep.Revert", False },
563 { "menuOptions.Auto Comment", False },
564 { "menuOptions.Auto Observe", False },
565 { "menuOptions.Auto Raise Board", False },
566 { "menuOptions.Get Move List", False },
567 { "menuOptions.Premove", False },
568 { "menuOptions.Quiet Play", False },
570 /* The next two options rely on SetCmailMode being called *after* */
571 /* SetGNUMode so that when GNU is being used to give hints these */
572 /* menu options are still available */
574 { "menuFile.Mail Move", False },
575 { "menuFile.Reload CMail Message", False },
579 Enables cmailEnables[] = {
581 { "menuAction.Call Flag", False },
582 { "menuAction.Draw", True },
583 { "menuAction.Adjourn", False },
584 { "menuAction.Abort", False },
585 { "menuAction.Stop Observing", False },
586 { "menuAction.Stop Examining", False },
587 { "menuFile.Mail Move", True },
588 { "menuFile.Reload CMail Message", True },
592 Enables trainingOnEnables[] = {
593 { "menuMode.Edit Comment", False },
594 { "menuMode.Pause", False },
595 { "menuStep.Forward", False },
596 { "menuStep.Backward", False },
597 { "menuStep.Forward to End", False },
598 { "menuStep.Back to Start", False },
599 { "menuStep.Move Now", False },
600 { "menuStep.Truncate Game", False },
604 Enables trainingOffEnables[] = {
605 { "menuMode.Edit Comment", True },
606 { "menuMode.Pause", True },
607 { "menuStep.Forward", True },
608 { "menuStep.Backward", True },
609 { "menuStep.Forward to End", True },
610 { "menuStep.Back to Start", True },
611 { "menuStep.Move Now", True },
612 { "menuStep.Truncate Game", True },
616 Enables machineThinkingEnables[] = {
617 { "menuFile.Load Game", False },
618 { "menuFile.Load Next Game", False },
619 { "menuFile.Load Previous Game", False },
620 { "menuFile.Reload Same Game", False },
621 { "menuFile.Paste Game", False },
622 { "menuFile.Load Position", False },
623 { "menuFile.Load Next Position", False },
624 { "menuFile.Load Previous Position", False },
625 { "menuFile.Reload Same Position", False },
626 { "menuFile.Paste Position", False },
627 { "menuMode.Machine White", False },
628 { "menuMode.Machine Black", False },
629 { "menuMode.Two Machines", False },
630 { "menuStep.Retract Move", False },
634 Enables userThinkingEnables[] = {
635 { "menuFile.Load Game", True },
636 { "menuFile.Load Next Game", True },
637 { "menuFile.Load Previous Game", True },
638 { "menuFile.Reload Same Game", True },
639 { "menuFile.Paste Game", True },
640 { "menuFile.Load Position", True },
641 { "menuFile.Load Next Position", True },
642 { "menuFile.Load Previous Position", True },
643 { "menuFile.Reload Same Position", True },
644 { "menuFile.Paste Position", True },
645 { "menuMode.Machine White", True },
646 { "menuMode.Machine Black", True },
647 { "menuMode.Two Machines", True },
648 { "menuStep.Retract Move", True },
654 MenuItem fileMenu[] = {
655 {N_("New Shuffle Game ..."), ShuffleMenuProc},
656 {N_("New Variant ..."), NewVariantProc}, // [HGM] variant: not functional yet
657 {"----", NothingProc},
658 {N_("Save Game"), SaveGameProc},
659 {"----", NothingProc},
660 {N_("Copy Game"), CopyGameProc},
661 {N_("Paste Game"), PasteGameProc},
662 {"----", NothingProc},
663 {N_("Load Position"), LoadPositionProc},
664 {N_("Load Next Position"), LoadNextPositionProc},
665 {N_("Load Previous Position"), LoadPrevPositionProc},
666 {N_("Reload Same Position"), ReloadPositionProc},
667 {N_("Save Position"), SavePositionProc},
668 {"----", NothingProc},
669 {N_("Copy Position"), CopyPositionProc},
670 {N_("Paste Position"), PastePositionProc},
671 {"----", NothingProc},
672 {N_("Mail Move"), MailMoveProc},
673 {N_("Reload CMail Message"), ReloadCmailMsgProc},
674 {"----", NothingProc},
678 MenuItem modeMenu[] = {
679 // {N_("Machine White"), MachineWhiteProc},
680 // {N_("Machine Black"), MachineBlackProc},
681 // {N_("Two Machines"), TwoMachinesProc},
682 {N_("Analysis Mode"), AnalyzeModeProc},
683 {N_("Analyze File"), AnalyzeFileProc },
684 // {N_("ICS Client"), IcsClientProc},
685 {N_("Edit Game"), EditGameProc},
686 {N_("Edit Position"), EditPositionProc},
687 {N_("Training"), TrainingProc},
688 {"----", NothingProc},
689 {N_("Show Engine Output"), EngineOutputProc},
690 {N_("Show Evaluation Graph"), NothingProc}, // [HGM] evalgr: not functional yet
691 {N_("Show Game List"), ShowGameListProc},
692 // {"Show Move History", HistoryShowProc}, // [HGM] hist: activate 4.2.7 code
693 {"----", NothingProc},
694 {N_("Edit Tags"), EditTagsProc},
695 {N_("Edit Comment"), EditCommentProc},
696 {N_("ICS Input Box"), IcsInputBoxProc},
700 MenuItem optionsMenu[] = {
701 // {N_("Flip View"), FlipViewProc},
702 // {"----", NothingProc},
703 {N_("Adjudications ..."), EngineMenuProc},
704 {N_("General Settings ..."), UciMenuProc},
705 {N_("Engine #1 Settings ..."), FirstSettingsProc},
706 {N_("Engine #2 Settings ..."), SecondSettingsProc},
707 {N_("Time Control ..."), TimeControlProc},
708 {"----", NothingProc},
709 {N_("Always Queen"), AlwaysQueenProc},
710 {N_("Animate Dragging"), AnimateDraggingProc},
711 {N_("Animate Moving"), AnimateMovingProc},
712 {N_("Auto Comment"), AutocommProc},
713 {N_("Auto Flag"), AutoflagProc},
714 {N_("Auto Flip View"), AutoflipProc},
715 {N_("Auto Observe"), AutobsProc},
716 {N_("Auto Raise Board"), AutoraiseProc},
717 {N_("Auto Save"), AutosaveProc},
718 {N_("Blindfold"), BlindfoldProc},
719 {N_("Flash Moves"), FlashMovesProc},
720 // {N_("Get Move List"), GetMoveListProc},
722 {N_("Highlight Dragging"), HighlightDraggingProc},
724 {N_("Highlight Last Move"), HighlightLastMoveProc},
725 {N_("Move Sound"), MoveSoundProc},
726 {N_("ICS Alarm"), IcsAlarmProc},
727 {N_("Old Save Style"), OldSaveStyleProc},
728 {N_("Periodic Updates"), PeriodicUpdatesProc},
729 {N_("Ponder Next Move"), PonderNextMoveProc},
730 {N_("Popup Exit Message"), PopupExitMessageProc},
731 {N_("Popup Move Errors"), PopupMoveErrorsProc},
732 {N_("Premove"), PremoveProc},
733 {N_("Quiet Play"), QuietPlayProc},
734 {N_("Hide Thinking"), HideThinkingProc},
735 {N_("Test Legality"), TestLegalityProc},
740 {N_("File"), fileMenu},
741 {N_("Mode"), modeMenu},
742 {N_("Options"), optionsMenu},
746 #define PAUSE_BUTTON N_("P")
747 MenuItem buttonBar[] = {
748 // {"<<", ToStartProc},
749 // {"<", BackwardProc},
750 // {PAUSE_BUTTON, PauseProc},
751 // {">", ForwardProc},
752 // {">>", ToEndProc},
756 #define PIECE_MENU_SIZE 18
757 String pieceMenuStrings[2][PIECE_MENU_SIZE] = {
758 { N_("White"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
759 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
760 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
761 N_("Empty square"), N_("Clear board") },
762 { N_("Black"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
763 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
764 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
765 N_("Empty square"), N_("Clear board") }
767 /* must be in same order as PieceMenuStrings! */
768 ChessSquare pieceMenuTranslation[2][PIECE_MENU_SIZE] = {
769 { WhitePlay, (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
770 WhiteRook, WhiteQueen, WhiteKing, (ChessSquare) 0, WhiteAlfil,
771 WhiteCannon, WhiteAngel, WhiteMarshall, (ChessSquare) 0,
772 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
773 { BlackPlay, (ChessSquare) 0, BlackPawn, BlackKnight, BlackBishop,
774 BlackRook, BlackQueen, BlackKing, (ChessSquare) 0, BlackAlfil,
775 BlackCannon, BlackAngel, BlackMarshall, (ChessSquare) 0,
776 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
779 #define DROP_MENU_SIZE 6
780 String dropMenuStrings[DROP_MENU_SIZE] = {
781 "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"), N_("Queen")
783 /* must be in same order as PieceMenuStrings! */
784 ChessSquare dropMenuTranslation[DROP_MENU_SIZE] = {
785 (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
786 WhiteRook, WhiteQueen
794 DropMenuEnables dmEnables[] = {
803 { XtNborderWidth, 0 },
804 { XtNdefaultDistance, 0 },
808 { XtNborderWidth, 0 },
809 { XtNresizable, (XtArgVal) True },
813 { XtNborderWidth, 0 },
818 XtResource clientResources[] = {
819 { "whitePieceColor", "whitePieceColor", XtRString, sizeof(String),
820 XtOffset(AppDataPtr, whitePieceColor), XtRString,
822 { "blackPieceColor", "blackPieceColor", XtRString, sizeof(String),
823 XtOffset(AppDataPtr, blackPieceColor), XtRString,
825 { "lightSquareColor", "lightSquareColor", XtRString,
826 sizeof(String), XtOffset(AppDataPtr, lightSquareColor),
827 XtRString, LIGHT_SQUARE_COLOR },
828 { "darkSquareColor", "darkSquareColor", XtRString, sizeof(String),
829 XtOffset(AppDataPtr, darkSquareColor), XtRString,
831 { "highlightSquareColor", "highlightSquareColor", XtRString,
832 sizeof(String), XtOffset(AppDataPtr, highlightSquareColor),
833 XtRString, HIGHLIGHT_SQUARE_COLOR },
834 { "premoveHighlightColor", "premoveHighlightColor", XtRString,
835 sizeof(String), XtOffset(AppDataPtr, premoveHighlightColor),
836 XtRString, PREMOVE_HIGHLIGHT_COLOR },
837 { "movesPerSession", "movesPerSession", XtRInt, sizeof(int),
838 XtOffset(AppDataPtr, movesPerSession), XtRImmediate,
839 (XtPointer) MOVES_PER_SESSION },
840 { "timeIncrement", "timeIncrement", XtRInt, sizeof(int),
841 XtOffset(AppDataPtr, timeIncrement), XtRImmediate,
842 (XtPointer) TIME_INCREMENT },
843 { "initString", "initString", XtRString, sizeof(String),
844 XtOffset(AppDataPtr, initString), XtRString, INIT_STRING },
845 { "secondInitString", "secondInitString", XtRString, sizeof(String),
846 XtOffset(AppDataPtr, secondInitString), XtRString, INIT_STRING },
847 { "firstComputerString", "firstComputerString", XtRString,
848 sizeof(String), XtOffset(AppDataPtr, firstComputerString), XtRString,
850 { "secondComputerString", "secondComputerString", XtRString,
851 sizeof(String), XtOffset(AppDataPtr, secondComputerString), XtRString,
853 { "firstChessProgram", "firstChessProgram", XtRString,
854 sizeof(String), XtOffset(AppDataPtr, firstChessProgram),
855 XtRString, FIRST_CHESS_PROGRAM },
856 { "secondChessProgram", "secondChessProgram", XtRString,
857 sizeof(String), XtOffset(AppDataPtr, secondChessProgram),
858 XtRString, SECOND_CHESS_PROGRAM },
859 { "firstPlaysBlack", "firstPlaysBlack", XtRBoolean,
860 sizeof(Boolean), XtOffset(AppDataPtr, firstPlaysBlack),
861 XtRImmediate, (XtPointer) False },
862 { "noChessProgram", "noChessProgram", XtRBoolean,
863 sizeof(Boolean), XtOffset(AppDataPtr, noChessProgram),
864 XtRImmediate, (XtPointer) False },
865 { "firstHost", "firstHost", XtRString, sizeof(String),
866 XtOffset(AppDataPtr, firstHost), XtRString, FIRST_HOST },
867 { "secondHost", "secondHost", XtRString, sizeof(String),
868 XtOffset(AppDataPtr, secondHost), XtRString, SECOND_HOST },
869 { "firstDirectory", "firstDirectory", XtRString, sizeof(String),
870 XtOffset(AppDataPtr, firstDirectory), XtRString, "." },
871 { "secondDirectory", "secondDirectory", XtRString, sizeof(String),
872 XtOffset(AppDataPtr, secondDirectory), XtRString, "." },
873 { "bitmapDirectory", "bitmapDirectory", XtRString,
874 sizeof(String), XtOffset(AppDataPtr, bitmapDirectory),
876 { "remoteShell", "remoteShell", XtRString, sizeof(String),
877 XtOffset(AppDataPtr, remoteShell), XtRString, REMOTE_SHELL },
878 { "remoteUser", "remoteUser", XtRString, sizeof(String),
879 XtOffset(AppDataPtr, remoteUser), XtRString, "" },
880 { "timeDelay", "timeDelay", XtRFloat, sizeof(float),
881 XtOffset(AppDataPtr, timeDelay), XtRString,
882 (XtPointer) TIME_DELAY_QUOTE },
883 { "timeControl", "timeControl", XtRString, sizeof(String),
884 XtOffset(AppDataPtr, timeControl), XtRString,
885 (XtPointer) TIME_CONTROL },
886 { "internetChessServerMode", "internetChessServerMode",
887 XtRBoolean, sizeof(Boolean),
888 XtOffset(AppDataPtr, icsActive), XtRImmediate,
890 { "internetChessServerHost", "internetChessServerHost",
891 XtRString, sizeof(String),
892 XtOffset(AppDataPtr, icsHost),
893 XtRString, (XtPointer) ICS_HOST },
894 { "internetChessServerPort", "internetChessServerPort",
895 XtRString, sizeof(String),
896 XtOffset(AppDataPtr, icsPort), XtRString,
897 (XtPointer) ICS_PORT },
898 { "internetChessServerCommPort", "internetChessServerCommPort",
899 XtRString, sizeof(String),
900 XtOffset(AppDataPtr, icsCommPort), XtRString,
902 { "internetChessServerLogonScript", "internetChessServerLogonScript",
903 XtRString, sizeof(String),
904 XtOffset(AppDataPtr, icsLogon), XtRString,
906 { "internetChessServerHelper", "internetChessServerHelper",
907 XtRString, sizeof(String),
908 XtOffset(AppDataPtr, icsHelper), XtRString, "" },
909 { "internetChessServerInputBox", "internetChessServerInputBox",
910 XtRBoolean, sizeof(Boolean),
911 XtOffset(AppDataPtr, icsInputBox), XtRImmediate,
913 { "icsAlarm", "icsAlarm",
914 XtRBoolean, sizeof(Boolean),
915 XtOffset(AppDataPtr, icsAlarm), XtRImmediate,
917 { "icsAlarmTime", "icsAlarmTime",
919 XtOffset(AppDataPtr, icsAlarmTime), XtRImmediate,
921 { "useTelnet", "useTelnet", XtRBoolean, sizeof(Boolean),
922 XtOffset(AppDataPtr, useTelnet), XtRImmediate,
924 { "telnetProgram", "telnetProgram", XtRString, sizeof(String),
925 XtOffset(AppDataPtr, telnetProgram), XtRString, TELNET_PROGRAM },
926 { "gateway", "gateway", XtRString, sizeof(String),
927 XtOffset(AppDataPtr, gateway), XtRString, "" },
928 { "loadGameFile", "loadGameFile", XtRString, sizeof(String),
929 XtOffset(AppDataPtr, loadGameFile), XtRString, "" },
930 { "loadGameIndex", "loadGameIndex",
932 XtOffset(AppDataPtr, loadGameIndex), XtRImmediate,
934 { "saveGameFile", "saveGameFile", XtRString, sizeof(String),
935 XtOffset(AppDataPtr, saveGameFile), XtRString, "" },
936 { "autoRaiseBoard", "autoRaiseBoard", XtRBoolean,
937 sizeof(Boolean), XtOffset(AppDataPtr, autoRaiseBoard),
938 XtRImmediate, (XtPointer) True },
939 { "autoSaveGames", "autoSaveGames", XtRBoolean,
940 sizeof(Boolean), XtOffset(AppDataPtr, autoSaveGames),
941 XtRImmediate, (XtPointer) False },
942 { "blindfold", "blindfold", XtRBoolean,
943 sizeof(Boolean), XtOffset(AppDataPtr, blindfold),
944 XtRImmediate, (XtPointer) False },
945 { "loadPositionFile", "loadPositionFile", XtRString,
946 sizeof(String), XtOffset(AppDataPtr, loadPositionFile),
948 { "loadPositionIndex", "loadPositionIndex",
950 XtOffset(AppDataPtr, loadPositionIndex), XtRImmediate,
952 { "savePositionFile", "savePositionFile", XtRString,
953 sizeof(String), XtOffset(AppDataPtr, savePositionFile),
955 { "matchMode", "matchMode", XtRBoolean, sizeof(Boolean),
956 XtOffset(AppDataPtr, matchMode), XtRImmediate, (XtPointer) False },
957 { "matchGames", "matchGames", XtRInt, sizeof(int),
958 XtOffset(AppDataPtr, matchGames), XtRImmediate,
960 { "monoMode", "monoMode", XtRBoolean, sizeof(Boolean),
961 XtOffset(AppDataPtr, monoMode), XtRImmediate,
963 { "debugMode", "debugMode", XtRBoolean, sizeof(Boolean),
964 XtOffset(AppDataPtr, debugMode), XtRImmediate,
966 { "clockMode", "clockMode", XtRBoolean, sizeof(Boolean),
967 XtOffset(AppDataPtr, clockMode), XtRImmediate,
969 { "boardSize", "boardSize", XtRString, sizeof(String),
970 XtOffset(AppDataPtr, boardSize), XtRString, "" },
971 { "searchTime", "searchTime", XtRString, sizeof(String),
972 XtOffset(AppDataPtr, searchTime), XtRString,
974 { "searchDepth", "searchDepth", XtRInt, sizeof(int),
975 XtOffset(AppDataPtr, searchDepth), XtRImmediate,
977 { "showCoords", "showCoords", XtRBoolean, sizeof(Boolean),
978 XtOffset(AppDataPtr, showCoords), XtRImmediate,
980 { "showJail", "showJail", XtRInt, sizeof(int),
981 XtOffset(AppDataPtr, showJail), XtRImmediate,
983 { "showThinking", "showThinking", XtRBoolean, sizeof(Boolean),
984 XtOffset(AppDataPtr, showThinking), XtRImmediate,
986 { "ponderNextMove", "ponderNextMove", XtRBoolean, sizeof(Boolean),
987 XtOffset(AppDataPtr, ponderNextMove), XtRImmediate,
989 { "periodicUpdates", "periodicUpdates", XtRBoolean, sizeof(Boolean),
990 XtOffset(AppDataPtr, periodicUpdates), XtRImmediate,
992 { "clockFont", "clockFont", XtRString, sizeof(String),
993 XtOffset(AppDataPtr, clockFont), XtRString, CLOCK_FONT },
994 { "coordFont", "coordFont", XtRString, sizeof(String),
995 XtOffset(AppDataPtr, coordFont), XtRString, COORD_FONT },
996 { "font", "font", XtRString, sizeof(String),
997 XtOffset(AppDataPtr, font), XtRString, DEFAULT_FONT },
998 { "ringBellAfterMoves", "ringBellAfterMoves",
999 XtRBoolean, sizeof(Boolean),
1000 XtOffset(AppDataPtr, ringBellAfterMoves),
1001 XtRImmediate, (XtPointer) False },
1002 { "autoCallFlag", "autoCallFlag", XtRBoolean,
1003 sizeof(Boolean), XtOffset(AppDataPtr, autoCallFlag),
1004 XtRImmediate, (XtPointer) False },
1005 { "autoFlipView", "autoFlipView", XtRBoolean,
1006 sizeof(Boolean), XtOffset(AppDataPtr, autoFlipView),
1007 XtRImmediate, (XtPointer) True },
1008 { "autoObserve", "autoObserve", XtRBoolean,
1009 sizeof(Boolean), XtOffset(AppDataPtr, autoObserve),
1010 XtRImmediate, (XtPointer) False },
1011 { "autoComment", "autoComment", XtRBoolean,
1012 sizeof(Boolean), XtOffset(AppDataPtr, autoComment),
1013 XtRImmediate, (XtPointer) False },
1014 { "getMoveList", "getMoveList", XtRBoolean,
1015 sizeof(Boolean), XtOffset(AppDataPtr, getMoveList),
1016 XtRImmediate, (XtPointer) True },
1018 { "highlightDragging", "highlightDragging", XtRBoolean,
1019 sizeof(Boolean), XtOffset(AppDataPtr, highlightDragging),
1020 XtRImmediate, (XtPointer) False },
1022 { "highlightLastMove", "highlightLastMove", XtRBoolean,
1023 sizeof(Boolean), XtOffset(AppDataPtr, highlightLastMove),
1024 XtRImmediate, (XtPointer) False },
1025 { "premove", "premove", XtRBoolean,
1026 sizeof(Boolean), XtOffset(AppDataPtr, premove),
1027 XtRImmediate, (XtPointer) True },
1028 { "testLegality", "testLegality", XtRBoolean,
1029 sizeof(Boolean), XtOffset(AppDataPtr, testLegality),
1030 XtRImmediate, (XtPointer) True },
1031 { "flipView", "flipView", XtRBoolean,
1032 sizeof(Boolean), XtOffset(AppDataPtr, flipView),
1033 XtRImmediate, (XtPointer) False },
1034 { "cmail", "cmailGameName", XtRString, sizeof(String),
1035 XtOffset(AppDataPtr, cmailGameName), XtRString, "" },
1036 { "alwaysPromoteToQueen", "alwaysPromoteToQueen", XtRBoolean,
1037 sizeof(Boolean), XtOffset(AppDataPtr, alwaysPromoteToQueen),
1038 XtRImmediate, (XtPointer) False },
1039 { "oldSaveStyle", "oldSaveStyle", XtRBoolean,
1040 sizeof(Boolean), XtOffset(AppDataPtr, oldSaveStyle),
1041 XtRImmediate, (XtPointer) False },
1042 { "quietPlay", "quietPlay", XtRBoolean,
1043 sizeof(Boolean), XtOffset(AppDataPtr, quietPlay),
1044 XtRImmediate, (XtPointer) False },
1045 { "titleInWindow", "titleInWindow", XtRBoolean,
1046 sizeof(Boolean), XtOffset(AppDataPtr, titleInWindow),
1047 XtRImmediate, (XtPointer) False },
1048 { "localLineEditing", "localLineEditing", XtRBoolean,
1049 sizeof(Boolean), XtOffset(AppDataPtr, localLineEditing),
1050 XtRImmediate, (XtPointer) True }, /* not implemented, must be True */
1052 { "zippyTalk", "zippyTalk", XtRBoolean,
1053 sizeof(Boolean), XtOffset(AppDataPtr, zippyTalk),
1054 XtRImmediate, (XtPointer) ZIPPY_TALK },
1055 { "zippyPlay", "zippyPlay", XtRBoolean,
1056 sizeof(Boolean), XtOffset(AppDataPtr, zippyPlay),
1057 XtRImmediate, (XtPointer) ZIPPY_PLAY },
1058 { "zippyLines", "zippyLines", XtRString, sizeof(String),
1059 XtOffset(AppDataPtr, zippyLines), XtRString, ZIPPY_LINES },
1060 { "zippyPinhead", "zippyPinhead", XtRString, sizeof(String),
1061 XtOffset(AppDataPtr, zippyPinhead), XtRString, ZIPPY_PINHEAD },
1062 { "zippyPassword", "zippyPassword", XtRString, sizeof(String),
1063 XtOffset(AppDataPtr, zippyPassword), XtRString, ZIPPY_PASSWORD },
1064 { "zippyPassword2", "zippyPassword2", XtRString, sizeof(String),
1065 XtOffset(AppDataPtr, zippyPassword2), XtRString, ZIPPY_PASSWORD2 },
1066 { "zippyWrongPassword", "zippyWrongPassword", XtRString, sizeof(String),
1067 XtOffset(AppDataPtr, zippyWrongPassword), XtRString,
1068 ZIPPY_WRONG_PASSWORD },
1069 { "zippyAcceptOnly", "zippyAcceptOnly", XtRString, sizeof(String),
1070 XtOffset(AppDataPtr, zippyAcceptOnly), XtRString, ZIPPY_ACCEPT_ONLY },
1071 { "zippyUseI", "zippyUseI", XtRBoolean,
1072 sizeof(Boolean), XtOffset(AppDataPtr, zippyUseI),
1073 XtRImmediate, (XtPointer) ZIPPY_USE_I },
1074 { "zippyBughouse", "zippyBughouse", XtRInt,
1075 sizeof(int), XtOffset(AppDataPtr, zippyBughouse),
1076 XtRImmediate, (XtPointer) ZIPPY_BUGHOUSE },
1077 { "zippyNoplayCrafty", "zippyNoplayCrafty", XtRBoolean,
1078 sizeof(Boolean), XtOffset(AppDataPtr, zippyNoplayCrafty),
1079 XtRImmediate, (XtPointer) ZIPPY_NOPLAY_CRAFTY },
1080 { "zippyGameEnd", "zippyGameEnd", XtRString, sizeof(String),
1081 XtOffset(AppDataPtr, zippyGameEnd), XtRString, ZIPPY_GAME_END },
1082 { "zippyGameStart", "zippyGameStart", XtRString, sizeof(String),
1083 XtOffset(AppDataPtr, zippyGameStart), XtRString, ZIPPY_GAME_START },
1084 { "zippyAdjourn", "zippyAdjourn", XtRBoolean,
1085 sizeof(Boolean), XtOffset(AppDataPtr, zippyAdjourn),
1086 XtRImmediate, (XtPointer) ZIPPY_ADJOURN },
1087 { "zippyAbort", "zippyAbort", XtRBoolean,
1088 sizeof(Boolean), XtOffset(AppDataPtr, zippyAbort),
1089 XtRImmediate, (XtPointer) ZIPPY_ABORT },
1090 { "zippyVariants", "zippyVariants", XtRString, sizeof(String),
1091 XtOffset(AppDataPtr, zippyVariants), XtRString, ZIPPY_VARIANTS },
1092 { "zippyMaxGames", "zippyMaxGames", XtRInt, sizeof(int),
1093 XtOffset(AppDataPtr, zippyMaxGames), XtRImmediate,
1094 (XtPointer) ZIPPY_MAX_GAMES },
1095 { "zippyReplayTimeout", "zippyReplayTimeout", XtRInt, sizeof(int),
1096 XtOffset(AppDataPtr, zippyReplayTimeout), XtRImmediate,
1097 (XtPointer) ZIPPY_REPLAY_TIMEOUT },
1098 { "zippyShortGame", "zippyShortGame", XtRInt, sizeof(int),
1099 XtOffset(AppDataPtr, zippyShortGame), XtRImmediate,
1102 { "flashCount", "flashCount", XtRInt, sizeof(int),
1103 XtOffset(AppDataPtr, flashCount), XtRImmediate,
1104 (XtPointer) FLASH_COUNT },
1105 { "flashRate", "flashRate", XtRInt, sizeof(int),
1106 XtOffset(AppDataPtr, flashRate), XtRImmediate,
1107 (XtPointer) FLASH_RATE },
1108 { "pixmapDirectory", "pixmapDirectory", XtRString,
1109 sizeof(String), XtOffset(AppDataPtr, pixmapDirectory),
1111 { "msLoginDelay", "msLoginDelay", XtRInt, sizeof(int),
1112 XtOffset(AppDataPtr, msLoginDelay), XtRImmediate,
1113 (XtPointer) MS_LOGIN_DELAY },
1114 { "colorizeMessages", "colorizeMessages", XtRBoolean,
1115 sizeof(Boolean), XtOffset(AppDataPtr, colorize),
1116 XtRImmediate, (XtPointer) False },
1117 { "colorShout", "colorShout", XtRString,
1118 sizeof(String), XtOffset(AppDataPtr, colorShout),
1119 XtRString, COLOR_SHOUT },
1120 { "colorSShout", "colorSShout", XtRString,
1121 sizeof(String), XtOffset(AppDataPtr, colorSShout),
1122 XtRString, COLOR_SSHOUT },
1123 { "colorChannel1", "colorChannel1", XtRString,
1124 sizeof(String), XtOffset(AppDataPtr, colorChannel1),
1125 XtRString, COLOR_CHANNEL1 },
1126 { "colorChannel", "colorChannel", XtRString,
1127 sizeof(String), XtOffset(AppDataPtr, colorChannel),
1128 XtRString, COLOR_CHANNEL },
1129 { "colorKibitz", "colorKibitz", XtRString,
1130 sizeof(String), XtOffset(AppDataPtr, colorKibitz),
1131 XtRString, COLOR_KIBITZ },
1132 { "colorTell", "colorTell", XtRString,
1133 sizeof(String), XtOffset(AppDataPtr, colorTell),
1134 XtRString, COLOR_TELL },
1135 { "colorChallenge", "colorChallenge", XtRString,
1136 sizeof(String), XtOffset(AppDataPtr, colorChallenge),
1137 XtRString, COLOR_CHALLENGE },
1138 { "colorRequest", "colorRequest", XtRString,
1139 sizeof(String), XtOffset(AppDataPtr, colorRequest),
1140 XtRString, COLOR_REQUEST },
1141 { "colorSeek", "colorSeek", XtRString,
1142 sizeof(String), XtOffset(AppDataPtr, colorSeek),
1143 XtRString, COLOR_SEEK },
1144 { "colorNormal", "colorNormal", XtRString,
1145 sizeof(String), XtOffset(AppDataPtr, colorNormal),
1146 XtRString, COLOR_NORMAL },
1147 { "soundProgram", "soundProgram", XtRString,
1148 sizeof(String), XtOffset(AppDataPtr, soundProgram),
1149 XtRString, "play" },
1150 { "soundShout", "soundShout", XtRString,
1151 sizeof(String), XtOffset(AppDataPtr, soundShout),
1153 { "soundSShout", "soundSShout", XtRString,
1154 sizeof(String), XtOffset(AppDataPtr, soundSShout),
1156 { "soundChannel1", "soundChannel1", XtRString,
1157 sizeof(String), XtOffset(AppDataPtr, soundChannel1),
1159 { "soundChannel", "soundChannel", XtRString,
1160 sizeof(String), XtOffset(AppDataPtr, soundChannel),
1162 { "soundKibitz", "soundKibitz", XtRString,
1163 sizeof(String), XtOffset(AppDataPtr, soundKibitz),
1165 { "soundTell", "soundTell", XtRString,
1166 sizeof(String), XtOffset(AppDataPtr, soundTell),
1168 { "soundChallenge", "soundChallenge", XtRString,
1169 sizeof(String), XtOffset(AppDataPtr, soundChallenge),
1171 { "soundRequest", "soundRequest", XtRString,
1172 sizeof(String), XtOffset(AppDataPtr, soundRequest),
1174 { "soundSeek", "soundSeek", XtRString,
1175 sizeof(String), XtOffset(AppDataPtr, soundSeek),
1177 { "soundMove", "soundMove", XtRString,
1178 sizeof(String), XtOffset(AppDataPtr, soundMove),
1180 { "soundIcsWin", "soundIcsWin", XtRString,
1181 sizeof(String), XtOffset(AppDataPtr, soundIcsWin),
1183 { "soundIcsLoss", "soundIcsLoss", XtRString,
1184 sizeof(String), XtOffset(AppDataPtr, soundIcsLoss),
1186 { "soundIcsDraw", "soundIcsDraw", XtRString,
1187 sizeof(String), XtOffset(AppDataPtr, soundIcsDraw),
1189 { "soundIcsUnfinished", "soundIcsUnfinished", XtRString,
1190 sizeof(String), XtOffset(AppDataPtr, soundIcsUnfinished),
1192 { "soundIcsAlarm", "soundIcsAlarm", XtRString,
1193 sizeof(String), XtOffset(AppDataPtr, soundIcsAlarm),
1195 { "reuseFirst", "reuseFirst", XtRBoolean,
1196 sizeof(Boolean), XtOffset(AppDataPtr, reuseFirst),
1197 XtRImmediate, (XtPointer) True },
1198 { "reuseSecond", "reuseSecond", XtRBoolean,
1199 sizeof(Boolean), XtOffset(AppDataPtr, reuseSecond),
1200 XtRImmediate, (XtPointer) True },
1201 { "animateDragging", "animateDragging", XtRBoolean,
1202 sizeof(Boolean), XtOffset(AppDataPtr, animateDragging),
1203 XtRImmediate, (XtPointer) True },
1204 { "animateMoving", "animateMoving", XtRBoolean,
1205 sizeof(Boolean), XtOffset(AppDataPtr, animate),
1206 XtRImmediate, (XtPointer) True },
1207 { "animateSpeed", "animateSpeed", XtRInt,
1208 sizeof(int), XtOffset(AppDataPtr, animSpeed),
1209 XtRImmediate, (XtPointer)10 },
1210 { "popupExitMessage", "popupExitMessage", XtRBoolean,
1211 sizeof(Boolean), XtOffset(AppDataPtr, popupExitMessage),
1212 XtRImmediate, (XtPointer) True },
1213 { "popupMoveErrors", "popupMoveErrors", XtRBoolean,
1214 sizeof(Boolean), XtOffset(AppDataPtr, popupMoveErrors),
1215 XtRImmediate, (XtPointer) False },
1216 { "fontSizeTolerance", "fontSizeTolerance", XtRInt,
1217 sizeof(int), XtOffset(AppDataPtr, fontSizeTolerance),
1218 XtRImmediate, (XtPointer)4 },
1219 { "initialMode", "initialMode", XtRString,
1220 sizeof(String), XtOffset(AppDataPtr, initialMode),
1221 XtRImmediate, (XtPointer) "" },
1222 { "variant", "variant", XtRString,
1223 sizeof(String), XtOffset(AppDataPtr, variant),
1224 XtRImmediate, (XtPointer) "normal" },
1225 { "firstProtocolVersion", "firstProtocolVersion", XtRInt,
1226 sizeof(int), XtOffset(AppDataPtr, firstProtocolVersion),
1227 XtRImmediate, (XtPointer)PROTOVER },
1228 { "secondProtocolVersion", "secondProtocolVersion", XtRInt,
1229 sizeof(int), XtOffset(AppDataPtr, secondProtocolVersion),
1230 XtRImmediate, (XtPointer)PROTOVER },
1231 { "showButtonBar", "showButtonBar", XtRBoolean,
1232 sizeof(Boolean), XtOffset(AppDataPtr, showButtonBar),
1233 XtRImmediate, (XtPointer) True },
1234 { "lowTimeWarningColor", "lowTimeWarningColor", XtRString,
1235 sizeof(String), XtOffset(AppDataPtr, lowTimeWarningColor),
1236 XtRString, COLOR_LOWTIMEWARNING },
1237 { "lowTimeWarning", "lowTimeWarning", XtRBoolean,
1238 sizeof(Boolean), XtOffset(AppDataPtr, lowTimeWarning),
1239 XtRImmediate, (XtPointer) False },
1240 {"icsEngineAnalyze", "icsEngineAnalyze", XtRBoolean, /* [DM] icsEngineAnalyze */
1241 sizeof(Boolean), XtOffset(AppDataPtr, icsEngineAnalyze),
1242 XtRImmediate, (XtPointer) False },
1243 { "firstScoreAbs", "firstScoreAbs", XtRBoolean,
1244 sizeof(Boolean), XtOffset(AppDataPtr, firstScoreIsAbsolute),
1245 XtRImmediate, (XtPointer) False },
1246 { "secondScoreAbs", "secondScoreAbs", XtRBoolean,
1247 sizeof(Boolean), XtOffset(AppDataPtr, secondScoreIsAbsolute),
1248 XtRImmediate, (XtPointer) False },
1249 { "pgnExtendedInfo", "pgnExtendedInfo", XtRBoolean,
1250 sizeof(Boolean), XtOffset(AppDataPtr, saveExtendedInfoInPGN),
1251 XtRImmediate, (XtPointer) False },
1252 { "hideThinkingFromHuman", "hideThinkingFromHuman", XtRBoolean,
1253 sizeof(Boolean), XtOffset(AppDataPtr, hideThinkingFromHuman),
1254 XtRImmediate, (XtPointer) True },
1255 { "adjudicateLossThreshold", "adjudicateLossThreshold", XtRInt,
1256 sizeof(int), XtOffset(AppDataPtr, adjudicateLossThreshold),
1257 XtRImmediate, (XtPointer) 0},
1258 { "adjudicateDrawMoves", "adjudicateDrawMoves", XtRInt,
1259 sizeof(int), XtOffset(AppDataPtr, adjudicateDrawMoves),
1260 XtRImmediate, (XtPointer) 0},
1261 { "pgnEventHeader", "pgnEventHeader", XtRString,
1262 sizeof(String), XtOffset(AppDataPtr, pgnEventHeader),
1263 XtRImmediate, (XtPointer) "Computer Chess Game" },
1264 { "defaultFrcPosition", "defaultFrcPositon", XtRInt,
1265 sizeof(int), XtOffset(AppDataPtr, defaultFrcPosition),
1266 XtRImmediate, (XtPointer) -1},
1267 { "gameListTags", "gameListTags", XtRString,
1268 sizeof(String), XtOffset(AppDataPtr, gameListTags),
1269 XtRImmediate, (XtPointer) GLT_DEFAULT_TAGS },
1271 // [HGM] 4.3.xx options
1272 { "boardWidth", "boardWidth", XtRInt,
1273 sizeof(int), XtOffset(AppDataPtr, NrFiles),
1274 XtRImmediate, (XtPointer) -1},
1275 { "boardHeight", "boardHeight", XtRInt,
1276 sizeof(int), XtOffset(AppDataPtr, NrRanks),
1277 XtRImmediate, (XtPointer) -1},
1278 { "matchPause", "matchPause", XtRInt,
1279 sizeof(int), XtOffset(AppDataPtr, matchPause),
1280 XtRImmediate, (XtPointer) 10000},
1281 { "holdingsSize", "holdingsSize", XtRInt,
1282 sizeof(int), XtOffset(AppDataPtr, holdingsSize),
1283 XtRImmediate, (XtPointer) -1},
1284 { "flipBlack", "flipBlack", XtRBoolean,
1285 sizeof(Boolean), XtOffset(AppDataPtr, upsideDown),
1286 XtRImmediate, (XtPointer) False},
1287 { "allWhite", "allWhite", XtRBoolean,
1288 sizeof(Boolean), XtOffset(AppDataPtr, allWhite),
1289 XtRImmediate, (XtPointer) False},
1290 { "pieceToCharTable", "pieceToCharTable", XtRString,
1291 sizeof(String), XtOffset(AppDataPtr, pieceToCharTable),
1292 XtRImmediate, (XtPointer) 0},
1293 { "alphaRank", "alphaRank", XtRBoolean,
1294 sizeof(Boolean), XtOffset(AppDataPtr, alphaRank),
1295 XtRImmediate, (XtPointer) False},
1296 { "testClaims", "testClaims", XtRBoolean,
1297 sizeof(Boolean), XtOffset(AppDataPtr, testClaims),
1298 XtRImmediate, (XtPointer) True},
1299 { "checkMates", "checkMates", XtRBoolean,
1300 sizeof(Boolean), XtOffset(AppDataPtr, checkMates),
1301 XtRImmediate, (XtPointer) True},
1302 { "materialDraws", "materialDraws", XtRBoolean,
1303 sizeof(Boolean), XtOffset(AppDataPtr, materialDraws),
1304 XtRImmediate, (XtPointer) True},
1305 { "trivialDraws", "trivialDraws", XtRBoolean,
1306 sizeof(Boolean), XtOffset(AppDataPtr, trivialDraws),
1307 XtRImmediate, (XtPointer) False},
1308 { "ruleMoves", "ruleMoves", XtRInt,
1309 sizeof(int), XtOffset(AppDataPtr, ruleMoves),
1310 XtRImmediate, (XtPointer) 51},
1311 { "repeatsToDraw", "repeatsToDraw", XtRInt,
1312 sizeof(int), XtOffset(AppDataPtr, drawRepeats),
1313 XtRImmediate, (XtPointer) 6},
1314 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1315 sizeof(int), XtOffset(AppDataPtr, engineComments),
1316 XtRImmediate, (XtPointer) 1},
1317 { "userName", "userName", XtRString,
1318 sizeof(int), XtOffset(AppDataPtr, userName),
1319 XtRImmediate, (XtPointer) 0},
1320 { "autoKibitz", "autoKibitz", XtRBoolean,
1321 sizeof(Boolean), XtOffset(AppDataPtr, autoKibitz),
1322 XtRImmediate, (XtPointer) False},
1323 { "firstTimeOdds", "firstTimeOdds", XtRInt,
1324 sizeof(int), XtOffset(AppDataPtr, firstTimeOdds),
1325 XtRImmediate, (XtPointer) 1},
1326 { "secondTimeOdds", "secondTimeOdds", XtRInt,
1327 sizeof(int), XtOffset(AppDataPtr, secondTimeOdds),
1328 XtRImmediate, (XtPointer) 1},
1329 { "timeOddsMode", "timeOddsMode", XtRInt,
1330 sizeof(int), XtOffset(AppDataPtr, timeOddsMode),
1331 XtRImmediate, (XtPointer) 0},
1332 { "firstAccumulateTC", "firstAccumulateTC", XtRInt,
1333 sizeof(int), XtOffset(AppDataPtr, firstAccumulateTC),
1334 XtRImmediate, (XtPointer) 1},
1335 { "secondAccumulateTC", "secondAccumulateTC", XtRInt,
1336 sizeof(int), XtOffset(AppDataPtr, secondAccumulateTC),
1337 XtRImmediate, (XtPointer) 1},
1338 { "firstNPS", "firstNPS", XtRInt,
1339 sizeof(int), XtOffset(AppDataPtr, firstNPS),
1340 XtRImmediate, (XtPointer) -1},
1341 { "secondNPS", "secondNPS", XtRInt,
1342 sizeof(int), XtOffset(AppDataPtr, secondNPS),
1343 XtRImmediate, (XtPointer) -1},
1344 { "serverMoves", "serverMoves", XtRString,
1345 sizeof(String), XtOffset(AppDataPtr, serverMovesName),
1346 XtRImmediate, (XtPointer) 0},
1347 { "serverPause", "serverPause", XtRInt,
1348 sizeof(int), XtOffset(AppDataPtr, serverPause),
1349 XtRImmediate, (XtPointer) 0},
1350 { "suppressLoadMoves", "suppressLoadMoves", XtRBoolean,
1351 sizeof(Boolean), XtOffset(AppDataPtr, suppressLoadMoves),
1352 XtRImmediate, (XtPointer) False},
1353 { "userName", "userName", XtRString,
1354 sizeof(String), XtOffset(AppDataPtr, userName),
1355 XtRImmediate, (XtPointer) 0},
1356 { "egtFormats", "egtFormats", XtRString,
1357 sizeof(String), XtOffset(AppDataPtr, egtFormats),
1358 XtRImmediate, (XtPointer) 0},
1359 { "rewindIndex", "rewindIndex", XtRInt,
1360 sizeof(int), XtOffset(AppDataPtr, rewindIndex),
1361 XtRImmediate, (XtPointer) 0},
1362 { "sameColorGames", "sameColorGames", XtRInt,
1363 sizeof(int), XtOffset(AppDataPtr, sameColorGames),
1364 XtRImmediate, (XtPointer) 0},
1365 { "smpCores", "smpCores", XtRInt,
1366 sizeof(int), XtOffset(AppDataPtr, smpCores),
1367 XtRImmediate, (XtPointer) 1},
1368 { "niceEngines", "niceEngines", XtRInt,
1369 sizeof(int), XtOffset(AppDataPtr, niceEngines),
1370 XtRImmediate, (XtPointer) 0},
1371 { "nameOfDebugFile", "nameOfDebugFile", XtRString,
1372 sizeof(String), XtOffset(AppDataPtr, nameOfDebugFile),
1373 XtRImmediate, (XtPointer) "xboard.debug"},
1374 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1375 sizeof(int), XtOffset(AppDataPtr, engineComments),
1376 XtRImmediate, (XtPointer) 1},
1377 { "noGUI", "noGUI", XtRBoolean,
1378 sizeof(Boolean), XtOffset(AppDataPtr, noGUI),
1379 XtRImmediate, (XtPointer) 0},
1380 { "firstOptions", "firstOptions", XtRString,
1381 sizeof(String), XtOffset(AppDataPtr, firstOptions),
1382 XtRImmediate, (XtPointer) "" },
1383 { "secondOptions", "secondOptions", XtRString,
1384 sizeof(String), XtOffset(AppDataPtr, secondOptions),
1385 XtRImmediate, (XtPointer) "" },
1386 { "firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XtRString,
1387 sizeof(String), XtOffset(AppDataPtr, fenOverride1),
1388 XtRImmediate, (XtPointer) 0 },
1389 { "secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XtRString,
1390 sizeof(String), XtOffset(AppDataPtr, fenOverride2),
1391 XtRImmediate, (XtPointer) 0 },
1393 // [HGM] Winboard_x UCI options
1394 { "firstIsUCI", "firstIsUCI", XtRBoolean,
1395 sizeof(Boolean), XtOffset(AppDataPtr, firstIsUCI),
1396 XtRImmediate, (XtPointer) False},
1397 { "secondIsUCI", "secondIsUCI", XtRBoolean,
1398 sizeof(Boolean), XtOffset(AppDataPtr, secondIsUCI),
1399 XtRImmediate, (XtPointer) False},
1400 { "firstHasOwnBookUCI", "firstHasOwnBookUCI", XtRBoolean,
1401 sizeof(Boolean), XtOffset(AppDataPtr, firstHasOwnBookUCI),
1402 XtRImmediate, (XtPointer) True},
1403 { "secondHasOwnBookUCI", "secondHasOwnBookUCI", XtRBoolean,
1404 sizeof(Boolean), XtOffset(AppDataPtr, secondHasOwnBookUCI),
1405 XtRImmediate, (XtPointer) True},
1406 { "usePolyglotBook", "usePolyglotBook", XtRBoolean,
1407 sizeof(Boolean), XtOffset(AppDataPtr, usePolyglotBook),
1408 XtRImmediate, (XtPointer) False},
1409 { "defaultHashSize", "defaultHashSize", XtRInt,
1410 sizeof(int), XtOffset(AppDataPtr, defaultHashSize),
1411 XtRImmediate, (XtPointer) 64},
1412 { "defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XtRInt,
1413 sizeof(int), XtOffset(AppDataPtr, defaultCacheSizeEGTB),
1414 XtRImmediate, (XtPointer) 4},
1415 { "polyglotDir", "polyglotDir", XtRString,
1416 sizeof(String), XtOffset(AppDataPtr, polyglotDir),
1417 XtRImmediate, (XtPointer) "." },
1418 { "polyglotBook", "polyglotBook", XtRString,
1419 sizeof(String), XtOffset(AppDataPtr, polyglotBook),
1420 XtRImmediate, (XtPointer) "" },
1421 { "defaultPathEGTB", "defaultPathEGTB", XtRString,
1422 sizeof(String), XtOffset(AppDataPtr, defaultPathEGTB),
1423 XtRImmediate, (XtPointer) "/usr/local/share/egtb"},
1424 { "delayBeforeQuit", "delayBeforeQuit", XtRInt,
1425 sizeof(int), XtOffset(AppDataPtr, delayBeforeQuit),
1426 XtRImmediate, (XtPointer) 0},
1427 { "delayAfterQuit", "delayAfterQuit", XtRInt,
1428 sizeof(int), XtOffset(AppDataPtr, delayAfterQuit),
1429 XtRImmediate, (XtPointer) 0},
1430 { "keepAlive", "keepAlive", XtRInt,
1431 sizeof(int), XtOffset(AppDataPtr, keepAlive),
1432 XtRImmediate, (XtPointer) 0},
1433 { "forceIllegalMoves", "forceIllegalMoves", XtRBoolean,
1434 sizeof(Boolean), XtOffset(AppDataPtr, forceIllegal),
1435 XtRImmediate, (XtPointer) False},
1438 XrmOptionDescRec shellOptions[] = {
1439 { "-whitePieceColor", "whitePieceColor", XrmoptionSepArg, NULL },
1440 { "-blackPieceColor", "blackPieceColor", XrmoptionSepArg, NULL },
1441 { "-lightSquareColor", "lightSquareColor", XrmoptionSepArg, NULL },
1442 { "-darkSquareColor", "darkSquareColor", XrmoptionSepArg, NULL },
1443 { "-highlightSquareColor", "highlightSquareColor", XrmoptionSepArg, NULL },
1444 { "-premoveHighlightColor", "premoveHighlightColor", XrmoptionSepArg,NULL},
1445 { "-movesPerSession", "movesPerSession", XrmoptionSepArg, NULL },
1446 { "-mps", "movesPerSession", XrmoptionSepArg, NULL },
1447 { "-timeIncrement", "timeIncrement", XrmoptionSepArg, NULL },
1448 { "-inc", "timeIncrement", XrmoptionSepArg, NULL },
1449 { "-initString", "initString", XrmoptionSepArg, NULL },
1450 { "-firstInitString", "initString", XrmoptionSepArg, NULL },
1451 { "-secondInitString", "secondInitString", XrmoptionSepArg, NULL },
1452 { "-firstComputerString", "firstComputerString", XrmoptionSepArg, NULL },
1453 { "-secondComputerString", "secondComputerString", XrmoptionSepArg, NULL },
1454 { "-firstChessProgram", "firstChessProgram", XrmoptionSepArg, NULL },
1455 { "-fcp", "firstChessProgram", XrmoptionSepArg, NULL },
1456 { "-secondChessProgram", "secondChessProgram", XrmoptionSepArg, NULL },
1457 { "-scp", "secondChessProgram", XrmoptionSepArg, NULL },
1458 { "-firstPlaysBlack", "firstPlaysBlack", XrmoptionSepArg, NULL },
1459 { "-fb", "firstPlaysBlack", XrmoptionNoArg, "True" },
1460 { "-xfb", "firstPlaysBlack", XrmoptionNoArg, "False" },
1461 { "-noChessProgram", "noChessProgram", XrmoptionSepArg, NULL },
1462 { "-ncp", "noChessProgram", XrmoptionNoArg, "True" },
1463 { "-xncp", "noChessProgram", XrmoptionNoArg, "False" },
1464 { "-firstHost", "firstHost", XrmoptionSepArg, NULL },
1465 { "-fh", "firstHost", XrmoptionSepArg, NULL },
1466 { "-secondHost", "secondHost", XrmoptionSepArg, NULL },
1467 { "-sh", "secondHost", XrmoptionSepArg, NULL },
1468 { "-firstDirectory", "firstDirectory", XrmoptionSepArg, NULL },
1469 { "-fd", "firstDirectory", XrmoptionSepArg, NULL },
1470 { "-secondDirectory", "secondDirectory", XrmoptionSepArg, NULL },
1471 { "-sd", "secondDirectory", XrmoptionSepArg, NULL },
1472 { "-bitmapDirectory", "bitmapDirectory", XrmoptionSepArg, NULL },
1473 { "-bm", "bitmapDirectory", XrmoptionSepArg, NULL },
1474 { "-remoteShell", "remoteShell", XrmoptionSepArg, NULL },
1475 { "-rsh", "remoteShell", XrmoptionSepArg, NULL },
1476 { "-remoteUser", "remoteUser", XrmoptionSepArg, NULL },
1477 { "-ruser", "remoteUser", XrmoptionSepArg, NULL },
1478 { "-timeDelay", "timeDelay", XrmoptionSepArg, NULL },
1479 { "-td", "timeDelay", XrmoptionSepArg, NULL },
1480 { "-timeControl", "timeControl", XrmoptionSepArg, NULL },
1481 { "-tc", "timeControl", XrmoptionSepArg, NULL },
1482 { "-internetChessServerMode", "internetChessServerMode",
1483 XrmoptionSepArg, NULL },
1484 { "-ics", "internetChessServerMode", XrmoptionNoArg, "True" },
1485 { "-xics", "internetChessServerMode", XrmoptionNoArg, "False" },
1486 { "-internetChessServerHost", "internetChessServerHost",
1487 XrmoptionSepArg, NULL },
1488 { "-icshost", "internetChessServerHost", XrmoptionSepArg, NULL },
1489 { "-internetChessServerPort", "internetChessServerPort",
1490 XrmoptionSepArg, NULL },
1491 { "-icsport", "internetChessServerPort", XrmoptionSepArg, NULL },
1492 { "-internetChessServerCommPort", "internetChessServerCommPort",
1493 XrmoptionSepArg, NULL },
1494 { "-icscomm", "internetChessServerCommPort", XrmoptionSepArg, NULL },
1495 { "-internetChessServerLogonScript", "internetChessServerLogonScript",
1496 XrmoptionSepArg, NULL },
1497 { "-icslogon", "internetChessServerLogonScript", XrmoptionSepArg, NULL },
1498 { "-internetChessServerHelper", "internetChessServerHelper",
1499 XrmoptionSepArg, NULL },
1500 { "-icshelper", "internetChessServerHelper", XrmoptionSepArg, NULL },
1501 { "-internetChessServerInputBox", "internetChessServerInputBox",
1502 XrmoptionSepArg, NULL },
1503 { "-icsinput", "internetChessServerInputBox", XrmoptionNoArg, "True" },
1504 { "-xicsinput", "internetChessServerInputBox", XrmoptionNoArg, "False" },
1505 { "-icsAlarm", "icsAlarm", XrmoptionSepArg, NULL },
1506 { "-alarm", "icsAlarm", XrmoptionNoArg, "True" },
1507 { "-xalarm", "icsAlarm", XrmoptionNoArg, "False" },
1508 { "-icsAlarmTime", "icsAlarmTime", XrmoptionSepArg, NULL },
1509 { "-useTelnet", "useTelnet", XrmoptionSepArg, NULL },
1510 { "-telnet", "useTelnet", XrmoptionNoArg, "True" },
1511 { "-xtelnet", "useTelnet", XrmoptionNoArg, "False" },
1512 { "-telnetProgram", "telnetProgram", XrmoptionSepArg, NULL },
1513 { "-gateway", "gateway", XrmoptionSepArg, NULL },
1514 { "-loadGameFile", "loadGameFile", XrmoptionSepArg, NULL },
1515 { "-lgf", "loadGameFile", XrmoptionSepArg, NULL },
1516 { "-loadGameIndex", "loadGameIndex", XrmoptionSepArg, NULL },
1517 { "-lgi", "loadGameIndex", XrmoptionSepArg, NULL },
1518 { "-saveGameFile", "saveGameFile", XrmoptionSepArg, NULL },
1519 { "-sgf", "saveGameFile", XrmoptionSepArg, NULL },
1520 { "-autoSaveGames", "autoSaveGames", XrmoptionSepArg, NULL },
1521 { "-autosave", "autoSaveGames", XrmoptionNoArg, "True" },
1522 { "-xautosave", "autoSaveGames", XrmoptionNoArg, "False" },
1523 { "-autoRaiseBoard", "autoRaiseBoard", XrmoptionSepArg, NULL },
1524 { "-autoraise", "autoRaiseBoard", XrmoptionNoArg, "True" },
1525 { "-xautoraise", "autoRaiseBoard", XrmoptionNoArg, "False" },
1526 { "-blindfold", "blindfold", XrmoptionSepArg, NULL },
1527 { "-blind", "blindfold", XrmoptionNoArg, "True" },
1528 { "-xblind", "blindfold", XrmoptionNoArg, "False" },
1529 { "-loadPositionFile", "loadPositionFile", XrmoptionSepArg, NULL },
1530 { "-lpf", "loadPositionFile", XrmoptionSepArg, NULL },
1531 { "-loadPositionIndex", "loadPositionIndex", XrmoptionSepArg, NULL },
1532 { "-lpi", "loadPositionIndex", XrmoptionSepArg, NULL },
1533 { "-savePositionFile", "savePositionFile", XrmoptionSepArg, NULL },
1534 { "-spf", "savePositionFile", XrmoptionSepArg, NULL },
1535 { "-matchMode", "matchMode", XrmoptionSepArg, NULL },
1536 { "-mm", "matchMode", XrmoptionNoArg, "True" },
1537 { "-xmm", "matchMode", XrmoptionNoArg, "False" },
1538 { "-matchGames", "matchGames", XrmoptionSepArg, NULL },
1539 { "-mg", "matchGames", XrmoptionSepArg, NULL },
1540 { "-monoMode", "monoMode", XrmoptionSepArg, NULL },
1541 { "-mono", "monoMode", XrmoptionNoArg, "True" },
1542 { "-xmono", "monoMode", XrmoptionNoArg, "False" },
1543 { "-debugMode", "debugMode", XrmoptionSepArg, NULL },
1544 { "-debug", "debugMode", XrmoptionNoArg, "True" },
1545 { "-xdebug", "debugMode", XrmoptionNoArg, "False" },
1546 { "-clockMode", "clockMode", XrmoptionSepArg, NULL },
1547 { "-clock", "clockMode", XrmoptionNoArg, "True" },
1548 { "-xclock", "clockMode", XrmoptionNoArg, "False" },
1549 { "-boardSize", "boardSize", XrmoptionSepArg, NULL },
1550 { "-size", "boardSize", XrmoptionSepArg, NULL },
1551 { "-searchTime", "searchTime", XrmoptionSepArg, NULL },
1552 { "-st", "searchTime", XrmoptionSepArg, NULL },
1553 { "-searchDepth", "searchDepth", XrmoptionSepArg, NULL },
1554 { "-depth", "searchDepth", XrmoptionSepArg, NULL },
1555 { "-showCoords", "showCoords", XrmoptionSepArg, NULL },
1556 { "-coords", "showCoords", XrmoptionNoArg, "True" },
1557 { "-xcoords", "showCoords", XrmoptionNoArg, "False" },
1559 { "-showJail", "showJail", XrmoptionSepArg, NULL },
1560 { "-jail", "showJail", XrmoptionNoArg, "1" },
1561 { "-sidejail", "showJail", XrmoptionNoArg, "2" },
1562 { "-xjail", "showJail", XrmoptionNoArg, "0" },
1564 { "-showThinking", "showThinking", XrmoptionSepArg, NULL },
1565 { "-thinking", "showThinking", XrmoptionNoArg, "True" },
1566 { "-xthinking", "showThinking", XrmoptionNoArg, "False" },
1567 { "-ponderNextMove", "ponderNextMove", XrmoptionSepArg, NULL },
1568 { "-ponder", "ponderNextMove", XrmoptionNoArg, "True" },
1569 { "-xponder", "ponderNextMove", XrmoptionNoArg, "False" },
1570 { "-periodicUpdates", "periodicUpdates", XrmoptionSepArg, NULL },
1571 { "-periodic", "periodicUpdates", XrmoptionNoArg, "True" },
1572 { "-xperiodic", "periodicUpdates", XrmoptionNoArg, "False" },
1573 { "-clockFont", "clockFont", XrmoptionSepArg, NULL },
1574 { "-coordFont", "coordFont", XrmoptionSepArg, NULL },
1575 { "-font", "font", XrmoptionSepArg, NULL },
1576 { "-ringBellAfterMoves", "ringBellAfterMoves", XrmoptionSepArg, NULL },
1577 { "-bell", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1578 { "-xbell", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1579 { "-movesound", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1580 { "-xmovesound", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1581 { "-autoCallFlag", "autoCallFlag", XrmoptionSepArg, NULL },
1582 { "-autoflag", "autoCallFlag", XrmoptionNoArg, "True" },
1583 { "-xautoflag", "autoCallFlag", XrmoptionNoArg, "False" },
1584 { "-autoFlipView", "autoFlipView", XrmoptionSepArg, NULL },
1585 { "-autoflip", "autoFlipView", XrmoptionNoArg, "True" },
1586 { "-xautoflip", "autoFlipView", XrmoptionNoArg, "False" },
1587 { "-autoObserve", "autoObserve", XrmoptionSepArg, NULL },
1588 { "-autobs", "autoObserve", XrmoptionNoArg, "True" },
1589 { "-xautobs", "autoObserve", XrmoptionNoArg, "False" },
1590 { "-autoComment", "autoComment", XrmoptionSepArg, NULL },
1591 { "-autocomm", "autoComment", XrmoptionNoArg, "True" },
1592 { "-xautocomm", "autoComment", XrmoptionNoArg, "False" },
1593 { "-getMoveList", "getMoveList", XrmoptionSepArg, NULL },
1594 { "-moves", "getMoveList", XrmoptionNoArg, "True" },
1595 { "-xmoves", "getMoveList", XrmoptionNoArg, "False" },
1597 { "-highlightDragging", "highlightDragging", XrmoptionSepArg, NULL },
1598 { "-highdrag", "highlightDragging", XrmoptionNoArg, "True" },
1599 { "-xhighdrag", "highlightDragging", XrmoptionNoArg, "False" },
1601 { "-highlightLastMove", "highlightLastMove", XrmoptionSepArg, NULL },
1602 { "-highlight", "highlightLastMove", XrmoptionNoArg, "True" },
1603 { "-xhighlight", "highlightLastMove", XrmoptionNoArg, "False" },
1604 { "-premove", "premove", XrmoptionSepArg, NULL },
1605 { "-pre", "premove", XrmoptionNoArg, "True" },
1606 { "-xpre", "premove", XrmoptionNoArg, "False" },
1607 { "-testLegality", "testLegality", XrmoptionSepArg, NULL },
1608 { "-legal", "testLegality", XrmoptionNoArg, "True" },
1609 { "-xlegal", "testLegality", XrmoptionNoArg, "False" },
1610 { "-flipView", "flipView", XrmoptionSepArg, NULL },
1611 { "-flip", "flipView", XrmoptionNoArg, "True" },
1612 { "-xflip", "flipView", XrmoptionNoArg, "False" },
1613 { "-cmail", "cmailGameName", XrmoptionSepArg, NULL },
1614 { "-alwaysPromoteToQueen", "alwaysPromoteToQueen",
1615 XrmoptionSepArg, NULL },
1616 { "-queen", "alwaysPromoteToQueen", XrmoptionNoArg, "True" },
1617 { "-xqueen", "alwaysPromoteToQueen", XrmoptionNoArg, "False" },
1618 { "-oldSaveStyle", "oldSaveStyle", XrmoptionSepArg, NULL },
1619 { "-oldsave", "oldSaveStyle", XrmoptionNoArg, "True" },
1620 { "-xoldsave", "oldSaveStyle", XrmoptionNoArg, "False" },
1621 { "-quietPlay", "quietPlay", XrmoptionSepArg, NULL },
1622 { "-quiet", "quietPlay", XrmoptionNoArg, "True" },
1623 { "-xquiet", "quietPlay", XrmoptionNoArg, "False" },
1624 { "-titleInWindow", "titleInWindow", XrmoptionSepArg, NULL },
1625 { "-title", "titleInWindow", XrmoptionNoArg, "True" },
1626 { "-xtitle", "titleInWindow", XrmoptionNoArg, "False" },
1628 { "-zippyTalk", "zippyTalk", XrmoptionSepArg, NULL },
1629 { "-zt", "zippyTalk", XrmoptionNoArg, "True" },
1630 { "-xzt", "zippyTalk", XrmoptionNoArg, "False" },
1631 { "-zippyPlay", "zippyPlay", XrmoptionSepArg, NULL },
1632 { "-zp", "zippyPlay", XrmoptionNoArg, "True" },
1633 { "-xzp", "zippyPlay", XrmoptionNoArg, "False" },
1634 { "-zippyLines", "zippyLines", XrmoptionSepArg, NULL },
1635 { "-zippyPinhead", "zippyPinhead", XrmoptionSepArg, NULL },
1636 { "-zippyPassword", "zippyPassword", XrmoptionSepArg, NULL },
1637 { "-zippyPassword2", "zippyPassword2", XrmoptionSepArg, NULL },
1638 { "-zippyWrongPassword", "zippyWrongPassword", XrmoptionSepArg, NULL },
1639 { "-zippyAcceptOnly", "zippyAcceptOnly", XrmoptionSepArg, NULL },
1640 { "-zippyUseI", "zippyUseI", XrmoptionSepArg, NULL },
1641 { "-zui", "zippyUseI", XrmoptionNoArg, "True" },
1642 { "-xzui", "zippyUseI", XrmoptionNoArg, "False" },
1643 { "-zippyBughouse", "zippyBughouse", XrmoptionSepArg, NULL },
1644 { "-zippyNoplayCrafty", "zippyNoplayCrafty", XrmoptionSepArg, NULL },
1645 { "-znc", "zippyNoplayCrafty", XrmoptionNoArg, "True" },
1646 { "-xznc", "zippyNoplayCrafty", XrmoptionNoArg, "False" },
1647 { "-zippyGameEnd", "zippyGameEnd", XrmoptionSepArg, NULL },
1648 { "-zippyGameStart", "zippyGameStart", XrmoptionSepArg, NULL },
1649 { "-zippyAdjourn", "zippyAdjourn", XrmoptionSepArg, NULL },
1650 { "-zadj", "zippyAdjourn", XrmoptionNoArg, "True" },
1651 { "-xzadj", "zippyAdjourn", XrmoptionNoArg, "False" },
1652 { "-zippyAbort", "zippyAbort", XrmoptionSepArg, NULL },
1653 { "-zab", "zippyAbort", XrmoptionNoArg, "True" },
1654 { "-xzab", "zippyAbort", XrmoptionNoArg, "False" },
1655 { "-zippyVariants", "zippyVariants", XrmoptionSepArg, NULL },
1656 { "-zippyMaxGames", "zippyMaxGames", XrmoptionSepArg, NULL },
1657 { "-zippyReplayTimeout", "zippyReplayTimeout", XrmoptionSepArg, NULL },
1658 { "-zippyShortGame", "zippyShortGame", XrmoptionSepArg, NULL },
1660 { "-flashCount", "flashCount", XrmoptionSepArg, NULL },
1661 { "-flash", "flashCount", XrmoptionNoArg, "3" },
1662 { "-xflash", "flashCount", XrmoptionNoArg, "0" },
1663 { "-flashRate", "flashRate", XrmoptionSepArg, NULL },
1664 { "-pixmapDirectory", "pixmapDirectory", XrmoptionSepArg, NULL },
1665 { "-msLoginDelay", "msLoginDelay", XrmoptionSepArg, NULL },
1666 { "-pixmap", "pixmapDirectory", XrmoptionSepArg, NULL },
1667 { "-colorizeMessages", "colorizeMessages", XrmoptionSepArg, NULL },
1668 { "-colorize", "colorizeMessages", XrmoptionNoArg, "True" },
1669 { "-xcolorize", "colorizeMessages", XrmoptionNoArg, "False" },
1670 { "-colorShout", "colorShout", XrmoptionSepArg, NULL },
1671 { "-colorSShout", "colorSShout", XrmoptionSepArg, NULL },
1672 { "-colorCShout", "colorSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1673 { "-colorChannel1", "colorChannel1", XrmoptionSepArg, NULL },
1674 { "-colorChannel", "colorChannel", XrmoptionSepArg, NULL },
1675 { "-colorKibitz", "colorKibitz", XrmoptionSepArg, NULL },
1676 { "-colorTell", "colorTell", XrmoptionSepArg, NULL },
1677 { "-colorChallenge", "colorChallenge", XrmoptionSepArg, NULL },
1678 { "-colorRequest", "colorRequest", XrmoptionSepArg, NULL },
1679 { "-colorSeek", "colorSeek", XrmoptionSepArg, NULL },
1680 { "-colorNormal", "colorNormal", XrmoptionSepArg, NULL },
1681 { "-soundProgram", "soundProgram", XrmoptionSepArg, NULL },
1682 { "-soundShout", "soundShout", XrmoptionSepArg, NULL },
1683 { "-soundSShout", "soundSShout", XrmoptionSepArg, NULL },
1684 { "-soundCShout", "soundSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1685 { "-soundChannel1", "soundChannel1", XrmoptionSepArg, NULL },
1686 { "-soundChannel", "soundChannel", XrmoptionSepArg, NULL },
1687 { "-soundKibitz", "soundKibitz", XrmoptionSepArg, NULL },
1688 { "-soundTell", "soundTell", XrmoptionSepArg, NULL },
1689 { "-soundChallenge", "soundChallenge", XrmoptionSepArg, NULL },
1690 { "-soundRequest", "soundRequest", XrmoptionSepArg, NULL },
1691 { "-soundSeek", "soundSeek", XrmoptionSepArg, NULL },
1692 { "-soundMove", "soundMove", XrmoptionSepArg, NULL },
1693 { "-soundIcsWin", "soundIcsWin", XrmoptionSepArg, NULL },
1694 { "-soundIcsLoss", "soundIcsLoss", XrmoptionSepArg, NULL },
1695 { "-soundIcsDraw", "soundIcsDraw", XrmoptionSepArg, NULL },
1696 { "-soundIcsUnfinished", "soundIcsUnfinished", XrmoptionSepArg, NULL },
1697 { "-soundIcsAlarm", "soundIcsAlarm", XrmoptionSepArg, NULL },
1698 { "-reuseFirst", "reuseFirst", XrmoptionSepArg, NULL },
1699 { "-reuseChessPrograms", "reuseFirst", XrmoptionSepArg, NULL }, /*compat*/
1700 { "-reuse", "reuseFirst", XrmoptionNoArg, "True" },
1701 { "-xreuse", "reuseFirst", XrmoptionNoArg, "False" },
1702 { "-reuseSecond", "reuseSecond", XrmoptionSepArg, NULL },
1703 { "-reuse2", "reuseSecond", XrmoptionNoArg, "True" },
1704 { "-xreuse2", "reuseSecond", XrmoptionNoArg, "False" },
1705 { "-animateMoving", "animateMoving", XrmoptionSepArg, NULL },
1706 { "-animate", "animateMoving", XrmoptionNoArg, "True" },
1707 { "-xanimate", "animateMoving", XrmoptionNoArg, "False" },
1708 { "-animateDragging", "animateDragging", XrmoptionSepArg, NULL },
1709 { "-drag", "animateDragging", XrmoptionNoArg, "True" },
1710 { "-xdrag", "animateDragging", XrmoptionNoArg, "False" },
1711 { "-animateSpeed", "animateSpeed", XrmoptionSepArg, NULL },
1712 { "-popupExitMessage", "popupExitMessage", XrmoptionSepArg, NULL },
1713 { "-exit", "popupExitMessage", XrmoptionNoArg, "True" },
1714 { "-xexit", "popupExitMessage", XrmoptionNoArg, "False" },
1715 { "-popupMoveErrors", "popupMoveErrors", XrmoptionSepArg, NULL },
1716 { "-popup", "popupMoveErrors", XrmoptionNoArg, "True" },
1717 { "-xpopup", "popupMoveErrors", XrmoptionNoArg, "False" },
1718 { "-fontSizeTolerance", "fontSizeTolerance", XrmoptionSepArg, NULL },
1719 { "-initialMode", "initialMode", XrmoptionSepArg, NULL },
1720 { "-mode", "initialMode", XrmoptionSepArg, NULL },
1721 { "-variant", "variant", XrmoptionSepArg, NULL },
1722 { "-firstProtocolVersion", "firstProtocolVersion", XrmoptionSepArg, NULL },
1723 { "-secondProtocolVersion","secondProtocolVersion",XrmoptionSepArg, NULL },
1724 { "-showButtonBar", "showButtonBar", XrmoptionSepArg, NULL },
1725 { "-buttons", "showButtonBar", XrmoptionNoArg, "True" },
1726 { "-xbuttons", "showButtonBar", XrmoptionNoArg, "False" },
1727 { "-lowTimeWarningColor", "lowTimeWarningColor", XrmoptionSepArg, NULL },
1728 { "-lowTimeWarning", "lowTimeWarning", XrmoptionSepArg, NULL },
1729 /* [AS,HR] New features */
1730 { "-firstScoreAbs", "firstScoreAbs", XrmoptionSepArg, NULL },
1731 { "-secondScoreAbs", "secondScoreAbs", XrmoptionSepArg, NULL },
1732 { "-pgnExtendedInfo", "pgnExtendedInfo", XrmoptionSepArg, NULL },
1733 { "-hideThinkingFromHuman", "hideThinkingFromHuman", XrmoptionSepArg, NULL },
1734 { "-adjudicateLossThreshold", "adjudicateLossThreshold", XrmoptionSepArg, NULL },
1735 { "-adjudicateDrawMoves", "adjudicateDrawMoves", XrmoptionSepArg, NULL },
1736 { "-pgnEventHeader", "pgnEventHeader", XrmoptionSepArg, NULL },
1737 { "-firstIsUCI", "firstIsUCI", XrmoptionSepArg, NULL },
1738 { "-secondIsUCI", "secondIsUCI", XrmoptionSepArg, NULL },
1739 { "-fUCI", "firstIsUCI", XrmoptionNoArg, "True" },
1740 { "-sUCI", "secondIsUCI", XrmoptionNoArg, "True" },
1741 { "-firstHasOwnBookUCI", "firstHasOwnBookUCI", XrmoptionSepArg, NULL },
1742 { "-secondHasOwnBookUCI", "secondHasOwnBookUCI", XrmoptionSepArg, NULL },
1743 { "-fNoOwnBookUCI", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1744 { "-sNoOwnBookUCI", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1745 { "-firstXBook", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1746 { "-secondXBook", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1747 { "-polyglotDir", "polyglotDir", XrmoptionSepArg, NULL },
1748 { "-usePolyglotBook", "usePolyglotBook", XrmoptionSepArg, NULL },
1749 { "-polyglotBook", "polyglotBook", XrmoptionSepArg, NULL },
1750 { "-defaultHashSize", "defaultHashSize", XrmoptionSepArg, NULL },
1751 { "-defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XrmoptionSepArg, NULL },
1752 { "-defaultPathEGTB", "defaultPathEGTB", XrmoptionSepArg, NULL },
1753 { "-defaultFrcPosition", "defaultFrcPosition", XrmoptionSepArg, NULL },
1754 { "-gameListTags", "gameListTags", XrmoptionSepArg, NULL },
1755 // [HGM] I am sure AS added many more options, but we have to fish them out, from the list in winboard.c
1757 /* [HGM,HR] User-selectable board size */
1758 { "-boardWidth", "boardWidth", XrmoptionSepArg, NULL },
1759 { "-boardHeight", "boardHeight", XrmoptionSepArg, NULL },
1760 { "-matchPause", "matchPause", XrmoptionSepArg, NULL },
1762 /* [HGM] new arguments of 4.3.xx. All except first three are back-end options, which should work immediately */
1763 { "-holdingsSize", "holdingsSize", XrmoptionSepArg, NULL }, // requires extensive front-end changes to work
1764 { "-flipBlack", "flipBlack", XrmoptionSepArg, NULL }, // requires front-end changes to work
1765 { "-allWhite", "allWhite", XrmoptionSepArg, NULL }, // requires front-end changes to work
1766 { "-pieceToCharTable", "pieceToCharTable", XrmoptionSepArg, NULL },
1767 { "-alphaRank", "alphaRank", XrmoptionSepArg, NULL },
1768 { "-testClaims", "testClaims", XrmoptionSepArg, NULL },
1769 { "-checkMates", "checkMates", XrmoptionSepArg, NULL },
1770 { "-materialDraws", "materialDraws", XrmoptionSepArg, NULL },
1771 { "-trivialDraws", "trivialDraws", XrmoptionSepArg, NULL },
1772 { "-ruleMoves", "ruleMoves", XrmoptionSepArg, NULL },
1773 { "-repeatsToDraw", "repeatsToDraw", XrmoptionSepArg, NULL },
1774 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1775 { "-userName", "userName", XrmoptionSepArg, NULL },
1776 { "-autoKibitz", "autoKibitz", XrmoptionNoArg, "True" },
1777 { "-firstTimeOdds", "firstTimeOdds", XrmoptionSepArg, NULL },
1778 { "-secondTimeOdds", "secondTimeOdds", XrmoptionSepArg, NULL },
1779 { "-timeOddsMode", "timeOddsMode", XrmoptionSepArg, NULL },
1780 { "-firstAccumulateTC", "firstAccumulateTC", XrmoptionSepArg, NULL },
1781 { "-secondAccumulateTC", "secondAccumulateTC", XrmoptionSepArg, NULL },
1782 { "-firstNPS", "firstNPS", XrmoptionSepArg, NULL },
1783 { "-secondNPS", "secondNPS", XrmoptionSepArg, NULL },
1784 { "-serverMoves", "serverMoves", XrmoptionSepArg, NULL },
1785 { "-serverPause", "serverPause", XrmoptionSepArg, NULL },
1786 { "-suppressLoadMoves", "suppressLoadMoves", XrmoptionSepArg, NULL },
1787 { "-egtFormats", "egtFormats", XrmoptionSepArg, NULL },
1788 { "-userName", "userName", XrmoptionSepArg, NULL },
1789 { "-smpCores", "smpCores", XrmoptionSepArg, NULL },
1790 { "-sameColorGames", "sameColorGames", XrmoptionSepArg, NULL },
1791 { "-rewindIndex", "rewindIndex", XrmoptionSepArg, NULL },
1792 { "-niceEngines", "niceEngines", XrmoptionSepArg, NULL },
1793 { "-delayBeforeQuit", "delayBeforeQuit", XrmoptionSepArg, NULL },
1794 { "-delayAfterQuit", "delayAfterQuit", XrmoptionSepArg, NULL },
1795 { "-nameOfDebugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1796 { "-debugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1797 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1798 { "-noGUI", "noGUI", XrmoptionNoArg, "True" },
1799 { "-firstOptions", "firstOptions", XrmoptionSepArg, NULL },
1800 { "-secondOptions", "secondOptions", XrmoptionSepArg, NULL },
1801 { "-firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1802 { "-secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1803 { "-keepAlive", "keepAlive", XrmoptionSepArg, NULL },
1804 { "-forceIllegalMoves", "forceIllegalMoves", XrmoptionNoArg, "True" },
1808 XtActionsRec boardActions[] = {
1809 { "HandleUserMove", HandleUserMove },
1810 { "AnimateUserMove", AnimateUserMove },
1811 { "FileNameAction", FileNameAction },
1812 { "AskQuestionProc", AskQuestionProc },
1813 { "AskQuestionReplyAction", AskQuestionReplyAction },
1814 { "PieceMenuPopup", PieceMenuPopup },
1815 { "WhiteClock", WhiteClock },
1816 { "BlackClock", BlackClock },
1817 { "Iconify", Iconify },
1818 { "LoadSelectedProc", LoadSelectedProc },
1819 { "LoadPositionProc", LoadPositionProc },
1820 { "LoadNextPositionProc", LoadNextPositionProc },
1821 { "LoadPrevPositionProc", LoadPrevPositionProc },
1822 { "ReloadPositionProc", ReloadPositionProc },
1823 { "CopyPositionProc", CopyPositionProc },
1824 { "PastePositionProc", PastePositionProc },
1825 { "CopyGameProc", CopyGameProc },
1826 { "PasteGameProc", PasteGameProc },
1827 { "SaveGameProc", SaveGameProc },
1828 { "SavePositionProc", SavePositionProc },
1829 { "MailMoveProc", MailMoveProc },
1830 { "ReloadCmailMsgProc", ReloadCmailMsgProc },
1831 // { "MachineWhiteProc", MachineWhiteProc },
1832 // { "MachineBlackProc", MachineBlackProc },
1833 { "AnalysisModeProc", AnalyzeModeProc },
1834 { "AnalyzeFileProc", AnalyzeFileProc },
1835 // { "TwoMachinesProc", TwoMachinesProc },
1836 // { "IcsClientProc", IcsClientProc },
1837 { "EditGameProc", EditGameProc },
1838 { "EditPositionProc", EditPositionProc },
1839 { "TrainingProc", EditPositionProc },
1840 { "EngineOutputProc", EngineOutputProc}, // [HGM] Winboard_x engine-output window
1841 { "ShowGameListProc", ShowGameListProc },
1842 // { "ShowMoveListProc", HistoryShowProc},
1843 { "EditTagsProc", EditCommentProc },
1844 { "EditCommentProc", EditCommentProc },
1845 { "IcsAlarmProc", IcsAlarmProc },
1846 { "IcsInputBoxProc", IcsInputBoxProc },
1847 // { "AcceptProc", AcceptProc },
1848 // { "DeclineProc", DeclineProc },
1849 // { "RematchProc", RematchProc },
1850 // { "CallFlagProc", CallFlagProc },
1851 // { "DrawProc", DrawProc },
1852 // { "AdjournProc", AdjournProc },
1853 // { "AbortProc", AbortProc },
1854 // { "ResignProc", ResignProc },
1855 // { "AdjuWhiteProc", AdjuWhiteProc },
1856 // { "AdjuBlackProc", AdjuBlackProc },
1857 // { "AdjuDrawProc", AdjuDrawProc },
1858 { "EnterKeyProc", EnterKeyProc },
1859 // { "StopObservingProc", StopObservingProc },
1860 // { "StopExaminingProc", StopExaminingProc },
1861 // { "BackwardProc", BackwardProc },
1862 // { "ForwardProc", ForwardProc },
1863 // { "ToStartProc", ToStartProc },
1864 // { "ToEndProc", ToEndProc },
1865 // { "RevertProc", RevertProc },
1866 // { "TruncateGameProc", TruncateGameProc },
1867 // { "MoveNowProc", MoveNowProc },
1868 // { "RetractMoveProc", RetractMoveProc },
1869 { "AlwaysQueenProc", AlwaysQueenProc },
1870 { "AnimateDraggingProc", AnimateDraggingProc },
1871 { "AnimateMovingProc", AnimateMovingProc },
1872 { "AutoflagProc", AutoflagProc },
1873 { "AutoflipProc", AutoflipProc },
1874 { "AutobsProc", AutobsProc },
1875 { "AutoraiseProc", AutoraiseProc },
1876 { "AutosaveProc", AutosaveProc },
1877 { "BlindfoldProc", BlindfoldProc },
1878 { "FlashMovesProc", FlashMovesProc },
1879 // { "FlipViewProc", FlipViewProc },
1880 // { "GetMoveListProc", GetMoveListProc },
1882 { "HighlightDraggingProc", HighlightDraggingProc },
1884 { "HighlightLastMoveProc", HighlightLastMoveProc },
1885 { "IcsAlarmProc", IcsAlarmProc },
1886 { "MoveSoundProc", MoveSoundProc },
1887 { "OldSaveStyleProc", OldSaveStyleProc },
1888 { "PeriodicUpdatesProc", PeriodicUpdatesProc },
1889 { "PonderNextMoveProc", PonderNextMoveProc },
1890 { "PopupExitMessageProc", PopupExitMessageProc },
1891 { "PopupMoveErrorsProc", PopupMoveErrorsProc },
1892 { "PremoveProc", PremoveProc },
1893 { "QuietPlayProc", QuietPlayProc },
1894 { "ShowThinkingProc", ShowThinkingProc },
1895 { "HideThinkingProc", HideThinkingProc },
1896 { "TestLegalityProc", TestLegalityProc },
1897 // { "InfoProc", InfoProc },
1898 // { "ManProc", ManProc },
1899 // { "HintProc", HintProc },
1900 // { "BookProc", BookProc },
1901 { "AboutGameProc", AboutGameProc },
1902 { "DebugProc", DebugProc },
1903 { "NothingProc", NothingProc },
1904 { "CommentPopDown", (XtActionProc) CommentPopDown },
1905 { "EditCommentPopDown", (XtActionProc) EditCommentPopDown },
1906 { "TagsPopDown", (XtActionProc) TagsPopDown },
1907 { "ErrorPopDown", (XtActionProc) ErrorPopDown },
1908 { "ICSInputBoxPopDown", (XtActionProc) ICSInputBoxPopDown },
1909 { "AnalysisPopDown", (XtActionProc) AnalysisPopDown },
1910 { "FileNamePopDown", (XtActionProc) FileNamePopDown },
1911 { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown },
1912 { "GameListPopDown", (XtActionProc) GameListPopDown },
1913 { "PromotionPopDown", (XtActionProc) PromotionPopDown },
1914 // { "HistoryPopDown", (XtActionProc) HistoryPopDown },
1915 { "EngineOutputPopDown", (XtActionProc) EngineOutputPopDown },
1916 { "ShufflePopDown", (XtActionProc) ShufflePopDown },
1917 { "EnginePopDown", (XtActionProc) EnginePopDown },
1918 { "UciPopDown", (XtActionProc) UciPopDown },
1919 { "TimeControlPopDown", (XtActionProc) TimeControlPopDown },
1920 { "NewVariantPopDown", (XtActionProc) NewVariantPopDown },
1921 { "SettingsPopDown", (XtActionProc) SettingsPopDown },
1925 char ICSInputTranslations[] =
1926 "<Key>Return: EnterKeyProc() \n";
1928 String xboardResources[] = {
1929 "*fileName*value.translations: #override\\n <Key>Return: FileNameAction()",
1930 "*question*value.translations: #override\\n <Key>Return: AskQuestionReplyAction()",
1931 "*errorpopup*translations: #override\\n <Key>Return: ErrorPopDown()",
1935 static char *cnames[9] = { "black", "red", "green", "yellow", "blue",
1936 "magenta", "cyan", "white" };
1940 TextColors textColors[(int)NColorClasses];
1942 /* String is: "fg, bg, attr". Which is 0, 1, 2 */
1944 parse_color(str, which)
1948 char *p, buf[100], *d;
1951 if (strlen(str) > 99) /* watch bounds on buf */
1956 for (i=0; i<which; ++i) {
1963 /* Could be looking at something like:
1965 .. in which case we want to stop on a comma also */
1966 while (*p && *p != ',' && !isalpha(*p) && !isdigit(*p))
1970 return -1; /* Use default for empty field */
1973 if (which == 2 || isdigit(*p))
1976 while (*p && isalpha(*p))
1981 for (i=0; i<8; ++i) {
1982 if (!StrCaseCmp(buf, cnames[i]))
1983 return which? (i+40) : (i+30);
1985 if (!StrCaseCmp(buf, "default")) return -1;
1987 fprintf(stderr, _("%s: unrecognized color %s\n"), programName, buf);
1992 parse_cpair(cc, str)
1996 if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {
1997 fprintf(stderr, _("%s: can't parse foreground color in `%s'\n"),
2002 /* bg and attr are optional */
2003 textColors[(int)cc].bg = parse_color(str, 1);
2004 if ((textColors[(int)cc].attr = parse_color(str, 2)) < 0) {
2005 textColors[(int)cc].attr = 0;
2011 /* Arrange to catch delete-window events */
2012 Atom wm_delete_window;
2014 CatchDeleteWindow(Widget w, String procname)
2017 XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
2018 snprintf(buf, sizeof(buf), "<Message>WM_PROTOCOLS: %s() \n", procname);
2019 XtAugmentTranslations(w, XtParseTranslationTable(buf));
2025 /* this should raise the board to the top */
2026 gtk_window_present(GTK_WINDOW(GUI_Window));
2031 // eventually, all layout determining code should go into a subroutine, but until then IDSIZE remains undefined
2033 #define BoardSize int
2034 void InitDrawingSizes(BoardSize boardSize, int flags)
2035 { // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
2036 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2038 XtGeometryResult gres;
2041 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2042 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2044 timerWidth = (boardWidth - sep) / 2;
2046 if (appData.titleInWindow)
2051 w = boardWidth - 2*bor;
2055 w = boardWidth - w - sep - 2*bor - 2; // WIDTH_FUDGE
2059 if(!formWidget) return;
2062 * Inhibit shell resizing.
2065 // [HGM] pieces: tailor piece bitmaps to needs of specific variant
2068 for(i=0; i<4; i++) {
2070 for(p=0; p<=(int)WhiteKing; p++)
2071 xpmPieceBitmap[i][p] = xpmPieceBitmap2[i][p]; // defaults
2072 if(gameInfo.variant == VariantShogi) {
2073 xpmPieceBitmap[i][(int)WhiteCannon] = xpmPieceBitmap2[i][(int)WhiteKing+1];
2074 xpmPieceBitmap[i][(int)WhiteNightrider] = xpmPieceBitmap2[i][(int)WhiteKing+2];
2075 xpmPieceBitmap[i][(int)WhiteSilver] = xpmPieceBitmap2[i][(int)WhiteKing+3];
2076 xpmPieceBitmap[i][(int)WhiteGrasshopper] = xpmPieceBitmap2[i][(int)WhiteKing+4];
2077 xpmPieceBitmap[i][(int)WhiteQueen] = xpmPieceBitmap2[i][(int)WhiteLance];
2080 if(gameInfo.variant == VariantGothic) {
2081 xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteSilver];
2085 // [HGM] why are thee ximMasks used at all? the ximPieceBitmaps seem to be never used!
2086 for(p=0; p<=(int)WhiteKing; p++)
2087 ximMaskPm[p] = ximMaskPm2[p]; // defaults
2088 if(gameInfo.variant == VariantShogi) {
2089 ximMaskPm[(int)WhiteCannon] = ximMaskPm2[(int)WhiteKing+1];
2090 ximMaskPm[(int)WhiteNightrider] = ximMaskPm2[(int)WhiteKing+2];
2091 ximMaskPm[(int)WhiteSilver] = ximMaskPm2[(int)WhiteKing+3];
2092 ximMaskPm[(int)WhiteGrasshopper] = ximMaskPm2[(int)WhiteKing+4];
2093 ximMaskPm[(int)WhiteQueen] = ximMaskPm2[(int)WhiteLance];
2096 if(gameInfo.variant == VariantGothic) {
2097 ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[(int)WhiteSilver];
2103 for(i=0; i<2; i++) {
2105 for(p=0; p<=(int)WhiteKing; p++)
2106 pieceBitmap[i][p] = pieceBitmap2[i][p]; // defaults
2107 if(gameInfo.variant == VariantShogi) {
2108 pieceBitmap[i][(int)WhiteCannon] = pieceBitmap2[i][(int)WhiteKing+1];
2109 pieceBitmap[i][(int)WhiteNightrider] = pieceBitmap2[i][(int)WhiteKing+2];
2110 pieceBitmap[i][(int)WhiteSilver] = pieceBitmap2[i][(int)WhiteKing+3];
2111 pieceBitmap[i][(int)WhiteGrasshopper] = pieceBitmap2[i][(int)WhiteKing+4];
2112 pieceBitmap[i][(int)WhiteQueen] = pieceBitmap2[i][(int)WhiteLance];
2115 if(gameInfo.variant == VariantGothic) {
2116 pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteSilver];
2127 void EscapeExpand(char *p, char *q)
2128 { // [HGM] initstring: routine to shape up string arguments
2129 while(*p++ = *q++) if(p[-1] == '\\')
2131 case 'n': p[-1] = '\n'; break;
2132 case 'r': p[-1] = '\r'; break;
2133 case 't': p[-1] = '\t'; break;
2134 case '\\': p[-1] = '\\'; break;
2135 case 0: *p = 0; return;
2136 default: p[-1] = q[-1]; break;
2145 int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
2146 XSetWindowAttributes window_attributes;
2148 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2149 XrmValue vFrom, vTo;
2150 XtGeometryResult gres;
2153 int forceMono = False;
2157 // [HGM] before anything else, expand any indirection files amongst options
2158 char *argvCopy[1000]; // 1000 seems enough
2159 char newArgs[10000]; // holds actual characters
2162 srandom(time(0)); // [HGM] book: make random truly random
2165 for(i=0; i<argc; i++) {
2166 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2167 //fprintf(stderr, "arg %s\n", argv[i]);
2168 if(argv[i][0] != '@') argvCopy[j++] = argv[i]; else {
2170 FILE *f = fopen(argv[i]+1, "rb");
2171 if(f == NULL) { fprintf(stderr, _("ignore %s\n"), argv[i]); continue; } // do not expand non-existing
2172 argvCopy[j++] = newArgs + k; // get ready for first argument from file
2173 while((c = fgetc(f)) != EOF) { // each line of file inserts 1 argument in the list
2175 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2176 newArgs[k++] = 0; // terminate current arg
2177 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2178 argvCopy[j++] = newArgs + k; // get ready for next
2180 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2194 setbuf(stdout, NULL);
2195 setbuf(stderr, NULL);
2198 programName = strrchr(argv[0], '/');
2199 if (programName == NULL)
2200 programName = argv[0];
2205 XtSetLanguageProc(NULL, NULL, NULL);
2206 bindtextdomain(PACKAGE, LOCALEDIR);
2207 textdomain(PACKAGE);
2211 XtAppInitialize(&appContext, "XBoard", shellOptions,
2212 XtNumber(shellOptions),
2213 &argc, argv, xboardResources, NULL, 0);
2216 gtk_init (&argc, &argv);
2218 /* parse glade file to build widgets */
2220 builder = gtk_builder_new ();
2221 gtk_builder_add_from_file (builder, "gtk-interface.xml", NULL);
2223 /* test if everything worked ok */
2225 GUI_Window = GTK_WIDGET (gtk_builder_get_object (builder, "MainWindow"));
2226 if(!GUI_Window) printf("Error: gtk_builder didn't work!\n");
2228 GUI_History = GTK_WIDGET (gtk_builder_get_object (builder, "MoveHistory"));
2229 if(!GUI_History) printf("Error: gtk_builder didn't work!\n");
2231 GUI_Board = GTK_WIDGET (gtk_builder_get_object (builder, "Board"));
2232 if(!GUI_Board) printf("Error: gtk_builder didn't work!\n");
2234 GUI_Whiteclock = GTK_WIDGET (gtk_builder_get_object (builder, "WhiteClock"));
2235 if(!GUI_Whiteclock) printf("Error: gtk_builder didn't work!\n");
2237 GUI_Blackclock = GTK_WIDGET (gtk_builder_get_object (builder, "BlackClock"));
2238 if(!GUI_Blackclock) printf("Error: gtk_builder didn't work!\n");
2240 LIST_MoveHistory = GTK_LIST_STORE (gtk_builder_get_object (builder, "MoveHistoryStore"));
2241 if(!LIST_MoveHistory) printf("Error: gtk_builder didn't work!\n");
2244 gtk_builder_connect_signals (builder, NULL);
2246 // don't unref the builder, since we use it to get references to widgets
2247 // g_object_unref (G_OBJECT (builder));
2249 /* end parse glade file */
2253 fprintf(stderr, _("%s: unrecognized argument %s\n"),
2254 programName, argv[1]);
2256 fprintf(stderr, "Recognized options:\n");
2257 for(i = 0; i < XtNumber(shellOptions); i++)
2259 /* print first column */
2260 j = fprintf(stderr, " %s%s", shellOptions[i].option,
2261 (shellOptions[i].argKind == XrmoptionSepArg
2263 /* print second column and end line */
2264 if (++i < XtNumber(shellOptions))
2266 fprintf(stderr, "%*c%s%s\n", 40 - j, ' ',
2267 shellOptions[i].option,
2268 (shellOptions[i].argKind == XrmoptionSepArg
2273 fprintf(stderr, "\n");
2280 if (p == NULL) p = "/tmp";
2281 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
2282 gameCopyFilename = (char*) malloc(i);
2283 gamePasteFilename = (char*) malloc(i);
2284 snprintf(gameCopyFilename,i, "%s/.xboard%05uc.pgn", p, getpid());
2285 snprintf(gamePasteFilename,i, "%s/.xboard%05up.pgn", p, getpid());
2287 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
2288 clientResources, XtNumber(clientResources),
2291 { // [HGM] initstring: kludge to fix bad bug. expand '\n' characters in init string and computer string.
2292 static char buf[MSG_SIZ];
2293 EscapeExpand(buf, appData.initString);
2294 appData.initString = strdup(buf);
2295 EscapeExpand(buf, appData.secondInitString);
2296 appData.secondInitString = strdup(buf);
2297 EscapeExpand(buf, appData.firstComputerString);
2298 appData.firstComputerString = strdup(buf);
2299 EscapeExpand(buf, appData.secondComputerString);
2300 appData.secondComputerString = strdup(buf);
2303 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
2306 if (chdir(chessDir) != 0) {
2307 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
2313 if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) {
2314 /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */
2315 if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL) {
2316 printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile);
2319 setbuf(debugFP, NULL);
2322 /* [HGM,HR] make sure board size is acceptable */
2323 if(appData.NrFiles > BOARD_SIZE ||
2324 appData.NrRanks > BOARD_SIZE )
2325 DisplayFatalError(_("Recompile with BOARD_SIZE > 12, to support this size"), 0, 2);
2328 /* This feature does not work; animation needs a rewrite */
2329 appData.highlightDragging = FALSE;
2333 xDisplay = XtDisplay(shellWidget);
2334 xScreen = DefaultScreen(xDisplay);
2335 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
2337 gameInfo.variant = StringToVariant(appData.variant);
2338 InitPosition(FALSE);
2342 InitDrawingSizes(-1, 0); // [HGM] initsize: make this into a subroutine
2344 if (isdigit(appData.boardSize[0])) {
2345 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
2346 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
2347 &fontPxlSize, &smallLayout, &tinyLayout);
2349 fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
2350 programName, appData.boardSize);
2354 /* Find some defaults; use the nearest known size */
2355 SizeDefaults *szd, *nearest;
2356 int distance = 99999;
2357 nearest = szd = sizeDefaults;
2358 while (szd->name != NULL) {
2359 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;
2374 SizeDefaults *szd = sizeDefaults;
2375 if (*appData.boardSize == NULLCHAR) {
2376 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize ||
2377 DisplayHeight(xDisplay, xScreen) < szd->minScreenSize) {
2380 if (szd->name == NULL) szd--;
2382 while (szd->name != NULL &&
2383 StrCaseCmp(szd->name, appData.boardSize) != 0) szd++;
2384 if (szd->name == NULL) {
2385 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
2386 programName, appData.boardSize);
2390 squareSize = szd->squareSize;
2391 lineGap = szd->lineGap;
2392 clockFontPxlSize = szd->clockFontPxlSize;
2393 coordFontPxlSize = szd->coordFontPxlSize;
2394 fontPxlSize = szd->fontPxlSize;
2395 smallLayout = szd->smallLayout;
2396 tinyLayout = szd->tinyLayout;
2399 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2400 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2401 if (appData.showJail == 1) {
2402 /* Jail on top and bottom */
2403 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2404 XtSetArg(boardArgs[2], XtNheight,
2405 boardHeight + 2*(lineGap + squareSize));
2406 } else if (appData.showJail == 2) {
2408 XtSetArg(boardArgs[1], XtNwidth,
2409 boardWidth + 2*(lineGap + squareSize));
2410 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2413 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2414 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2418 * Determine what fonts to use.
2420 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
2421 clockFontID = XLoadFont(xDisplay, appData.clockFont);
2422 clockFontStruct = XQueryFont(xDisplay, clockFontID);
2423 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
2424 coordFontID = XLoadFont(xDisplay, appData.coordFont);
2425 coordFontStruct = XQueryFont(xDisplay, coordFontID);
2426 appData.font = FindFont(appData.font, fontPxlSize);
2427 countFontID = XLoadFont(xDisplay, appData.coordFont); // [HGM] holdings
2428 countFontStruct = XQueryFont(xDisplay, countFontID);
2429 // appData.font = FindFont(appData.font, fontPxlSize);
2431 xdb = XtDatabase(xDisplay);
2432 XrmPutStringResource(&xdb, "*font", appData.font);
2435 * Detect if there are not enough colors available and adapt.
2437 if (DefaultDepth(xDisplay, xScreen) <= 2) {
2438 appData.monoMode = True;
2441 if (!appData.monoMode) {
2442 vFrom.addr = (caddr_t) appData.lightSquareColor;
2443 vFrom.size = strlen(appData.lightSquareColor);
2444 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2445 if (vTo.addr == NULL) {
2446 appData.monoMode = True;
2449 lightSquareColor = *(Pixel *) vTo.addr;
2452 if (!appData.monoMode) {
2453 vFrom.addr = (caddr_t) appData.darkSquareColor;
2454 vFrom.size = strlen(appData.darkSquareColor);
2455 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2456 if (vTo.addr == NULL) {
2457 appData.monoMode = True;
2460 darkSquareColor = *(Pixel *) vTo.addr;
2463 if (!appData.monoMode) {
2464 vFrom.addr = (caddr_t) appData.whitePieceColor;
2465 vFrom.size = strlen(appData.whitePieceColor);
2466 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2467 if (vTo.addr == NULL) {
2468 appData.monoMode = True;
2471 whitePieceColor = *(Pixel *) vTo.addr;
2474 if (!appData.monoMode) {
2475 vFrom.addr = (caddr_t) appData.blackPieceColor;
2476 vFrom.size = strlen(appData.blackPieceColor);
2477 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2478 if (vTo.addr == NULL) {
2479 appData.monoMode = True;
2482 blackPieceColor = *(Pixel *) vTo.addr;
2486 if (!appData.monoMode) {
2487 vFrom.addr = (caddr_t) appData.highlightSquareColor;
2488 vFrom.size = strlen(appData.highlightSquareColor);
2489 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2490 if (vTo.addr == NULL) {
2491 appData.monoMode = True;
2494 highlightSquareColor = *(Pixel *) vTo.addr;
2498 if (!appData.monoMode) {
2499 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
2500 vFrom.size = strlen(appData.premoveHighlightColor);
2501 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2502 if (vTo.addr == NULL) {
2503 appData.monoMode = True;
2506 premoveHighlightColor = *(Pixel *) vTo.addr;
2511 fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2514 if (appData.bitmapDirectory == NULL ||
2515 appData.bitmapDirectory[0] == NULLCHAR)
2516 appData.bitmapDirectory = DEF_BITMAP_DIR;
2519 if (appData.lowTimeWarning && !appData.monoMode) {
2520 vFrom.addr = (caddr_t) appData.lowTimeWarningColor;
2521 vFrom.size = strlen(appData.lowTimeWarningColor);
2522 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2523 if (vTo.addr == NULL)
2524 appData.monoMode = True;
2526 lowTimeWarningColor = *(Pixel *) vTo.addr;
2529 if (appData.monoMode && appData.debugMode) {
2530 fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2531 (unsigned long) XWhitePixel(xDisplay, xScreen),
2532 (unsigned long) XBlackPixel(xDisplay, xScreen));
2535 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
2536 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
2537 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
2538 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
2539 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
2540 parse_cpair(ColorTell, appData.colorTell) < 0 ||
2541 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
2542 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
2543 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
2544 parse_cpair(ColorNormal, appData.colorNormal) < 0)
2546 if (appData.colorize) {
2548 _("%s: can't parse color names; disabling colorization\n"),
2551 appData.colorize = FALSE;
2553 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2554 textColors[ColorNone].attr = 0;
2556 // XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2562 layoutName = "tinyLayout";
2563 } else if (smallLayout) {
2564 layoutName = "smallLayout";
2566 layoutName = "normalLayout";
2569 if (appData.titleInWindow) {
2570 /* todo check what this appdata does */
2573 if (appData.showButtonBar) {
2574 /* TODO hide button bar if requested */
2578 * gtk set properties of widgets
2581 /* set board size */
2582 gtk_widget_set_size_request(GTK_WIDGET(GUI_Board),
2583 boardWidth,boardHeight);
2585 /* end gtk set properties of widgets */
2587 if (appData.titleInWindow)
2592 if (appData.showButtonBar)
2599 if (appData.showButtonBar)
2608 // [HGM] it seems the layout code ends here, but perhaps the color stuff is size independent and would
2609 // not need to go into InitDrawingSizes().
2612 /* set some checkboxes in the menu according to appData */
2614 if (appData.alwaysPromoteToQueen)
2615 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Always Queen")),TRUE);
2617 if (appData.animateDragging)
2618 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Animate Dragging")),TRUE);
2620 if (appData.animate)
2621 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Animate Moving")),TRUE);
2623 if (appData.autoComment)
2624 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Comment")),TRUE);
2626 if (appData.autoCallFlag)
2627 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Flag")),TRUE);
2629 if (appData.autoFlipView)
2630 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Flip View")),TRUE);
2632 if (appData.autoObserve)
2633 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Observe")),TRUE);
2635 if (appData.autoRaiseBoard)
2636 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Raise Board")),TRUE);
2638 if (appData.autoSaveGames)
2639 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Save")),TRUE);
2641 if (appData.saveGameFile[0] != NULLCHAR)
2643 /* Can't turn this off from menu */
2644 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Save")),TRUE);
2645 gtk_action_set_sensitive(GTK_ACTION (gtk_builder_get_object (builder, "menuOptions.Auto Save")),FALSE);
2648 if (appData.blindfold)
2649 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Blindfold")),TRUE);
2651 if (appData.flashCount > 0)
2652 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Flash Moves")),TRUE);
2654 if (appData.getMoveList)
2655 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Get Move List")),TRUE);
2658 if (appData.highlightDragging)
2659 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Highlight Dragging")),TRUE);
2662 if (appData.highlightLastMove)
2663 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Highlight Last Move")),TRUE);
2665 if (appData.icsAlarm)
2666 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.ICS Alarm")),TRUE);
2668 if (appData.ringBellAfterMoves)
2669 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Move Sound")),TRUE);
2671 if (appData.oldSaveStyle)
2672 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Old Save Style")),TRUE);
2674 if (appData.periodicUpdates)
2675 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Periodic Updates")),TRUE);
2677 if (appData.ponderNextMove)
2678 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Ponder Next Move")),TRUE);
2680 if (appData.popupExitMessage)
2681 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Popup Exit Message")),TRUE);
2683 if (appData.popupMoveErrors)
2684 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Popup Move Errors")),TRUE);
2686 if (appData.premove)
2687 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Premove")),TRUE);
2689 if (appData.quietPlay)
2690 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Quit Play")),TRUE);
2692 if (appData.showCoords)
2693 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Show Coords")),TRUE);
2695 if (appData.showThinking)
2696 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Show Thinking")),TRUE);
2698 if (appData.testLegality)
2699 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Test Legality")),TRUE);
2701 /* end setting check boxes */
2704 /* load square colors */
2705 SVGLightSquare = load_pixbuf("svg/LightSquare.svg",squareSize);
2706 SVGDarkSquare = load_pixbuf("svg/DarkSquare.svg",squareSize);
2707 SVGNeutralSquare = load_pixbuf("svg/NeutralSquare.svg",squareSize);
2709 /* use two icons to indicate if it is white's or black's turn */
2710 WhiteIcon = load_pixbuf("svg/icon_white.svg",0);
2711 BlackIcon = load_pixbuf("svg/icon_black.svg",0);
2712 WindowIcon = WhiteIcon;
2713 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
2715 /* do resizing to a fixed aspect ratio */
2720 GUI_SetAspectRatio(0.7);
2722 /* realize window */
2723 gtk_widget_show (GUI_Window);
2729 if (appData.animate || appData.animateDragging)
2734 if (errorExitStatus == -1) {
2735 if (appData.icsActive) {
2736 /* We now wait until we see "login:" from the ICS before
2737 sending the logon script (problems with timestamp otherwise) */
2738 /*ICSInitScript();*/
2739 if (appData.icsInputBox) ICSInputBoxPopUp();
2742 signal(SIGINT, IntSigHandler);
2743 signal(SIGTERM, IntSigHandler);
2744 if (*appData.cmailGameName != NULLCHAR) {
2745 signal(SIGUSR1, CmailSigHandler);
2748 gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes()
2752 * Create a cursor for the board widget.
2753 * (This needs to be called after the window has been created to have access to board-window)
2756 BoardCursor = gdk_cursor_new(GDK_HAND2);
2757 gdk_window_set_cursor(GUI_Board->window, BoardCursor);
2758 gdk_cursor_destroy(BoardCursor);
2763 if (appData.debugMode) fclose(debugFP); // [DM] debug
2770 if (appData.icsActive && oldICSInteractionTitle != NULL) {
2771 DisplayIcsInteractionTitle(oldICSInteractionTitle);
2773 unlink(gameCopyFilename);
2774 unlink(gamePasteFilename);
2785 CmailSigHandler(sig)
2791 signal(SIGUSR1, SIG_IGN); /* suspend handler */
2793 /* Activate call-back function CmailSigHandlerCallBack() */
2794 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
2796 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
2800 CmailSigHandlerCallBack(isr, closure, message, count, error)
2808 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
2810 /**** end signal code ****/
2820 f = fopen(appData.icsLogon, "r");
2826 strcat(buf, appData.icsLogon);
2827 f = fopen(buf, "r");
2831 ProcessICSInitScript(f);
2838 EditCommentPopDown();
2844 SetMenuEnables(enab)
2849 if (!builder) return;
2850 while (enab->name != NULL) {
2851 o = gtk_builder_get_object(builder, enab->name);
2852 if(GTK_IS_WIDGET(o))
2853 gtk_widget_set_sensitive(GTK_WIDGET (o),enab->value);
2856 if(GTK_IS_ACTION(o))
2857 gtk_action_set_sensitive(GTK_ACTION (o),enab->value);
2859 DisplayError(enab->name, 0);
2867 SetMenuEnables(icsEnables);
2870 if (appData.zippyPlay && !appData.noChessProgram) /* [DM] icsEngineAnalyze */
2871 {}; // XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
2878 SetMenuEnables(ncpEnables);
2884 SetMenuEnables(gnuEnables);
2890 SetMenuEnables(cmailEnables);
2896 SetMenuEnables(trainingOnEnables);
2897 if (appData.showButtonBar) {
2898 // XtSetSensitive(buttonBarWidget, False);
2904 SetTrainingModeOff()
2906 SetMenuEnables(trainingOffEnables);
2907 if (appData.showButtonBar) {
2908 // XtSetSensitive(buttonBarWidget, True);
2913 SetUserThinkingEnables()
2915 if (appData.noChessProgram) return;
2916 SetMenuEnables(userThinkingEnables);
2920 SetMachineThinkingEnables()
2922 if (appData.noChessProgram) return;
2923 SetMenuEnables(machineThinkingEnables);
2925 case MachinePlaysBlack:
2926 case MachinePlaysWhite:
2927 case TwoMachinesPlay:
2928 // XtSetSensitive(XtNameToWidget(menuBarWidget,
2929 // ModeToWidgetName(gameMode)), True);
2936 #define Abs(n) ((n)<0 ? -(n) : (n))
2939 * Find a font that matches "pattern" that is as close as
2940 * possible to the targetPxlSize. Prefer fonts that are k
2941 * pixels smaller to fonts that are k pixels larger. The
2942 * pattern must be in the X Consortium standard format,
2943 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
2944 * The return value should be freed with XtFree when no
2947 char *FindFont(pattern, targetPxlSize)
2951 char **fonts, *p, *best, *scalable, *scalableTail;
2952 int i, j, nfonts, minerr, err, pxlSize;
2955 char **missing_list;
2957 char *def_string, *base_fnt_lst, strInt[3];
2959 XFontStruct **fnt_list;
2961 base_fnt_lst = calloc(1, strlen(pattern) + 3);
2962 sprintf(strInt, "%d", targetPxlSize);
2963 p = strstr(pattern, "--");
2964 strncpy(base_fnt_lst, pattern, p - pattern + 2);
2965 strcat(base_fnt_lst, strInt);
2966 strcat(base_fnt_lst, strchr(p + 2, '-'));
2968 if ((fntSet = XCreateFontSet(xDisplay,
2972 &def_string)) == NULL) {
2974 fprintf(stderr, _("Unable to create font set.\n"));
2978 nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
2980 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
2982 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
2983 programName, pattern);
2991 for (i=0; i<nfonts; i++) {
2994 if (*p != '-') continue;
2996 if (*p == NULLCHAR) break;
2997 if (*p++ == '-') j++;
2999 if (j < 7) continue;
3002 scalable = fonts[i];
3005 err = pxlSize - targetPxlSize;
3006 if (Abs(err) < Abs(minerr) ||
3007 (minerr > 0 && err < 0 && -err == minerr)) {
3013 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
3014 /* If the error is too big and there is a scalable font,
3015 use the scalable font. */
3016 int headlen = scalableTail - scalable;
3017 p = (char *) XtMalloc(strlen(scalable) + 10);
3018 while (isdigit(*scalableTail)) scalableTail++;
3019 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
3021 p = (char *) XtMalloc(strlen(best) + 1);
3024 if (appData.debugMode) {
3025 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
3026 pattern, targetPxlSize, p);
3029 if (missing_count > 0)
3030 XFreeStringList(missing_list);
3031 XFreeFontSet(xDisplay, fntSet);
3033 XFreeFontNames(fonts);
3040 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
3041 | GCBackground | GCFunction | GCPlaneMask;
3042 XGCValues gc_values;
3045 gc_values.plane_mask = AllPlanes;
3046 gc_values.line_width = lineGap;
3047 gc_values.line_style = LineSolid;
3048 gc_values.function = GXcopy;
3050 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3051 gc_values.background = XWhitePixel(xDisplay, xScreen);
3052 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
3053 XSetFont(xDisplay, coordGC, coordFontID);
3055 if (appData.monoMode) {
3056 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3057 gc_values.background = XBlackPixel(xDisplay, xScreen);
3058 lightSquareGC = wbPieceGC
3059 = XtGetGC(shellWidget, value_mask, &gc_values);
3061 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3062 gc_values.background = XWhitePixel(xDisplay, xScreen);
3063 darkSquareGC = bwPieceGC
3064 = XtGetGC(shellWidget, value_mask, &gc_values);
3066 if (DefaultDepth(xDisplay, xScreen) == 1) {
3067 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3068 gc_values.function = GXcopyInverted;
3069 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3070 gc_values.function = GXcopy;
3071 if (XBlackPixel(xDisplay, xScreen) == 1) {
3072 bwPieceGC = darkSquareGC;
3073 wbPieceGC = copyInvertedGC;
3075 bwPieceGC = copyInvertedGC;
3076 wbPieceGC = lightSquareGC;
3080 gc_values.foreground = lightSquareColor;
3081 gc_values.background = darkSquareColor;
3082 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3084 gc_values.foreground = darkSquareColor;
3085 gc_values.background = lightSquareColor;
3086 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3088 gc_values.foreground = jailSquareColor;
3089 gc_values.background = jailSquareColor;
3090 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3092 gc_values.foreground = whitePieceColor;
3093 gc_values.background = darkSquareColor;
3094 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3096 gc_values.foreground = whitePieceColor;
3097 gc_values.background = lightSquareColor;
3098 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3100 gc_values.foreground = whitePieceColor;
3101 gc_values.background = jailSquareColor;
3102 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3104 gc_values.foreground = blackPieceColor;
3105 gc_values.background = darkSquareColor;
3106 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3108 gc_values.foreground = blackPieceColor;
3109 gc_values.background = lightSquareColor;
3110 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3112 gc_values.foreground = blackPieceColor;
3113 gc_values.background = jailSquareColor;
3114 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3121 WhitePawn, WhiteKnight, WhiteBishop, WhiteRook, WhiteQueen, WhiteKing,
3122 BlackPawn, BlackKnight, BlackBishop, BlackRook, BlackQueen, BlackKing,
3126 /* get some defaults going */
3127 for(i=WhitePawn; i<DemotePiece+1; i++)
3128 SVGpieces[i] = load_pixbuf("svg/NeutralSquare.svg",squareSize);
3131 SVGpieces[WhitePawn] = load_pixbuf("svg/WhitePawn.svg",squareSize);
3132 SVGpieces[WhiteKnight] = load_pixbuf("svg/WhiteKnight.svg",squareSize);
3133 SVGpieces[WhiteBishop] = load_pixbuf("svg/WhiteBishop.svg",squareSize);
3134 SVGpieces[WhiteRook] = load_pixbuf("svg/WhiteRook.svg",squareSize);
3135 SVGpieces[WhiteQueen] = load_pixbuf("svg/WhiteQueen.svg",squareSize);
3136 SVGpieces[WhiteKing] = load_pixbuf("svg/WhiteKing.svg",squareSize);
3138 SVGpieces[BlackPawn] = load_pixbuf("svg/BlackPawn.svg",squareSize);
3139 SVGpieces[BlackKnight] = load_pixbuf("svg/BlackKnight.svg",squareSize);
3140 SVGpieces[BlackBishop] = load_pixbuf("svg/BlackBishop.svg",squareSize);
3141 SVGpieces[BlackRook] = load_pixbuf("svg/BlackRook.svg",squareSize);
3142 SVGpieces[BlackQueen] = load_pixbuf("svg/BlackQueen.svg",squareSize);
3143 SVGpieces[BlackKing] = load_pixbuf("svg/BlackKing.svg",squareSize);
3149 static void MenuBarSelect(w, addr, index)
3154 XtActionProc proc = (XtActionProc) addr;
3156 (proc)(NULL, NULL, NULL, NULL);
3159 void CreateMenuBarPopup(parent, name, mb)
3169 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3172 XtSetArg(args[j], XtNleftMargin, 20); j++;
3173 XtSetArg(args[j], XtNrightMargin, 20); j++;
3175 while (mi->string != NULL) {
3176 if (strcmp(mi->string, "----") == 0) {
3177 entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
3180 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string)));
3181 entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass,
3183 XtAddCallback(entry, XtNcallback,
3184 (XtCallbackProc) MenuBarSelect,
3185 (caddr_t) mi->proc);
3191 Widget CreateMenuBar(mb)
3195 Widget anchor, menuBar;
3197 char menuName[MSG_SIZ];
3200 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3201 XtSetArg(args[j], XtNvSpace, 0); j++;
3202 XtSetArg(args[j], XtNborderWidth, 0); j++;
3203 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
3204 formWidget, args, j);
3206 while (mb->name != NULL) {
3207 strcpy(menuName, "menu");
3208 strcat(menuName, mb->name);
3210 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
3213 shortName[0] = _(mb->name)[0];
3214 shortName[1] = NULLCHAR;
3215 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
3218 XtSetArg(args[j], XtNlabel, XtNewString(_(mb->name))); j++;
3221 XtSetArg(args[j], XtNborderWidth, 0); j++;
3222 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
3224 CreateMenuBarPopup(menuBar, menuName, mb);
3230 Widget CreateButtonBar(mi)
3234 Widget button, buttonBar;
3238 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3240 XtSetArg(args[j], XtNhSpace, 0); j++;
3242 XtSetArg(args[j], XtNborderWidth, 0); j++;
3243 XtSetArg(args[j], XtNvSpace, 0); j++;
3244 buttonBar = XtCreateWidget("buttonBar", boxWidgetClass,
3245 formWidget, args, j);
3247 while (mi->string != NULL) {
3250 XtSetArg(args[j], XtNinternalWidth, 2); j++;
3251 XtSetArg(args[j], XtNborderWidth, 0); j++;
3253 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string))); j++;
3254 button = XtCreateManagedWidget(mi->string, commandWidgetClass,
3255 buttonBar, args, j);
3256 XtAddCallback(button, XtNcallback,
3257 (XtCallbackProc) MenuBarSelect,
3258 (caddr_t) mi->proc);
3265 CreatePieceMenu(name, color)
3272 ChessSquare selection;
3274 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3275 boardWidget, args, 0);
3277 for (i = 0; i < PIECE_MENU_SIZE; i++) {
3278 String item = pieceMenuStrings[color][i];
3280 if (strcmp(item, "----") == 0) {
3281 entry = XtCreateManagedWidget(item, smeLineObjectClass,
3284 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3285 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3287 selection = pieceMenuTranslation[color][i];
3288 XtAddCallback(entry, XtNcallback,
3289 (XtCallbackProc) PieceMenuSelect,
3290 (caddr_t) selection);
3291 if (selection == WhitePawn || selection == BlackPawn) {
3292 XtSetArg(args[0], XtNpopupOnEntry, entry);
3293 XtSetValues(menu, args, 1);
3306 ChessSquare selection;
3308 // whitePieceMenu = CreatePieceMenu("menuW", 0);
3309 // blackPieceMenu = CreatePieceMenu("menuB", 1);
3311 // XtRegisterGrabAction(PieceMenuPopup, True,
3312 // (unsigned)(ButtonPressMask|ButtonReleaseMask),
3313 // GrabModeAsync, GrabModeAsync);
3315 // XtSetArg(args[0], XtNlabel, _("Drop"));
3316 // dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
3317 // boardWidget, args, 1);
3318 // for (i = 0; i < DROP_MENU_SIZE; i++) {
3319 // String item = dropMenuStrings[i];
3321 // if (strcmp(item, "----") == 0) {
3322 // entry = XtCreateManagedWidget(item, smeLineObjectClass,
3323 // dropMenu, NULL, 0);
3325 // XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3326 // entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3327 // dropMenu, args, 1);
3328 // selection = dropMenuTranslation[i];
3329 // XtAddCallback(entry, XtNcallback,
3330 // (XtCallbackProc) DropMenuSelect,
3331 // (caddr_t) selection);
3336 void SetupDropMenu()
3344 for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
3345 entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
3346 p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
3347 dmEnables[i].piece);
3348 XtSetSensitive(entry, p != NULL || !appData.testLegality
3349 /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
3350 && !appData.icsActive));
3352 while (p && *p++ == dmEnables[i].piece) count++;
3353 snprintf(label, sizeof(label), "%s %d", dmEnables[i].widget, count);
3355 XtSetArg(args[j], XtNlabel, label); j++;
3356 XtSetValues(entry, args, j);
3360 void PieceMenuPopup(w, event, params, num_params)
3364 Cardinal *num_params;
3367 if (event->type != ButtonPress) return;
3368 if (errorUp) ErrorPopDown();
3372 whichMenu = params[0];
3374 case IcsPlayingWhite:
3375 case IcsPlayingBlack:
3377 case MachinePlaysWhite:
3378 case MachinePlaysBlack:
3379 if (appData.testLegality &&
3380 gameInfo.variant != VariantBughouse &&
3381 gameInfo.variant != VariantCrazyhouse) return;
3383 whichMenu = "menuD";
3389 if (((pmFromX = EventToSquare(event->xbutton.x, BOARD_WIDTH)) < 0) ||
3390 ((pmFromY = EventToSquare(event->xbutton.y, BOARD_HEIGHT)) < 0)) {
3391 pmFromX = pmFromY = -1;
3395 pmFromX = BOARD_WIDTH - 1 - pmFromX;
3397 pmFromY = BOARD_HEIGHT - 1 - pmFromY;
3399 XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
3402 static void PieceMenuSelect(w, piece, junk)
3407 if (pmFromX < 0 || pmFromY < 0) return;
3408 EditPositionMenuEvent(piece, pmFromX, pmFromY);
3411 static void DropMenuSelect(w, piece, junk)
3416 if (pmFromX < 0 || pmFromY < 0) return;
3417 DropMenuEvent(piece, pmFromX, pmFromY);
3420 void WhiteClock(w, event, prms, nprms)
3426 if (gameMode == EditPosition || gameMode == IcsExamining) {
3427 SetWhiteToPlayEvent();
3428 } else if (gameMode == IcsPlayingBlack || gameMode == MachinePlaysWhite) {
3433 void BlackClock(w, event, prms, nprms)
3439 if (gameMode == EditPosition || gameMode == IcsExamining) {
3440 SetBlackToPlayEvent();
3441 } else if (gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) {
3448 * If the user selects on a border boundary, return -1; if off the board,
3449 * return -2. Otherwise map the event coordinate to the square.
3451 int EventToSquare(x, limit)
3459 if ((x % (squareSize + lineGap)) >= squareSize)
3461 x /= (squareSize + lineGap);
3467 static void do_flash_delay(msec)
3473 static void drawHighlight(file, rank, line_type)
3474 int file, rank, line_type;
3479 if (lineGap == 0 || appData.blindfold) return;
3483 x = lineGap/2 + ((BOARD_WIDTH-1)-file) *
3484 (squareSize + lineGap);
3485 y = lineGap/2 + rank * (squareSize + lineGap);
3489 x = lineGap/2 + file * (squareSize + lineGap);
3490 y = lineGap/2 + ((BOARD_HEIGHT-1)-rank) *
3491 (squareSize + lineGap);
3495 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3497 /* draw the highlight */
3498 cairo_move_to (cr, x, y);
3499 cairo_rel_line_to (cr, 0,squareSize+lineGap);
3500 cairo_rel_line_to (cr, squareSize+lineGap,0);
3501 cairo_rel_line_to (cr, 0,-squareSize-lineGap);
3502 cairo_close_path (cr);
3504 cairo_set_line_width (cr, lineGap);
3507 /* TODO: use appdata colors */
3508 case LINE_TYPE_HIGHLIGHT:
3509 cairo_set_source_rgba (cr, 1, 1, 0, 1.0);
3512 cairo_set_source_rgba (cr, 1, 0, 0, 1.0);
3514 case LINE_TYPE_NORMAL:
3516 cairo_set_source_rgba (cr, 0, 1, 0, 1.0);
3527 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
3528 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
3531 SetHighlights(fromX, fromY, toX, toY)
3532 int fromX, fromY, toX, toY;
3534 if (hi1X != fromX || hi1Y != fromY)
3536 if (hi1X >= 0 && hi1Y >= 0)
3538 drawHighlight(hi1X, hi1Y, LINE_TYPE_NORMAL);
3540 if (fromX >= 0 && fromY >= 0)
3542 drawHighlight(fromX, fromY, LINE_TYPE_HIGHLIGHT);
3545 if (hi2X != toX || hi2Y != toY)
3547 if (hi2X >= 0 && hi2Y >= 0)
3549 drawHighlight(hi2X, hi2Y, LINE_TYPE_NORMAL);
3551 if (toX >= 0 && toY >= 0)
3553 drawHighlight(toX, toY, LINE_TYPE_HIGHLIGHT);
3567 SetHighlights(-1, -1, -1, -1);
3572 SetPremoveHighlights(fromX, fromY, toX, toY)
3573 int fromX, fromY, toX, toY;
3575 if (pm1X != fromX || pm1Y != fromY)
3577 if (pm1X >= 0 && pm1Y >= 0)
3579 drawHighlight(pm1X, pm1Y, LINE_TYPE_NORMAL);
3581 if (fromX >= 0 && fromY >= 0)
3583 drawHighlight(fromX, fromY, LINE_TYPE_PRE);
3586 if (pm2X != toX || pm2Y != toY)
3588 if (pm2X >= 0 && pm2Y >= 0)
3590 drawHighlight(pm2X, pm2Y, LINE_TYPE_NORMAL);
3592 if (toX >= 0 && toY >= 0)
3594 drawHighlight(toX, toY, LINE_TYPE_PRE);
3607 ClearPremoveHighlights()
3609 SetPremoveHighlights(-1, -1, -1, -1);
3612 static void BlankSquare(x, y, color, piece, dest)
3625 pb = SVGLightSquare;
3627 case 2: /* neutral */
3629 pb = SVGNeutralSquare;
3632 gdk_draw_pixbuf(GDK_WINDOW(GUI_Board->window),NULL,pb,0,0,x,y,-1,-1, GDK_RGB_DITHER_NORMAL, 0, 0);
3636 static void DrawPiece(piece, square_color, x, y, dest)
3638 int square_color, x, y;
3641 /* redraw background, since piece might be transparent in some areas */
3642 BlankSquare(x,y,square_color,piece,dest);
3645 gdk_draw_pixbuf(GDK_WINDOW(GUI_Board->window),NULL,
3646 GDK_PIXBUF(SVGpieces[piece]),0,0,x,y,-1,-1,
3647 GDK_RGB_DITHER_NORMAL, 0, 0);
3651 /* [HR] determine square color depending on chess variant. */
3652 static int SquareColor(row, column)
3657 if (gameInfo.variant == VariantXiangqi) {
3658 if (column >= 3 && column <= 5 && row >= 0 && row <= 2) {
3660 } else if (column >= 3 && column <= 5 && row >= 7 && row <= 9) {
3662 } else if (row <= 4) {
3668 square_color = ((column + row) % 2) == 1;
3671 /* [hgm] holdings: next line makes all holdings squares light */
3672 if(column < BOARD_LEFT || column >= BOARD_RGHT) square_color = 1;
3674 return square_color;
3677 void DrawSquare(row, column, piece, do_flash)
3678 int row, column, do_flash;
3681 int square_color, x, y;
3686 /* Calculate delay in milliseconds (2-delays per complete flash) */
3687 flash_delay = 500 / appData.flashRate;
3689 /* calculate x and y coordinates from row and column */
3692 x = lineGap + ((BOARD_WIDTH-1)-column) *
3693 (squareSize + lineGap);
3694 y = lineGap + row * (squareSize + lineGap);
3698 x = lineGap + column * (squareSize + lineGap);
3699 y = lineGap + ((BOARD_HEIGHT-1)-row) *
3700 (squareSize + lineGap);
3703 square_color = SquareColor(row, column);
3705 // [HGM] holdings: blank out area between board and holdings
3706 if ( column == BOARD_LEFT-1 || column == BOARD_RGHT
3707 || (column == BOARD_LEFT-2 && row < BOARD_HEIGHT-gameInfo.holdingsSize)
3708 || (column == BOARD_RGHT+1 && row >= gameInfo.holdingsSize) )
3710 BlankSquare(x, y, 2, EmptySquare, xBoardWindow);
3712 // [HGM] print piece counts next to holdings
3713 string[1] = NULLCHAR;
3716 cairo_text_extents_t extents;
3721 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3723 string[0] = '0' + piece;
3725 /* TODO this has to go into the font-selection */
3726 cairo_select_font_face (cr, "Sans",
3727 CAIRO_FONT_SLANT_NORMAL,
3728 CAIRO_FONT_WEIGHT_NORMAL);
3730 cairo_set_font_size (cr, 12.0);
3731 cairo_text_extents (cr, string, &extents);
3733 if (column == (flipView ? BOARD_LEFT-1 : BOARD_RGHT) )
3735 xpos= x + squareSize - extents.width - 2;
3736 ypos= y + extents.y_bearing + 1;
3738 if (column == (flipView ? BOARD_RGHT : BOARD_LEFT-1) && piece > 1)
3741 ypos = y + extents.y_bearing + 1;
3744 /* TODO mono mode? */
3745 cairo_move_to (cr, xpos, ypos);
3746 cairo_text_path (cr, string);
3747 cairo_set_source_rgb (cr, 1.0, 1.0, 1);
3748 cairo_fill_preserve (cr);
3749 cairo_set_source_rgb (cr, 0, 0, 0);
3750 cairo_set_line_width (cr, 0.1);
3759 /* square on the board */
3760 if (piece == EmptySquare || appData.blindfold)
3762 BlankSquare(x, y, square_color, piece, xBoardWindow);
3766 if (do_flash && appData.flashCount > 0)
3768 for (i=0; i<appData.flashCount; ++i)
3771 DrawPiece(piece, square_color, x, y, xBoardWindow);
3772 do_flash_delay(flash_delay);
3774 BlankSquare(x, y, square_color, piece, xBoardWindow);
3775 do_flash_delay(flash_delay);
3778 DrawPiece(piece, square_color, x, y, xBoardWindow);
3782 /* show coordinates if necessary */
3783 if(appData.showCoords)
3785 cairo_text_extents_t extents;
3789 /* TODO this has to go into the font-selection */
3790 cairo_select_font_face (cr, "Sans",
3791 CAIRO_FONT_SLANT_NORMAL,
3792 CAIRO_FONT_WEIGHT_NORMAL);
3793 cairo_set_font_size (cr, 12.0);
3795 string[1] = NULLCHAR;
3798 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3800 if (row == (flipView ? BOARD_HEIGHT-1 : 0) &&
3801 column >= BOARD_LEFT && column < BOARD_RGHT)
3803 string[0] = 'a' + column - BOARD_LEFT;
3804 cairo_text_extents (cr, string, &extents);
3806 xpos = x + squareSize - extents.width - 2;
3807 ypos = y + squareSize - extents.height - extents.y_bearing - 1;
3809 if (appData.monoMode)
3816 cairo_move_to (cr, xpos, ypos);
3817 cairo_text_path (cr, string);
3818 cairo_set_source_rgb (cr, 0.0, 0.0, 0);
3819 cairo_fill_preserve (cr);
3820 cairo_set_source_rgb (cr, 0, 1.0, 0);
3821 cairo_set_line_width (cr, 0.1);
3824 if ( column == (flipView ? BOARD_RGHT-1 : BOARD_LEFT))
3827 string[0] = ONE + row;
3828 cairo_text_extents (cr, string, &extents);
3831 ypos = y + extents.height + 1;
3833 if (appData.monoMode)
3840 cairo_move_to (cr, xpos, ypos);
3841 cairo_text_path (cr, string);
3842 cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
3843 cairo_fill_preserve (cr);
3844 cairo_set_source_rgb (cr, 0, 0, 1.0);
3845 cairo_set_line_width (cr, 0.1);
3857 /* Returns 1 if there are "too many" differences between b1 and b2
3858 (i.e. more than 1 move was made) */
3859 static int too_many_diffs(b1, b2)
3865 for (i=0; i<BOARD_HEIGHT; ++i) {
3866 for (j=0; j<BOARD_WIDTH; ++j) {
3867 if (b1[i][j] != b2[i][j]) {
3868 if (++c > 4) /* Castling causes 4 diffs */
3877 /* Matrix describing castling maneuvers */
3878 /* Row, ColRookFrom, ColKingFrom, ColRookTo, ColKingTo */
3879 static int castling_matrix[4][5] = {
3880 { 0, 0, 4, 3, 2 }, /* 0-0-0, white */
3881 { 0, 7, 4, 5, 6 }, /* 0-0, white */
3882 { 7, 0, 4, 3, 2 }, /* 0-0-0, black */
3883 { 7, 7, 4, 5, 6 } /* 0-0, black */
3886 /* Checks whether castling occurred. If it did, *rrow and *rcol
3887 are set to the destination (row,col) of the rook that moved.
3889 Returns 1 if castling occurred, 0 if not.
3891 Note: Only handles a max of 1 castling move, so be sure
3892 to call too_many_diffs() first.
3894 static int check_castle_draw(newb, oldb, rrow, rcol)
3901 /* For each type of castling... */
3902 for (i=0; i<4; ++i) {
3903 r = castling_matrix[i];
3905 /* Check the 4 squares involved in the castling move */
3907 for (j=1; j<=4; ++j) {
3908 if (newb[r[0]][r[j]] == oldb[r[0]][r[j]]) {
3915 /* All 4 changed, so it must be a castling move */
3924 static int damage[BOARD_SIZE][BOARD_SIZE];
3927 * event handler for redrawing the board
3929 void DrawPosition( repaint, board)
3930 /*Boolean*/int repaint;
3934 static int lastFlipView = 0;
3935 static int lastBoardValid = 0;
3936 static Board lastBoard;
3939 if (board == NULL) {
3940 if (!lastBoardValid) return;
3943 if (!lastBoardValid || lastFlipView != flipView) {
3944 // XtSetArg(args[0], XtNleftBitmap, (flipView ? xMarkPixmap : None));
3945 // XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flip View"),
3950 * It would be simpler to clear the window with XClearWindow()
3951 * but this causes a very distracting flicker.
3954 if (!repaint && lastBoardValid && lastFlipView == flipView)
3956 /* If too much changes (begin observing new game, etc.), don't
3958 do_flash = too_many_diffs(board, lastBoard) ? 0 : 1;
3960 /* Special check for castling so we don't flash both the king
3961 and the rook (just flash the king). */
3964 if (check_castle_draw(board, lastBoard, &rrow, &rcol))
3966 /* Draw rook with NO flashing. King will be drawn flashing later */
3967 DrawSquare(rrow, rcol, board[rrow][rcol], 0);
3968 lastBoard[rrow][rcol] = board[rrow][rcol];
3972 /* First pass -- Draw (newly) empty squares and repair damage.
3973 This prevents you from having a piece show up twice while it
3974 is flashing on its new square */
3975 for (i = 0; i < BOARD_HEIGHT; i++)
3976 for (j = 0; j < BOARD_WIDTH; j++)
3977 if ((board[i][j] != lastBoard[i][j] && board[i][j] == EmptySquare)
3980 DrawSquare(i, j, board[i][j], 0);
3981 damage[i][j] = False;
3984 /* Second pass -- Draw piece(s) in new position and flash them */
3985 for (i = 0; i < BOARD_HEIGHT; i++)
3986 for (j = 0; j < BOARD_WIDTH; j++)
3987 if (board[i][j] != lastBoard[i][j])
3989 DrawSquare(i, j, board[i][j], do_flash);
4001 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
4003 cairo_set_line_width (cr, lineGap);
4005 /* TODO: use appdata colors */
4006 cairo_set_source_rgba (cr, 0, 1, 0, 1.0);
4010 for (i = 0; i < BOARD_HEIGHT + 1; i++)
4013 x2 = lineGap + BOARD_WIDTH * (squareSize + lineGap);
4014 y1 = y2 = lineGap / 2 + (i * (squareSize + lineGap));
4016 cairo_move_to (cr, x1, y1);
4017 cairo_rel_line_to (cr, x2,0);
4021 for (j = 0; j < BOARD_WIDTH + 1; j++)
4024 y2 = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
4025 x1 = x2 = lineGap / 2 + (j * (squareSize + lineGap));
4027 cairo_move_to (cr, x1, y1);
4028 cairo_rel_line_to (cr, 0, y2);
4037 for (i = 0; i < BOARD_HEIGHT; i++)
4038 for (j = 0; j < BOARD_WIDTH; j++)
4040 DrawSquare(i, j, board[i][j], 0);
4041 damage[i][j] = False;
4045 CopyBoard(lastBoard, board);
4047 lastFlipView = flipView;
4049 /* Draw highlights */
4050 if (pm1X >= 0 && pm1Y >= 0)
4052 drawHighlight(pm1X, pm1Y, LINE_TYPE_PRE);
4054 if (pm2X >= 0 && pm2Y >= 0)
4056 drawHighlight(pm2X, pm2Y, LINE_TYPE_PRE);
4058 if (hi1X >= 0 && hi1Y >= 0)
4060 drawHighlight(hi1X, hi1Y, LINE_TYPE_HIGHLIGHT);
4062 if (hi2X >= 0 && hi2Y >= 0)
4064 drawHighlight(hi2X, hi2Y, LINE_TYPE_HIGHLIGHT);
4067 /* If piece being dragged around board, must redraw that too */
4074 * event handler for parsing user moves
4076 // [HGM] This routine will need quite some reworking. Although the backend still supports the old
4077 // way of doing things, by calling UserMoveEvent() to test the legality of the move and then perform
4078 // it at the end, and doing all kind of preliminary tests here (e.g. to weed out self-captures), it
4079 // should be made to use the new way, of calling UserMoveTest early to determine the legality of the
4080 // move, (which will weed out the illegal selfcaptures and moves into the holdings, and flag promotions),
4081 // and at the end FinishMove() to perform the move after optional promotion popups.
4082 // For now I patched it to allow self-capture with King, and suppress clicks between board and holdings.
4083 void HandleUserMove(w, event, prms, nprms)
4090 Boolean saveAnimate;
4091 static int second = 0, promotionChoice = 0;
4094 if (w != boardWidget || errorExitStatus != -1) return;
4096 x = EventToSquare(event->xbutton.x, BOARD_WIDTH);
4097 y = EventToSquare(event->xbutton.y, BOARD_HEIGHT);
4098 if (!flipView && y >= 0) {
4099 y = BOARD_HEIGHT - 1 - y;
4101 if (flipView && x >= 0) {
4102 x = BOARD_WIDTH - 1 - x;
4105 if(promotionChoice) { // we are waiting for a click to indicate promotion piece
4106 if(event->type == ButtonRelease) return; // ignore upclick of click-click destination
4107 promotionChoice = FALSE; // only one chance: if click not OK it is interpreted as cancel
4108 if(appData.debugMode) fprintf(debugFP, "promotion click, x=%d, y=%d\n", x, y);
4109 if(gameInfo.holdingsWidth &&
4110 (WhiteOnMove(currentMove)
4111 ? x == BOARD_WIDTH-1 && y < gameInfo.holdingsSize && y > 0
4112 : x == 0 && y >= BOARD_HEIGHT - gameInfo.holdingsSize && y < BOARD_HEIGHT-1) ) {
4113 // click in right holdings, for determining promotion piece
4114 ChessSquare p = boards[currentMove][y][x];
4115 if(appData.debugMode) fprintf(debugFP, "square contains %d\n", (int)p);
4116 if(p != EmptySquare) {
4117 FinishMove(NormalMove, fromX, fromY, toX, toY, ToLower(PieceToChar(p)));
4122 DrawPosition(FALSE, boards[currentMove]);
4125 if (event->type == ButtonPress) ErrorPopDown();
4128 if (event->type == ButtonPress) {
4129 // XtPopdown(promotionShell);
4130 // XtDestroyWidget(promotionShell);
4131 promotionUp = False;
4139 /* [HGM] holdings: next 5 lines: ignore all clicks between board and holdings */
4140 if(event->type == ButtonPress
4141 && ( x == BOARD_LEFT-1 ||
4143 (x == BOARD_LEFT-2 && y < BOARD_HEIGHT-gameInfo.holdingsSize ) ||
4144 (x == BOARD_RGHT+1 && y >= gameInfo.holdingsSize)) )
4148 if (event->type == ButtonPress) {
4149 /* First square, prepare to drag */
4150 if (OKToStartUserMove(x, y)) {
4154 DragPieceBegin(event->xbutton.x, event->xbutton.y);
4155 if (appData.highlightDragging) {
4156 SetHighlights(x, y, -1, -1);
4164 if (event->type == ButtonRelease && x == fromX && y == fromY) {
4165 /* Click on single square in stead of drag-drop */
4166 DragPieceEnd(event->xbutton.x, event->xbutton.y);
4167 if (appData.animateDragging) {
4168 /* Undo animation damage if any */
4169 DrawPosition(FALSE, NULL);
4172 /* Second up/down in same square; just abort move */
4177 ClearPremoveHighlights();
4179 /* First upclick in same square; start click-click mode */
4180 SetHighlights(x, y, -1, -1);
4185 moveType = UserMoveTest(fromX, fromY, x, y, NULLCHAR, event->type == ButtonRelease);
4187 if (moveType == Comment) { // kludge for indicating capture-own on Press
4188 /* Clicked again on same color piece -- changed his mind */
4189 /* note that re-clicking same square always hits same color piece */
4190 second = (x == fromX && y == fromY);
4191 if (appData.highlightDragging) {
4192 SetHighlights(x, y, -1, -1);
4196 if (OKToStartUserMove(x, y)) {
4199 DragPieceBegin(event->xbutton.x, event->xbutton.y);
4204 if(moveType == AmbiguousMove) { // kludge to indicate edit-position move
4207 DragPieceEnd(event->xbutton.x, event->xbutton.y);
4208 DrawPosition(FALSE, boards[currentMove]);
4212 /* Complete move; (x,y) is now different from (fromX, fromY) on both Press and Release */
4215 saveAnimate = appData.animate;
4216 if (event->type == ButtonPress) {
4217 /* Finish clickclick move */
4218 if (appData.animate || appData.highlightLastMove) {
4219 SetHighlights(fromX, fromY, toX, toY);
4224 /* Finish drag move */
4225 if (appData.highlightLastMove) {
4226 SetHighlights(fromX, fromY, toX, toY);
4230 DragPieceEnd(event->xbutton.x, event->xbutton.y);
4231 /* Don't animate move and drag both */
4232 appData.animate = FALSE;
4234 if (moveType == WhitePromotionKnight || moveType == BlackPromotionKnight ||
4235 (moveType == WhitePromotionQueen || moveType == BlackPromotionQueen) &&
4236 appData.alwaysPromoteToQueen) { // promotion, but no choice
4237 FinishMove(moveType, fromX, fromY, toX, toY, 'q');
4239 if (moveType == WhitePromotionQueen || moveType == BlackPromotionQueen ) {
4240 SetHighlights(fromX, fromY, toX, toY);
4241 if(gameInfo.variant == VariantSuper || gameInfo.variant == VariantGreat) {
4242 // [HGM] super: promotion to captured piece selected from holdings
4243 ChessSquare p = boards[currentMove][fromY][fromX], q = boards[currentMove][toY][toX];
4244 promotionChoice = TRUE;
4245 // kludge follows to temporarily execute move on display, without promoting yet
4246 boards[currentMove][fromY][fromX] = EmptySquare; // move Pawn to 8th rank
4247 boards[currentMove][toY][toX] = p;
4248 DrawPosition(FALSE, boards[currentMove]);
4249 boards[currentMove][fromY][fromX] = p; // take back, but display stays
4250 boards[currentMove][toY][toX] = q;
4251 DisplayMessage("Click in holdings to choose piece", "");
4255 goto skipClearingFrom; // the skipped stuff is done asynchronously by PromotionCallback
4257 if(moveType != ImpossibleMove) { // valid move, but no promotion
4258 FinishMove(moveType, fromX, fromY, toX, toY, NULLCHAR);
4259 } else { // invalid move; could have set premove
4262 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
4263 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
4266 appData.animate = saveAnimate;
4267 if (appData.animate || appData.animateDragging) {
4268 /* Undo animation damage if needed */
4269 DrawPosition(FALSE, NULL);
4273 void AnimateUserMove (Widget w, XEvent * event,
4274 String * params, Cardinal * nParams)
4276 DragPieceMove(event->xmotion.x, event->xmotion.y);
4279 Widget CommentCreate(name, text, mutable, callback, lines)
4281 int /*Boolean*/ mutable;
4282 XtCallbackProc callback;
4286 Widget shell, layout, form, edit, b_ok, b_cancel, b_clear, b_close, b_edit;
4291 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4292 XtGetValues(boardWidget, args, j);
4295 XtSetArg(args[j], XtNresizable, True); j++;
4298 XtCreatePopupShell(name, topLevelShellWidgetClass,
4299 shellWidget, args, j);
4302 XtCreatePopupShell(name, transientShellWidgetClass,
4303 shellWidget, args, j);
4306 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
4307 layoutArgs, XtNumber(layoutArgs));
4309 XtCreateManagedWidget("form", formWidgetClass, layout,
4310 formArgs, XtNumber(formArgs));
4314 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
4315 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
4317 XtSetArg(args[j], XtNstring, text); j++;
4318 XtSetArg(args[j], XtNtop, XtChainTop); j++;
4319 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4320 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4321 XtSetArg(args[j], XtNright, XtChainRight); j++;
4322 XtSetArg(args[j], XtNresizable, True); j++;
4323 XtSetArg(args[j], XtNwidth, bw_width); j++; /*force wider than buttons*/
4324 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
4325 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
4326 XtSetArg(args[j], XtNautoFill, True); j++;
4327 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
4329 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
4333 XtSetArg(args[j], XtNfromVert, edit); j++;
4334 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4335 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4336 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4337 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4339 XtCreateManagedWidget(_("ok"), commandWidgetClass, form, args, j);
4340 XtAddCallback(b_ok, XtNcallback, callback, (XtPointer) 0);
4343 XtSetArg(args[j], XtNfromVert, edit); j++;
4344 XtSetArg(args[j], XtNfromHoriz, b_ok); j++;
4345 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4346 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4347 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4348 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4350 XtCreateManagedWidget(_("cancel"), commandWidgetClass, form, args, j);
4351 XtAddCallback(b_cancel, XtNcallback, callback, (XtPointer) 0);
4354 XtSetArg(args[j], XtNfromVert, edit); j++;
4355 XtSetArg(args[j], XtNfromHoriz, b_cancel); j++;
4356 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4357 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4358 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4359 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4361 XtCreateManagedWidget(_("clear"), commandWidgetClass, form, args, j);
4362 XtAddCallback(b_clear, XtNcallback, callback, (XtPointer) 0);
4365 XtSetArg(args[j], XtNfromVert, edit); j++;
4366 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4367 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4368 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4369 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4371 XtCreateManagedWidget(_("close"), commandWidgetClass, form, args, j);
4372 XtAddCallback(b_close, XtNcallback, callback, (XtPointer) 0);
4375 XtSetArg(args[j], XtNfromVert, edit); j++;
4376 XtSetArg(args[j], XtNfromHoriz, b_close); j++;
4377 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4378 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4379 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4380 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4382 XtCreateManagedWidget(_("edit"), commandWidgetClass, form, args, j);
4383 XtAddCallback(b_edit, XtNcallback, callback, (XtPointer) 0);
4386 XtRealizeWidget(shell);
4388 if (commentX == -1) {
4391 Dimension pw_height;
4392 Dimension ew_height;
4395 XtSetArg(args[j], XtNheight, &ew_height); j++;
4396 XtGetValues(edit, args, j);
4399 XtSetArg(args[j], XtNheight, &pw_height); j++;
4400 XtGetValues(shell, args, j);
4401 commentH = pw_height + (lines - 1) * ew_height;
4402 commentW = bw_width - 16;
4404 XSync(xDisplay, False);
4406 /* This code seems to tickle an X bug if it is executed too soon
4407 after xboard starts up. The coordinates get transformed as if
4408 the main window was positioned at (0, 0).
4410 XtTranslateCoords(shellWidget,
4411 (bw_width - commentW) / 2, 0 - commentH / 2,
4412 &commentX, &commentY);
4414 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
4415 RootWindowOfScreen(XtScreen(shellWidget)),
4416 (bw_width - commentW) / 2, 0 - commentH / 2,
4421 if (commentY < 0) commentY = 0; /*avoid positioning top offscreen*/
4424 XtSetArg(args[j], XtNheight, commentH); j++;
4425 XtSetArg(args[j], XtNwidth, commentW); j++;
4426 XtSetArg(args[j], XtNx, commentX); j++;
4427 XtSetArg(args[j], XtNy, commentY); j++;
4428 XtSetValues(shell, args, j);
4429 XtSetKeyboardFocus(shell, edit);
4434 /* Used for analysis window and ICS input window */
4435 Widget MiscCreate(name, text, mutable, callback, lines)
4437 int /*Boolean*/ mutable;
4438 XtCallbackProc callback;
4442 Widget shell, layout, form, edit;
4444 Dimension bw_width, pw_height, ew_height, w, h;
4450 XtSetArg(args[j], XtNresizable, True); j++;
4453 XtCreatePopupShell(name, topLevelShellWidgetClass,
4454 shellWidget, args, j);
4457 XtCreatePopupShell(name, transientShellWidgetClass,
4458 shellWidget, args, j);
4461 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
4462 layoutArgs, XtNumber(layoutArgs));
4464 XtCreateManagedWidget("form", formWidgetClass, layout,
4465 formArgs, XtNumber(formArgs));
4469 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
4470 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
4472 XtSetArg(args[j], XtNstring, text); j++;
4473 XtSetArg(args[j], XtNtop, XtChainTop); j++;
4474 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4475 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4476 XtSetArg(args[j], XtNright, XtChainRight); j++;
4477 XtSetArg(args[j], XtNresizable, True); j++;
4478 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
4479 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
4480 XtSetArg(args[j], XtNautoFill, True); j++;
4481 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
4483 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
4485 XtRealizeWidget(shell);
4488 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4489 XtGetValues(boardWidget, args, j);
4492 XtSetArg(args[j], XtNheight, &ew_height); j++;
4493 XtGetValues(edit, args, j);
4496 XtSetArg(args[j], XtNheight, &pw_height); j++;
4497 XtGetValues(shell, args, j);
4498 h = pw_height + (lines - 1) * ew_height;
4501 XSync(xDisplay, False);
4503 /* This code seems to tickle an X bug if it is executed too soon
4504 after xboard starts up. The coordinates get transformed as if
4505 the main window was positioned at (0, 0).
4507 XtTranslateCoords(shellWidget, (bw_width - w) / 2, 0 - h / 2, &x, &y);
4509 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
4510 RootWindowOfScreen(XtScreen(shellWidget)),
4511 (bw_width - w) / 2, 0 - h / 2, &xx, &yy, &junk);
4515 if (y < 0) y = 0; /*avoid positioning top offscreen*/
4518 XtSetArg(args[j], XtNheight, h); j++;
4519 XtSetArg(args[j], XtNwidth, w); j++;
4520 XtSetArg(args[j], XtNx, x); j++;
4521 XtSetArg(args[j], XtNy, y); j++;
4522 XtSetValues(shell, args, j);
4528 static int savedIndex; /* gross that this is global */
4530 void EditCommentPopUp(index, title, text)
4539 if (text == NULL) text = "";
4541 if (editShell == NULL) {
4543 CommentCreate(title, text, True, EditCommentCallback, 4);
4544 XtRealizeWidget(editShell);
4545 CatchDeleteWindow(editShell, "EditCommentPopDown");
4547 edit = XtNameToWidget(editShell, "*form.text");
4549 XtSetArg(args[j], XtNstring, text); j++;
4550 XtSetValues(edit, args, j);
4552 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4553 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4554 XtSetValues(editShell, args, j);
4557 XtPopup(editShell, XtGrabNone);
4561 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
4562 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
4566 void EditCommentCallback(w, client_data, call_data)
4568 XtPointer client_data, call_data;
4576 XtSetArg(args[j], XtNlabel, &name); j++;
4577 XtGetValues(w, args, j);
4579 if (strcmp(name, _("ok")) == 0) {
4580 edit = XtNameToWidget(editShell, "*form.text");
4582 XtSetArg(args[j], XtNstring, &val); j++;
4583 XtGetValues(edit, args, j);
4584 ReplaceComment(savedIndex, val);
4585 EditCommentPopDown();
4586 } else if (strcmp(name, _("cancel")) == 0) {
4587 EditCommentPopDown();
4588 } else if (strcmp(name, _("clear")) == 0) {
4589 edit = XtNameToWidget(editShell, "*form.text");
4590 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
4591 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
4595 void EditCommentPopDown()
4600 if (!editUp) return;
4602 XtSetArg(args[j], XtNx, &commentX); j++;
4603 XtSetArg(args[j], XtNy, &commentY); j++;
4604 XtSetArg(args[j], XtNheight, &commentH); j++;
4605 XtSetArg(args[j], XtNwidth, &commentW); j++;
4606 XtGetValues(editShell, args, j);
4607 XtPopdown(editShell);
4610 XtSetArg(args[j], XtNleftBitmap, None); j++;
4611 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
4615 void ICSInputBoxPopUp()
4620 char *title = _("ICS Input");
4623 if (ICSInputShell == NULL) {
4624 ICSInputShell = MiscCreate(title, "", True, NULL, 1);
4625 tr = XtParseTranslationTable(ICSInputTranslations);
4626 edit = XtNameToWidget(ICSInputShell, "*form.text");
4627 XtOverrideTranslations(edit, tr);
4628 XtRealizeWidget(ICSInputShell);
4629 CatchDeleteWindow(ICSInputShell, "ICSInputBoxPopDown");
4632 edit = XtNameToWidget(ICSInputShell, "*form.text");
4634 XtSetArg(args[j], XtNstring, ""); j++;
4635 XtSetValues(edit, args, j);
4637 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4638 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4639 XtSetValues(ICSInputShell, args, j);
4642 XtPopup(ICSInputShell, XtGrabNone);
4643 XtSetKeyboardFocus(ICSInputShell, edit);
4645 ICSInputBoxUp = True;
4647 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
4648 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
4652 void ICSInputSendText()
4659 edit = XtNameToWidget(ICSInputShell, "*form.text");
4661 XtSetArg(args[j], XtNstring, &val); j++;
4662 XtGetValues(edit, args, j);
4663 SendMultiLineToICS(val);
4664 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
4665 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
4668 void ICSInputBoxPopDown()
4673 if (!ICSInputBoxUp) return;
4675 XtPopdown(ICSInputShell);
4676 ICSInputBoxUp = False;
4678 XtSetArg(args[j], XtNleftBitmap, None); j++;
4679 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
4683 void CommentPopUp(title, text)
4690 if (commentShell == NULL) {
4692 CommentCreate(title, text, False, CommentCallback, 4);
4693 XtRealizeWidget(commentShell);
4694 CatchDeleteWindow(commentShell, "CommentPopDown");
4696 edit = XtNameToWidget(commentShell, "*form.text");
4698 XtSetArg(args[j], XtNstring, text); j++;
4699 XtSetValues(edit, args, j);
4701 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4702 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4703 XtSetValues(commentShell, args, j);
4706 XtPopup(commentShell, XtGrabNone);
4707 XSync(xDisplay, False);
4712 void AnalysisPopUp(title, text)
4719 if (analysisShell == NULL) {
4720 analysisShell = MiscCreate(title, text, False, NULL, 4);
4721 XtRealizeWidget(analysisShell);
4722 CatchDeleteWindow(analysisShell, "AnalysisPopDown");
4725 edit = XtNameToWidget(analysisShell, "*form.text");
4727 XtSetArg(args[j], XtNstring, text); j++;
4728 XtSetValues(edit, args, j);
4730 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4731 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4732 XtSetValues(analysisShell, args, j);
4736 XtPopup(analysisShell, XtGrabNone);
4738 XSync(xDisplay, False);
4743 void CommentCallback(w, client_data, call_data)
4745 XtPointer client_data, call_data;
4752 XtSetArg(args[j], XtNlabel, &name); j++;
4753 XtGetValues(w, args, j);
4755 if (strcmp(name, _("close")) == 0) {
4757 } else if (strcmp(name, _("edit")) == 0) {
4764 void CommentPopDown()
4769 if (!commentUp) return;
4771 XtSetArg(args[j], XtNx, &commentX); j++;
4772 XtSetArg(args[j], XtNy, &commentY); j++;
4773 XtSetArg(args[j], XtNwidth, &commentW); j++;
4774 XtSetArg(args[j], XtNheight, &commentH); j++;
4775 XtGetValues(commentShell, args, j);
4776 XtPopdown(commentShell);
4777 XSync(xDisplay, False);
4781 void AnalysisPopDown()
4783 if (!analysisUp) return;
4784 XtPopdown(analysisShell);
4785 XSync(xDisplay, False);
4787 if (appData.icsEngineAnalyze) ExitAnalyzeMode(); /* [DM] icsEngineAnalyze */
4791 void FileNamePopUp(label, def, proc, openMode)
4798 Widget popup, layout, dialog, edit;
4804 fileProc = proc; /* I can't see a way not */
4805 fileOpenMode = openMode; /* to use globals here */
4808 XtSetArg(args[i], XtNresizable, True); i++;
4809 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
4810 XtSetArg(args[i], XtNtitle, XtNewString(_("File name prompt"))); i++;
4811 fileNameShell = popup =
4812 XtCreatePopupShell("File name prompt", transientShellWidgetClass,
4813 shellWidget, args, i);
4816 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
4817 layoutArgs, XtNumber(layoutArgs));
4820 XtSetArg(args[i], XtNlabel, label); i++;
4821 XtSetArg(args[i], XtNvalue, def); i++;
4822 XtSetArg(args[i], XtNborderWidth, 0); i++;
4823 dialog = XtCreateManagedWidget("fileName", dialogWidgetClass,
4826 XawDialogAddButton(dialog, _("ok"), FileNameCallback, (XtPointer) dialog);
4827 XawDialogAddButton(dialog, _("cancel"), FileNameCallback,
4828 (XtPointer) dialog);
4830 XtRealizeWidget(popup);
4831 CatchDeleteWindow(popup, "FileNamePopDown");
4833 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
4834 &x, &y, &win_x, &win_y, &mask);
4836 XtSetArg(args[0], XtNx, x - 10);
4837 XtSetArg(args[1], XtNy, y - 30);
4838 XtSetValues(popup, args, 2);
4840 XtPopup(popup, XtGrabExclusive);
4843 edit = XtNameToWidget(dialog, "*value");
4844 XtSetKeyboardFocus(popup, edit);
4847 void FileNamePopDown()
4849 if (!filenameUp) return;
4850 XtPopdown(fileNameShell);
4851 XtDestroyWidget(fileNameShell);
4856 void FileNameCallback(w, client_data, call_data)
4858 XtPointer client_data, call_data;
4863 XtSetArg(args[0], XtNlabel, &name);
4864 XtGetValues(w, args, 1);
4866 if (strcmp(name, _("cancel")) == 0) {
4871 FileNameAction(w, NULL, NULL, NULL);
4874 void FileNameAction(w, event, prms, nprms)
4886 name = XawDialogGetValueString(w = XtParent(w));
4888 if ((name != NULL) && (*name != NULLCHAR)) {
4890 XtPopdown(w = XtParent(XtParent(w)));
4894 p = strrchr(buf, ' ');
4901 fullname = ExpandPathName(buf);
4903 ErrorPopUp(_("Error"), _("Can't open file"), FALSE);
4906 f = fopen(fullname, fileOpenMode);
4908 DisplayError(_("Failed to open file"), errno);
4910 (void) (*fileProc)(f, index, buf);
4917 XtPopdown(w = XtParent(XtParent(w)));
4923 void PromotionPopUp()
4926 Widget dialog, layout;
4928 Dimension bw_width, pw_width;
4932 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4933 XtGetValues(boardWidget, args, j);
4936 XtSetArg(args[j], XtNresizable, True); j++;
4937 XtSetArg(args[j], XtNtitle, XtNewString(_("Promotion"))); j++;
4939 XtCreatePopupShell("Promotion", transientShellWidgetClass,
4940 shellWidget, args, j);
4942 XtCreateManagedWidget(layoutName, formWidgetClass, promotionShell,
4943 layoutArgs, XtNumber(layoutArgs));
4946 XtSetArg(args[j], XtNlabel, _("Promote to what?")); j++;
4947 XtSetArg(args[j], XtNborderWidth, 0); j++;
4948 dialog = XtCreateManagedWidget("promotion", dialogWidgetClass,
4951 if(gameInfo.variant != VariantShogi) {
4952 XawDialogAddButton(dialog, _("Queen"), PromotionCallback,
4953 (XtPointer) dialog);
4954 XawDialogAddButton(dialog, _("Rook"), PromotionCallback,
4955 (XtPointer) dialog);
4956 XawDialogAddButton(dialog, _("Bishop"), PromotionCallback,
4957 (XtPointer) dialog);
4958 XawDialogAddButton(dialog, _("Knight"), PromotionCallback,
4959 (XtPointer) dialog);
4960 if (!appData.testLegality || gameInfo.variant == VariantSuicide ||
4961 gameInfo.variant == VariantGiveaway) {
4962 XawDialogAddButton(dialog, _("King"), PromotionCallback,
4963 (XtPointer) dialog);
4965 if(gameInfo.variant == VariantCapablanca ||
4966 gameInfo.variant == VariantGothic ||
4967 gameInfo.variant == VariantCapaRandom) {
4968 XawDialogAddButton(dialog, _("Archbishop"), PromotionCallback,
4969 (XtPointer) dialog);
4970 XawDialogAddButton(dialog, _("Chancellor"), PromotionCallback,
4971 (XtPointer) dialog);
4973 } else // [HGM] shogi
4975 XawDialogAddButton(dialog, _("Promote"), PromotionCallback,
4976 (XtPointer) dialog);
4977 XawDialogAddButton(dialog, _("Defer"), PromotionCallback,
4978 (XtPointer) dialog);
4980 XawDialogAddButton(dialog, _("cancel"), PromotionCallback,
4981 (XtPointer) dialog);
4983 XtRealizeWidget(promotionShell);
4984 CatchDeleteWindow(promotionShell, "PromotionPopDown");
4987 XtSetArg(args[j], XtNwidth, &pw_width); j++;
4988 XtGetValues(promotionShell, args, j);
4990 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
4991 lineGap + squareSize/3 +
4992 ((toY == BOARD_HEIGHT-1) ^ (flipView) ?
4993 0 : 6*(squareSize + lineGap)), &x, &y);
4996 XtSetArg(args[j], XtNx, x); j++;
4997 XtSetArg(args[j], XtNy, y); j++;
4998 XtSetValues(promotionShell, args, j);
5000 XtPopup(promotionShell, XtGrabNone);
5005 void PromotionPopDown()
5007 if (!promotionUp) return;
5008 XtPopdown(promotionShell);
5009 XtDestroyWidget(promotionShell);
5010 promotionUp = False;
5013 void PromotionCallback(w, client_data, call_data)
5015 XtPointer client_data, call_data;
5021 XtSetArg(args[0], XtNlabel, &name);
5022 XtGetValues(w, args, 1);
5026 if (fromX == -1) return;
5028 if (strcmp(name, _("cancel")) == 0) {
5032 } else if (strcmp(name, _("Knight")) == 0) {
5034 } else if (strcmp(name, _("Promote")) == 0) {
5036 } else if (strcmp(name, _("Defer")) == 0) {
5039 promoChar = ToLower(name[0]);
5042 FinishMove(NormalMove, fromX, fromY, toX, toY, promoChar);
5044 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
5045 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
5050 void ErrorCallback(w, client_data, call_data)
5052 XtPointer client_data, call_data;
5055 XtPopdown(w = XtParent(XtParent(XtParent(w))));
5057 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5063 if (!errorUp) return;
5067 gtk_widget_destroy(GTK_WIDGET(GUI_Error));
5069 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5074 void ErrorPopUp(title, label, modal)
5075 char *title, *label;
5078 GUI_Error = gtk_message_dialog_new(GTK_WINDOW(GUI_Window),
5079 GTK_DIALOG_DESTROY_WITH_PARENT,
5084 gtk_window_set_title(GTK_WINDOW(GUI_Error),(gchar *) title);
5087 gtk_dialog_run(GTK_DIALOG(GUI_Error));
5088 gtk_widget_destroy(GTK_WIDGET(GUI_Error));
5092 g_signal_connect_swapped (GUI_Error, "response",
5093 G_CALLBACK (ErrorPopDownProc),
5096 gtk_widget_show(GTK_WIDGET(GUI_Error));
5102 /* Disable all user input other than deleting the window */
5103 static int frozen = 0;
5107 /* Grab by a widget that doesn't accept input */
5108 // XtAddGrab(messageWidget, TRUE, FALSE);
5112 /* Undo a FreezeUI */
5115 if (!frozen) return;
5116 // XtRemoveGrab(messageWidget);
5120 char *ModeToWidgetName(mode)
5124 case BeginningOfGame:
5125 if (appData.icsActive)
5126 return "menuMode.ICS Client";
5127 else if (appData.noChessProgram ||
5128 *appData.cmailGameName != NULLCHAR)
5129 return "menuMode.Edit Game";
5131 return "menuMode.Machine Black";
5132 case MachinePlaysBlack:
5133 return "menuMode.Machine Black";
5134 case MachinePlaysWhite:
5135 return "menuMode.Machine White";
5137 return "menuMode.Analysis Mode";
5139 return "menuMode.Analyze File";
5140 case TwoMachinesPlay:
5141 return "menuMode.Two Machines";
5143 return "menuMode.Edit Game";
5144 case PlayFromGameFile:
5145 return "menuFile.Load Game";
5147 return "menuMode.Edit Position";
5149 return "menuMode.Training";
5150 case IcsPlayingWhite:
5151 case IcsPlayingBlack:
5155 return "menuMode.ICS Client";
5162 void ModeHighlight()
5164 static int oldPausing = FALSE;
5165 static GameMode oldmode = (GameMode) -1;
5168 // todo this toggling of the pause button doesn't seem to work?
5169 // e.g. select pause from buttonbar doesn't activate menumode.pause
5171 // if (!boardWidget || !XtIsRealized(boardWidget)) return;
5173 if (pausing != oldPausing) {
5174 oldPausing = pausing;
5175 gtk_button_set_relief(GTK_BUTTON (gtk_builder_get_object (builder, "menuMode.Pause")),pausing?GTK_RELIEF_NORMAL:GTK_RELIEF_NONE);
5176 /* toggle background color in showbuttonbar */
5177 if (appData.showButtonBar) {
5179 gtk_button_pressed(GTK_BUTTON (gtk_builder_get_object (builder, "buttonbar.Pause")));
5181 gtk_button_released(GTK_BUTTON (gtk_builder_get_object (builder, "buttonbar.Pause")));
5186 wname = ModeToWidgetName(oldmode);
5188 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, wname)),True);
5192 /* Maybe all the enables should be handled here, not just this one */
5193 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuMode.Training")),
5194 gameMode == Training || gameMode == PlayFromGameFile);
5199 * Button/menu procedures
5202 int LoadGamePopUp(f, gameNumber, title)
5207 cmailMsgLoaded = FALSE;
5209 if (gameNumber == 0)
5211 int error = GameListBuild(f);
5215 DisplayError(_("Cannot build game list"), error);
5217 else if (!ListEmpty(&gameList)
5218 && ((ListGame *) gameList.tailPred)->number > 1)
5220 GameListPopUp(f, title);
5228 return LoadGame(f, gameNumber, title, FALSE);
5232 void LoadNextPositionProc(w, event, prms, nprms)
5241 void LoadPrevPositionProc(w, event, prms, nprms)
5250 void ReloadPositionProc(w, event, prms, nprms)
5259 void LoadPositionProc(w, event, prms, nprms)
5265 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
5268 FileNamePopUp(_("Load position file name?"), "", LoadPosition, "rb");
5271 void SaveGameProc(w, event, prms, nprms)
5277 FileNamePopUp(_("Save game file name?"),
5278 DefaultFileName(appData.oldSaveStyle ? "game" : "pgn"),
5282 void SavePositionProc(w, event, prms, nprms)
5288 FileNamePopUp(_("Save position file name?"),
5289 DefaultFileName(appData.oldSaveStyle ? "pos" : "fen"),
5293 void ReloadCmailMsgProc(w, event, prms, nprms)
5299 ReloadCmailMsgEvent(FALSE);
5302 void MailMoveProc(w, event, prms, nprms)
5311 /* this variable is shared between CopyPositionProc and SendPositionSelection */
5312 static char *selected_fen_position=NULL;
5315 SendPositionSelection(Widget w, Atom *selection, Atom *target,
5316 Atom *type_return, XtPointer *value_return,
5317 unsigned long *length_return, int *format_return)
5319 char *selection_tmp;
5321 if (!selected_fen_position) return False; /* should never happen */
5322 if (*target == XA_STRING){
5323 /* note: since no XtSelectionDoneProc was registered, Xt will
5324 * automatically call XtFree on the value returned. So have to
5325 * make a copy of it allocated with XtMalloc */
5326 selection_tmp= XtMalloc(strlen(selected_fen_position)+16);
5327 strcpy(selection_tmp, selected_fen_position);
5329 *value_return=selection_tmp;
5330 *length_return=strlen(selection_tmp);
5331 *type_return=XA_STRING;
5332 *format_return = 8; /* bits per byte */
5339 /* note: when called from menu all parameters are NULL, so no clue what the
5340 * Widget which was clicked on was, or what the click event was
5342 void CopyPositionProc(w, event, prms, nprms)
5350 if (selected_fen_position) free(selected_fen_position);
5351 selected_fen_position = (char *)PositionToFEN(currentMove, NULL);
5352 if (!selected_fen_position) return;
5353 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
5355 SendPositionSelection,
5356 NULL/* lose_ownership_proc */ ,
5357 NULL/* transfer_done_proc */);
5359 free(selected_fen_position);
5360 selected_fen_position=NULL;
5364 /* function called when the data to Paste is ready */
5366 PastePositionCB(Widget w, XtPointer client_data, Atom *selection,
5367 Atom *type, XtPointer value, unsigned long *len, int *format)
5370 if (value==NULL || *len==0) return; /* nothing had been selected to copy */
5371 fenstr[*len]='\0'; /* normally this string is terminated, but be safe */
5372 EditPositionPasteFEN(fenstr);
5376 /* called when Paste Position button is pressed,
5377 * all parameters will be NULL */
5378 void PastePositionProc(w, event, prms, nprms)
5384 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
5385 /* (XtSelectionCallbackProc) */ PastePositionCB,
5386 NULL, /* client_data passed to PastePositionCB */
5388 /* better to use the time field from the event that triggered the
5389 * call to this function, but that isn't trivial to get
5397 SendGameSelection(Widget w, Atom *selection, Atom *target,
5398 Atom *type_return, XtPointer *value_return,
5399 unsigned long *length_return, int *format_return)
5401 char *selection_tmp;
5403 if (*target == XA_STRING){
5404 FILE* f = fopen(gameCopyFilename, "r");
5407 if (f == NULL) return False;
5411 selection_tmp = XtMalloc(len + 1);
5412 count = fread(selection_tmp, 1, len, f);
5414 XtFree(selection_tmp);
5417 selection_tmp[len] = NULLCHAR;
5418 *value_return = selection_tmp;
5419 *length_return = len;
5420 *type_return = XA_STRING;
5421 *format_return = 8; /* bits per byte */
5428 /* note: when called from menu all parameters are NULL, so no clue what the
5429 * Widget which was clicked on was, or what the click event was
5431 void CopyGameProc(w, event, prms, nprms)
5439 ret = SaveGameToFile(gameCopyFilename, FALSE);
5442 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
5445 NULL/* lose_ownership_proc */ ,
5446 NULL/* transfer_done_proc */);
5449 /* function called when the data to Paste is ready */
5451 PasteGameCB(Widget w, XtPointer client_data, Atom *selection,
5452 Atom *type, XtPointer value, unsigned long *len, int *format)
5455 if (value == NULL || *len == 0) {
5456 return; /* nothing had been selected to copy */
5458 f = fopen(gamePasteFilename, "w");
5460 DisplayError(_("Can't open temp file"), errno);
5463 fwrite(value, 1, *len, f);
5466 LoadGameFromFile(gamePasteFilename, 0, gamePasteFilename, TRUE);
5469 /* called when Paste Game button is pressed,
5470 * all parameters will be NULL */
5471 void PasteGameProc(w, event, prms, nprms)
5477 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
5478 /* (XtSelectionCallbackProc) */ PasteGameCB,
5479 NULL, /* client_data passed to PasteGameCB */
5481 /* better to use the time field from the event that triggered the
5482 * call to this function, but that isn't trivial to get
5492 SaveGameProc(NULL, NULL, NULL, NULL);
5495 void AnalyzeModeProc(w, event, prms, nprms)
5503 if (!first.analysisSupport) {
5504 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
5505 DisplayError(buf, 0);
5508 /* [DM] icsEngineAnalyze [HGM] This is horrible code; reverse the gameMode and isEngineAnalyze tests! */
5509 if (appData.icsActive) {
5510 if (gameMode != IcsObserving) {
5511 sprintf(buf,_("You are not observing a game"));
5512 DisplayError(buf, 0);
5514 if (appData.icsEngineAnalyze) {
5515 if (appData.debugMode)
5516 fprintf(debugFP, _("Found unexpected active ICS engine analyze \n"));
5522 /* if enable, use want disable icsEngineAnalyze */
5523 if (appData.icsEngineAnalyze) {
5528 appData.icsEngineAnalyze = TRUE;
5529 if (appData.debugMode)
5530 fprintf(debugFP, _("ICS engine analyze starting... \n"));
5532 if (!appData.showThinking)
5533 ShowThinkingProc(w,event,prms,nprms);
5538 void AnalyzeFileProc(w, event, prms, nprms)
5544 if (!first.analysisSupport) {
5546 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
5547 DisplayError(buf, 0);
5552 if (!appData.showThinking)
5553 ShowThinkingProc(w,event,prms,nprms);
5556 FileNamePopUp(_("File to analyze"), "", LoadGamePopUp, "rb");
5557 AnalysisPeriodicEvent(1);
5561 void EditGameProc(w, event, prms, nprms)
5570 void EditPositionProc(w, event, prms, nprms)
5576 EditPositionEvent();
5579 void TrainingProc(w, event, prms, nprms)
5588 void EditCommentProc(w, event, prms, nprms)
5595 EditCommentPopDown();
5601 void IcsInputBoxProc(w, event, prms, nprms)
5607 if (ICSInputBoxUp) {
5608 ICSInputBoxPopDown();
5615 void EnterKeyProc(w, event, prms, nprms)
5621 if (ICSInputBoxUp == True)
5625 void AlwaysQueenProc(w, event, prms, nprms)
5633 appData.alwaysPromoteToQueen = !appData.alwaysPromoteToQueen;
5635 if (appData.alwaysPromoteToQueen) {
5636 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5638 XtSetArg(args[0], XtNleftBitmap, None);
5640 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
5644 void AnimateDraggingProc(w, event, prms, nprms)
5652 appData.animateDragging = !appData.animateDragging;
5654 if (appData.animateDragging) {
5655 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5658 XtSetArg(args[0], XtNleftBitmap, None);
5660 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Dragging"),
5664 void AnimateMovingProc(w, event, prms, nprms)
5672 appData.animate = !appData.animate;
5674 if (appData.animate) {
5675 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5678 XtSetArg(args[0], XtNleftBitmap, None);
5680 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
5684 void AutocommProc(w, event, prms, nprms)
5692 appData.autoComment = !appData.autoComment;
5694 if (appData.autoComment) {
5695 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5697 XtSetArg(args[0], XtNleftBitmap, None);
5699 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
5704 void AutoflagProc(w, event, prms, nprms)
5712 appData.autoCallFlag = !appData.autoCallFlag;
5714 if (appData.autoCallFlag) {
5715 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5717 XtSetArg(args[0], XtNleftBitmap, None);
5719 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
5723 void AutoflipProc(w, event, prms, nprms)
5731 appData.autoFlipView = !appData.autoFlipView;
5733 if (appData.autoFlipView) {
5734 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5736 XtSetArg(args[0], XtNleftBitmap, None);
5738 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flip View"),
5742 void AutobsProc(w, event, prms, nprms)
5750 appData.autoObserve = !appData.autoObserve;
5752 if (appData.autoObserve) {
5753 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5755 XtSetArg(args[0], XtNleftBitmap, None);
5757 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
5761 void AutoraiseProc(w, event, prms, nprms)
5769 appData.autoRaiseBoard = !appData.autoRaiseBoard;
5771 if (appData.autoRaiseBoard) {
5772 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5774 XtSetArg(args[0], XtNleftBitmap, None);
5776 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Raise Board"),
5780 void AutosaveProc(w, event, prms, nprms)
5788 appData.autoSaveGames = !appData.autoSaveGames;
5790 if (appData.autoSaveGames) {
5791 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5793 XtSetArg(args[0], XtNleftBitmap, None);
5795 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
5799 void BlindfoldProc(w, event, prms, nprms)
5807 appData.blindfold = !appData.blindfold;
5809 if (appData.blindfold) {
5810 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5812 XtSetArg(args[0], XtNleftBitmap, None);
5814 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Blindfold"),
5817 DrawPosition(True, NULL);
5820 void TestLegalityProc(w, event, prms, nprms)
5828 appData.testLegality = !appData.testLegality;
5830 if (appData.testLegality) {
5831 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5833 XtSetArg(args[0], XtNleftBitmap, None);
5835 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Test Legality"),
5840 void FlashMovesProc(w, event, prms, nprms)
5848 if (appData.flashCount == 0) {
5849 appData.flashCount = 3;
5851 appData.flashCount = -appData.flashCount;
5854 if (appData.flashCount > 0) {
5855 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5857 XtSetArg(args[0], XtNleftBitmap, None);
5859 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flash Moves"),
5864 void HighlightDraggingProc(w, event, prms, nprms)
5872 appData.highlightDragging = !appData.highlightDragging;
5874 if (appData.highlightDragging) {
5875 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5877 XtSetArg(args[0], XtNleftBitmap, None);
5879 XtSetValues(XtNameToWidget(menuBarWidget,
5880 "menuOptions.Highlight Dragging"), args, 1);
5884 void HighlightLastMoveProc(w, event, prms, nprms)
5892 appData.highlightLastMove = !appData.highlightLastMove;
5894 if (appData.highlightLastMove) {
5895 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5897 XtSetArg(args[0], XtNleftBitmap, None);
5899 XtSetValues(XtNameToWidget(menuBarWidget,
5900 "menuOptions.Highlight Last Move"), args, 1);
5903 void IcsAlarmProc(w, event, prms, nprms)
5911 appData.icsAlarm = !appData.icsAlarm;
5913 if (appData.icsAlarm) {
5914 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5916 XtSetArg(args[0], XtNleftBitmap, None);
5918 XtSetValues(XtNameToWidget(menuBarWidget,
5919 "menuOptions.ICS Alarm"), args, 1);
5922 void MoveSoundProc(w, event, prms, nprms)
5930 appData.ringBellAfterMoves = !appData.ringBellAfterMoves;
5932 if (appData.ringBellAfterMoves) {
5933 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5935 XtSetArg(args[0], XtNleftBitmap, None);
5937 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
5942 void OldSaveStyleProc(w, event, prms, nprms)
5950 appData.oldSaveStyle = !appData.oldSaveStyle;
5952 if (appData.oldSaveStyle) {
5953 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5955 XtSetArg(args[0], XtNleftBitmap, None);
5957 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Old Save Style"),
5961 void PeriodicUpdatesProc(w, event, prms, nprms)
5969 PeriodicUpdatesEvent(!appData.periodicUpdates);
5971 if (appData.periodicUpdates) {
5972 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5974 XtSetArg(args[0], XtNleftBitmap, None);
5976 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Periodic Updates"),
5980 void PonderNextMoveProc(w, event, prms, nprms)
5988 PonderNextMoveEvent(!appData.ponderNextMove);
5990 if (appData.ponderNextMove) {
5991 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5993 XtSetArg(args[0], XtNleftBitmap, None);
5995 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Ponder Next Move"),
5999 void PopupExitMessageProc(w, event, prms, nprms)
6007 appData.popupExitMessage = !appData.popupExitMessage;
6009 if (appData.popupExitMessage) {
6010 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6012 XtSetArg(args[0], XtNleftBitmap, None);
6014 XtSetValues(XtNameToWidget(menuBarWidget,
6015 "menuOptions.Popup Exit Message"), args, 1);
6018 void PopupMoveErrorsProc(w, event, prms, nprms)
6026 appData.popupMoveErrors = !appData.popupMoveErrors;
6028 if (appData.popupMoveErrors) {
6029 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6031 XtSetArg(args[0], XtNleftBitmap, None);
6033 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Popup Move Errors"),
6037 void PremoveProc(w, event, prms, nprms)
6045 appData.premove = !appData.premove;
6047 if (appData.premove) {
6048 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6050 XtSetArg(args[0], XtNleftBitmap, None);
6052 XtSetValues(XtNameToWidget(menuBarWidget,
6053 "menuOptions.Premove"), args, 1);
6056 void QuietPlayProc(w, event, prms, nprms)
6064 appData.quietPlay = !appData.quietPlay;
6066 if (appData.quietPlay) {
6067 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6069 XtSetArg(args[0], XtNleftBitmap, None);
6071 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Quiet Play"),
6075 void ShowThinkingProc(w, event, prms, nprms)
6083 appData.showThinking = !appData.showThinking; // [HGM] thinking: tken out of ShowThinkingEvent
6084 ShowThinkingEvent();
6087 void HideThinkingProc(w, event, prms, nprms)
6095 appData.hideThinkingFromHuman = !appData.hideThinkingFromHuman; // [HGM] thinking: tken out of ShowThinkingEvent
6096 ShowThinkingEvent();
6098 if (appData.hideThinkingFromHuman) {
6099 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6101 XtSetArg(args[0], XtNleftBitmap, None);
6103 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
6107 void DebugProc(w, event, prms, nprms)
6113 appData.debugMode = !appData.debugMode;
6116 void AboutGameProc(w, event, prms, nprms)
6125 void NothingProc(w, event, prms, nprms)
6134 void Iconify(w, event, prms, nprms)
6143 XtSetArg(args[0], XtNiconic, True);
6144 XtSetValues(shellWidget, args, 1);
6147 void DisplayMessage(message, extMessage)
6148 gchar *message, *extMessage;
6155 snprintf(buf, sizeof(buf), "%s %s", message, extMessage);
6158 message = extMessage;
6161 gtk_label_set_text( GTK_LABEL(gtk_builder_get_object (builder, "Messages")),message);
6166 void DisplayTitle(text)
6169 gchar title[MSG_SIZ];
6171 if (text == NULL) text = "";
6173 if (appData.titleInWindow)
6178 if (*text != NULLCHAR)
6180 strcpy(title, text);
6182 else if (appData.icsActive)
6184 snprintf(title, sizeof(title), "%s: %s", programName, appData.icsHost);
6186 else if (appData.cmailGameName[0] != NULLCHAR)
6188 snprintf(title,sizeof(title), "%s: %s", programName, "CMail");
6190 // [HGM] license: This stuff should really be done in back-end, but WinBoard already had a pop-up for it
6192 else if (gameInfo.variant == VariantGothic)
6194 strcpy(title, GOTHIC);
6198 else if (gameInfo.variant == VariantFalcon)
6200 strcpy(title, FALCON);
6203 else if (appData.noChessProgram)
6205 strcpy(title, programName);
6209 snprintf(title,sizeof(title), "%s: %s", programName, first.tidy);
6211 gtk_window_set_title(GTK_WINDOW(GUI_Window),title);
6217 void DisplayError(message, error)
6224 if (appData.debugMode || appData.matchMode) {
6225 fprintf(stderr, "%s: %s\n", programName, message);
6228 if (appData.debugMode || appData.matchMode) {
6229 fprintf(stderr, "%s: %s: %s\n",
6230 programName, message, strerror(error));
6232 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
6235 ErrorPopUp(_("Error"), message, FALSE);
6239 void DisplayMoveError(message)
6244 DrawPosition(FALSE, NULL);
6245 if (appData.debugMode || appData.matchMode) {
6246 fprintf(stderr, "%s: %s\n", programName, message);
6248 if (appData.popupMoveErrors) {
6249 ErrorPopUp(_("Error"), message, FALSE);
6251 DisplayMessage(message, "");
6256 void DisplayFatalError(message, error, status)
6262 errorExitStatus = status;
6264 fprintf(stderr, "%s: %s\n", programName, message);
6266 fprintf(stderr, "%s: %s: %s\n",
6267 programName, message, strerror(error));
6268 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
6271 if (appData.popupExitMessage && boardWidget && XtIsRealized(boardWidget)) {
6272 ErrorPopUp(status ? _("Fatal Error") : _("Exiting"), message, TRUE);
6278 void DisplayInformation(message)
6282 ErrorPopUp(_("Information"), message, TRUE);
6285 void DisplayNote(message)
6289 ErrorPopUp(_("Note"), message, FALSE);
6293 NullXErrorCheck(dpy, error_event)
6295 XErrorEvent *error_event;
6300 void DisplayIcsInteractionTitle(message)
6303 if (oldICSInteractionTitle == NULL) {
6304 /* Magic to find the old window title, adapted from vim */
6305 char *wina = getenv("WINDOWID");
6307 Window win = (Window) atoi(wina);
6308 Window root, parent, *children;
6309 unsigned int nchildren;
6310 int (*oldHandler)() = XSetErrorHandler(NullXErrorCheck);
6312 if (XFetchName(xDisplay, win, &oldICSInteractionTitle)) break;
6313 if (!XQueryTree(xDisplay, win, &root, &parent,
6314 &children, &nchildren)) break;
6315 if (children) XFree((void *)children);
6316 if (parent == root || parent == 0) break;
6319 XSetErrorHandler(oldHandler);
6321 if (oldICSInteractionTitle == NULL) {
6322 oldICSInteractionTitle = "xterm";
6325 printf("\033]0;%s\007", message);
6329 char pendingReplyPrefix[MSG_SIZ];
6330 ProcRef pendingReplyPR;
6332 void AskQuestionProc(w, event, prms, nprms)
6339 fprintf(stderr, _("AskQuestionProc needed 4 parameters, got %d\n"),
6343 AskQuestionEvent(prms[0], prms[1], prms[2], prms[3]);
6346 void AskQuestionPopDown()
6348 if (!askQuestionUp) return;
6349 XtPopdown(askQuestionShell);
6350 XtDestroyWidget(askQuestionShell);
6351 askQuestionUp = False;
6354 void AskQuestionReplyAction(w, event, prms, nprms)
6364 reply = XawDialogGetValueString(w = XtParent(w));
6365 strcpy(buf, pendingReplyPrefix);
6366 if (*buf) strcat(buf, " ");
6369 OutputToProcess(pendingReplyPR, buf, strlen(buf), &err);
6370 AskQuestionPopDown();
6372 if (err) DisplayFatalError(_("Error writing to chess program"), err, 0);
6375 void AskQuestionCallback(w, client_data, call_data)
6377 XtPointer client_data, call_data;
6382 XtSetArg(args[0], XtNlabel, &name);
6383 XtGetValues(w, args, 1);
6385 if (strcmp(name, _("cancel")) == 0) {
6386 AskQuestionPopDown();
6388 AskQuestionReplyAction(w, NULL, NULL, NULL);
6392 void AskQuestion(title, question, replyPrefix, pr)
6393 char *title, *question, *replyPrefix;
6397 Widget popup, layout, dialog, edit;
6403 strcpy(pendingReplyPrefix, replyPrefix);
6404 pendingReplyPR = pr;
6407 XtSetArg(args[i], XtNresizable, True); i++;
6408 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
6409 askQuestionShell = popup =
6410 XtCreatePopupShell(title, transientShellWidgetClass,
6411 shellWidget, args, i);
6414 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
6415 layoutArgs, XtNumber(layoutArgs));
6418 XtSetArg(args[i], XtNlabel, question); i++;
6419 XtSetArg(args[i], XtNvalue, ""); i++;
6420 XtSetArg(args[i], XtNborderWidth, 0); i++;
6421 dialog = XtCreateManagedWidget("question", dialogWidgetClass,
6424 XawDialogAddButton(dialog, _("enter"), AskQuestionCallback,
6425 (XtPointer) dialog);
6426 XawDialogAddButton(dialog, _("cancel"), AskQuestionCallback,
6427 (XtPointer) dialog);
6429 XtRealizeWidget(popup);
6430 CatchDeleteWindow(popup, "AskQuestionPopDown");
6432 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
6433 &x, &y, &win_x, &win_y, &mask);
6435 XtSetArg(args[0], XtNx, x - 10);
6436 XtSetArg(args[1], XtNy, y - 30);
6437 XtSetValues(popup, args, 2);
6439 XtPopup(popup, XtGrabExclusive);
6440 askQuestionUp = True;
6442 edit = XtNameToWidget(dialog, "*value");
6443 XtSetKeyboardFocus(popup, edit);
6451 if (*name == NULLCHAR) {
6453 } else if (strcmp(name, "$") == 0) {
6454 putc(BELLCHAR, stderr);
6457 snprintf(buf, sizeof(buf), "%s '%s' &", appData.soundProgram, name);
6465 PlaySound(appData.soundMove);
6471 PlaySound(appData.soundIcsWin);
6477 PlaySound(appData.soundIcsLoss);
6483 PlaySound(appData.soundIcsDraw);
6487 PlayIcsUnfinishedSound()
6489 PlaySound(appData.soundIcsUnfinished);
6495 PlaySound(appData.soundIcsAlarm);
6501 system("stty echo");
6507 system("stty -echo");
6511 Colorize(cc, continuation)
6516 int count, outCount, error;
6518 if (textColors[(int)cc].bg > 0) {
6519 if (textColors[(int)cc].fg > 0) {
6520 sprintf(buf, "\033[0;%d;%d;%dm", textColors[(int)cc].attr,
6521 textColors[(int)cc].fg, textColors[(int)cc].bg);
6523 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
6524 textColors[(int)cc].bg);
6527 if (textColors[(int)cc].fg > 0) {
6528 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
6529 textColors[(int)cc].fg);
6531 sprintf(buf, "\033[0;%dm", textColors[(int)cc].attr);
6534 count = strlen(buf);
6535 outCount = OutputToProcess(NoProc, buf, count, &error);
6536 if (outCount < count) {
6537 DisplayFatalError(_("Error writing to display"), error, 1);
6540 if (continuation) return;
6543 PlaySound(appData.soundShout);
6546 PlaySound(appData.soundSShout);
6549 PlaySound(appData.soundChannel1);
6552 PlaySound(appData.soundChannel);
6555 PlaySound(appData.soundKibitz);
6558 PlaySound(appData.soundTell);
6560 case ColorChallenge:
6561 PlaySound(appData.soundChallenge);
6564 PlaySound(appData.soundRequest);
6567 PlaySound(appData.soundSeek);
6578 return getpwuid(getuid())->pw_name;
6581 static char *ExpandPathName(path)
6584 static char static_buf[2000];
6585 char *d, *s, buf[2000];
6591 while (*s && isspace(*s))
6600 if (*(s+1) == '/') {
6601 strcpy(d, getpwuid(getuid())->pw_dir);
6606 *strchr(buf, '/') = 0;
6607 pwd = getpwnam(buf);
6610 fprintf(stderr, _("ERROR: Unknown user %s (in path %s)\n"),
6614 strcpy(d, pwd->pw_dir);
6615 strcat(d, strchr(s+1, '/'));
6626 static char host_name[MSG_SIZ];
6628 #if HAVE_GETHOSTNAME
6629 gethostname(host_name, MSG_SIZ);
6631 #else /* not HAVE_GETHOSTNAME */
6632 # if HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H
6633 sysinfo(SI_HOSTNAME, host_name, MSG_SIZ);
6635 # else /* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
6637 # endif/* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
6638 #endif /* not HAVE_GETHOSTNAME */
6641 guint delayedEventTimerTag = 0;
6642 DelayedEventCallback delayedEventCallback = 0;
6645 FireDelayedEvent(data)
6649 g_source_remove(delayedEventTimerTag);
6650 delayedEventTimerTag = 0;
6653 delayedEventCallback();
6659 ScheduleDelayedEvent(cb, millisec)
6660 DelayedEventCallback cb; guint millisec;
6662 if(delayedEventTimerTag && delayedEventCallback == cb)
6663 // [HGM] alive: replace, rather than add or flush identical event
6664 g_source_remove(delayedEventTimerTag);
6665 delayedEventCallback = cb;
6666 delayedEventTimerTag = g_timeout_add(millisec,(GSourceFunc) FireDelayedEvent, NULL);
6670 DelayedEventCallback
6673 if (delayedEventTimerTag)
6675 return delayedEventCallback;
6684 CancelDelayedEvent()
6686 if (delayedEventTimerTag)
6688 g_source_remove(delayedEventTimerTag);
6689 delayedEventTimerTag = 0;
6695 guint loadGameTimerTag = 0;
6697 int LoadGameTimerRunning()
6699 return loadGameTimerTag != 0;
6702 int StopLoadGameTimer()
6704 if (loadGameTimerTag != 0) {
6705 g_source_remove(loadGameTimerTag);
6706 loadGameTimerTag = 0;
6714 LoadGameTimerCallback(data)
6718 g_source_remove(loadGameTimerTag);
6719 loadGameTimerTag = 0;
6726 StartLoadGameTimer(millisec)
6730 g_timeout_add( millisec, (GSourceFunc) LoadGameTimerCallback, NULL);
6734 guint analysisClockTag = 0;
6737 AnalysisClockCallback(data)
6740 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile
6741 || appData.icsEngineAnalyze)
6743 AnalysisPeriodicEvent(0);
6744 return 1; /* keep on going */
6746 return 0; /* stop timer */
6750 StartAnalysisClock()
6753 g_timeout_add( 2000,(GSourceFunc) AnalysisClockCallback, NULL);
6757 guint clockTimerTag = 0;
6759 int ClockTimerRunning()
6761 return clockTimerTag != 0;
6764 int StopClockTimer()
6766 if (clockTimerTag != 0)
6768 g_source_remove(clockTimerTag);
6779 ClockTimerCallback(data)
6783 g_source_remove(clockTimerTag);
6791 StartClockTimer(millisec)
6794 clockTimerTag = g_timeout_add(millisec,(GSourceFunc) ClockTimerCallback,NULL);
6799 DisplayTimerLabel(w, color, timer, highlight)
6808 if (appData.clockMode) {
6809 sprintf(buf, "%s: %s", color, TimeString(timer));
6811 sprintf(buf, "%s ", color);
6813 gtk_label_set_text(GTK_LABEL(w),buf);
6815 /* check for low time warning */
6816 // Pixel foregroundOrWarningColor = timerForegroundPixel;
6819 // appData.lowTimeWarning &&
6820 // (timer / 1000) < appData.icsAlarmTime)
6821 // foregroundOrWarningColor = lowTimeWarningColor;
6823 // if (appData.clockMode) {
6824 // sprintf(buf, "%s: %s", color, TimeString(timer));
6825 // XtSetArg(args[0], XtNlabel, buf);
6827 // sprintf(buf, "%s ", color);
6828 // XtSetArg(args[0], XtNlabel, buf);
6833 // XtSetArg(args[1], XtNbackground, foregroundOrWarningColor);
6834 // XtSetArg(args[2], XtNforeground, timerBackgroundPixel);
6836 // XtSetArg(args[1], XtNbackground, timerBackgroundPixel);
6837 // XtSetArg(args[2], XtNforeground, foregroundOrWarningColor);
6840 // XtSetValues(w, args, 3);
6845 DisplayWhiteClock(timeRemaining, highlight)
6849 if(appData.noGUI) return;
6851 DisplayTimerLabel(GUI_Whiteclock, _("White"), timeRemaining, highlight);
6852 if (highlight && WindowIcon == BlackIcon)
6854 WindowIcon = WhiteIcon;
6855 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
6860 DisplayBlackClock(timeRemaining, highlight)
6864 if(appData.noGUI) return;
6866 DisplayTimerLabel(GUI_Blackclock, _("Black"), timeRemaining, highlight);
6867 if (highlight && WindowIcon == WhiteIcon)
6869 WindowIcon = BlackIcon;
6870 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
6888 int StartChildProcess(cmdLine, dir, pr)
6895 int to_prog[2], from_prog[2];
6899 if (appData.debugMode) {
6900 fprintf(stderr, "StartChildProcess (dir=\"%s\") %s\n",dir, cmdLine);
6903 /* We do NOT feed the cmdLine to the shell; we just
6904 parse it into blank-separated arguments in the
6905 most simple-minded way possible.
6908 strcpy(buf, cmdLine);
6913 if (p == NULL) break;
6918 SetUpChildIO(to_prog, from_prog);
6920 if ((pid = fork()) == 0) {
6922 // [HGM] PSWBTM: made order resistant against case where fd of created pipe was 0 or 1
6923 close(to_prog[1]); // first close the unused pipe ends
6924 close(from_prog[0]);
6925 dup2(to_prog[0], 0); // to_prog was created first, nd is the only one to use 0 or 1
6926 dup2(from_prog[1], 1);
6927 if(to_prog[0] >= 2) close(to_prog[0]); // if 0 or 1, the dup2 already cosed the original
6928 close(from_prog[1]); // and closing again loses one of the pipes!
6929 if(fileno(stderr) >= 2) // better safe than sorry...
6930 dup2(1, fileno(stderr)); /* force stderr to the pipe */
6932 if (dir[0] != NULLCHAR && chdir(dir) != 0) {
6937 nice(appData.niceEngines); // [HGM] nice: adjust priority of engine proc
6939 execvp(argv[0], argv);
6941 /* If we get here, exec failed */
6946 /* Parent process */
6948 close(from_prog[1]);
6950 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
6953 cp->fdFrom = from_prog[0];
6954 cp->fdTo = to_prog[1];
6959 // [HGM] kill: implement the 'hard killing' of AS's Winboard_x
6960 static RETSIGTYPE AlarmCallBack(int n)
6966 DestroyChildProcess(pr, signalType)
6970 ChildProc *cp = (ChildProc *) pr;
6972 if (cp->kind != CPReal) return;
6974 if (signalType == 10) { // [HGM] kill: if it does not terminate in 3 sec, kill
6975 signal(SIGALRM, AlarmCallBack);
6977 if(wait((int *) 0) == -1) { // process does not terminate on its own accord
6978 kill(cp->pid, SIGKILL); // kill it forcefully
6979 wait((int *) 0); // and wait again
6983 kill(cp->pid, signalType == 9 ? SIGKILL : SIGTERM); // [HGM] kill: use hard kill if so requested
6985 /* Process is exiting either because of the kill or because of
6986 a quit command sent by the backend; either way, wait for it to die.
6995 InterruptChildProcess(pr)
6998 ChildProc *cp = (ChildProc *) pr;
7000 if (cp->kind != CPReal) return;
7001 (void) kill(cp->pid, SIGINT); /* stop it thinking */
7004 int OpenTelnet(host, port, pr)
7009 char cmdLine[MSG_SIZ];
7011 if (port[0] == NULLCHAR) {
7012 snprintf(cmdLine, sizeof(cmdLine), "%s %s", appData.telnetProgram, host);
7014 snprintf(cmdLine, sizeof(cmdLine), "%s %s %s", appData.telnetProgram, host, port);
7016 return StartChildProcess(cmdLine, "", pr);
7019 int OpenTCP(host, port, pr)
7025 DisplayFatalError(_("Socket support is not configured in"), 0, 2);
7026 #else /* !OMIT_SOCKETS */
7028 struct sockaddr_in sa;
7030 unsigned short uport;
7033 if ((s = socket(AF_INET, SOCK_STREAM, 6)) < 0) {
7037 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
7038 sa.sin_family = AF_INET;
7039 sa.sin_addr.s_addr = INADDR_ANY;
7040 uport = (unsigned short) 0;
7041 sa.sin_port = htons(uport);
7042 if (bind(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)) < 0) {
7046 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
7047 if (!(hp = gethostbyname(host))) {
7049 if (sscanf(host, "%d.%d.%d.%d", &b0, &b1, &b2, &b3) == 4) {
7050 hp = (struct hostent *) calloc(1, sizeof(struct hostent));
7051 hp->h_addrtype = AF_INET;
7053 hp->h_addr_list = (char **) calloc(2, sizeof(char *));
7054 hp->h_addr_list[0] = (char *) malloc(4);
7055 hp->h_addr_list[0][0] = b0;
7056 hp->h_addr_list[0][1] = b1;
7057 hp->h_addr_list[0][2] = b2;
7058 hp->h_addr_list[0][3] = b3;
7063 sa.sin_family = hp->h_addrtype;
7064 uport = (unsigned short) atoi(port);
7065 sa.sin_port = htons(uport);
7066 memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);
7068 if (connect(s, (struct sockaddr *) &sa,
7069 sizeof(struct sockaddr_in)) < 0) {
7073 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7080 #endif /* !OMIT_SOCKETS */
7085 int OpenCommPort(name, pr)
7092 fd = open(name, 2, 0);
7093 if (fd < 0) return errno;
7095 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7105 int OpenLoopback(pr)
7111 SetUpChildIO(to, from);
7113 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7116 cp->fdFrom = to[0]; /* note not from[0]; we are doing a loopback */
7123 int OpenRcmd(host, user, cmd, pr)
7124 char *host, *user, *cmd;
7127 DisplayFatalError(_("internal rcmd not implemented for Unix"), 0, 1);
7131 #define INPUT_SOURCE_BUF_SIZE 8192
7140 char buf[INPUT_SOURCE_BUF_SIZE];
7145 DoInputCallback(io,cond,data)
7150 /* read input from one of the input source (for example a chess program, ICS, etc).
7151 * and call a function that will handle the input
7154 int count; /* how many bytes did we read */
7158 /* All information (callback function, file descriptor, etc) is
7159 * saved in an InputSource structure
7161 InputSource *is = (InputSource *) data;
7165 count = read(is->fd, is->unused,
7166 INPUT_SOURCE_BUF_SIZE - (is->unused - is->buf));
7170 (is->func)(is, is->closure, is->buf, count, count ? errno : 0);
7173 is->unused += count;
7175 /* break input into lines and call the callback function on each
7178 while (p < is->unused)
7180 q = memchr(p, '\n', is->unused - p);
7181 if (q == NULL) break;
7183 (is->func)(is, is->closure, p, q - p, 0);
7186 /* remember not yet used part of the buffer */
7188 while (p < is->unused)
7196 /* read maximum length of input buffer and send the whole buffer
7197 * to the callback function
7199 count = read(is->fd, is->buf, INPUT_SOURCE_BUF_SIZE);
7204 (is->func)(is, is->closure, is->buf, count, error);
7210 InputSourceRef AddInputSource(pr, lineByLine, func, closure)
7217 GIOChannel *channel;
7218 ChildProc *cp = (ChildProc *) pr;
7220 is = (InputSource *) calloc(1, sizeof(InputSource));
7221 is->lineByLine = lineByLine;
7225 is->fd = fileno(stdin);
7227 is->kind = cp->kind;
7228 is->fd = cp->fdFrom;
7231 is->unused = is->buf;
7235 // is->xid = XtAppAddInput(appContext, is->fd,
7236 // (XtPointer) (XtInputReadMask),
7237 // (XtInputCallbackProc) DoInputCallback,
7241 /* TODO: will this work on windows?*/
7242 printf("DEBUG: fd=%d %d\n",is->fd,is);
7244 channel = g_io_channel_unix_new(is->fd);
7245 g_io_channel_set_close_on_unref (channel, TRUE);
7246 is->sid = g_io_add_watch(channel, G_IO_IN,(GIOFunc) DoInputCallback, is);
7247 is->closure = closure;
7248 return (InputSourceRef) is;
7252 RemoveInputSource(isr)
7255 InputSource *is = (InputSource *) isr;
7257 if (is->sid == 0) return;
7258 g_source_remove(is->sid);
7263 int OutputToProcess(pr, message, count, outError)
7269 ChildProc *cp = (ChildProc *) pr;
7273 outCount = fwrite(message, 1, count, stdout);
7275 outCount = write(cp->fdTo, message, count);
7285 /* Output message to process, with "ms" milliseconds of delay
7286 between each character. This is needed when sending the logon
7287 script to ICC, which for some reason doesn't like the
7288 instantaneous send. */
7289 int OutputToProcessDelayed(pr, message, count, outError, msdelay)
7296 ChildProc *cp = (ChildProc *) pr;
7301 r = write(cp->fdTo, message++, 1);
7314 /**** Animation code by Hugh Fisher, DCS, ANU.
7316 Known problem: if a window overlapping the board is
7317 moved away while a piece is being animated underneath,
7318 the newly exposed area won't be updated properly.
7319 I can live with this.
7321 Known problem: if you look carefully at the animation
7322 of pieces in mono mode, they are being drawn as solid
7323 shapes without interior detail while moving. Fixing
7324 this would be a major complication for minimal return.
7327 /* Masks for XPM pieces. Black and white pieces can have
7328 different shapes, but in the interest of retaining my
7329 sanity pieces must have the same outline on both light
7330 and dark squares, and all pieces must use the same
7331 background square colors/images. */
7333 static int xpmDone = 0;
7336 CreateAnimMasks (pieceDepth)
7343 unsigned long plane;
7346 /* just return for gtk at the moment */
7349 /* Need a bitmap just to get a GC with right depth */
7350 buf = XCreatePixmap(xDisplay, xBoardWindow,
7352 values.foreground = 1;
7353 values.background = 0;
7354 /* Don't use XtGetGC, not read only */
7355 maskGC = XCreateGC(xDisplay, buf,
7356 GCForeground | GCBackground, &values);
7357 XFreePixmap(xDisplay, buf);
7359 buf = XCreatePixmap(xDisplay, xBoardWindow,
7360 squareSize, squareSize, pieceDepth);
7361 values.foreground = XBlackPixel(xDisplay, xScreen);
7362 values.background = XWhitePixel(xDisplay, xScreen);
7363 bufGC = XCreateGC(xDisplay, buf,
7364 GCForeground | GCBackground, &values);
7366 for (piece = WhitePawn; piece <= BlackKing; piece++) {
7367 /* Begin with empty mask */
7368 if(!xpmDone) // [HGM] pieces: keep using existing
7369 xpmMask[piece] = XCreatePixmap(xDisplay, xBoardWindow,
7370 squareSize, squareSize, 1);
7371 XSetFunction(xDisplay, maskGC, GXclear);
7372 XFillRectangle(xDisplay, xpmMask[piece], maskGC,
7373 0, 0, squareSize, squareSize);
7375 /* Take a copy of the piece */
7380 XSetFunction(xDisplay, bufGC, GXcopy);
7381 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn],
7383 0, 0, squareSize, squareSize, 0, 0);
7385 /* XOR the background (light) over the piece */
7386 XSetFunction(xDisplay, bufGC, GXxor);
7388 XCopyArea(xDisplay, xpmLightSquare, buf, bufGC,
7389 0, 0, squareSize, squareSize, 0, 0);
7391 XSetForeground(xDisplay, bufGC, lightSquareColor);
7392 XFillRectangle(xDisplay, buf, bufGC, 0, 0, squareSize, squareSize);
7395 /* We now have an inverted piece image with the background
7396 erased. Construct mask by just selecting all the non-zero
7397 pixels - no need to reconstruct the original image. */
7398 XSetFunction(xDisplay, maskGC, GXor);
7400 /* Might be quicker to download an XImage and create bitmap
7401 data from it rather than this N copies per piece, but it
7402 only takes a fraction of a second and there is a much
7403 longer delay for loading the pieces. */
7404 for (n = 0; n < pieceDepth; n ++) {
7405 XCopyPlane(xDisplay, buf, xpmMask[piece], maskGC,
7406 0, 0, squareSize, squareSize,
7412 XFreePixmap(xDisplay, buf);
7413 XFreeGC(xDisplay, bufGC);
7414 XFreeGC(xDisplay, maskGC);
7418 InitAnimState (anim, info)
7420 XWindowAttributes * info;
7425 /* Each buffer is square size, same depth as window */
7426 // anim->saveBuf = XCreatePixmap(xDisplay, xBoardWindow,
7427 // squareSize, squareSize, info->depth);
7428 // anim->newBuf = XCreatePixmap(xDisplay, xBoardWindow,
7429 // squareSize, squareSize, info->depth);
7431 // /* Create a plain GC for blitting */
7432 // mask = GCForeground | GCBackground | GCFunction |
7433 // GCPlaneMask | GCGraphicsExposures;
7434 // values.foreground = XBlackPixel(xDisplay, xScreen);
7435 // values.background = XWhitePixel(xDisplay, xScreen);
7436 // values.function = GXcopy;
7437 // values.plane_mask = AllPlanes;
7438 // values.graphics_exposures = False;
7439 // anim->blitGC = XCreateGC(xDisplay, xBoardWindow, mask, &values);
7441 // /* Piece will be copied from an existing context at
7442 // the start of each new animation/drag. */
7443 // anim->pieceGC = XCreateGC(xDisplay, xBoardWindow, 0, &values);
7445 // /* Outline will be a read-only copy of an existing */
7446 // anim->outlineGC = None;
7452 static VariantClass old = (VariantClass) -1; // [HGM] pieces: redo every time variant changes
7453 XWindowAttributes info;
7455 /* for gtk at the moment just ... */
7458 if (xpmDone && gameInfo.variant == old) return;
7459 if(xpmDone) old = gameInfo.variant; // first time pieces might not be created yet
7460 // XGetWindowAttributes(xDisplay, xBoardWindow, &info);
7462 // InitAnimState(&game, &info);
7463 // InitAnimState(&player, &info);
7465 /* For XPM pieces, we need bitmaps to use as masks. */
7467 // CreateAnimMasks(info.depth);
7473 static Boolean frameWaiting;
7475 static RETSIGTYPE FrameAlarm (sig)
7478 frameWaiting = False;
7479 /* In case System-V style signals. Needed?? */
7480 signal(SIGALRM, FrameAlarm);
7487 struct itimerval delay;
7489 XSync(xDisplay, False);
7492 frameWaiting = True;
7493 signal(SIGALRM, FrameAlarm);
7494 delay.it_interval.tv_sec =
7495 delay.it_value.tv_sec = time / 1000;
7496 delay.it_interval.tv_usec =
7497 delay.it_value.tv_usec = (time % 1000) * 1000;
7498 setitimer(ITIMER_REAL, &delay, NULL);
7499 while (frameWaiting) pause();
7500 delay.it_interval.tv_sec = delay.it_value.tv_sec = 0;
7501 delay.it_interval.tv_usec = delay.it_value.tv_usec = 0;
7502 setitimer(ITIMER_REAL, &delay, NULL);
7512 // XSync(xDisplay, False);
7514 usleep(time * 1000);
7519 /* Convert board position to corner of screen rect and color */
7522 ScreenSquare(column, row, pt, color)
7523 int column; int row; XPoint * pt; int * color;
7526 pt->x = lineGap + ((BOARD_WIDTH-1)-column) * (squareSize + lineGap);
7527 pt->y = lineGap + row * (squareSize + lineGap);
7529 pt->x = lineGap + column * (squareSize + lineGap);
7530 pt->y = lineGap + ((BOARD_HEIGHT-1)-row) * (squareSize + lineGap);
7532 *color = SquareColor(row, column);
7535 /* Convert window coords to square */
7538 BoardSquare(x, y, column, row)
7539 int x; int y; int * column; int * row;
7541 *column = EventToSquare(x, BOARD_WIDTH);
7542 if (flipView && *column >= 0)
7543 *column = BOARD_WIDTH - 1 - *column;
7544 *row = EventToSquare(y, BOARD_HEIGHT);
7545 if (!flipView && *row >= 0)
7546 *row = BOARD_HEIGHT - 1 - *row;
7551 #undef Max /* just in case */
7553 #define Max(a, b) ((a) > (b) ? (a) : (b))
7554 #define Min(a, b) ((a) < (b) ? (a) : (b))
7557 SetRect(rect, x, y, width, height)
7558 XRectangle * rect; int x; int y; int width; int height;
7562 rect->width = width;
7563 rect->height = height;
7566 /* Test if two frames overlap. If they do, return
7567 intersection rect within old and location of
7568 that rect within new. */
7571 Intersect(old, new, size, area, pt)
7572 XPoint * old; XPoint * new;
7573 int size; XRectangle * area; XPoint * pt;
7575 if (old->x > new->x + size || new->x > old->x + size ||
7576 old->y > new->y + size || new->y > old->y + size) {
7579 SetRect(area, Max(new->x - old->x, 0), Max(new->y - old->y, 0),
7580 size - abs(old->x - new->x), size - abs(old->y - new->y));
7581 pt->x = Max(old->x - new->x, 0);
7582 pt->y = Max(old->y - new->y, 0);
7587 /* For two overlapping frames, return the rect(s)
7588 in the old that do not intersect with the new. */
7591 CalcUpdateRects(old, new, size, update, nUpdates)
7592 XPoint * old; XPoint * new; int size;
7593 XRectangle update[]; int * nUpdates;
7597 /* If old = new (shouldn't happen) then nothing to draw */
7598 if (old->x == new->x && old->y == new->y) {
7602 /* Work out what bits overlap. Since we know the rects
7603 are the same size we don't need a full intersect calc. */
7605 /* Top or bottom edge? */
7606 if (new->y > old->y) {
7607 SetRect(&(update[count]), old->x, old->y, size, new->y - old->y);
7609 } else if (old->y > new->y) {
7610 SetRect(&(update[count]), old->x, old->y + size - (old->y - new->y),
7611 size, old->y - new->y);
7614 /* Left or right edge - don't overlap any update calculated above. */
7615 if (new->x > old->x) {
7616 SetRect(&(update[count]), old->x, Max(new->y, old->y),
7617 new->x - old->x, size - abs(new->y - old->y));
7619 } else if (old->x > new->x) {
7620 SetRect(&(update[count]), new->x + size, Max(new->y, old->y),
7621 old->x - new->x, size - abs(new->y - old->y));
7628 /* Generate a series of frame coords from start->mid->finish.
7629 The movement rate doubles until the half way point is
7630 reached, then halves back down to the final destination,
7631 which gives a nice slow in/out effect. The algorithmn
7632 may seem to generate too many intermediates for short
7633 moves, but remember that the purpose is to attract the
7634 viewers attention to the piece about to be moved and
7635 then to where it ends up. Too few frames would be less
7639 Tween(start, mid, finish, factor, frames, nFrames)
7640 XPoint * start; XPoint * mid;
7641 XPoint * finish; int factor;
7642 XPoint frames[]; int * nFrames;
7644 int fraction, n, count;
7648 /* Slow in, stepping 1/16th, then 1/8th, ... */
7650 for (n = 0; n < factor; n++)
7652 for (n = 0; n < factor; n++) {
7653 frames[count].x = start->x + (mid->x - start->x) / fraction;
7654 frames[count].y = start->y + (mid->y - start->y) / fraction;
7656 fraction = fraction / 2;
7660 frames[count] = *mid;
7663 /* Slow out, stepping 1/2, then 1/4, ... */
7665 for (n = 0; n < factor; n++) {
7666 frames[count].x = finish->x - (finish->x - mid->x) / fraction;
7667 frames[count].y = finish->y - (finish->y - mid->y) / fraction;
7669 fraction = fraction * 2;
7674 /* Draw a piece on the screen without disturbing what's there */
7677 SelectGCMask(piece, clip, outline, mask)
7678 ChessSquare piece; GC * clip; GC * outline; Pixmap * mask;
7682 /* Bitmap for piece being moved. */
7683 if (appData.monoMode) {
7684 *mask = *pieceToSolid(piece);
7685 } else if (useImages) {
7687 *mask = xpmMask[piece];
7689 *mask = ximMaskPm[piece];
7692 *mask = *pieceToSolid(piece);
7695 /* GC for piece being moved. Square color doesn't matter, but
7696 since it gets modified we make a copy of the original. */
7698 if (appData.monoMode)
7703 if (appData.monoMode)
7708 // XCopyGC(xDisplay, source, 0xFFFFFFFF, *clip);
7710 /* Outline only used in mono mode and is not modified */
7712 *outline = bwPieceGC;
7714 *outline = wbPieceGC;
7718 OverlayPiece(piece, clip, outline, dest)
7719 ChessSquare piece; GC clip; GC outline; Drawable dest;
7724 /* Draw solid rectangle which will be clipped to shape of piece */
7725 // XFillRectangle(xDisplay, dest, clip,
7726 // 0, 0, squareSize, squareSize)
7728 if (appData.monoMode)
7729 /* Also draw outline in contrasting color for black
7730 on black / white on white cases */
7731 // XCopyPlane(xDisplay, *pieceToOutline(piece), dest, outline,
7732 // 0, 0, squareSize, squareSize, 0, 0, 1)
7735 /* Copy the piece */
7740 // XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
7742 // 0, 0, squareSize, squareSize,
7747 /* Animate the movement of a single piece */
7750 BeginAnimation(anim, piece, startColor, start)
7758 /* The old buffer is initialised with the start square (empty) */
7759 BlankSquare(0, 0, startColor, EmptySquare, anim->saveBuf);
7760 anim->prevFrame = *start;
7762 /* The piece will be drawn using its own bitmap as a matte */
7763 // SelectGCMask(piece, &anim->pieceGC, &anim->outlineGC, &mask);
7764 // XSetClipMask(xDisplay, anim->pieceGC, mask);
7768 AnimationFrame(anim, frame, piece)
7773 XRectangle updates[4];
7778 /* Save what we are about to draw into the new buffer */
7779 // XCopyArea(xDisplay, xBoardWindow, anim->newBuf, anim->blitGC,
7780 // frame->x, frame->y, squareSize, squareSize,
7783 /* Erase bits of the previous frame */
7784 if (Intersect(&anim->prevFrame, frame, squareSize, &overlap, &pt)) {
7785 /* Where the new frame overlapped the previous,
7786 the contents in newBuf are wrong. */
7787 // XCopyArea(xDisplay, anim->saveBuf, anim->newBuf, anim->blitGC,
7788 // overlap.x, overlap.y,
7789 // overlap.width, overlap.height,
7791 /* Repaint the areas in the old that don't overlap new */
7792 CalcUpdateRects(&anim->prevFrame, frame, squareSize, updates, &count);
7793 for (i = 0; i < count; i++)
7794 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
7795 // updates[i].x - anim->prevFrame.x,
7796 // updates[i].y - anim->prevFrame.y,
7797 // updates[i].width, updates[i].height,
7798 // updates[i].x, updates[i].y)
7801 /* Easy when no overlap */
7802 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
7803 // 0, 0, squareSize, squareSize,
7804 // anim->prevFrame.x, anim->prevFrame.y);
7807 /* Save this frame for next time round */
7808 // XCopyArea(xDisplay, anim->newBuf, anim->saveBuf, anim->blitGC,
7809 // 0, 0, squareSize, squareSize,
7811 anim->prevFrame = *frame;
7813 /* Draw piece over original screen contents, not current,
7814 and copy entire rect. Wipes out overlapping piece images. */
7815 OverlayPiece(piece, anim->pieceGC, anim->outlineGC, anim->newBuf);
7816 // XCopyArea(xDisplay, anim->newBuf, xBoardWindow, anim->blitGC,
7817 // 0, 0, squareSize, squareSize,
7818 // frame->x, frame->y);
7822 EndAnimation (anim, finish)
7826 XRectangle updates[4];
7831 /* The main code will redraw the final square, so we
7832 only need to erase the bits that don't overlap. */
7833 if (Intersect(&anim->prevFrame, finish, squareSize, &overlap, &pt)) {
7834 CalcUpdateRects(&anim->prevFrame, finish, squareSize, updates, &count);
7835 for (i = 0; i < count; i++)
7836 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
7837 // updates[i].x - anim->prevFrame.x,
7838 // updates[i].y - anim->prevFrame.y,
7839 // updates[i].width, updates[i].height,
7840 // updates[i].x, updates[i].y)
7843 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
7844 // 0, 0, squareSize, squareSize,
7845 // anim->prevFrame.x, anim->prevFrame.y);
7850 FrameSequence(anim, piece, startColor, start, finish, frames, nFrames)
7852 ChessSquare piece; int startColor;
7853 XPoint * start; XPoint * finish;
7854 XPoint frames[]; int nFrames;
7858 BeginAnimation(anim, piece, startColor, start);
7859 for (n = 0; n < nFrames; n++) {
7860 AnimationFrame(anim, &(frames[n]), piece);
7861 FrameDelay(appData.animSpeed);
7863 EndAnimation(anim, finish);
7866 /* Main control logic for deciding what to animate and how */
7869 AnimateMove(board, fromX, fromY, toX, toY)
7878 XPoint start, finish, mid;
7879 XPoint frames[kFactor * 2 + 1];
7880 int nFrames, startColor, endColor;
7882 /* Are we animating? */
7883 if (!appData.animate || appData.blindfold)
7886 if(board[toY][toX] == WhiteRook && board[fromY][fromX] == WhiteKing ||
7887 board[toY][toX] == BlackRook && board[fromY][fromX] == BlackKing)
7888 return; // [HGM] FRC: no animtion of FRC castlings, as to-square is not true to-square
7890 if (fromY < 0 || fromX < 0 || toX < 0 || toY < 0) return;
7891 piece = board[fromY][fromX];
7892 if (piece >= EmptySquare) return;
7897 hop = (piece == WhiteKnight || piece == BlackKnight);
7900 if (appData.debugMode) {
7901 fprintf(debugFP, hop ? _("AnimateMove: piece %d hops from %d,%d to %d,%d \n") :
7902 _("AnimateMove: piece %d slides from %d,%d to %d,%d \n"),
7903 piece, fromX, fromY, toX, toY); }
7905 ScreenSquare(fromX, fromY, &start, &startColor);
7906 ScreenSquare(toX, toY, &finish, &endColor);
7909 /* Knight: make diagonal movement then straight */
7910 if (abs(toY - fromY) < abs(toX - fromX)) {
7911 mid.x = start.x + (finish.x - start.x) / 2;
7915 mid.y = start.y + (finish.y - start.y) / 2;
7918 mid.x = start.x + (finish.x - start.x) / 2;
7919 mid.y = start.y + (finish.y - start.y) / 2;
7922 /* Don't use as many frames for very short moves */
7923 if (abs(toY - fromY) + abs(toX - fromX) <= 2)
7924 Tween(&start, &mid, &finish, kFactor - 1, frames, &nFrames);
7926 Tween(&start, &mid, &finish, kFactor, frames, &nFrames);
7927 FrameSequence(&game, piece, startColor, &start, &finish, frames, nFrames);
7929 /* Be sure end square is redrawn */
7930 damage[toY][toX] = True;
7934 DragPieceBegin(x, y)
7937 int boardX, boardY, color;
7940 /* Are we animating? */
7941 if (!appData.animateDragging || appData.blindfold)
7944 /* Figure out which square we start in and the
7945 mouse position relative to top left corner. */
7946 BoardSquare(x, y, &boardX, &boardY);
7947 player.startBoardX = boardX;
7948 player.startBoardY = boardY;
7949 ScreenSquare(boardX, boardY, &corner, &color);
7950 player.startSquare = corner;
7951 player.startColor = color;
7952 /* As soon as we start dragging, the piece will jump slightly to
7953 be centered over the mouse pointer. */
7954 player.mouseDelta.x = squareSize/2;
7955 player.mouseDelta.y = squareSize/2;
7956 /* Initialise animation */
7957 player.dragPiece = PieceForSquare(boardX, boardY);
7959 if (player.dragPiece >= 0 && player.dragPiece < EmptySquare) {
7960 player.dragActive = True;
7961 BeginAnimation(&player, player.dragPiece, color, &corner);
7962 /* Mark this square as needing to be redrawn. Note that
7963 we don't remove the piece though, since logically (ie
7964 as seen by opponent) the move hasn't been made yet. */
7965 if(boardX == BOARD_RGHT+1 && PieceForSquare(boardX-1, boardY) > 1 ||
7966 boardX == BOARD_LEFT-2 && PieceForSquare(boardX+1, boardY) > 1)
7967 // XCopyArea(xDisplay, xBoardWindow, player.saveBuf, player.blitGC,
7968 // corner.x, corner.y, squareSize, squareSize,
7969 // 0, 0); // [HGM] zh: unstack in stead of grab
7970 damage[boardY][boardX] = True;
7972 player.dragActive = False;
7982 /* Are we animating? */
7983 if (!appData.animateDragging || appData.blindfold)
7987 if (! player.dragActive)
7989 /* Move piece, maintaining same relative position
7990 of mouse within square */
7991 corner.x = x - player.mouseDelta.x;
7992 corner.y = y - player.mouseDelta.y;
7993 AnimationFrame(&player, &corner, player.dragPiece);
7995 if (appData.highlightDragging) {
7997 BoardSquare(x, y, &boardX, &boardY);
7998 SetHighlights(fromX, fromY, boardX, boardY);
8007 int boardX, boardY, color;
8010 /* Are we animating? */
8011 if (!appData.animateDragging || appData.blindfold)
8015 if (! player.dragActive)
8017 /* Last frame in sequence is square piece is
8018 placed on, which may not match mouse exactly. */
8019 BoardSquare(x, y, &boardX, &boardY);
8020 ScreenSquare(boardX, boardY, &corner, &color);
8021 EndAnimation(&player, &corner);
8023 /* Be sure end square is redrawn */
8024 damage[boardY][boardX] = True;
8026 /* This prevents weird things happening with fast successive
8027 clicks which on my Sun at least can cause motion events
8028 without corresponding press/release. */
8029 player.dragActive = False;
8032 /* Handle expose event while piece being dragged */
8037 if (!player.dragActive || appData.blindfold)
8040 /* What we're doing: logically, the move hasn't been made yet,
8041 so the piece is still in it's original square. But visually
8042 it's being dragged around the board. So we erase the square
8043 that the piece is on and draw it at the last known drag point. */
8044 BlankSquare(player.startSquare.x, player.startSquare.y,
8045 player.startColor, EmptySquare, xBoardWindow);
8046 AnimationFrame(&player, &player.prevFrame, player.dragPiece);
8047 damage[player.startBoardY][player.startBoardX] = TRUE;
8051 SetProgramStats( FrontEndProgramStats * stats )
8054 // [HGM] done, but perhaps backend should call this directly?
8055 EngineOutputUpdate( stats );