2 * xboard.c -- X front end for XBoard
4 * Copyright 1991 by Digital Equipment Corporation, Maynard,
7 * Enhancements Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006,
8 * 2007, 2008, 2009 Free Software Foundation, Inc.
10 * The following terms apply to Digital Equipment Corporation's copyright
12 * ------------------------------------------------------------------------
15 * Permission to use, copy, modify, and distribute this software and its
16 * documentation for any purpose and without fee is hereby granted,
17 * provided that the above copyright notice appear in all copies and that
18 * both that copyright notice and this permission notice appear in
19 * supporting documentation, and that the name of Digital not be
20 * used in advertising or publicity pertaining to distribution of the
21 * software without specific, written prior permission.
23 * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
24 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
25 * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
26 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
27 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
28 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
30 * ------------------------------------------------------------------------
32 * The following terms apply to the enhanced version of XBoard
33 * distributed by the Free Software Foundation:
34 * ------------------------------------------------------------------------
36 * GNU XBoard is free software: you can redistribute it and/or modify
37 * it under the terms of the GNU General Public License as published by
38 * the Free Software Foundation, either version 3 of the License, or (at
39 * your option) any later version.
41 * GNU XBoard is distributed in the hope that it will be useful, but
42 * WITHOUT ANY WARRANTY; without even the implied warranty of
43 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
44 * General Public License for more details.
46 * You should have received a copy of the GNU General Public License
47 * along with this program. If not, see http://www.gnu.org/licenses/. *
49 *------------------------------------------------------------------------
50 ** See the file ChangeLog for a revision history. */
58 #include <sys/types.h>
63 # if HAVE_SYS_SOCKET_H
64 # include <sys/socket.h>
65 # include <netinet/in.h>
67 # else /* not HAVE_SYS_SOCKET_H */
68 # if HAVE_LAN_SOCKET_H
69 # include <lan/socket.h>
71 # include <lan/netdb.h>
72 # else /* not HAVE_LAN_SOCKET_H */
73 # define OMIT_SOCKETS 1
74 # endif /* not HAVE_LAN_SOCKET_H */
75 # endif /* not HAVE_SYS_SOCKET_H */
76 #endif /* !OMIT_SOCKETS */
81 #else /* not STDC_HEADERS */
82 extern char *getenv();
85 # else /* not HAVE_STRING_H */
87 # endif /* not HAVE_STRING_H */
88 #endif /* not STDC_HEADERS */
91 # include <sys/fcntl.h>
92 #else /* not HAVE_SYS_FCNTL_H */
95 # endif /* HAVE_FCNTL_H */
96 #endif /* not HAVE_SYS_FCNTL_H */
98 #if HAVE_SYS_SYSTEMINFO_H
99 # include <sys/systeminfo.h>
100 #endif /* HAVE_SYS_SYSTEMINFO_H */
102 #if TIME_WITH_SYS_TIME
103 # include <sys/time.h>
107 # include <sys/time.h>
118 # include <sys/wait.h>
123 # define NAMLEN(dirent) strlen((dirent)->d_name)
124 # define HAVE_DIR_STRUCT
126 # define dirent direct
127 # define NAMLEN(dirent) (dirent)->d_namlen
129 # include <sys/ndir.h>
130 # define HAVE_DIR_STRUCT
133 # include <sys/dir.h>
134 # define HAVE_DIR_STRUCT
138 # define HAVE_DIR_STRUCT
142 #include <X11/Intrinsic.h>
143 #include <X11/StringDefs.h>
144 #include <X11/Shell.h>
145 #include <X11/cursorfont.h>
146 #include <X11/Xatom.h>
148 #include <X11/Xaw3d/Dialog.h>
149 #include <X11/Xaw3d/Form.h>
150 #include <X11/Xaw3d/List.h>
151 #include <X11/Xaw3d/Label.h>
152 #include <X11/Xaw3d/SimpleMenu.h>
153 #include <X11/Xaw3d/SmeBSB.h>
154 #include <X11/Xaw3d/SmeLine.h>
155 #include <X11/Xaw3d/Box.h>
156 #include <X11/Xaw3d/MenuButton.h>
157 #include <X11/Xaw3d/Text.h>
158 #include <X11/Xaw3d/AsciiText.h>
160 #include <X11/Xaw/Dialog.h>
161 #include <X11/Xaw/Form.h>
162 #include <X11/Xaw/List.h>
163 #include <X11/Xaw/Label.h>
164 #include <X11/Xaw/SimpleMenu.h>
165 #include <X11/Xaw/SmeBSB.h>
166 #include <X11/Xaw/SmeLine.h>
167 #include <X11/Xaw/Box.h>
168 #include <X11/Xaw/MenuButton.h>
169 #include <X11/Xaw/Text.h>
170 #include <X11/Xaw/AsciiText.h>
173 // [HGM] bitmaps: put before incuding the bitmaps / pixmaps, to know how many piece types there are.
178 #include "pixmaps/pixmaps.h"
179 #define IMAGE_EXT "xpm"
181 #define IMAGE_EXT "xim"
182 #include "bitmaps/bitmaps.h"
187 #include <gdk-pixbuf/gdk-pixbuf.h>
189 #include "bitmaps/icon_white.bm"
190 #include "bitmaps/icon_black.bm"
191 #include "bitmaps/checkmark.bm"
193 #include "frontend.h"
198 #include "xgamelist.h"
199 #include "xhistory.h"
200 #include "xedittags.h"
202 #include "callback.h"
203 #include "interface.h"
205 // must be moved to xengineoutput.h
207 void EngineOutputProc P((Widget w, XEvent *event,
208 String *prms, Cardinal *nprms));
210 void EngineOutputPopDown();
217 #define usleep(t) _sleep2(((t)+500)/1000)
221 # define _(s) gettext (s)
222 # define N_(s) gettext_noop (s)
245 int main P((int argc, char **argv));
246 RETSIGTYPE CmailSigHandler P((int sig));
247 RETSIGTYPE IntSigHandler P((int sig));
248 void CreateGCs P((void));
249 void CreateXIMPieces P((void));
250 void CreateXPMPieces P((void));
251 void CreatePieces P((void));
252 void CreatePieceMenus P((void));
253 Widget CreateMenuBar P((Menu *mb));
254 Widget CreateButtonBar P ((MenuItem *mi));
255 char *FindFont P((char *pattern, int targetPxlSize));
256 void PieceMenuPopup P((Widget w, XEvent *event,
257 String *params, Cardinal *num_params));
258 static void PieceMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
259 static void DropMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
260 int EventToSquare P((int x, int limit));
261 void DrawSquare P((int row, int column, ChessSquare piece, int do_flash));
262 void HandleUserMove P((Widget w, XEvent *event,
263 String *prms, Cardinal *nprms));
264 void AnimateUserMove P((Widget w, XEvent * event,
265 String * params, Cardinal * nParams));
266 void WhiteClock P((Widget w, XEvent *event,
267 String *prms, Cardinal *nprms));
268 void BlackClock P((Widget w, XEvent *event,
269 String *prms, Cardinal *nprms));
270 void CommentPopUp P((char *title, char *label));
271 void CommentPopDown P((void));
272 void CommentCallback P((Widget w, XtPointer client_data,
273 XtPointer call_data));
274 void ICSInputBoxPopUp P((void));
275 void ICSInputBoxPopDown P((void));
276 void FileNamePopUp P((char *label, char *def,
277 FileProc proc, char *openMode));
278 void FileNamePopDown P((void));
279 void FileNameCallback P((Widget w, XtPointer client_data,
280 XtPointer call_data));
281 void FileNameAction P((Widget w, XEvent *event,
282 String *prms, Cardinal *nprms));
283 void AskQuestionReplyAction P((Widget w, XEvent *event,
284 String *prms, Cardinal *nprms));
285 void AskQuestionProc P((Widget w, XEvent *event,
286 String *prms, Cardinal *nprms));
287 void AskQuestionPopDown P((void));
288 void PromotionPopUp P((void));
289 void PromotionPopDown P((void));
290 void PromotionCallback P((Widget w, XtPointer client_data,
291 XtPointer call_data));
292 void EditCommentPopDown P((void));
293 void EditCommentCallback P((Widget w, XtPointer client_data,
294 XtPointer call_data));
295 void SelectCommand P((Widget w, XtPointer client_data, XtPointer call_data));
296 void LoadPositionProc P((Widget w, XEvent *event,
297 String *prms, Cardinal *nprms));
298 void LoadNextPositionProc P((Widget w, XEvent *event, String *prms,
300 void LoadPrevPositionProc P((Widget w, XEvent *event, String *prms,
302 void ReloadPositionProc P((Widget w, XEvent *event, String *prms,
304 void CopyPositionProc P((Widget w, XEvent *event, String *prms,
306 void PastePositionProc P((Widget w, XEvent *event, String *prms,
308 void CopyGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
309 void PasteGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
310 void SaveGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
311 void SavePositionProc P((Widget w, XEvent *event,
312 String *prms, Cardinal *nprms));
313 void MailMoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
314 void ReloadCmailMsgProc P((Widget w, XEvent *event, String *prms,
316 void AnalyzeModeProc P((Widget w, XEvent *event,
317 String *prms, Cardinal *nprms));
318 void AnalyzeFileProc P((Widget w, XEvent *event,
319 String *prms, Cardinal *nprms));
320 void EditGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
321 void EditPositionProc P((Widget w, XEvent *event,
322 String *prms, Cardinal *nprms));
323 void TrainingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
324 void EditCommentProc P((Widget w, XEvent *event,
325 String *prms, Cardinal *nprms));
326 void IcsInputBoxProc P((Widget w, XEvent *event,
327 String *prms, Cardinal *nprms));
328 void EnterKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
329 void AlwaysQueenProc P((Widget w, XEvent *event, String *prms,
331 void AnimateDraggingProc P((Widget w, XEvent *event, String *prms,
333 void AnimateMovingProc P((Widget w, XEvent *event, String *prms,
335 void AutocommProc P((Widget w, XEvent *event, String *prms,
337 void AutoflagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
338 void AutoflipProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
339 void AutobsProc P((Widget w, XEvent *event, String *prms,
341 void AutoraiseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
342 void AutosaveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
343 void BlindfoldProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
344 void FlashMovesProc P((Widget w, XEvent *event, String *prms,
346 void HighlightDraggingProc P((Widget w, XEvent *event, String *prms,
348 void HighlightLastMoveProc P((Widget w, XEvent *event, String *prms,
350 void MoveSoundProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
351 void IcsAlarmProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
352 void OldSaveStyleProc P((Widget w, XEvent *event, String *prms,
354 void PeriodicUpdatesProc P((Widget w, XEvent *event, String *prms,
356 void PonderNextMoveProc P((Widget w, XEvent *event, String *prms,
358 void PopupMoveErrorsProc P((Widget w, XEvent *event, String *prms,
360 void PopupExitMessageProc P((Widget w, XEvent *event, String *prms,
362 void PremoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
363 void QuietPlayProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
364 void TestLegalityProc P((Widget w, XEvent *event, String *prms,
366 void AboutGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
367 void DebugProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
368 void NothingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
369 void Iconify P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
370 void DisplayMove P((int moveNumber));
371 void DisplayTitle P((char *title));
372 void ICSInitScript P((void));
373 int LoadGamePopUp P((FILE *f, int gameNumber, char *title));
374 void ErrorPopUp P((char *title, char *text, int modal));
375 void ErrorPopDown P((void));
376 static char *ExpandPathName P((char *path));
377 static void CreateAnimVars P((void));
378 void DragPieceBegin P((int x, int y));
379 static void DragPieceMove P((int x, int y));
380 void DragPieceEnd P((int x, int y));
381 static void DrawDragPiece P((void));
382 char *ModeToWidgetName P((GameMode mode));
383 void EngineOutputUpdate( FrontEndProgramStats * stats );
384 void ShuffleMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
385 void EngineMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
386 void UciMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
387 void TimeControlProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
388 void NewVariantProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
389 void FirstSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
390 void SecondSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
391 void ShufflePopDown P(());
392 void EnginePopDown P(());
393 void UciPopDown P(());
394 void TimeControlPopDown P(());
395 void NewVariantPopDown P(());
396 void SettingsPopDown P(());
397 void SetMenuEnables P((Enables *enab));
400 * XBoard depends on Xt R4 or higher
402 int xtVersion = XtSpecificationRelease;
407 Pixel lightSquareColor, darkSquareColor, whitePieceColor, blackPieceColor,
408 jailSquareColor, highlightSquareColor, premoveHighlightColor;
409 Pixel lowTimeWarningColor;
411 #define LINE_TYPE_NORMAL 0
412 #define LINE_TYPE_HIGHLIGHT 1
413 #define LINE_TYPE_PRE 2
416 GC lightSquareGC, darkSquareGC, jailSquareGC, wdPieceGC, wlPieceGC,
417 bdPieceGC, blPieceGC, wbPieceGC, bwPieceGC, coordGC,
418 wjPieceGC, bjPieceGC;
419 Pixmap iconPixmap, wIconPixmap, bIconPixmap, xMarkPixmap;
420 Widget shellWidget, layoutWidget, formWidget, boardWidget, messageWidget,
421 whiteTimerWidget, blackTimerWidget, titleWidget, widgetList[16],
422 commentShell, promotionShell, whitePieceMenu, blackPieceMenu, dropMenu,
423 menuBarWidget, buttonBarWidget, editShell, errorShell, analysisShell,
424 ICSInputShell, fileNameShell, askQuestionShell;
425 Font clockFontID, coordFontID, countFontID;
426 XFontStruct *clockFontStruct, *coordFontStruct, *countFontStruct;
427 XtAppContext appContext;
429 char *oldICSInteractionTitle;
433 char installDir[] = "."; // [HGM] UCI: needed for UCI; probably needs run-time initializtion
435 Position commentX = -1, commentY = -1;
436 Dimension commentW, commentH;
438 int squareSize, smallLayout = 0, tinyLayout = 0,
439 marginW, marginH, // [HGM] for run-time resizing
440 fromX = -1, fromY = -1, toX, toY, commentUp = False, analysisUp = False,
441 ICSInputBoxUp = False, askQuestionUp = False,
442 filenameUp = False, promotionUp = False, pmFromX = -1, pmFromY = -1,
443 editUp = False, errorUp = False, errorExitStatus = -1, lineGap;
444 Pixel timerForegroundPixel, timerBackgroundPixel;
445 Pixel buttonForegroundPixel, buttonBackgroundPixel;
446 char *chessDir, *programName, *programVersion,
447 *gameCopyFilename, *gamePasteFilename;
451 Pixmap pieceBitmap[2][(int)BlackPawn];
452 Pixmap pieceBitmap2[2][(int)BlackPawn+4]; /* [HGM] pieces */
453 Pixmap xpmPieceBitmap[4][(int)BlackPawn]; /* LL, LD, DL, DD actually used*/
454 Pixmap xpmPieceBitmap2[4][(int)BlackPawn+4]; /* LL, LD, DL, DD set to select from */
455 Pixmap xpmLightSquare, xpmDarkSquare, xpmJailSquare;
456 int useImages=0, useImageSqs;
457 XImage *ximPieceBitmap[4][(int)BlackPawn+4]; /* LL, LD, DL, DD */
458 Pixmap ximMaskPm[(int)BlackPawn]; /* clipmasks, used for XIM pieces */
459 Pixmap ximMaskPm2[(int)BlackPawn+4]; /* clipmasks, used for XIM pieces */
460 XImage *ximLightSquare, *ximDarkSquare;
463 #define pieceToSolid(piece) &pieceBitmap[SOLID][(piece) % (int)BlackPawn]
464 #define pieceToOutline(piece) &pieceBitmap[OUTLINE][(piece) % (int)BlackPawn]
466 #define White(piece) ((int)(piece) < (int)BlackPawn)
468 /* Variables for doing smooth animation. This whole thing
469 would be much easier if the board was double-buffered,
470 but that would require a fairly major rewrite. */
475 GC blitGC, pieceGC, outlineGC;
476 XPoint startSquare, prevFrame, mouseDelta;
480 int startBoardX, startBoardY;
483 /* There can be two pieces being animated at once: a player
484 can begin dragging a piece before the remote opponent has moved. */
486 static AnimState game, player;
488 /* Bitmaps for use as masks when drawing XPM pieces.
489 Need one for each black and white piece. */
490 static Pixmap xpmMask[BlackKing + 1];
492 /* This magic number is the number of intermediate frames used
493 in each half of the animation. For short moves it's reduced
494 by 1. The total number of frames will be factor * 2 + 1. */
497 SizeDefaults sizeDefaults[] = SIZE_DEFAULTS;
499 Enables icsEnables[] = {
500 { "menuFile.Mail Move", False },
501 { "menuFile.Reload CMail Message", False },
502 { "menuMode.Machine Black", False },
503 { "menuMode.Machine White", False },
504 { "menuMode.Analysis Mode", False },
505 { "menuMode.Analyze File", False },
506 { "menuMode.Two Machines", False },
508 { "menuHelp.Hint", False },
509 { "menuHelp.Book", False },
510 { "menuStep.Move Now", False },
511 { "menuOptions.Periodic Updates", False },
512 { "menuOptions.Hide Thinking", False },
513 { "menuOptions.Ponder Next Move", False },
518 Enables ncpEnables[] = {
519 { "menuFile.Mail Move", False },
520 { "menuFile.Reload CMail Message", False },
521 { "menuMode.Machine White", False },
522 { "menuMode.Machine Black", False },
523 { "menuMode.Analysis Mode", False },
524 { "menuMode.Analyze File", False },
525 { "menuMode.Two Machines", False },
526 { "menuMode.ICS Client", False },
527 { "menuMode.ICS Input Box", False },
529 { "menuStep.Revert", False },
530 { "menuStep.Move Now", False },
531 { "menuStep.Retract Move", False },
532 { "menuOptions.Auto Comment", False },
533 { "menuOptions.Auto Flag", False },
534 { "menuOptions.Auto Flip View", False },
535 { "menuOptions.Auto Observe", False },
536 { "menuOptions.Auto Raise Board", False },
537 { "menuOptions.Get Move List", False },
538 { "menuOptions.ICS Alarm", False },
539 { "menuOptions.Move Sound", False },
540 { "menuOptions.Quiet Play", False },
541 { "menuOptions.Hide Thinking", False },
542 { "menuOptions.Periodic Updates", False },
543 { "menuOptions.Ponder Next Move", False },
544 { "menuHelp.Hint", False },
545 { "menuHelp.Book", False },
549 Enables gnuEnables[] = {
550 { "menuMode.ICS Client", False },
551 { "menuMode.ICS Input Box", False },
552 { "menuAction.Accept", False },
553 { "menuAction.Decline", False },
554 { "menuAction.Rematch", False },
555 { "menuAction.Adjourn", False },
556 { "menuAction.Stop Examining", False },
557 { "menuAction.Stop Observing", False },
558 { "menuStep.Revert", False },
559 { "menuOptions.Auto Comment", False },
560 { "menuOptions.Auto Observe", False },
561 { "menuOptions.Auto Raise Board", False },
562 { "menuOptions.Get Move List", False },
563 { "menuOptions.Premove", False },
564 { "menuOptions.Quiet Play", False },
566 /* The next two options rely on SetCmailMode being called *after* */
567 /* SetGNUMode so that when GNU is being used to give hints these */
568 /* menu options are still available */
570 { "menuFile.Mail Move", False },
571 { "menuFile.Reload CMail Message", False },
575 Enables cmailEnables[] = {
577 { "menuAction.Call Flag", False },
578 { "menuAction.Draw", True },
579 { "menuAction.Adjourn", False },
580 { "menuAction.Abort", False },
581 { "menuAction.Stop Observing", False },
582 { "menuAction.Stop Examining", False },
583 { "menuFile.Mail Move", True },
584 { "menuFile.Reload CMail Message", True },
588 Enables trainingOnEnables[] = {
589 { "menuMode.Edit Comment", False },
590 { "menuMode.Pause", False },
591 { "menuStep.Forward", False },
592 { "menuStep.Backward", False },
593 { "menuStep.Forward to End", False },
594 { "menuStep.Back to Start", False },
595 { "menuStep.Move Now", False },
596 { "menuStep.Truncate Game", False },
600 Enables trainingOffEnables[] = {
601 { "menuMode.Edit Comment", True },
602 { "menuMode.Pause", True },
603 { "menuStep.Forward", True },
604 { "menuStep.Backward", True },
605 { "menuStep.Forward to End", True },
606 { "menuStep.Back to Start", True },
607 { "menuStep.Move Now", True },
608 { "menuStep.Truncate Game", True },
612 Enables machineThinkingEnables[] = {
613 { "menuFile.Load Game", False },
614 { "menuFile.Load Next Game", False },
615 { "menuFile.Load Previous Game", False },
616 { "menuFile.Reload Same Game", False },
617 { "menuFile.Paste Game", False },
618 { "menuFile.Load Position", False },
619 { "menuFile.Load Next Position", False },
620 { "menuFile.Load Previous Position", False },
621 { "menuFile.Reload Same Position", False },
622 { "menuFile.Paste Position", False },
623 { "menuMode.Machine White", False },
624 { "menuMode.Machine Black", False },
625 { "menuMode.Two Machines", False },
626 { "menuStep.Retract Move", False },
630 Enables userThinkingEnables[] = {
631 { "menuFile.Load Game", True },
632 { "menuFile.Load Next Game", True },
633 { "menuFile.Load Previous Game", True },
634 { "menuFile.Reload Same Game", True },
635 { "menuFile.Paste Game", True },
636 { "menuFile.Load Position", True },
637 { "menuFile.Load Next Position", True },
638 { "menuFile.Load Previous Position", True },
639 { "menuFile.Reload Same Position", True },
640 { "menuFile.Paste Position", True },
641 { "menuMode.Machine White", True },
642 { "menuMode.Machine Black", True },
643 { "menuMode.Two Machines", True },
644 { "menuStep.Retract Move", True },
650 MenuItem fileMenu[] = {
651 {N_("New Shuffle Game ..."), ShuffleMenuProc},
652 {N_("New Variant ..."), NewVariantProc}, // [HGM] variant: not functional yet
653 {"----", NothingProc},
654 {N_("Save Game"), SaveGameProc},
655 {"----", NothingProc},
656 {N_("Copy Game"), CopyGameProc},
657 {N_("Paste Game"), PasteGameProc},
658 {"----", NothingProc},
659 {N_("Load Position"), LoadPositionProc},
660 {N_("Load Next Position"), LoadNextPositionProc},
661 {N_("Load Previous Position"), LoadPrevPositionProc},
662 {N_("Reload Same Position"), ReloadPositionProc},
663 {N_("Save Position"), SavePositionProc},
664 {"----", NothingProc},
665 {N_("Copy Position"), CopyPositionProc},
666 {N_("Paste Position"), PastePositionProc},
667 {"----", NothingProc},
668 {N_("Mail Move"), MailMoveProc},
669 {N_("Reload CMail Message"), ReloadCmailMsgProc},
670 {"----", NothingProc},
674 MenuItem modeMenu[] = {
675 // {N_("Machine White"), MachineWhiteProc},
676 // {N_("Machine Black"), MachineBlackProc},
677 // {N_("Two Machines"), TwoMachinesProc},
678 {N_("Analysis Mode"), AnalyzeModeProc},
679 {N_("Analyze File"), AnalyzeFileProc },
680 // {N_("ICS Client"), IcsClientProc},
681 {N_("Edit Game"), EditGameProc},
682 {N_("Edit Position"), EditPositionProc},
683 {N_("Training"), TrainingProc},
684 {"----", NothingProc},
685 {N_("Show Engine Output"), EngineOutputProc},
686 {N_("Show Evaluation Graph"), NothingProc}, // [HGM] evalgr: not functional yet
687 {N_("Show Game List"), ShowGameListProc},
688 // {"Show Move History", HistoryShowProc}, // [HGM] hist: activate 4.2.7 code
689 {"----", NothingProc},
690 {N_("Edit Tags"), EditTagsProc},
691 {N_("Edit Comment"), EditCommentProc},
692 {N_("ICS Input Box"), IcsInputBoxProc},
696 MenuItem optionsMenu[] = {
697 // {N_("Flip View"), FlipViewProc},
698 // {"----", NothingProc},
699 {N_("Adjudications ..."), EngineMenuProc},
700 {N_("General Settings ..."), UciMenuProc},
701 {N_("Engine #1 Settings ..."), FirstSettingsProc},
702 {N_("Engine #2 Settings ..."), SecondSettingsProc},
703 {N_("Time Control ..."), TimeControlProc},
704 {"----", NothingProc},
705 {N_("Always Queen"), AlwaysQueenProc},
706 {N_("Animate Dragging"), AnimateDraggingProc},
707 {N_("Animate Moving"), AnimateMovingProc},
708 {N_("Auto Comment"), AutocommProc},
709 {N_("Auto Flag"), AutoflagProc},
710 {N_("Auto Flip View"), AutoflipProc},
711 {N_("Auto Observe"), AutobsProc},
712 {N_("Auto Raise Board"), AutoraiseProc},
713 {N_("Auto Save"), AutosaveProc},
714 {N_("Blindfold"), BlindfoldProc},
715 {N_("Flash Moves"), FlashMovesProc},
716 // {N_("Get Move List"), GetMoveListProc},
718 {N_("Highlight Dragging"), HighlightDraggingProc},
720 {N_("Highlight Last Move"), HighlightLastMoveProc},
721 {N_("Move Sound"), MoveSoundProc},
722 {N_("ICS Alarm"), IcsAlarmProc},
723 {N_("Old Save Style"), OldSaveStyleProc},
724 {N_("Periodic Updates"), PeriodicUpdatesProc},
725 {N_("Ponder Next Move"), PonderNextMoveProc},
726 {N_("Popup Exit Message"), PopupExitMessageProc},
727 {N_("Popup Move Errors"), PopupMoveErrorsProc},
728 {N_("Premove"), PremoveProc},
729 {N_("Quiet Play"), QuietPlayProc},
730 // {N_("Hide Thinking"), HideThinkingProc},
731 {N_("Test Legality"), TestLegalityProc},
736 {N_("File"), fileMenu},
737 {N_("Mode"), modeMenu},
738 {N_("Options"), optionsMenu},
742 #define PAUSE_BUTTON N_("P")
743 MenuItem buttonBar[] = {
744 // {"<<", ToStartProc},
745 // {"<", BackwardProc},
746 // {PAUSE_BUTTON, PauseProc},
747 // {">", ForwardProc},
748 // {">>", ToEndProc},
752 #define PIECE_MENU_SIZE 18
753 String pieceMenuStrings[2][PIECE_MENU_SIZE] = {
754 { N_("White"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
755 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
756 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
757 N_("Empty square"), N_("Clear board") },
758 { N_("Black"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
759 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
760 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
761 N_("Empty square"), N_("Clear board") }
763 /* must be in same order as PieceMenuStrings! */
764 ChessSquare pieceMenuTranslation[2][PIECE_MENU_SIZE] = {
765 { WhitePlay, (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
766 WhiteRook, WhiteQueen, WhiteKing, (ChessSquare) 0, WhiteAlfil,
767 WhiteCannon, WhiteAngel, WhiteMarshall, (ChessSquare) 0,
768 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
769 { BlackPlay, (ChessSquare) 0, BlackPawn, BlackKnight, BlackBishop,
770 BlackRook, BlackQueen, BlackKing, (ChessSquare) 0, BlackAlfil,
771 BlackCannon, BlackAngel, BlackMarshall, (ChessSquare) 0,
772 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
775 #define DROP_MENU_SIZE 6
776 String dropMenuStrings[DROP_MENU_SIZE] = {
777 "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"), N_("Queen")
779 /* must be in same order as PieceMenuStrings! */
780 ChessSquare dropMenuTranslation[DROP_MENU_SIZE] = {
781 (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
782 WhiteRook, WhiteQueen
790 DropMenuEnables dmEnables[] = {
799 { XtNborderWidth, 0 },
800 { XtNdefaultDistance, 0 },
804 { XtNborderWidth, 0 },
805 { XtNresizable, (XtArgVal) True },
809 { XtNborderWidth, 0 },
814 XtResource clientResources[] = {
815 { "whitePieceColor", "whitePieceColor", XtRString, sizeof(String),
816 XtOffset(AppDataPtr, whitePieceColor), XtRString,
818 { "blackPieceColor", "blackPieceColor", XtRString, sizeof(String),
819 XtOffset(AppDataPtr, blackPieceColor), XtRString,
821 { "lightSquareColor", "lightSquareColor", XtRString,
822 sizeof(String), XtOffset(AppDataPtr, lightSquareColor),
823 XtRString, LIGHT_SQUARE_COLOR },
824 { "darkSquareColor", "darkSquareColor", XtRString, sizeof(String),
825 XtOffset(AppDataPtr, darkSquareColor), XtRString,
827 { "highlightSquareColor", "highlightSquareColor", XtRString,
828 sizeof(String), XtOffset(AppDataPtr, highlightSquareColor),
829 XtRString, HIGHLIGHT_SQUARE_COLOR },
830 { "premoveHighlightColor", "premoveHighlightColor", XtRString,
831 sizeof(String), XtOffset(AppDataPtr, premoveHighlightColor),
832 XtRString, PREMOVE_HIGHLIGHT_COLOR },
833 { "movesPerSession", "movesPerSession", XtRInt, sizeof(int),
834 XtOffset(AppDataPtr, movesPerSession), XtRImmediate,
835 (XtPointer) MOVES_PER_SESSION },
836 { "timeIncrement", "timeIncrement", XtRInt, sizeof(int),
837 XtOffset(AppDataPtr, timeIncrement), XtRImmediate,
838 (XtPointer) TIME_INCREMENT },
839 { "initString", "initString", XtRString, sizeof(String),
840 XtOffset(AppDataPtr, initString), XtRString, INIT_STRING },
841 { "secondInitString", "secondInitString", XtRString, sizeof(String),
842 XtOffset(AppDataPtr, secondInitString), XtRString, INIT_STRING },
843 { "firstComputerString", "firstComputerString", XtRString,
844 sizeof(String), XtOffset(AppDataPtr, firstComputerString), XtRString,
846 { "secondComputerString", "secondComputerString", XtRString,
847 sizeof(String), XtOffset(AppDataPtr, secondComputerString), XtRString,
849 { "firstChessProgram", "firstChessProgram", XtRString,
850 sizeof(String), XtOffset(AppDataPtr, firstChessProgram),
851 XtRString, FIRST_CHESS_PROGRAM },
852 { "secondChessProgram", "secondChessProgram", XtRString,
853 sizeof(String), XtOffset(AppDataPtr, secondChessProgram),
854 XtRString, SECOND_CHESS_PROGRAM },
855 { "firstPlaysBlack", "firstPlaysBlack", XtRBoolean,
856 sizeof(Boolean), XtOffset(AppDataPtr, firstPlaysBlack),
857 XtRImmediate, (XtPointer) False },
858 { "noChessProgram", "noChessProgram", XtRBoolean,
859 sizeof(Boolean), XtOffset(AppDataPtr, noChessProgram),
860 XtRImmediate, (XtPointer) False },
861 { "firstHost", "firstHost", XtRString, sizeof(String),
862 XtOffset(AppDataPtr, firstHost), XtRString, FIRST_HOST },
863 { "secondHost", "secondHost", XtRString, sizeof(String),
864 XtOffset(AppDataPtr, secondHost), XtRString, SECOND_HOST },
865 { "firstDirectory", "firstDirectory", XtRString, sizeof(String),
866 XtOffset(AppDataPtr, firstDirectory), XtRString, "." },
867 { "secondDirectory", "secondDirectory", XtRString, sizeof(String),
868 XtOffset(AppDataPtr, secondDirectory), XtRString, "." },
869 { "bitmapDirectory", "bitmapDirectory", XtRString,
870 sizeof(String), XtOffset(AppDataPtr, bitmapDirectory),
872 { "remoteShell", "remoteShell", XtRString, sizeof(String),
873 XtOffset(AppDataPtr, remoteShell), XtRString, REMOTE_SHELL },
874 { "remoteUser", "remoteUser", XtRString, sizeof(String),
875 XtOffset(AppDataPtr, remoteUser), XtRString, "" },
876 { "timeDelay", "timeDelay", XtRFloat, sizeof(float),
877 XtOffset(AppDataPtr, timeDelay), XtRString,
878 (XtPointer) TIME_DELAY_QUOTE },
879 { "timeControl", "timeControl", XtRString, sizeof(String),
880 XtOffset(AppDataPtr, timeControl), XtRString,
881 (XtPointer) TIME_CONTROL },
882 { "internetChessServerMode", "internetChessServerMode",
883 XtRBoolean, sizeof(Boolean),
884 XtOffset(AppDataPtr, icsActive), XtRImmediate,
886 { "internetChessServerHost", "internetChessServerHost",
887 XtRString, sizeof(String),
888 XtOffset(AppDataPtr, icsHost),
889 XtRString, (XtPointer) ICS_HOST },
890 { "internetChessServerPort", "internetChessServerPort",
891 XtRString, sizeof(String),
892 XtOffset(AppDataPtr, icsPort), XtRString,
893 (XtPointer) ICS_PORT },
894 { "internetChessServerCommPort", "internetChessServerCommPort",
895 XtRString, sizeof(String),
896 XtOffset(AppDataPtr, icsCommPort), XtRString,
898 { "internetChessServerLogonScript", "internetChessServerLogonScript",
899 XtRString, sizeof(String),
900 XtOffset(AppDataPtr, icsLogon), XtRString,
902 { "internetChessServerHelper", "internetChessServerHelper",
903 XtRString, sizeof(String),
904 XtOffset(AppDataPtr, icsHelper), XtRString, "" },
905 { "internetChessServerInputBox", "internetChessServerInputBox",
906 XtRBoolean, sizeof(Boolean),
907 XtOffset(AppDataPtr, icsInputBox), XtRImmediate,
909 { "icsAlarm", "icsAlarm",
910 XtRBoolean, sizeof(Boolean),
911 XtOffset(AppDataPtr, icsAlarm), XtRImmediate,
913 { "icsAlarmTime", "icsAlarmTime",
915 XtOffset(AppDataPtr, icsAlarmTime), XtRImmediate,
917 { "useTelnet", "useTelnet", XtRBoolean, sizeof(Boolean),
918 XtOffset(AppDataPtr, useTelnet), XtRImmediate,
920 { "telnetProgram", "telnetProgram", XtRString, sizeof(String),
921 XtOffset(AppDataPtr, telnetProgram), XtRString, TELNET_PROGRAM },
922 { "gateway", "gateway", XtRString, sizeof(String),
923 XtOffset(AppDataPtr, gateway), XtRString, "" },
924 { "loadGameFile", "loadGameFile", XtRString, sizeof(String),
925 XtOffset(AppDataPtr, loadGameFile), XtRString, "" },
926 { "loadGameIndex", "loadGameIndex",
928 XtOffset(AppDataPtr, loadGameIndex), XtRImmediate,
930 { "saveGameFile", "saveGameFile", XtRString, sizeof(String),
931 XtOffset(AppDataPtr, saveGameFile), XtRString, "" },
932 { "autoRaiseBoard", "autoRaiseBoard", XtRBoolean,
933 sizeof(Boolean), XtOffset(AppDataPtr, autoRaiseBoard),
934 XtRImmediate, (XtPointer) True },
935 { "autoSaveGames", "autoSaveGames", XtRBoolean,
936 sizeof(Boolean), XtOffset(AppDataPtr, autoSaveGames),
937 XtRImmediate, (XtPointer) False },
938 { "blindfold", "blindfold", XtRBoolean,
939 sizeof(Boolean), XtOffset(AppDataPtr, blindfold),
940 XtRImmediate, (XtPointer) False },
941 { "loadPositionFile", "loadPositionFile", XtRString,
942 sizeof(String), XtOffset(AppDataPtr, loadPositionFile),
944 { "loadPositionIndex", "loadPositionIndex",
946 XtOffset(AppDataPtr, loadPositionIndex), XtRImmediate,
948 { "savePositionFile", "savePositionFile", XtRString,
949 sizeof(String), XtOffset(AppDataPtr, savePositionFile),
951 { "matchMode", "matchMode", XtRBoolean, sizeof(Boolean),
952 XtOffset(AppDataPtr, matchMode), XtRImmediate, (XtPointer) False },
953 { "matchGames", "matchGames", XtRInt, sizeof(int),
954 XtOffset(AppDataPtr, matchGames), XtRImmediate,
956 { "monoMode", "monoMode", XtRBoolean, sizeof(Boolean),
957 XtOffset(AppDataPtr, monoMode), XtRImmediate,
959 { "debugMode", "debugMode", XtRBoolean, sizeof(Boolean),
960 XtOffset(AppDataPtr, debugMode), XtRImmediate,
962 { "clockMode", "clockMode", XtRBoolean, sizeof(Boolean),
963 XtOffset(AppDataPtr, clockMode), XtRImmediate,
965 { "boardSize", "boardSize", XtRString, sizeof(String),
966 XtOffset(AppDataPtr, boardSize), XtRString, "" },
967 { "searchTime", "searchTime", XtRString, sizeof(String),
968 XtOffset(AppDataPtr, searchTime), XtRString,
970 { "searchDepth", "searchDepth", XtRInt, sizeof(int),
971 XtOffset(AppDataPtr, searchDepth), XtRImmediate,
973 { "showCoords", "showCoords", XtRBoolean, sizeof(Boolean),
974 XtOffset(AppDataPtr, showCoords), XtRImmediate,
976 { "showJail", "showJail", XtRInt, sizeof(int),
977 XtOffset(AppDataPtr, showJail), XtRImmediate,
979 { "showThinking", "showThinking", XtRBoolean, sizeof(Boolean),
980 XtOffset(AppDataPtr, showThinking), XtRImmediate,
982 { "ponderNextMove", "ponderNextMove", XtRBoolean, sizeof(Boolean),
983 XtOffset(AppDataPtr, ponderNextMove), XtRImmediate,
985 { "periodicUpdates", "periodicUpdates", XtRBoolean, sizeof(Boolean),
986 XtOffset(AppDataPtr, periodicUpdates), XtRImmediate,
988 { "clockFont", "clockFont", XtRString, sizeof(String),
989 XtOffset(AppDataPtr, clockFont), XtRString, CLOCK_FONT },
990 { "coordFont", "coordFont", XtRString, sizeof(String),
991 XtOffset(AppDataPtr, coordFont), XtRString, COORD_FONT },
992 { "font", "font", XtRString, sizeof(String),
993 XtOffset(AppDataPtr, font), XtRString, DEFAULT_FONT },
994 { "ringBellAfterMoves", "ringBellAfterMoves",
995 XtRBoolean, sizeof(Boolean),
996 XtOffset(AppDataPtr, ringBellAfterMoves),
997 XtRImmediate, (XtPointer) False },
998 { "autoCallFlag", "autoCallFlag", XtRBoolean,
999 sizeof(Boolean), XtOffset(AppDataPtr, autoCallFlag),
1000 XtRImmediate, (XtPointer) False },
1001 { "autoFlipView", "autoFlipView", XtRBoolean,
1002 sizeof(Boolean), XtOffset(AppDataPtr, autoFlipView),
1003 XtRImmediate, (XtPointer) True },
1004 { "autoObserve", "autoObserve", XtRBoolean,
1005 sizeof(Boolean), XtOffset(AppDataPtr, autoObserve),
1006 XtRImmediate, (XtPointer) False },
1007 { "autoComment", "autoComment", XtRBoolean,
1008 sizeof(Boolean), XtOffset(AppDataPtr, autoComment),
1009 XtRImmediate, (XtPointer) False },
1010 { "getMoveList", "getMoveList", XtRBoolean,
1011 sizeof(Boolean), XtOffset(AppDataPtr, getMoveList),
1012 XtRImmediate, (XtPointer) True },
1014 { "highlightDragging", "highlightDragging", XtRBoolean,
1015 sizeof(Boolean), XtOffset(AppDataPtr, highlightDragging),
1016 XtRImmediate, (XtPointer) False },
1018 { "highlightLastMove", "highlightLastMove", XtRBoolean,
1019 sizeof(Boolean), XtOffset(AppDataPtr, highlightLastMove),
1020 XtRImmediate, (XtPointer) False },
1021 { "premove", "premove", XtRBoolean,
1022 sizeof(Boolean), XtOffset(AppDataPtr, premove),
1023 XtRImmediate, (XtPointer) True },
1024 { "testLegality", "testLegality", XtRBoolean,
1025 sizeof(Boolean), XtOffset(AppDataPtr, testLegality),
1026 XtRImmediate, (XtPointer) True },
1027 { "flipView", "flipView", XtRBoolean,
1028 sizeof(Boolean), XtOffset(AppDataPtr, flipView),
1029 XtRImmediate, (XtPointer) False },
1030 { "cmail", "cmailGameName", XtRString, sizeof(String),
1031 XtOffset(AppDataPtr, cmailGameName), XtRString, "" },
1032 { "alwaysPromoteToQueen", "alwaysPromoteToQueen", XtRBoolean,
1033 sizeof(Boolean), XtOffset(AppDataPtr, alwaysPromoteToQueen),
1034 XtRImmediate, (XtPointer) False },
1035 { "oldSaveStyle", "oldSaveStyle", XtRBoolean,
1036 sizeof(Boolean), XtOffset(AppDataPtr, oldSaveStyle),
1037 XtRImmediate, (XtPointer) False },
1038 { "quietPlay", "quietPlay", XtRBoolean,
1039 sizeof(Boolean), XtOffset(AppDataPtr, quietPlay),
1040 XtRImmediate, (XtPointer) False },
1041 { "titleInWindow", "titleInWindow", XtRBoolean,
1042 sizeof(Boolean), XtOffset(AppDataPtr, titleInWindow),
1043 XtRImmediate, (XtPointer) False },
1044 { "localLineEditing", "localLineEditing", XtRBoolean,
1045 sizeof(Boolean), XtOffset(AppDataPtr, localLineEditing),
1046 XtRImmediate, (XtPointer) True }, /* not implemented, must be True */
1048 { "zippyTalk", "zippyTalk", XtRBoolean,
1049 sizeof(Boolean), XtOffset(AppDataPtr, zippyTalk),
1050 XtRImmediate, (XtPointer) ZIPPY_TALK },
1051 { "zippyPlay", "zippyPlay", XtRBoolean,
1052 sizeof(Boolean), XtOffset(AppDataPtr, zippyPlay),
1053 XtRImmediate, (XtPointer) ZIPPY_PLAY },
1054 { "zippyLines", "zippyLines", XtRString, sizeof(String),
1055 XtOffset(AppDataPtr, zippyLines), XtRString, ZIPPY_LINES },
1056 { "zippyPinhead", "zippyPinhead", XtRString, sizeof(String),
1057 XtOffset(AppDataPtr, zippyPinhead), XtRString, ZIPPY_PINHEAD },
1058 { "zippyPassword", "zippyPassword", XtRString, sizeof(String),
1059 XtOffset(AppDataPtr, zippyPassword), XtRString, ZIPPY_PASSWORD },
1060 { "zippyPassword2", "zippyPassword2", XtRString, sizeof(String),
1061 XtOffset(AppDataPtr, zippyPassword2), XtRString, ZIPPY_PASSWORD2 },
1062 { "zippyWrongPassword", "zippyWrongPassword", XtRString, sizeof(String),
1063 XtOffset(AppDataPtr, zippyWrongPassword), XtRString,
1064 ZIPPY_WRONG_PASSWORD },
1065 { "zippyAcceptOnly", "zippyAcceptOnly", XtRString, sizeof(String),
1066 XtOffset(AppDataPtr, zippyAcceptOnly), XtRString, ZIPPY_ACCEPT_ONLY },
1067 { "zippyUseI", "zippyUseI", XtRBoolean,
1068 sizeof(Boolean), XtOffset(AppDataPtr, zippyUseI),
1069 XtRImmediate, (XtPointer) ZIPPY_USE_I },
1070 { "zippyBughouse", "zippyBughouse", XtRInt,
1071 sizeof(int), XtOffset(AppDataPtr, zippyBughouse),
1072 XtRImmediate, (XtPointer) ZIPPY_BUGHOUSE },
1073 { "zippyNoplayCrafty", "zippyNoplayCrafty", XtRBoolean,
1074 sizeof(Boolean), XtOffset(AppDataPtr, zippyNoplayCrafty),
1075 XtRImmediate, (XtPointer) ZIPPY_NOPLAY_CRAFTY },
1076 { "zippyGameEnd", "zippyGameEnd", XtRString, sizeof(String),
1077 XtOffset(AppDataPtr, zippyGameEnd), XtRString, ZIPPY_GAME_END },
1078 { "zippyGameStart", "zippyGameStart", XtRString, sizeof(String),
1079 XtOffset(AppDataPtr, zippyGameStart), XtRString, ZIPPY_GAME_START },
1080 { "zippyAdjourn", "zippyAdjourn", XtRBoolean,
1081 sizeof(Boolean), XtOffset(AppDataPtr, zippyAdjourn),
1082 XtRImmediate, (XtPointer) ZIPPY_ADJOURN },
1083 { "zippyAbort", "zippyAbort", XtRBoolean,
1084 sizeof(Boolean), XtOffset(AppDataPtr, zippyAbort),
1085 XtRImmediate, (XtPointer) ZIPPY_ABORT },
1086 { "zippyVariants", "zippyVariants", XtRString, sizeof(String),
1087 XtOffset(AppDataPtr, zippyVariants), XtRString, ZIPPY_VARIANTS },
1088 { "zippyMaxGames", "zippyMaxGames", XtRInt, sizeof(int),
1089 XtOffset(AppDataPtr, zippyMaxGames), XtRImmediate,
1090 (XtPointer) ZIPPY_MAX_GAMES },
1091 { "zippyReplayTimeout", "zippyReplayTimeout", XtRInt, sizeof(int),
1092 XtOffset(AppDataPtr, zippyReplayTimeout), XtRImmediate,
1093 (XtPointer) ZIPPY_REPLAY_TIMEOUT },
1094 { "zippyShortGame", "zippyShortGame", XtRInt, sizeof(int),
1095 XtOffset(AppDataPtr, zippyShortGame), XtRImmediate,
1098 { "flashCount", "flashCount", XtRInt, sizeof(int),
1099 XtOffset(AppDataPtr, flashCount), XtRImmediate,
1100 (XtPointer) FLASH_COUNT },
1101 { "flashRate", "flashRate", XtRInt, sizeof(int),
1102 XtOffset(AppDataPtr, flashRate), XtRImmediate,
1103 (XtPointer) FLASH_RATE },
1104 { "pixmapDirectory", "pixmapDirectory", XtRString,
1105 sizeof(String), XtOffset(AppDataPtr, pixmapDirectory),
1107 { "msLoginDelay", "msLoginDelay", XtRInt, sizeof(int),
1108 XtOffset(AppDataPtr, msLoginDelay), XtRImmediate,
1109 (XtPointer) MS_LOGIN_DELAY },
1110 { "colorizeMessages", "colorizeMessages", XtRBoolean,
1111 sizeof(Boolean), XtOffset(AppDataPtr, colorize),
1112 XtRImmediate, (XtPointer) False },
1113 { "colorShout", "colorShout", XtRString,
1114 sizeof(String), XtOffset(AppDataPtr, colorShout),
1115 XtRString, COLOR_SHOUT },
1116 { "colorSShout", "colorSShout", XtRString,
1117 sizeof(String), XtOffset(AppDataPtr, colorSShout),
1118 XtRString, COLOR_SSHOUT },
1119 { "colorChannel1", "colorChannel1", XtRString,
1120 sizeof(String), XtOffset(AppDataPtr, colorChannel1),
1121 XtRString, COLOR_CHANNEL1 },
1122 { "colorChannel", "colorChannel", XtRString,
1123 sizeof(String), XtOffset(AppDataPtr, colorChannel),
1124 XtRString, COLOR_CHANNEL },
1125 { "colorKibitz", "colorKibitz", XtRString,
1126 sizeof(String), XtOffset(AppDataPtr, colorKibitz),
1127 XtRString, COLOR_KIBITZ },
1128 { "colorTell", "colorTell", XtRString,
1129 sizeof(String), XtOffset(AppDataPtr, colorTell),
1130 XtRString, COLOR_TELL },
1131 { "colorChallenge", "colorChallenge", XtRString,
1132 sizeof(String), XtOffset(AppDataPtr, colorChallenge),
1133 XtRString, COLOR_CHALLENGE },
1134 { "colorRequest", "colorRequest", XtRString,
1135 sizeof(String), XtOffset(AppDataPtr, colorRequest),
1136 XtRString, COLOR_REQUEST },
1137 { "colorSeek", "colorSeek", XtRString,
1138 sizeof(String), XtOffset(AppDataPtr, colorSeek),
1139 XtRString, COLOR_SEEK },
1140 { "colorNormal", "colorNormal", XtRString,
1141 sizeof(String), XtOffset(AppDataPtr, colorNormal),
1142 XtRString, COLOR_NORMAL },
1143 { "soundProgram", "soundProgram", XtRString,
1144 sizeof(String), XtOffset(AppDataPtr, soundProgram),
1145 XtRString, "play" },
1146 { "soundShout", "soundShout", XtRString,
1147 sizeof(String), XtOffset(AppDataPtr, soundShout),
1149 { "soundSShout", "soundSShout", XtRString,
1150 sizeof(String), XtOffset(AppDataPtr, soundSShout),
1152 { "soundChannel1", "soundChannel1", XtRString,
1153 sizeof(String), XtOffset(AppDataPtr, soundChannel1),
1155 { "soundChannel", "soundChannel", XtRString,
1156 sizeof(String), XtOffset(AppDataPtr, soundChannel),
1158 { "soundKibitz", "soundKibitz", XtRString,
1159 sizeof(String), XtOffset(AppDataPtr, soundKibitz),
1161 { "soundTell", "soundTell", XtRString,
1162 sizeof(String), XtOffset(AppDataPtr, soundTell),
1164 { "soundChallenge", "soundChallenge", XtRString,
1165 sizeof(String), XtOffset(AppDataPtr, soundChallenge),
1167 { "soundRequest", "soundRequest", XtRString,
1168 sizeof(String), XtOffset(AppDataPtr, soundRequest),
1170 { "soundSeek", "soundSeek", XtRString,
1171 sizeof(String), XtOffset(AppDataPtr, soundSeek),
1173 { "soundMove", "soundMove", XtRString,
1174 sizeof(String), XtOffset(AppDataPtr, soundMove),
1176 { "soundIcsWin", "soundIcsWin", XtRString,
1177 sizeof(String), XtOffset(AppDataPtr, soundIcsWin),
1179 { "soundIcsLoss", "soundIcsLoss", XtRString,
1180 sizeof(String), XtOffset(AppDataPtr, soundIcsLoss),
1182 { "soundIcsDraw", "soundIcsDraw", XtRString,
1183 sizeof(String), XtOffset(AppDataPtr, soundIcsDraw),
1185 { "soundIcsUnfinished", "soundIcsUnfinished", XtRString,
1186 sizeof(String), XtOffset(AppDataPtr, soundIcsUnfinished),
1188 { "soundIcsAlarm", "soundIcsAlarm", XtRString,
1189 sizeof(String), XtOffset(AppDataPtr, soundIcsAlarm),
1191 { "reuseFirst", "reuseFirst", XtRBoolean,
1192 sizeof(Boolean), XtOffset(AppDataPtr, reuseFirst),
1193 XtRImmediate, (XtPointer) True },
1194 { "reuseSecond", "reuseSecond", XtRBoolean,
1195 sizeof(Boolean), XtOffset(AppDataPtr, reuseSecond),
1196 XtRImmediate, (XtPointer) True },
1197 { "animateDragging", "animateDragging", XtRBoolean,
1198 sizeof(Boolean), XtOffset(AppDataPtr, animateDragging),
1199 XtRImmediate, (XtPointer) True },
1200 { "animateMoving", "animateMoving", XtRBoolean,
1201 sizeof(Boolean), XtOffset(AppDataPtr, animate),
1202 XtRImmediate, (XtPointer) True },
1203 { "animateSpeed", "animateSpeed", XtRInt,
1204 sizeof(int), XtOffset(AppDataPtr, animSpeed),
1205 XtRImmediate, (XtPointer)10 },
1206 { "popupExitMessage", "popupExitMessage", XtRBoolean,
1207 sizeof(Boolean), XtOffset(AppDataPtr, popupExitMessage),
1208 XtRImmediate, (XtPointer) True },
1209 { "popupMoveErrors", "popupMoveErrors", XtRBoolean,
1210 sizeof(Boolean), XtOffset(AppDataPtr, popupMoveErrors),
1211 XtRImmediate, (XtPointer) False },
1212 { "fontSizeTolerance", "fontSizeTolerance", XtRInt,
1213 sizeof(int), XtOffset(AppDataPtr, fontSizeTolerance),
1214 XtRImmediate, (XtPointer)4 },
1215 { "initialMode", "initialMode", XtRString,
1216 sizeof(String), XtOffset(AppDataPtr, initialMode),
1217 XtRImmediate, (XtPointer) "" },
1218 { "variant", "variant", XtRString,
1219 sizeof(String), XtOffset(AppDataPtr, variant),
1220 XtRImmediate, (XtPointer) "normal" },
1221 { "firstProtocolVersion", "firstProtocolVersion", XtRInt,
1222 sizeof(int), XtOffset(AppDataPtr, firstProtocolVersion),
1223 XtRImmediate, (XtPointer)PROTOVER },
1224 { "secondProtocolVersion", "secondProtocolVersion", XtRInt,
1225 sizeof(int), XtOffset(AppDataPtr, secondProtocolVersion),
1226 XtRImmediate, (XtPointer)PROTOVER },
1227 { "showButtonBar", "showButtonBar", XtRBoolean,
1228 sizeof(Boolean), XtOffset(AppDataPtr, showButtonBar),
1229 XtRImmediate, (XtPointer) True },
1230 { "lowTimeWarningColor", "lowTimeWarningColor", XtRString,
1231 sizeof(String), XtOffset(AppDataPtr, lowTimeWarningColor),
1232 XtRString, COLOR_LOWTIMEWARNING },
1233 { "lowTimeWarning", "lowTimeWarning", XtRBoolean,
1234 sizeof(Boolean), XtOffset(AppDataPtr, lowTimeWarning),
1235 XtRImmediate, (XtPointer) False },
1236 {"icsEngineAnalyze", "icsEngineAnalyze", XtRBoolean, /* [DM] icsEngineAnalyze */
1237 sizeof(Boolean), XtOffset(AppDataPtr, icsEngineAnalyze),
1238 XtRImmediate, (XtPointer) False },
1239 { "firstScoreAbs", "firstScoreAbs", XtRBoolean,
1240 sizeof(Boolean), XtOffset(AppDataPtr, firstScoreIsAbsolute),
1241 XtRImmediate, (XtPointer) False },
1242 { "secondScoreAbs", "secondScoreAbs", XtRBoolean,
1243 sizeof(Boolean), XtOffset(AppDataPtr, secondScoreIsAbsolute),
1244 XtRImmediate, (XtPointer) False },
1245 { "pgnExtendedInfo", "pgnExtendedInfo", XtRBoolean,
1246 sizeof(Boolean), XtOffset(AppDataPtr, saveExtendedInfoInPGN),
1247 XtRImmediate, (XtPointer) False },
1248 { "hideThinkingFromHuman", "hideThinkingFromHuman", XtRBoolean,
1249 sizeof(Boolean), XtOffset(AppDataPtr, hideThinkingFromHuman),
1250 XtRImmediate, (XtPointer) True },
1251 { "adjudicateLossThreshold", "adjudicateLossThreshold", XtRInt,
1252 sizeof(int), XtOffset(AppDataPtr, adjudicateLossThreshold),
1253 XtRImmediate, (XtPointer) 0},
1254 { "adjudicateDrawMoves", "adjudicateDrawMoves", XtRInt,
1255 sizeof(int), XtOffset(AppDataPtr, adjudicateDrawMoves),
1256 XtRImmediate, (XtPointer) 0},
1257 { "pgnEventHeader", "pgnEventHeader", XtRString,
1258 sizeof(String), XtOffset(AppDataPtr, pgnEventHeader),
1259 XtRImmediate, (XtPointer) "Computer Chess Game" },
1260 { "defaultFrcPosition", "defaultFrcPositon", XtRInt,
1261 sizeof(int), XtOffset(AppDataPtr, defaultFrcPosition),
1262 XtRImmediate, (XtPointer) -1},
1263 { "gameListTags", "gameListTags", XtRString,
1264 sizeof(String), XtOffset(AppDataPtr, gameListTags),
1265 XtRImmediate, (XtPointer) GLT_DEFAULT_TAGS },
1267 // [HGM] 4.3.xx options
1268 { "boardWidth", "boardWidth", XtRInt,
1269 sizeof(int), XtOffset(AppDataPtr, NrFiles),
1270 XtRImmediate, (XtPointer) -1},
1271 { "boardHeight", "boardHeight", XtRInt,
1272 sizeof(int), XtOffset(AppDataPtr, NrRanks),
1273 XtRImmediate, (XtPointer) -1},
1274 { "matchPause", "matchPause", XtRInt,
1275 sizeof(int), XtOffset(AppDataPtr, matchPause),
1276 XtRImmediate, (XtPointer) 10000},
1277 { "holdingsSize", "holdingsSize", XtRInt,
1278 sizeof(int), XtOffset(AppDataPtr, holdingsSize),
1279 XtRImmediate, (XtPointer) -1},
1280 { "flipBlack", "flipBlack", XtRBoolean,
1281 sizeof(Boolean), XtOffset(AppDataPtr, upsideDown),
1282 XtRImmediate, (XtPointer) False},
1283 { "allWhite", "allWhite", XtRBoolean,
1284 sizeof(Boolean), XtOffset(AppDataPtr, allWhite),
1285 XtRImmediate, (XtPointer) False},
1286 { "pieceToCharTable", "pieceToCharTable", XtRString,
1287 sizeof(String), XtOffset(AppDataPtr, pieceToCharTable),
1288 XtRImmediate, (XtPointer) 0},
1289 { "alphaRank", "alphaRank", XtRBoolean,
1290 sizeof(Boolean), XtOffset(AppDataPtr, alphaRank),
1291 XtRImmediate, (XtPointer) False},
1292 { "testClaims", "testClaims", XtRBoolean,
1293 sizeof(Boolean), XtOffset(AppDataPtr, testClaims),
1294 XtRImmediate, (XtPointer) True},
1295 { "checkMates", "checkMates", XtRBoolean,
1296 sizeof(Boolean), XtOffset(AppDataPtr, checkMates),
1297 XtRImmediate, (XtPointer) True},
1298 { "materialDraws", "materialDraws", XtRBoolean,
1299 sizeof(Boolean), XtOffset(AppDataPtr, materialDraws),
1300 XtRImmediate, (XtPointer) True},
1301 { "trivialDraws", "trivialDraws", XtRBoolean,
1302 sizeof(Boolean), XtOffset(AppDataPtr, trivialDraws),
1303 XtRImmediate, (XtPointer) False},
1304 { "ruleMoves", "ruleMoves", XtRInt,
1305 sizeof(int), XtOffset(AppDataPtr, ruleMoves),
1306 XtRImmediate, (XtPointer) 51},
1307 { "repeatsToDraw", "repeatsToDraw", XtRInt,
1308 sizeof(int), XtOffset(AppDataPtr, drawRepeats),
1309 XtRImmediate, (XtPointer) 6},
1310 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1311 sizeof(int), XtOffset(AppDataPtr, engineComments),
1312 XtRImmediate, (XtPointer) 1},
1313 { "userName", "userName", XtRString,
1314 sizeof(int), XtOffset(AppDataPtr, userName),
1315 XtRImmediate, (XtPointer) 0},
1316 { "autoKibitz", "autoKibitz", XtRBoolean,
1317 sizeof(Boolean), XtOffset(AppDataPtr, autoKibitz),
1318 XtRImmediate, (XtPointer) False},
1319 { "firstTimeOdds", "firstTimeOdds", XtRInt,
1320 sizeof(int), XtOffset(AppDataPtr, firstTimeOdds),
1321 XtRImmediate, (XtPointer) 1},
1322 { "secondTimeOdds", "secondTimeOdds", XtRInt,
1323 sizeof(int), XtOffset(AppDataPtr, secondTimeOdds),
1324 XtRImmediate, (XtPointer) 1},
1325 { "timeOddsMode", "timeOddsMode", XtRInt,
1326 sizeof(int), XtOffset(AppDataPtr, timeOddsMode),
1327 XtRImmediate, (XtPointer) 0},
1328 { "firstAccumulateTC", "firstAccumulateTC", XtRInt,
1329 sizeof(int), XtOffset(AppDataPtr, firstAccumulateTC),
1330 XtRImmediate, (XtPointer) 1},
1331 { "secondAccumulateTC", "secondAccumulateTC", XtRInt,
1332 sizeof(int), XtOffset(AppDataPtr, secondAccumulateTC),
1333 XtRImmediate, (XtPointer) 1},
1334 { "firstNPS", "firstNPS", XtRInt,
1335 sizeof(int), XtOffset(AppDataPtr, firstNPS),
1336 XtRImmediate, (XtPointer) -1},
1337 { "secondNPS", "secondNPS", XtRInt,
1338 sizeof(int), XtOffset(AppDataPtr, secondNPS),
1339 XtRImmediate, (XtPointer) -1},
1340 { "serverMoves", "serverMoves", XtRString,
1341 sizeof(String), XtOffset(AppDataPtr, serverMovesName),
1342 XtRImmediate, (XtPointer) 0},
1343 { "serverPause", "serverPause", XtRInt,
1344 sizeof(int), XtOffset(AppDataPtr, serverPause),
1345 XtRImmediate, (XtPointer) 0},
1346 { "suppressLoadMoves", "suppressLoadMoves", XtRBoolean,
1347 sizeof(Boolean), XtOffset(AppDataPtr, suppressLoadMoves),
1348 XtRImmediate, (XtPointer) False},
1349 { "userName", "userName", XtRString,
1350 sizeof(String), XtOffset(AppDataPtr, userName),
1351 XtRImmediate, (XtPointer) 0},
1352 { "egtFormats", "egtFormats", XtRString,
1353 sizeof(String), XtOffset(AppDataPtr, egtFormats),
1354 XtRImmediate, (XtPointer) 0},
1355 { "rewindIndex", "rewindIndex", XtRInt,
1356 sizeof(int), XtOffset(AppDataPtr, rewindIndex),
1357 XtRImmediate, (XtPointer) 0},
1358 { "sameColorGames", "sameColorGames", XtRInt,
1359 sizeof(int), XtOffset(AppDataPtr, sameColorGames),
1360 XtRImmediate, (XtPointer) 0},
1361 { "smpCores", "smpCores", XtRInt,
1362 sizeof(int), XtOffset(AppDataPtr, smpCores),
1363 XtRImmediate, (XtPointer) 1},
1364 { "niceEngines", "niceEngines", XtRInt,
1365 sizeof(int), XtOffset(AppDataPtr, niceEngines),
1366 XtRImmediate, (XtPointer) 0},
1367 { "nameOfDebugFile", "nameOfDebugFile", XtRString,
1368 sizeof(String), XtOffset(AppDataPtr, nameOfDebugFile),
1369 XtRImmediate, (XtPointer) "xboard.debug"},
1370 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1371 sizeof(int), XtOffset(AppDataPtr, engineComments),
1372 XtRImmediate, (XtPointer) 1},
1373 { "noGUI", "noGUI", XtRBoolean,
1374 sizeof(Boolean), XtOffset(AppDataPtr, noGUI),
1375 XtRImmediate, (XtPointer) 0},
1376 { "firstOptions", "firstOptions", XtRString,
1377 sizeof(String), XtOffset(AppDataPtr, firstOptions),
1378 XtRImmediate, (XtPointer) "" },
1379 { "secondOptions", "secondOptions", XtRString,
1380 sizeof(String), XtOffset(AppDataPtr, secondOptions),
1381 XtRImmediate, (XtPointer) "" },
1382 { "firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XtRString,
1383 sizeof(String), XtOffset(AppDataPtr, fenOverride1),
1384 XtRImmediate, (XtPointer) 0 },
1385 { "secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XtRString,
1386 sizeof(String), XtOffset(AppDataPtr, fenOverride2),
1387 XtRImmediate, (XtPointer) 0 },
1389 // [HGM] Winboard_x UCI options
1390 { "firstIsUCI", "firstIsUCI", XtRBoolean,
1391 sizeof(Boolean), XtOffset(AppDataPtr, firstIsUCI),
1392 XtRImmediate, (XtPointer) False},
1393 { "secondIsUCI", "secondIsUCI", XtRBoolean,
1394 sizeof(Boolean), XtOffset(AppDataPtr, secondIsUCI),
1395 XtRImmediate, (XtPointer) False},
1396 { "firstHasOwnBookUCI", "firstHasOwnBookUCI", XtRBoolean,
1397 sizeof(Boolean), XtOffset(AppDataPtr, firstHasOwnBookUCI),
1398 XtRImmediate, (XtPointer) True},
1399 { "secondHasOwnBookUCI", "secondHasOwnBookUCI", XtRBoolean,
1400 sizeof(Boolean), XtOffset(AppDataPtr, secondHasOwnBookUCI),
1401 XtRImmediate, (XtPointer) True},
1402 { "usePolyglotBook", "usePolyglotBook", XtRBoolean,
1403 sizeof(Boolean), XtOffset(AppDataPtr, usePolyglotBook),
1404 XtRImmediate, (XtPointer) False},
1405 { "defaultHashSize", "defaultHashSize", XtRInt,
1406 sizeof(int), XtOffset(AppDataPtr, defaultHashSize),
1407 XtRImmediate, (XtPointer) 64},
1408 { "defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XtRInt,
1409 sizeof(int), XtOffset(AppDataPtr, defaultCacheSizeEGTB),
1410 XtRImmediate, (XtPointer) 4},
1411 { "polyglotDir", "polyglotDir", XtRString,
1412 sizeof(String), XtOffset(AppDataPtr, polyglotDir),
1413 XtRImmediate, (XtPointer) "." },
1414 { "polyglotBook", "polyglotBook", XtRString,
1415 sizeof(String), XtOffset(AppDataPtr, polyglotBook),
1416 XtRImmediate, (XtPointer) "" },
1417 { "defaultPathEGTB", "defaultPathEGTB", XtRString,
1418 sizeof(String), XtOffset(AppDataPtr, defaultPathEGTB),
1419 XtRImmediate, (XtPointer) "/usr/local/share/egtb"},
1420 { "delayBeforeQuit", "delayBeforeQuit", XtRInt,
1421 sizeof(int), XtOffset(AppDataPtr, delayBeforeQuit),
1422 XtRImmediate, (XtPointer) 0},
1423 { "delayAfterQuit", "delayAfterQuit", XtRInt,
1424 sizeof(int), XtOffset(AppDataPtr, delayAfterQuit),
1425 XtRImmediate, (XtPointer) 0},
1426 { "keepAlive", "keepAlive", XtRInt,
1427 sizeof(int), XtOffset(AppDataPtr, keepAlive),
1428 XtRImmediate, (XtPointer) 0},
1429 { "forceIllegalMoves", "forceIllegalMoves", XtRBoolean,
1430 sizeof(Boolean), XtOffset(AppDataPtr, forceIllegal),
1431 XtRImmediate, (XtPointer) False},
1434 XrmOptionDescRec shellOptions[] = {
1435 { "-whitePieceColor", "whitePieceColor", XrmoptionSepArg, NULL },
1436 { "-blackPieceColor", "blackPieceColor", XrmoptionSepArg, NULL },
1437 { "-lightSquareColor", "lightSquareColor", XrmoptionSepArg, NULL },
1438 { "-darkSquareColor", "darkSquareColor", XrmoptionSepArg, NULL },
1439 { "-highlightSquareColor", "highlightSquareColor", XrmoptionSepArg, NULL },
1440 { "-premoveHighlightColor", "premoveHighlightColor", XrmoptionSepArg,NULL},
1441 { "-movesPerSession", "movesPerSession", XrmoptionSepArg, NULL },
1442 { "-mps", "movesPerSession", XrmoptionSepArg, NULL },
1443 { "-timeIncrement", "timeIncrement", XrmoptionSepArg, NULL },
1444 { "-inc", "timeIncrement", XrmoptionSepArg, NULL },
1445 { "-initString", "initString", XrmoptionSepArg, NULL },
1446 { "-firstInitString", "initString", XrmoptionSepArg, NULL },
1447 { "-secondInitString", "secondInitString", XrmoptionSepArg, NULL },
1448 { "-firstComputerString", "firstComputerString", XrmoptionSepArg, NULL },
1449 { "-secondComputerString", "secondComputerString", XrmoptionSepArg, NULL },
1450 { "-firstChessProgram", "firstChessProgram", XrmoptionSepArg, NULL },
1451 { "-fcp", "firstChessProgram", XrmoptionSepArg, NULL },
1452 { "-secondChessProgram", "secondChessProgram", XrmoptionSepArg, NULL },
1453 { "-scp", "secondChessProgram", XrmoptionSepArg, NULL },
1454 { "-firstPlaysBlack", "firstPlaysBlack", XrmoptionSepArg, NULL },
1455 { "-fb", "firstPlaysBlack", XrmoptionNoArg, "True" },
1456 { "-xfb", "firstPlaysBlack", XrmoptionNoArg, "False" },
1457 { "-noChessProgram", "noChessProgram", XrmoptionSepArg, NULL },
1458 { "-ncp", "noChessProgram", XrmoptionNoArg, "True" },
1459 { "-xncp", "noChessProgram", XrmoptionNoArg, "False" },
1460 { "-firstHost", "firstHost", XrmoptionSepArg, NULL },
1461 { "-fh", "firstHost", XrmoptionSepArg, NULL },
1462 { "-secondHost", "secondHost", XrmoptionSepArg, NULL },
1463 { "-sh", "secondHost", XrmoptionSepArg, NULL },
1464 { "-firstDirectory", "firstDirectory", XrmoptionSepArg, NULL },
1465 { "-fd", "firstDirectory", XrmoptionSepArg, NULL },
1466 { "-secondDirectory", "secondDirectory", XrmoptionSepArg, NULL },
1467 { "-sd", "secondDirectory", XrmoptionSepArg, NULL },
1468 { "-bitmapDirectory", "bitmapDirectory", XrmoptionSepArg, NULL },
1469 { "-bm", "bitmapDirectory", XrmoptionSepArg, NULL },
1470 { "-remoteShell", "remoteShell", XrmoptionSepArg, NULL },
1471 { "-rsh", "remoteShell", XrmoptionSepArg, NULL },
1472 { "-remoteUser", "remoteUser", XrmoptionSepArg, NULL },
1473 { "-ruser", "remoteUser", XrmoptionSepArg, NULL },
1474 { "-timeDelay", "timeDelay", XrmoptionSepArg, NULL },
1475 { "-td", "timeDelay", XrmoptionSepArg, NULL },
1476 { "-timeControl", "timeControl", XrmoptionSepArg, NULL },
1477 { "-tc", "timeControl", XrmoptionSepArg, NULL },
1478 { "-internetChessServerMode", "internetChessServerMode",
1479 XrmoptionSepArg, NULL },
1480 { "-ics", "internetChessServerMode", XrmoptionNoArg, "True" },
1481 { "-xics", "internetChessServerMode", XrmoptionNoArg, "False" },
1482 { "-internetChessServerHost", "internetChessServerHost",
1483 XrmoptionSepArg, NULL },
1484 { "-icshost", "internetChessServerHost", XrmoptionSepArg, NULL },
1485 { "-internetChessServerPort", "internetChessServerPort",
1486 XrmoptionSepArg, NULL },
1487 { "-icsport", "internetChessServerPort", XrmoptionSepArg, NULL },
1488 { "-internetChessServerCommPort", "internetChessServerCommPort",
1489 XrmoptionSepArg, NULL },
1490 { "-icscomm", "internetChessServerCommPort", XrmoptionSepArg, NULL },
1491 { "-internetChessServerLogonScript", "internetChessServerLogonScript",
1492 XrmoptionSepArg, NULL },
1493 { "-icslogon", "internetChessServerLogonScript", XrmoptionSepArg, NULL },
1494 { "-internetChessServerHelper", "internetChessServerHelper",
1495 XrmoptionSepArg, NULL },
1496 { "-icshelper", "internetChessServerHelper", XrmoptionSepArg, NULL },
1497 { "-internetChessServerInputBox", "internetChessServerInputBox",
1498 XrmoptionSepArg, NULL },
1499 { "-icsinput", "internetChessServerInputBox", XrmoptionNoArg, "True" },
1500 { "-xicsinput", "internetChessServerInputBox", XrmoptionNoArg, "False" },
1501 { "-icsAlarm", "icsAlarm", XrmoptionSepArg, NULL },
1502 { "-alarm", "icsAlarm", XrmoptionNoArg, "True" },
1503 { "-xalarm", "icsAlarm", XrmoptionNoArg, "False" },
1504 { "-icsAlarmTime", "icsAlarmTime", XrmoptionSepArg, NULL },
1505 { "-useTelnet", "useTelnet", XrmoptionSepArg, NULL },
1506 { "-telnet", "useTelnet", XrmoptionNoArg, "True" },
1507 { "-xtelnet", "useTelnet", XrmoptionNoArg, "False" },
1508 { "-telnetProgram", "telnetProgram", XrmoptionSepArg, NULL },
1509 { "-gateway", "gateway", XrmoptionSepArg, NULL },
1510 { "-loadGameFile", "loadGameFile", XrmoptionSepArg, NULL },
1511 { "-lgf", "loadGameFile", XrmoptionSepArg, NULL },
1512 { "-loadGameIndex", "loadGameIndex", XrmoptionSepArg, NULL },
1513 { "-lgi", "loadGameIndex", XrmoptionSepArg, NULL },
1514 { "-saveGameFile", "saveGameFile", XrmoptionSepArg, NULL },
1515 { "-sgf", "saveGameFile", XrmoptionSepArg, NULL },
1516 { "-autoSaveGames", "autoSaveGames", XrmoptionSepArg, NULL },
1517 { "-autosave", "autoSaveGames", XrmoptionNoArg, "True" },
1518 { "-xautosave", "autoSaveGames", XrmoptionNoArg, "False" },
1519 { "-autoRaiseBoard", "autoRaiseBoard", XrmoptionSepArg, NULL },
1520 { "-autoraise", "autoRaiseBoard", XrmoptionNoArg, "True" },
1521 { "-xautoraise", "autoRaiseBoard", XrmoptionNoArg, "False" },
1522 { "-blindfold", "blindfold", XrmoptionSepArg, NULL },
1523 { "-blind", "blindfold", XrmoptionNoArg, "True" },
1524 { "-xblind", "blindfold", XrmoptionNoArg, "False" },
1525 { "-loadPositionFile", "loadPositionFile", XrmoptionSepArg, NULL },
1526 { "-lpf", "loadPositionFile", XrmoptionSepArg, NULL },
1527 { "-loadPositionIndex", "loadPositionIndex", XrmoptionSepArg, NULL },
1528 { "-lpi", "loadPositionIndex", XrmoptionSepArg, NULL },
1529 { "-savePositionFile", "savePositionFile", XrmoptionSepArg, NULL },
1530 { "-spf", "savePositionFile", XrmoptionSepArg, NULL },
1531 { "-matchMode", "matchMode", XrmoptionSepArg, NULL },
1532 { "-mm", "matchMode", XrmoptionNoArg, "True" },
1533 { "-xmm", "matchMode", XrmoptionNoArg, "False" },
1534 { "-matchGames", "matchGames", XrmoptionSepArg, NULL },
1535 { "-mg", "matchGames", XrmoptionSepArg, NULL },
1536 { "-monoMode", "monoMode", XrmoptionSepArg, NULL },
1537 { "-mono", "monoMode", XrmoptionNoArg, "True" },
1538 { "-xmono", "monoMode", XrmoptionNoArg, "False" },
1539 { "-debugMode", "debugMode", XrmoptionSepArg, NULL },
1540 { "-debug", "debugMode", XrmoptionNoArg, "True" },
1541 { "-xdebug", "debugMode", XrmoptionNoArg, "False" },
1542 { "-clockMode", "clockMode", XrmoptionSepArg, NULL },
1543 { "-clock", "clockMode", XrmoptionNoArg, "True" },
1544 { "-xclock", "clockMode", XrmoptionNoArg, "False" },
1545 { "-boardSize", "boardSize", XrmoptionSepArg, NULL },
1546 { "-size", "boardSize", XrmoptionSepArg, NULL },
1547 { "-searchTime", "searchTime", XrmoptionSepArg, NULL },
1548 { "-st", "searchTime", XrmoptionSepArg, NULL },
1549 { "-searchDepth", "searchDepth", XrmoptionSepArg, NULL },
1550 { "-depth", "searchDepth", XrmoptionSepArg, NULL },
1551 { "-showCoords", "showCoords", XrmoptionSepArg, NULL },
1552 { "-coords", "showCoords", XrmoptionNoArg, "True" },
1553 { "-xcoords", "showCoords", XrmoptionNoArg, "False" },
1555 { "-showJail", "showJail", XrmoptionSepArg, NULL },
1556 { "-jail", "showJail", XrmoptionNoArg, "1" },
1557 { "-sidejail", "showJail", XrmoptionNoArg, "2" },
1558 { "-xjail", "showJail", XrmoptionNoArg, "0" },
1560 { "-showThinking", "showThinking", XrmoptionSepArg, NULL },
1561 { "-thinking", "showThinking", XrmoptionNoArg, "True" },
1562 { "-xthinking", "showThinking", XrmoptionNoArg, "False" },
1563 { "-ponderNextMove", "ponderNextMove", XrmoptionSepArg, NULL },
1564 { "-ponder", "ponderNextMove", XrmoptionNoArg, "True" },
1565 { "-xponder", "ponderNextMove", XrmoptionNoArg, "False" },
1566 { "-periodicUpdates", "periodicUpdates", XrmoptionSepArg, NULL },
1567 { "-periodic", "periodicUpdates", XrmoptionNoArg, "True" },
1568 { "-xperiodic", "periodicUpdates", XrmoptionNoArg, "False" },
1569 { "-clockFont", "clockFont", XrmoptionSepArg, NULL },
1570 { "-coordFont", "coordFont", XrmoptionSepArg, NULL },
1571 { "-font", "font", XrmoptionSepArg, NULL },
1572 { "-ringBellAfterMoves", "ringBellAfterMoves", XrmoptionSepArg, NULL },
1573 { "-bell", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1574 { "-xbell", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1575 { "-movesound", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1576 { "-xmovesound", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1577 { "-autoCallFlag", "autoCallFlag", XrmoptionSepArg, NULL },
1578 { "-autoflag", "autoCallFlag", XrmoptionNoArg, "True" },
1579 { "-xautoflag", "autoCallFlag", XrmoptionNoArg, "False" },
1580 { "-autoFlipView", "autoFlipView", XrmoptionSepArg, NULL },
1581 { "-autoflip", "autoFlipView", XrmoptionNoArg, "True" },
1582 { "-xautoflip", "autoFlipView", XrmoptionNoArg, "False" },
1583 { "-autoObserve", "autoObserve", XrmoptionSepArg, NULL },
1584 { "-autobs", "autoObserve", XrmoptionNoArg, "True" },
1585 { "-xautobs", "autoObserve", XrmoptionNoArg, "False" },
1586 { "-autoComment", "autoComment", XrmoptionSepArg, NULL },
1587 { "-autocomm", "autoComment", XrmoptionNoArg, "True" },
1588 { "-xautocomm", "autoComment", XrmoptionNoArg, "False" },
1589 { "-getMoveList", "getMoveList", XrmoptionSepArg, NULL },
1590 { "-moves", "getMoveList", XrmoptionNoArg, "True" },
1591 { "-xmoves", "getMoveList", XrmoptionNoArg, "False" },
1593 { "-highlightDragging", "highlightDragging", XrmoptionSepArg, NULL },
1594 { "-highdrag", "highlightDragging", XrmoptionNoArg, "True" },
1595 { "-xhighdrag", "highlightDragging", XrmoptionNoArg, "False" },
1597 { "-highlightLastMove", "highlightLastMove", XrmoptionSepArg, NULL },
1598 { "-highlight", "highlightLastMove", XrmoptionNoArg, "True" },
1599 { "-xhighlight", "highlightLastMove", XrmoptionNoArg, "False" },
1600 { "-premove", "premove", XrmoptionSepArg, NULL },
1601 { "-pre", "premove", XrmoptionNoArg, "True" },
1602 { "-xpre", "premove", XrmoptionNoArg, "False" },
1603 { "-testLegality", "testLegality", XrmoptionSepArg, NULL },
1604 { "-legal", "testLegality", XrmoptionNoArg, "True" },
1605 { "-xlegal", "testLegality", XrmoptionNoArg, "False" },
1606 { "-flipView", "flipView", XrmoptionSepArg, NULL },
1607 { "-flip", "flipView", XrmoptionNoArg, "True" },
1608 { "-xflip", "flipView", XrmoptionNoArg, "False" },
1609 { "-cmail", "cmailGameName", XrmoptionSepArg, NULL },
1610 { "-alwaysPromoteToQueen", "alwaysPromoteToQueen",
1611 XrmoptionSepArg, NULL },
1612 { "-queen", "alwaysPromoteToQueen", XrmoptionNoArg, "True" },
1613 { "-xqueen", "alwaysPromoteToQueen", XrmoptionNoArg, "False" },
1614 { "-oldSaveStyle", "oldSaveStyle", XrmoptionSepArg, NULL },
1615 { "-oldsave", "oldSaveStyle", XrmoptionNoArg, "True" },
1616 { "-xoldsave", "oldSaveStyle", XrmoptionNoArg, "False" },
1617 { "-quietPlay", "quietPlay", XrmoptionSepArg, NULL },
1618 { "-quiet", "quietPlay", XrmoptionNoArg, "True" },
1619 { "-xquiet", "quietPlay", XrmoptionNoArg, "False" },
1620 { "-titleInWindow", "titleInWindow", XrmoptionSepArg, NULL },
1621 { "-title", "titleInWindow", XrmoptionNoArg, "True" },
1622 { "-xtitle", "titleInWindow", XrmoptionNoArg, "False" },
1624 { "-zippyTalk", "zippyTalk", XrmoptionSepArg, NULL },
1625 { "-zt", "zippyTalk", XrmoptionNoArg, "True" },
1626 { "-xzt", "zippyTalk", XrmoptionNoArg, "False" },
1627 { "-zippyPlay", "zippyPlay", XrmoptionSepArg, NULL },
1628 { "-zp", "zippyPlay", XrmoptionNoArg, "True" },
1629 { "-xzp", "zippyPlay", XrmoptionNoArg, "False" },
1630 { "-zippyLines", "zippyLines", XrmoptionSepArg, NULL },
1631 { "-zippyPinhead", "zippyPinhead", XrmoptionSepArg, NULL },
1632 { "-zippyPassword", "zippyPassword", XrmoptionSepArg, NULL },
1633 { "-zippyPassword2", "zippyPassword2", XrmoptionSepArg, NULL },
1634 { "-zippyWrongPassword", "zippyWrongPassword", XrmoptionSepArg, NULL },
1635 { "-zippyAcceptOnly", "zippyAcceptOnly", XrmoptionSepArg, NULL },
1636 { "-zippyUseI", "zippyUseI", XrmoptionSepArg, NULL },
1637 { "-zui", "zippyUseI", XrmoptionNoArg, "True" },
1638 { "-xzui", "zippyUseI", XrmoptionNoArg, "False" },
1639 { "-zippyBughouse", "zippyBughouse", XrmoptionSepArg, NULL },
1640 { "-zippyNoplayCrafty", "zippyNoplayCrafty", XrmoptionSepArg, NULL },
1641 { "-znc", "zippyNoplayCrafty", XrmoptionNoArg, "True" },
1642 { "-xznc", "zippyNoplayCrafty", XrmoptionNoArg, "False" },
1643 { "-zippyGameEnd", "zippyGameEnd", XrmoptionSepArg, NULL },
1644 { "-zippyGameStart", "zippyGameStart", XrmoptionSepArg, NULL },
1645 { "-zippyAdjourn", "zippyAdjourn", XrmoptionSepArg, NULL },
1646 { "-zadj", "zippyAdjourn", XrmoptionNoArg, "True" },
1647 { "-xzadj", "zippyAdjourn", XrmoptionNoArg, "False" },
1648 { "-zippyAbort", "zippyAbort", XrmoptionSepArg, NULL },
1649 { "-zab", "zippyAbort", XrmoptionNoArg, "True" },
1650 { "-xzab", "zippyAbort", XrmoptionNoArg, "False" },
1651 { "-zippyVariants", "zippyVariants", XrmoptionSepArg, NULL },
1652 { "-zippyMaxGames", "zippyMaxGames", XrmoptionSepArg, NULL },
1653 { "-zippyReplayTimeout", "zippyReplayTimeout", XrmoptionSepArg, NULL },
1654 { "-zippyShortGame", "zippyShortGame", XrmoptionSepArg, NULL },
1656 { "-flashCount", "flashCount", XrmoptionSepArg, NULL },
1657 { "-flash", "flashCount", XrmoptionNoArg, "3" },
1658 { "-xflash", "flashCount", XrmoptionNoArg, "0" },
1659 { "-flashRate", "flashRate", XrmoptionSepArg, NULL },
1660 { "-pixmapDirectory", "pixmapDirectory", XrmoptionSepArg, NULL },
1661 { "-msLoginDelay", "msLoginDelay", XrmoptionSepArg, NULL },
1662 { "-pixmap", "pixmapDirectory", XrmoptionSepArg, NULL },
1663 { "-colorizeMessages", "colorizeMessages", XrmoptionSepArg, NULL },
1664 { "-colorize", "colorizeMessages", XrmoptionNoArg, "True" },
1665 { "-xcolorize", "colorizeMessages", XrmoptionNoArg, "False" },
1666 { "-colorShout", "colorShout", XrmoptionSepArg, NULL },
1667 { "-colorSShout", "colorSShout", XrmoptionSepArg, NULL },
1668 { "-colorCShout", "colorSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1669 { "-colorChannel1", "colorChannel1", XrmoptionSepArg, NULL },
1670 { "-colorChannel", "colorChannel", XrmoptionSepArg, NULL },
1671 { "-colorKibitz", "colorKibitz", XrmoptionSepArg, NULL },
1672 { "-colorTell", "colorTell", XrmoptionSepArg, NULL },
1673 { "-colorChallenge", "colorChallenge", XrmoptionSepArg, NULL },
1674 { "-colorRequest", "colorRequest", XrmoptionSepArg, NULL },
1675 { "-colorSeek", "colorSeek", XrmoptionSepArg, NULL },
1676 { "-colorNormal", "colorNormal", XrmoptionSepArg, NULL },
1677 { "-soundProgram", "soundProgram", XrmoptionSepArg, NULL },
1678 { "-soundShout", "soundShout", XrmoptionSepArg, NULL },
1679 { "-soundSShout", "soundSShout", XrmoptionSepArg, NULL },
1680 { "-soundCShout", "soundSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1681 { "-soundChannel1", "soundChannel1", XrmoptionSepArg, NULL },
1682 { "-soundChannel", "soundChannel", XrmoptionSepArg, NULL },
1683 { "-soundKibitz", "soundKibitz", XrmoptionSepArg, NULL },
1684 { "-soundTell", "soundTell", XrmoptionSepArg, NULL },
1685 { "-soundChallenge", "soundChallenge", XrmoptionSepArg, NULL },
1686 { "-soundRequest", "soundRequest", XrmoptionSepArg, NULL },
1687 { "-soundSeek", "soundSeek", XrmoptionSepArg, NULL },
1688 { "-soundMove", "soundMove", XrmoptionSepArg, NULL },
1689 { "-soundIcsWin", "soundIcsWin", XrmoptionSepArg, NULL },
1690 { "-soundIcsLoss", "soundIcsLoss", XrmoptionSepArg, NULL },
1691 { "-soundIcsDraw", "soundIcsDraw", XrmoptionSepArg, NULL },
1692 { "-soundIcsUnfinished", "soundIcsUnfinished", XrmoptionSepArg, NULL },
1693 { "-soundIcsAlarm", "soundIcsAlarm", XrmoptionSepArg, NULL },
1694 { "-reuseFirst", "reuseFirst", XrmoptionSepArg, NULL },
1695 { "-reuseChessPrograms", "reuseFirst", XrmoptionSepArg, NULL }, /*compat*/
1696 { "-reuse", "reuseFirst", XrmoptionNoArg, "True" },
1697 { "-xreuse", "reuseFirst", XrmoptionNoArg, "False" },
1698 { "-reuseSecond", "reuseSecond", XrmoptionSepArg, NULL },
1699 { "-reuse2", "reuseSecond", XrmoptionNoArg, "True" },
1700 { "-xreuse2", "reuseSecond", XrmoptionNoArg, "False" },
1701 { "-animateMoving", "animateMoving", XrmoptionSepArg, NULL },
1702 { "-animate", "animateMoving", XrmoptionNoArg, "True" },
1703 { "-xanimate", "animateMoving", XrmoptionNoArg, "False" },
1704 { "-animateDragging", "animateDragging", XrmoptionSepArg, NULL },
1705 { "-drag", "animateDragging", XrmoptionNoArg, "True" },
1706 { "-xdrag", "animateDragging", XrmoptionNoArg, "False" },
1707 { "-animateSpeed", "animateSpeed", XrmoptionSepArg, NULL },
1708 { "-popupExitMessage", "popupExitMessage", XrmoptionSepArg, NULL },
1709 { "-exit", "popupExitMessage", XrmoptionNoArg, "True" },
1710 { "-xexit", "popupExitMessage", XrmoptionNoArg, "False" },
1711 { "-popupMoveErrors", "popupMoveErrors", XrmoptionSepArg, NULL },
1712 { "-popup", "popupMoveErrors", XrmoptionNoArg, "True" },
1713 { "-xpopup", "popupMoveErrors", XrmoptionNoArg, "False" },
1714 { "-fontSizeTolerance", "fontSizeTolerance", XrmoptionSepArg, NULL },
1715 { "-initialMode", "initialMode", XrmoptionSepArg, NULL },
1716 { "-mode", "initialMode", XrmoptionSepArg, NULL },
1717 { "-variant", "variant", XrmoptionSepArg, NULL },
1718 { "-firstProtocolVersion", "firstProtocolVersion", XrmoptionSepArg, NULL },
1719 { "-secondProtocolVersion","secondProtocolVersion",XrmoptionSepArg, NULL },
1720 { "-showButtonBar", "showButtonBar", XrmoptionSepArg, NULL },
1721 { "-buttons", "showButtonBar", XrmoptionNoArg, "True" },
1722 { "-xbuttons", "showButtonBar", XrmoptionNoArg, "False" },
1723 { "-lowTimeWarningColor", "lowTimeWarningColor", XrmoptionSepArg, NULL },
1724 { "-lowTimeWarning", "lowTimeWarning", XrmoptionSepArg, NULL },
1725 /* [AS,HR] New features */
1726 { "-firstScoreAbs", "firstScoreAbs", XrmoptionSepArg, NULL },
1727 { "-secondScoreAbs", "secondScoreAbs", XrmoptionSepArg, NULL },
1728 { "-pgnExtendedInfo", "pgnExtendedInfo", XrmoptionSepArg, NULL },
1729 { "-hideThinkingFromHuman", "hideThinkingFromHuman", XrmoptionSepArg, NULL },
1730 { "-adjudicateLossThreshold", "adjudicateLossThreshold", XrmoptionSepArg, NULL },
1731 { "-adjudicateDrawMoves", "adjudicateDrawMoves", XrmoptionSepArg, NULL },
1732 { "-pgnEventHeader", "pgnEventHeader", XrmoptionSepArg, NULL },
1733 { "-firstIsUCI", "firstIsUCI", XrmoptionSepArg, NULL },
1734 { "-secondIsUCI", "secondIsUCI", XrmoptionSepArg, NULL },
1735 { "-fUCI", "firstIsUCI", XrmoptionNoArg, "True" },
1736 { "-sUCI", "secondIsUCI", XrmoptionNoArg, "True" },
1737 { "-firstHasOwnBookUCI", "firstHasOwnBookUCI", XrmoptionSepArg, NULL },
1738 { "-secondHasOwnBookUCI", "secondHasOwnBookUCI", XrmoptionSepArg, NULL },
1739 { "-fNoOwnBookUCI", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1740 { "-sNoOwnBookUCI", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1741 { "-firstXBook", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1742 { "-secondXBook", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1743 { "-polyglotDir", "polyglotDir", XrmoptionSepArg, NULL },
1744 { "-usePolyglotBook", "usePolyglotBook", XrmoptionSepArg, NULL },
1745 { "-polyglotBook", "polyglotBook", XrmoptionSepArg, NULL },
1746 { "-defaultHashSize", "defaultHashSize", XrmoptionSepArg, NULL },
1747 { "-defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XrmoptionSepArg, NULL },
1748 { "-defaultPathEGTB", "defaultPathEGTB", XrmoptionSepArg, NULL },
1749 { "-defaultFrcPosition", "defaultFrcPosition", XrmoptionSepArg, NULL },
1750 { "-gameListTags", "gameListTags", XrmoptionSepArg, NULL },
1751 // [HGM] I am sure AS added many more options, but we have to fish them out, from the list in winboard.c
1753 /* [HGM,HR] User-selectable board size */
1754 { "-boardWidth", "boardWidth", XrmoptionSepArg, NULL },
1755 { "-boardHeight", "boardHeight", XrmoptionSepArg, NULL },
1756 { "-matchPause", "matchPause", XrmoptionSepArg, NULL },
1758 /* [HGM] new arguments of 4.3.xx. All except first three are back-end options, which should work immediately */
1759 { "-holdingsSize", "holdingsSize", XrmoptionSepArg, NULL }, // requires extensive front-end changes to work
1760 { "-flipBlack", "flipBlack", XrmoptionSepArg, NULL }, // requires front-end changes to work
1761 { "-allWhite", "allWhite", XrmoptionSepArg, NULL }, // requires front-end changes to work
1762 { "-pieceToCharTable", "pieceToCharTable", XrmoptionSepArg, NULL },
1763 { "-alphaRank", "alphaRank", XrmoptionSepArg, NULL },
1764 { "-testClaims", "testClaims", XrmoptionSepArg, NULL },
1765 { "-checkMates", "checkMates", XrmoptionSepArg, NULL },
1766 { "-materialDraws", "materialDraws", XrmoptionSepArg, NULL },
1767 { "-trivialDraws", "trivialDraws", XrmoptionSepArg, NULL },
1768 { "-ruleMoves", "ruleMoves", XrmoptionSepArg, NULL },
1769 { "-repeatsToDraw", "repeatsToDraw", XrmoptionSepArg, NULL },
1770 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1771 { "-userName", "userName", XrmoptionSepArg, NULL },
1772 { "-autoKibitz", "autoKibitz", XrmoptionNoArg, "True" },
1773 { "-firstTimeOdds", "firstTimeOdds", XrmoptionSepArg, NULL },
1774 { "-secondTimeOdds", "secondTimeOdds", XrmoptionSepArg, NULL },
1775 { "-timeOddsMode", "timeOddsMode", XrmoptionSepArg, NULL },
1776 { "-firstAccumulateTC", "firstAccumulateTC", XrmoptionSepArg, NULL },
1777 { "-secondAccumulateTC", "secondAccumulateTC", XrmoptionSepArg, NULL },
1778 { "-firstNPS", "firstNPS", XrmoptionSepArg, NULL },
1779 { "-secondNPS", "secondNPS", XrmoptionSepArg, NULL },
1780 { "-serverMoves", "serverMoves", XrmoptionSepArg, NULL },
1781 { "-serverPause", "serverPause", XrmoptionSepArg, NULL },
1782 { "-suppressLoadMoves", "suppressLoadMoves", XrmoptionSepArg, NULL },
1783 { "-egtFormats", "egtFormats", XrmoptionSepArg, NULL },
1784 { "-userName", "userName", XrmoptionSepArg, NULL },
1785 { "-smpCores", "smpCores", XrmoptionSepArg, NULL },
1786 { "-sameColorGames", "sameColorGames", XrmoptionSepArg, NULL },
1787 { "-rewindIndex", "rewindIndex", XrmoptionSepArg, NULL },
1788 { "-niceEngines", "niceEngines", XrmoptionSepArg, NULL },
1789 { "-delayBeforeQuit", "delayBeforeQuit", XrmoptionSepArg, NULL },
1790 { "-delayAfterQuit", "delayAfterQuit", XrmoptionSepArg, NULL },
1791 { "-nameOfDebugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1792 { "-debugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1793 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1794 { "-noGUI", "noGUI", XrmoptionNoArg, "True" },
1795 { "-firstOptions", "firstOptions", XrmoptionSepArg, NULL },
1796 { "-secondOptions", "secondOptions", XrmoptionSepArg, NULL },
1797 { "-firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1798 { "-secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1799 { "-keepAlive", "keepAlive", XrmoptionSepArg, NULL },
1800 { "-forceIllegalMoves", "forceIllegalMoves", XrmoptionNoArg, "True" },
1804 XtActionsRec boardActions[] = {
1805 { "HandleUserMove", HandleUserMove },
1806 { "AnimateUserMove", AnimateUserMove },
1807 { "FileNameAction", FileNameAction },
1808 { "AskQuestionProc", AskQuestionProc },
1809 { "AskQuestionReplyAction", AskQuestionReplyAction },
1810 { "PieceMenuPopup", PieceMenuPopup },
1811 { "WhiteClock", WhiteClock },
1812 { "BlackClock", BlackClock },
1813 { "Iconify", Iconify },
1814 { "LoadSelectedProc", LoadSelectedProc },
1815 { "LoadPositionProc", LoadPositionProc },
1816 { "LoadNextPositionProc", LoadNextPositionProc },
1817 { "LoadPrevPositionProc", LoadPrevPositionProc },
1818 { "ReloadPositionProc", ReloadPositionProc },
1819 { "CopyPositionProc", CopyPositionProc },
1820 { "PastePositionProc", PastePositionProc },
1821 { "CopyGameProc", CopyGameProc },
1822 { "PasteGameProc", PasteGameProc },
1823 { "SaveGameProc", SaveGameProc },
1824 { "SavePositionProc", SavePositionProc },
1825 { "MailMoveProc", MailMoveProc },
1826 { "ReloadCmailMsgProc", ReloadCmailMsgProc },
1827 // { "MachineWhiteProc", MachineWhiteProc },
1828 // { "MachineBlackProc", MachineBlackProc },
1829 { "AnalysisModeProc", AnalyzeModeProc },
1830 { "AnalyzeFileProc", AnalyzeFileProc },
1831 // { "TwoMachinesProc", TwoMachinesProc },
1832 // { "IcsClientProc", IcsClientProc },
1833 { "EditGameProc", EditGameProc },
1834 { "EditPositionProc", EditPositionProc },
1835 { "TrainingProc", EditPositionProc },
1836 { "EngineOutputProc", EngineOutputProc}, // [HGM] Winboard_x engine-output window
1837 { "ShowGameListProc", ShowGameListProc },
1838 // { "ShowMoveListProc", HistoryShowProc},
1839 { "EditTagsProc", EditCommentProc },
1840 { "EditCommentProc", EditCommentProc },
1841 { "IcsAlarmProc", IcsAlarmProc },
1842 { "IcsInputBoxProc", IcsInputBoxProc },
1843 // { "AcceptProc", AcceptProc },
1844 // { "DeclineProc", DeclineProc },
1845 // { "RematchProc", RematchProc },
1846 // { "CallFlagProc", CallFlagProc },
1847 // { "DrawProc", DrawProc },
1848 // { "AdjournProc", AdjournProc },
1849 // { "AbortProc", AbortProc },
1850 // { "ResignProc", ResignProc },
1851 // { "AdjuWhiteProc", AdjuWhiteProc },
1852 // { "AdjuBlackProc", AdjuBlackProc },
1853 // { "AdjuDrawProc", AdjuDrawProc },
1854 { "EnterKeyProc", EnterKeyProc },
1855 // { "StopObservingProc", StopObservingProc },
1856 // { "StopExaminingProc", StopExaminingProc },
1857 // { "BackwardProc", BackwardProc },
1858 // { "ForwardProc", ForwardProc },
1859 // { "ToStartProc", ToStartProc },
1860 // { "ToEndProc", ToEndProc },
1861 // { "RevertProc", RevertProc },
1862 // { "TruncateGameProc", TruncateGameProc },
1863 // { "MoveNowProc", MoveNowProc },
1864 // { "RetractMoveProc", RetractMoveProc },
1865 { "AlwaysQueenProc", AlwaysQueenProc },
1866 { "AnimateDraggingProc", AnimateDraggingProc },
1867 { "AnimateMovingProc", AnimateMovingProc },
1868 { "AutoflagProc", AutoflagProc },
1869 { "AutoflipProc", AutoflipProc },
1870 { "AutobsProc", AutobsProc },
1871 { "AutoraiseProc", AutoraiseProc },
1872 { "AutosaveProc", AutosaveProc },
1873 { "BlindfoldProc", BlindfoldProc },
1874 { "FlashMovesProc", FlashMovesProc },
1875 // { "FlipViewProc", FlipViewProc },
1876 // { "GetMoveListProc", GetMoveListProc },
1878 { "HighlightDraggingProc", HighlightDraggingProc },
1880 { "HighlightLastMoveProc", HighlightLastMoveProc },
1881 { "IcsAlarmProc", IcsAlarmProc },
1882 { "MoveSoundProc", MoveSoundProc },
1883 { "OldSaveStyleProc", OldSaveStyleProc },
1884 { "PeriodicUpdatesProc", PeriodicUpdatesProc },
1885 { "PonderNextMoveProc", PonderNextMoveProc },
1886 { "PopupExitMessageProc", PopupExitMessageProc },
1887 { "PopupMoveErrorsProc", PopupMoveErrorsProc },
1888 { "PremoveProc", PremoveProc },
1889 { "QuietPlayProc", QuietPlayProc },
1890 // { "ShowThinkingProc", ShowThinkingProc },
1891 // { "HideThinkingProc", HideThinkingProc },
1892 { "TestLegalityProc", TestLegalityProc },
1893 // { "InfoProc", InfoProc },
1894 // { "ManProc", ManProc },
1895 // { "HintProc", HintProc },
1896 // { "BookProc", BookProc },
1897 { "AboutGameProc", AboutGameProc },
1898 { "DebugProc", DebugProc },
1899 { "NothingProc", NothingProc },
1900 { "CommentPopDown", (XtActionProc) CommentPopDown },
1901 { "EditCommentPopDown", (XtActionProc) EditCommentPopDown },
1902 { "TagsPopDown", (XtActionProc) TagsPopDown },
1903 { "ErrorPopDown", (XtActionProc) ErrorPopDown },
1904 { "ICSInputBoxPopDown", (XtActionProc) ICSInputBoxPopDown },
1905 { "AnalysisPopDown", (XtActionProc) AnalysisPopDown },
1906 { "FileNamePopDown", (XtActionProc) FileNamePopDown },
1907 { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown },
1908 { "GameListPopDown", (XtActionProc) GameListPopDown },
1909 { "PromotionPopDown", (XtActionProc) PromotionPopDown },
1910 // { "HistoryPopDown", (XtActionProc) HistoryPopDown },
1911 { "EngineOutputPopDown", (XtActionProc) EngineOutputPopDown },
1912 { "ShufflePopDown", (XtActionProc) ShufflePopDown },
1913 { "EnginePopDown", (XtActionProc) EnginePopDown },
1914 { "UciPopDown", (XtActionProc) UciPopDown },
1915 { "TimeControlPopDown", (XtActionProc) TimeControlPopDown },
1916 { "NewVariantPopDown", (XtActionProc) NewVariantPopDown },
1917 { "SettingsPopDown", (XtActionProc) SettingsPopDown },
1921 char ICSInputTranslations[] =
1922 "<Key>Return: EnterKeyProc() \n";
1924 String xboardResources[] = {
1925 "*fileName*value.translations: #override\\n <Key>Return: FileNameAction()",
1926 "*question*value.translations: #override\\n <Key>Return: AskQuestionReplyAction()",
1927 "*errorpopup*translations: #override\\n <Key>Return: ErrorPopDown()",
1931 static char *cnames[9] = { "black", "red", "green", "yellow", "blue",
1932 "magenta", "cyan", "white" };
1936 TextColors textColors[(int)NColorClasses];
1938 /* String is: "fg, bg, attr". Which is 0, 1, 2 */
1940 parse_color(str, which)
1944 char *p, buf[100], *d;
1947 if (strlen(str) > 99) /* watch bounds on buf */
1952 for (i=0; i<which; ++i) {
1959 /* Could be looking at something like:
1961 .. in which case we want to stop on a comma also */
1962 while (*p && *p != ',' && !isalpha(*p) && !isdigit(*p))
1966 return -1; /* Use default for empty field */
1969 if (which == 2 || isdigit(*p))
1972 while (*p && isalpha(*p))
1977 for (i=0; i<8; ++i) {
1978 if (!StrCaseCmp(buf, cnames[i]))
1979 return which? (i+40) : (i+30);
1981 if (!StrCaseCmp(buf, "default")) return -1;
1983 fprintf(stderr, _("%s: unrecognized color %s\n"), programName, buf);
1988 parse_cpair(cc, str)
1992 if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {
1993 fprintf(stderr, _("%s: can't parse foreground color in `%s'\n"),
1998 /* bg and attr are optional */
1999 textColors[(int)cc].bg = parse_color(str, 1);
2000 if ((textColors[(int)cc].attr = parse_color(str, 2)) < 0) {
2001 textColors[(int)cc].attr = 0;
2007 /* Arrange to catch delete-window events */
2008 Atom wm_delete_window;
2010 CatchDeleteWindow(Widget w, String procname)
2013 XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
2014 snprintf(buf, sizeof(buf), "<Message>WM_PROTOCOLS: %s() \n", procname);
2015 XtAugmentTranslations(w, XtParseTranslationTable(buf));
2021 /* this should raise the board to the top */
2022 gtk_window_present(GTK_WINDOW(GUI_Window));
2027 // eventually, all layout determining code should go into a subroutine, but until then IDSIZE remains undefined
2029 #define BoardSize int
2030 void InitDrawingSizes(BoardSize boardSize, int flags)
2031 { // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
2032 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2034 XtGeometryResult gres;
2037 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2038 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2040 timerWidth = (boardWidth - sep) / 2;
2042 if (appData.titleInWindow)
2047 w = boardWidth - 2*bor;
2051 w = boardWidth - w - sep - 2*bor - 2; // WIDTH_FUDGE
2055 if(!formWidget) return;
2058 * Inhibit shell resizing.
2061 // [HGM] pieces: tailor piece bitmaps to needs of specific variant
2064 for(i=0; i<4; i++) {
2066 for(p=0; p<=(int)WhiteKing; p++)
2067 xpmPieceBitmap[i][p] = xpmPieceBitmap2[i][p]; // defaults
2068 if(gameInfo.variant == VariantShogi) {
2069 xpmPieceBitmap[i][(int)WhiteCannon] = xpmPieceBitmap2[i][(int)WhiteKing+1];
2070 xpmPieceBitmap[i][(int)WhiteNightrider] = xpmPieceBitmap2[i][(int)WhiteKing+2];
2071 xpmPieceBitmap[i][(int)WhiteSilver] = xpmPieceBitmap2[i][(int)WhiteKing+3];
2072 xpmPieceBitmap[i][(int)WhiteGrasshopper] = xpmPieceBitmap2[i][(int)WhiteKing+4];
2073 xpmPieceBitmap[i][(int)WhiteQueen] = xpmPieceBitmap2[i][(int)WhiteLance];
2076 if(gameInfo.variant == VariantGothic) {
2077 xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteSilver];
2081 // [HGM] why are thee ximMasks used at all? the ximPieceBitmaps seem to be never used!
2082 for(p=0; p<=(int)WhiteKing; p++)
2083 ximMaskPm[p] = ximMaskPm2[p]; // defaults
2084 if(gameInfo.variant == VariantShogi) {
2085 ximMaskPm[(int)WhiteCannon] = ximMaskPm2[(int)WhiteKing+1];
2086 ximMaskPm[(int)WhiteNightrider] = ximMaskPm2[(int)WhiteKing+2];
2087 ximMaskPm[(int)WhiteSilver] = ximMaskPm2[(int)WhiteKing+3];
2088 ximMaskPm[(int)WhiteGrasshopper] = ximMaskPm2[(int)WhiteKing+4];
2089 ximMaskPm[(int)WhiteQueen] = ximMaskPm2[(int)WhiteLance];
2092 if(gameInfo.variant == VariantGothic) {
2093 ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[(int)WhiteSilver];
2099 for(i=0; i<2; i++) {
2101 for(p=0; p<=(int)WhiteKing; p++)
2102 pieceBitmap[i][p] = pieceBitmap2[i][p]; // defaults
2103 if(gameInfo.variant == VariantShogi) {
2104 pieceBitmap[i][(int)WhiteCannon] = pieceBitmap2[i][(int)WhiteKing+1];
2105 pieceBitmap[i][(int)WhiteNightrider] = pieceBitmap2[i][(int)WhiteKing+2];
2106 pieceBitmap[i][(int)WhiteSilver] = pieceBitmap2[i][(int)WhiteKing+3];
2107 pieceBitmap[i][(int)WhiteGrasshopper] = pieceBitmap2[i][(int)WhiteKing+4];
2108 pieceBitmap[i][(int)WhiteQueen] = pieceBitmap2[i][(int)WhiteLance];
2111 if(gameInfo.variant == VariantGothic) {
2112 pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteSilver];
2123 void EscapeExpand(char *p, char *q)
2124 { // [HGM] initstring: routine to shape up string arguments
2125 while(*p++ = *q++) if(p[-1] == '\\')
2127 case 'n': p[-1] = '\n'; break;
2128 case 'r': p[-1] = '\r'; break;
2129 case 't': p[-1] = '\t'; break;
2130 case '\\': p[-1] = '\\'; break;
2131 case 0: *p = 0; return;
2132 default: p[-1] = q[-1]; break;
2141 int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
2142 XSetWindowAttributes window_attributes;
2144 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2145 XrmValue vFrom, vTo;
2146 XtGeometryResult gres;
2149 int forceMono = False;
2153 // [HGM] before anything else, expand any indirection files amongst options
2154 char *argvCopy[1000]; // 1000 seems enough
2155 char newArgs[10000]; // holds actual characters
2158 srandom(time(0)); // [HGM] book: make random truly random
2161 for(i=0; i<argc; i++) {
2162 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2163 //fprintf(stderr, "arg %s\n", argv[i]);
2164 if(argv[i][0] != '@') argvCopy[j++] = argv[i]; else {
2166 FILE *f = fopen(argv[i]+1, "rb");
2167 if(f == NULL) { fprintf(stderr, _("ignore %s\n"), argv[i]); continue; } // do not expand non-existing
2168 argvCopy[j++] = newArgs + k; // get ready for first argument from file
2169 while((c = fgetc(f)) != EOF) { // each line of file inserts 1 argument in the list
2171 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2172 newArgs[k++] = 0; // terminate current arg
2173 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2174 argvCopy[j++] = newArgs + k; // get ready for next
2176 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2190 setbuf(stdout, NULL);
2191 setbuf(stderr, NULL);
2194 programName = strrchr(argv[0], '/');
2195 if (programName == NULL)
2196 programName = argv[0];
2201 XtSetLanguageProc(NULL, NULL, NULL);
2202 bindtextdomain(PACKAGE, LOCALEDIR);
2203 textdomain(PACKAGE);
2207 XtAppInitialize(&appContext, "XBoard", shellOptions,
2208 XtNumber(shellOptions),
2209 &argc, argv, xboardResources, NULL, 0);
2212 gtk_init (&argc, &argv);
2214 /* parse glade file to build widgets */
2216 builder = gtk_builder_new ();
2217 gtk_builder_add_from_file (builder, "gtk-interface.xml", NULL);
2219 /* test if everything worked ok */
2221 GUI_Window = GTK_WIDGET (gtk_builder_get_object (builder, "MainWindow"));
2222 if(!GUI_Window) printf("Error: gtk_builder didn't work!\n");
2224 GUI_History = GTK_WIDGET (gtk_builder_get_object (builder, "MoveHistory"));
2225 if(!GUI_History) printf("Error: gtk_builder didn't work!\n");
2227 GUI_Board = GTK_WIDGET (gtk_builder_get_object (builder, "Board"));
2228 if(!GUI_Board) printf("Error: gtk_builder didn't work!\n");
2230 GUI_Whiteclock = GTK_WIDGET (gtk_builder_get_object (builder, "WhiteClock"));
2231 if(!GUI_Whiteclock) printf("Error: gtk_builder didn't work!\n");
2233 GUI_Blackclock = GTK_WIDGET (gtk_builder_get_object (builder, "BlackClock"));
2234 if(!GUI_Blackclock) printf("Error: gtk_builder didn't work!\n");
2236 LIST_MoveHistory = GTK_LIST_STORE (gtk_builder_get_object (builder, "MoveHistoryStore"));
2237 if(!LIST_MoveHistory) printf("Error: gtk_builder didn't work!\n");
2240 gtk_builder_connect_signals (builder, NULL);
2242 // don't unref the builder, since we use it to get references to widgets
2243 // g_object_unref (G_OBJECT (builder));
2245 /* end parse glade file */
2249 fprintf(stderr, _("%s: unrecognized argument %s\n"),
2250 programName, argv[1]);
2252 fprintf(stderr, "Recognized options:\n");
2253 for(i = 0; i < XtNumber(shellOptions); i++)
2255 /* print first column */
2256 j = fprintf(stderr, " %s%s", shellOptions[i].option,
2257 (shellOptions[i].argKind == XrmoptionSepArg
2259 /* print second column and end line */
2260 if (++i < XtNumber(shellOptions))
2262 fprintf(stderr, "%*c%s%s\n", 40 - j, ' ',
2263 shellOptions[i].option,
2264 (shellOptions[i].argKind == XrmoptionSepArg
2269 fprintf(stderr, "\n");
2276 if (p == NULL) p = "/tmp";
2277 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
2278 gameCopyFilename = (char*) malloc(i);
2279 gamePasteFilename = (char*) malloc(i);
2280 snprintf(gameCopyFilename,i, "%s/.xboard%05uc.pgn", p, getpid());
2281 snprintf(gamePasteFilename,i, "%s/.xboard%05up.pgn", p, getpid());
2283 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
2284 clientResources, XtNumber(clientResources),
2287 { // [HGM] initstring: kludge to fix bad bug. expand '\n' characters in init string and computer string.
2288 static char buf[MSG_SIZ];
2289 EscapeExpand(buf, appData.initString);
2290 appData.initString = strdup(buf);
2291 EscapeExpand(buf, appData.secondInitString);
2292 appData.secondInitString = strdup(buf);
2293 EscapeExpand(buf, appData.firstComputerString);
2294 appData.firstComputerString = strdup(buf);
2295 EscapeExpand(buf, appData.secondComputerString);
2296 appData.secondComputerString = strdup(buf);
2299 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
2302 if (chdir(chessDir) != 0) {
2303 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
2309 if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) {
2310 /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */
2311 if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL) {
2312 printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile);
2315 setbuf(debugFP, NULL);
2318 /* [HGM,HR] make sure board size is acceptable */
2319 if(appData.NrFiles > BOARD_SIZE ||
2320 appData.NrRanks > BOARD_SIZE )
2321 DisplayFatalError(_("Recompile with BOARD_SIZE > 12, to support this size"), 0, 2);
2324 /* This feature does not work; animation needs a rewrite */
2325 appData.highlightDragging = FALSE;
2329 xDisplay = XtDisplay(shellWidget);
2330 xScreen = DefaultScreen(xDisplay);
2331 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
2333 gameInfo.variant = StringToVariant(appData.variant);
2334 InitPosition(FALSE);
2338 InitDrawingSizes(-1, 0); // [HGM] initsize: make this into a subroutine
2340 if (isdigit(appData.boardSize[0])) {
2341 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
2342 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
2343 &fontPxlSize, &smallLayout, &tinyLayout);
2345 fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
2346 programName, appData.boardSize);
2350 /* Find some defaults; use the nearest known size */
2351 SizeDefaults *szd, *nearest;
2352 int distance = 99999;
2353 nearest = szd = sizeDefaults;
2354 while (szd->name != NULL) {
2355 if (abs(szd->squareSize - squareSize) < distance) {
2357 distance = abs(szd->squareSize - squareSize);
2358 if (distance == 0) break;
2362 if (i < 2) lineGap = nearest->lineGap;
2363 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
2364 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
2365 if (i < 5) fontPxlSize = nearest->fontPxlSize;
2366 if (i < 6) smallLayout = nearest->smallLayout;
2367 if (i < 7) tinyLayout = nearest->tinyLayout;
2370 SizeDefaults *szd = sizeDefaults;
2371 if (*appData.boardSize == NULLCHAR) {
2372 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize ||
2373 DisplayHeight(xDisplay, xScreen) < szd->minScreenSize) {
2376 if (szd->name == NULL) szd--;
2378 while (szd->name != NULL &&
2379 StrCaseCmp(szd->name, appData.boardSize) != 0) szd++;
2380 if (szd->name == NULL) {
2381 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
2382 programName, appData.boardSize);
2386 squareSize = szd->squareSize;
2387 lineGap = szd->lineGap;
2388 clockFontPxlSize = szd->clockFontPxlSize;
2389 coordFontPxlSize = szd->coordFontPxlSize;
2390 fontPxlSize = szd->fontPxlSize;
2391 smallLayout = szd->smallLayout;
2392 tinyLayout = szd->tinyLayout;
2395 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2396 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2397 if (appData.showJail == 1) {
2398 /* Jail on top and bottom */
2399 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2400 XtSetArg(boardArgs[2], XtNheight,
2401 boardHeight + 2*(lineGap + squareSize));
2402 } else if (appData.showJail == 2) {
2404 XtSetArg(boardArgs[1], XtNwidth,
2405 boardWidth + 2*(lineGap + squareSize));
2406 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2409 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2410 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2414 * Determine what fonts to use.
2416 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
2417 clockFontID = XLoadFont(xDisplay, appData.clockFont);
2418 clockFontStruct = XQueryFont(xDisplay, clockFontID);
2419 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
2420 coordFontID = XLoadFont(xDisplay, appData.coordFont);
2421 coordFontStruct = XQueryFont(xDisplay, coordFontID);
2422 appData.font = FindFont(appData.font, fontPxlSize);
2423 countFontID = XLoadFont(xDisplay, appData.coordFont); // [HGM] holdings
2424 countFontStruct = XQueryFont(xDisplay, countFontID);
2425 // appData.font = FindFont(appData.font, fontPxlSize);
2427 xdb = XtDatabase(xDisplay);
2428 XrmPutStringResource(&xdb, "*font", appData.font);
2431 * Detect if there are not enough colors available and adapt.
2433 if (DefaultDepth(xDisplay, xScreen) <= 2) {
2434 appData.monoMode = True;
2437 if (!appData.monoMode) {
2438 vFrom.addr = (caddr_t) appData.lightSquareColor;
2439 vFrom.size = strlen(appData.lightSquareColor);
2440 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2441 if (vTo.addr == NULL) {
2442 appData.monoMode = True;
2445 lightSquareColor = *(Pixel *) vTo.addr;
2448 if (!appData.monoMode) {
2449 vFrom.addr = (caddr_t) appData.darkSquareColor;
2450 vFrom.size = strlen(appData.darkSquareColor);
2451 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2452 if (vTo.addr == NULL) {
2453 appData.monoMode = True;
2456 darkSquareColor = *(Pixel *) vTo.addr;
2459 if (!appData.monoMode) {
2460 vFrom.addr = (caddr_t) appData.whitePieceColor;
2461 vFrom.size = strlen(appData.whitePieceColor);
2462 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2463 if (vTo.addr == NULL) {
2464 appData.monoMode = True;
2467 whitePieceColor = *(Pixel *) vTo.addr;
2470 if (!appData.monoMode) {
2471 vFrom.addr = (caddr_t) appData.blackPieceColor;
2472 vFrom.size = strlen(appData.blackPieceColor);
2473 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2474 if (vTo.addr == NULL) {
2475 appData.monoMode = True;
2478 blackPieceColor = *(Pixel *) vTo.addr;
2482 if (!appData.monoMode) {
2483 vFrom.addr = (caddr_t) appData.highlightSquareColor;
2484 vFrom.size = strlen(appData.highlightSquareColor);
2485 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2486 if (vTo.addr == NULL) {
2487 appData.monoMode = True;
2490 highlightSquareColor = *(Pixel *) vTo.addr;
2494 if (!appData.monoMode) {
2495 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
2496 vFrom.size = strlen(appData.premoveHighlightColor);
2497 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2498 if (vTo.addr == NULL) {
2499 appData.monoMode = True;
2502 premoveHighlightColor = *(Pixel *) vTo.addr;
2507 fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2510 if (appData.bitmapDirectory == NULL ||
2511 appData.bitmapDirectory[0] == NULLCHAR)
2512 appData.bitmapDirectory = DEF_BITMAP_DIR;
2515 if (appData.lowTimeWarning && !appData.monoMode) {
2516 vFrom.addr = (caddr_t) appData.lowTimeWarningColor;
2517 vFrom.size = strlen(appData.lowTimeWarningColor);
2518 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2519 if (vTo.addr == NULL)
2520 appData.monoMode = True;
2522 lowTimeWarningColor = *(Pixel *) vTo.addr;
2525 if (appData.monoMode && appData.debugMode) {
2526 fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2527 (unsigned long) XWhitePixel(xDisplay, xScreen),
2528 (unsigned long) XBlackPixel(xDisplay, xScreen));
2531 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
2532 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
2533 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
2534 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
2535 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
2536 parse_cpair(ColorTell, appData.colorTell) < 0 ||
2537 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
2538 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
2539 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
2540 parse_cpair(ColorNormal, appData.colorNormal) < 0)
2542 if (appData.colorize) {
2544 _("%s: can't parse color names; disabling colorization\n"),
2547 appData.colorize = FALSE;
2549 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2550 textColors[ColorNone].attr = 0;
2552 // XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2558 layoutName = "tinyLayout";
2559 } else if (smallLayout) {
2560 layoutName = "smallLayout";
2562 layoutName = "normalLayout";
2565 if (appData.titleInWindow) {
2566 /* todo check what this appdata does */
2569 if (appData.showButtonBar) {
2570 /* TODO hide button bar if requested */
2574 * gtk set properties of widgets
2577 /* set board size */
2578 gtk_widget_set_size_request(GTK_WIDGET(GUI_Board),
2579 boardWidth,boardHeight);
2581 /* end gtk set properties of widgets */
2583 if (appData.titleInWindow)
2588 if (appData.showButtonBar)
2595 if (appData.showButtonBar)
2604 // [HGM] it seems the layout code ends here, but perhaps the color stuff is size independent and would
2605 // not need to go into InitDrawingSizes().
2608 /* set some checkboxes in the menu according to appData */
2610 if (appData.alwaysPromoteToQueen)
2611 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Always Queen")),TRUE);
2613 if (appData.animateDragging)
2614 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Animate Dragging")),TRUE);
2616 if (appData.animate)
2617 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Animate Moving")),TRUE);
2619 if (appData.autoComment)
2620 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Comment")),TRUE);
2622 if (appData.autoCallFlag)
2623 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Flag")),TRUE);
2625 if (appData.autoFlipView)
2626 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Flip View")),TRUE);
2628 if (appData.autoObserve)
2629 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Observe")),TRUE);
2631 if (appData.autoRaiseBoard)
2632 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Raise Board")),TRUE);
2634 if (appData.autoSaveGames)
2635 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Save")),TRUE);
2637 if (appData.saveGameFile[0] != NULLCHAR)
2639 /* Can't turn this off from menu */
2640 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Save")),TRUE);
2641 gtk_action_set_sensitive(GTK_ACTION (gtk_builder_get_object (builder, "menuOptions.Auto Save")),FALSE);
2644 if (appData.blindfold)
2645 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Blindfold")),TRUE);
2647 if (appData.flashCount > 0)
2648 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Flash Moves")),TRUE);
2650 if (appData.getMoveList)
2651 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Get Move List")),TRUE);
2654 if (appData.highlightDragging)
2655 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Highlight Dragging")),TRUE);
2658 if (appData.highlightLastMove)
2659 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Highlight Last Move")),TRUE);
2661 if (appData.icsAlarm)
2662 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.ICS Alarm")),TRUE);
2664 if (appData.ringBellAfterMoves)
2665 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Move Sound")),TRUE);
2667 if (appData.oldSaveStyle)
2668 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Old Save Style")),TRUE);
2670 if (appData.periodicUpdates)
2671 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Periodic Updates")),TRUE);
2673 if (appData.ponderNextMove)
2674 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Ponder Next Move")),TRUE);
2676 if (appData.popupExitMessage)
2677 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Popup Exit Message")),TRUE);
2679 if (appData.popupMoveErrors)
2680 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Popup Move Errors")),TRUE);
2682 if (appData.premove)
2683 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Premove")),TRUE);
2685 if (appData.quietPlay)
2686 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Quit Play")),TRUE);
2688 if (appData.showCoords)
2689 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Show Coords")),TRUE);
2691 if (appData.showThinking)
2692 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Show Thinking")),TRUE);
2694 if (appData.testLegality)
2695 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Test Legality")),TRUE);
2697 /* end setting check boxes */
2700 /* load square colors */
2701 SVGLightSquare = load_pixbuf("svg/LightSquare.svg",squareSize);
2702 SVGDarkSquare = load_pixbuf("svg/DarkSquare.svg",squareSize);
2703 SVGNeutralSquare = load_pixbuf("svg/NeutralSquare.svg",squareSize);
2705 /* use two icons to indicate if it is white's or black's turn */
2706 WhiteIcon = load_pixbuf("svg/icon_white.svg",0);
2707 BlackIcon = load_pixbuf("svg/icon_black.svg",0);
2708 WindowIcon = WhiteIcon;
2709 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
2711 /* do resizing to a fixed aspect ratio */
2716 GUI_SetAspectRatio(0.7);
2718 /* realize window */
2719 gtk_widget_show (GUI_Window);
2725 if (appData.animate || appData.animateDragging)
2730 if (errorExitStatus == -1) {
2731 if (appData.icsActive) {
2732 /* We now wait until we see "login:" from the ICS before
2733 sending the logon script (problems with timestamp otherwise) */
2734 /*ICSInitScript();*/
2735 if (appData.icsInputBox) ICSInputBoxPopUp();
2738 signal(SIGINT, IntSigHandler);
2739 signal(SIGTERM, IntSigHandler);
2740 if (*appData.cmailGameName != NULLCHAR) {
2741 signal(SIGUSR1, CmailSigHandler);
2744 gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes()
2748 * Create a cursor for the board widget.
2749 * (This needs to be called after the window has been created to have access to board-window)
2752 BoardCursor = gdk_cursor_new(GDK_HAND2);
2753 gdk_window_set_cursor(GUI_Board->window, BoardCursor);
2754 gdk_cursor_destroy(BoardCursor);
2759 if (appData.debugMode) fclose(debugFP); // [DM] debug
2766 if (appData.icsActive && oldICSInteractionTitle != NULL) {
2767 DisplayIcsInteractionTitle(oldICSInteractionTitle);
2769 unlink(gameCopyFilename);
2770 unlink(gamePasteFilename);
2781 CmailSigHandler(sig)
2787 signal(SIGUSR1, SIG_IGN); /* suspend handler */
2789 /* Activate call-back function CmailSigHandlerCallBack() */
2790 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
2792 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
2796 CmailSigHandlerCallBack(isr, closure, message, count, error)
2804 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
2806 /**** end signal code ****/
2816 f = fopen(appData.icsLogon, "r");
2822 strcat(buf, appData.icsLogon);
2823 f = fopen(buf, "r");
2827 ProcessICSInitScript(f);
2834 EditCommentPopDown();
2840 SetMenuEnables(enab)
2845 if (!builder) return;
2846 while (enab->name != NULL) {
2847 o = gtk_builder_get_object(builder, enab->name);
2848 if(GTK_IS_WIDGET(o))
2849 gtk_widget_set_sensitive(GTK_WIDGET (o),enab->value);
2852 if(GTK_IS_ACTION(o))
2853 gtk_action_set_sensitive(GTK_ACTION (o),enab->value);
2855 DisplayError(enab->name, 0);
2863 SetMenuEnables(icsEnables);
2866 if (appData.zippyPlay && !appData.noChessProgram) /* [DM] icsEngineAnalyze */
2867 {}; // XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
2874 SetMenuEnables(ncpEnables);
2880 SetMenuEnables(gnuEnables);
2886 SetMenuEnables(cmailEnables);
2892 SetMenuEnables(trainingOnEnables);
2893 if (appData.showButtonBar) {
2894 // XtSetSensitive(buttonBarWidget, False);
2900 SetTrainingModeOff()
2902 SetMenuEnables(trainingOffEnables);
2903 if (appData.showButtonBar) {
2904 // XtSetSensitive(buttonBarWidget, True);
2909 SetUserThinkingEnables()
2911 if (appData.noChessProgram) return;
2912 SetMenuEnables(userThinkingEnables);
2916 SetMachineThinkingEnables()
2918 if (appData.noChessProgram) return;
2919 SetMenuEnables(machineThinkingEnables);
2921 case MachinePlaysBlack:
2922 case MachinePlaysWhite:
2923 case TwoMachinesPlay:
2924 // XtSetSensitive(XtNameToWidget(menuBarWidget,
2925 // ModeToWidgetName(gameMode)), True);
2932 #define Abs(n) ((n)<0 ? -(n) : (n))
2935 * Find a font that matches "pattern" that is as close as
2936 * possible to the targetPxlSize. Prefer fonts that are k
2937 * pixels smaller to fonts that are k pixels larger. The
2938 * pattern must be in the X Consortium standard format,
2939 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
2940 * The return value should be freed with XtFree when no
2943 char *FindFont(pattern, targetPxlSize)
2947 char **fonts, *p, *best, *scalable, *scalableTail;
2948 int i, j, nfonts, minerr, err, pxlSize;
2951 char **missing_list;
2953 char *def_string, *base_fnt_lst, strInt[3];
2955 XFontStruct **fnt_list;
2957 base_fnt_lst = calloc(1, strlen(pattern) + 3);
2958 sprintf(strInt, "%d", targetPxlSize);
2959 p = strstr(pattern, "--");
2960 strncpy(base_fnt_lst, pattern, p - pattern + 2);
2961 strcat(base_fnt_lst, strInt);
2962 strcat(base_fnt_lst, strchr(p + 2, '-'));
2964 if ((fntSet = XCreateFontSet(xDisplay,
2968 &def_string)) == NULL) {
2970 fprintf(stderr, _("Unable to create font set.\n"));
2974 nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
2976 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
2978 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
2979 programName, pattern);
2987 for (i=0; i<nfonts; i++) {
2990 if (*p != '-') continue;
2992 if (*p == NULLCHAR) break;
2993 if (*p++ == '-') j++;
2995 if (j < 7) continue;
2998 scalable = fonts[i];
3001 err = pxlSize - targetPxlSize;
3002 if (Abs(err) < Abs(minerr) ||
3003 (minerr > 0 && err < 0 && -err == minerr)) {
3009 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
3010 /* If the error is too big and there is a scalable font,
3011 use the scalable font. */
3012 int headlen = scalableTail - scalable;
3013 p = (char *) XtMalloc(strlen(scalable) + 10);
3014 while (isdigit(*scalableTail)) scalableTail++;
3015 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
3017 p = (char *) XtMalloc(strlen(best) + 1);
3020 if (appData.debugMode) {
3021 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
3022 pattern, targetPxlSize, p);
3025 if (missing_count > 0)
3026 XFreeStringList(missing_list);
3027 XFreeFontSet(xDisplay, fntSet);
3029 XFreeFontNames(fonts);
3036 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
3037 | GCBackground | GCFunction | GCPlaneMask;
3038 XGCValues gc_values;
3041 gc_values.plane_mask = AllPlanes;
3042 gc_values.line_width = lineGap;
3043 gc_values.line_style = LineSolid;
3044 gc_values.function = GXcopy;
3046 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3047 gc_values.background = XWhitePixel(xDisplay, xScreen);
3048 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
3049 XSetFont(xDisplay, coordGC, coordFontID);
3051 if (appData.monoMode) {
3052 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3053 gc_values.background = XBlackPixel(xDisplay, xScreen);
3054 lightSquareGC = wbPieceGC
3055 = XtGetGC(shellWidget, value_mask, &gc_values);
3057 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3058 gc_values.background = XWhitePixel(xDisplay, xScreen);
3059 darkSquareGC = bwPieceGC
3060 = XtGetGC(shellWidget, value_mask, &gc_values);
3062 if (DefaultDepth(xDisplay, xScreen) == 1) {
3063 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3064 gc_values.function = GXcopyInverted;
3065 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3066 gc_values.function = GXcopy;
3067 if (XBlackPixel(xDisplay, xScreen) == 1) {
3068 bwPieceGC = darkSquareGC;
3069 wbPieceGC = copyInvertedGC;
3071 bwPieceGC = copyInvertedGC;
3072 wbPieceGC = lightSquareGC;
3076 gc_values.foreground = lightSquareColor;
3077 gc_values.background = darkSquareColor;
3078 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3080 gc_values.foreground = darkSquareColor;
3081 gc_values.background = lightSquareColor;
3082 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3084 gc_values.foreground = jailSquareColor;
3085 gc_values.background = jailSquareColor;
3086 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3088 gc_values.foreground = whitePieceColor;
3089 gc_values.background = darkSquareColor;
3090 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3092 gc_values.foreground = whitePieceColor;
3093 gc_values.background = lightSquareColor;
3094 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3096 gc_values.foreground = whitePieceColor;
3097 gc_values.background = jailSquareColor;
3098 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3100 gc_values.foreground = blackPieceColor;
3101 gc_values.background = darkSquareColor;
3102 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3104 gc_values.foreground = blackPieceColor;
3105 gc_values.background = lightSquareColor;
3106 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3108 gc_values.foreground = blackPieceColor;
3109 gc_values.background = jailSquareColor;
3110 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3117 WhitePawn, WhiteKnight, WhiteBishop, WhiteRook, WhiteQueen, WhiteKing,
3118 BlackPawn, BlackKnight, BlackBishop, BlackRook, BlackQueen, BlackKing,
3122 /* get some defaults going */
3123 for(i=WhitePawn; i<DemotePiece+1; i++)
3124 SVGpieces[i] = load_pixbuf("svg/NeutralSquare.svg",squareSize);
3127 SVGpieces[WhitePawn] = load_pixbuf("svg/WhitePawn.svg",squareSize);
3128 SVGpieces[WhiteKnight] = load_pixbuf("svg/WhiteKnight.svg",squareSize);
3129 SVGpieces[WhiteBishop] = load_pixbuf("svg/WhiteBishop.svg",squareSize);
3130 SVGpieces[WhiteRook] = load_pixbuf("svg/WhiteRook.svg",squareSize);
3131 SVGpieces[WhiteQueen] = load_pixbuf("svg/WhiteQueen.svg",squareSize);
3132 SVGpieces[WhiteKing] = load_pixbuf("svg/WhiteKing.svg",squareSize);
3134 SVGpieces[BlackPawn] = load_pixbuf("svg/BlackPawn.svg",squareSize);
3135 SVGpieces[BlackKnight] = load_pixbuf("svg/BlackKnight.svg",squareSize);
3136 SVGpieces[BlackBishop] = load_pixbuf("svg/BlackBishop.svg",squareSize);
3137 SVGpieces[BlackRook] = load_pixbuf("svg/BlackRook.svg",squareSize);
3138 SVGpieces[BlackQueen] = load_pixbuf("svg/BlackQueen.svg",squareSize);
3139 SVGpieces[BlackKing] = load_pixbuf("svg/BlackKing.svg",squareSize);
3145 static void MenuBarSelect(w, addr, index)
3150 XtActionProc proc = (XtActionProc) addr;
3152 (proc)(NULL, NULL, NULL, NULL);
3155 void CreateMenuBarPopup(parent, name, mb)
3165 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3168 XtSetArg(args[j], XtNleftMargin, 20); j++;
3169 XtSetArg(args[j], XtNrightMargin, 20); j++;
3171 while (mi->string != NULL) {
3172 if (strcmp(mi->string, "----") == 0) {
3173 entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
3176 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string)));
3177 entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass,
3179 XtAddCallback(entry, XtNcallback,
3180 (XtCallbackProc) MenuBarSelect,
3181 (caddr_t) mi->proc);
3187 Widget CreateMenuBar(mb)
3191 Widget anchor, menuBar;
3193 char menuName[MSG_SIZ];
3196 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3197 XtSetArg(args[j], XtNvSpace, 0); j++;
3198 XtSetArg(args[j], XtNborderWidth, 0); j++;
3199 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
3200 formWidget, args, j);
3202 while (mb->name != NULL) {
3203 strcpy(menuName, "menu");
3204 strcat(menuName, mb->name);
3206 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
3209 shortName[0] = _(mb->name)[0];
3210 shortName[1] = NULLCHAR;
3211 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
3214 XtSetArg(args[j], XtNlabel, XtNewString(_(mb->name))); j++;
3217 XtSetArg(args[j], XtNborderWidth, 0); j++;
3218 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
3220 CreateMenuBarPopup(menuBar, menuName, mb);
3226 Widget CreateButtonBar(mi)
3230 Widget button, buttonBar;
3234 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3236 XtSetArg(args[j], XtNhSpace, 0); j++;
3238 XtSetArg(args[j], XtNborderWidth, 0); j++;
3239 XtSetArg(args[j], XtNvSpace, 0); j++;
3240 buttonBar = XtCreateWidget("buttonBar", boxWidgetClass,
3241 formWidget, args, j);
3243 while (mi->string != NULL) {
3246 XtSetArg(args[j], XtNinternalWidth, 2); j++;
3247 XtSetArg(args[j], XtNborderWidth, 0); j++;
3249 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string))); j++;
3250 button = XtCreateManagedWidget(mi->string, commandWidgetClass,
3251 buttonBar, args, j);
3252 XtAddCallback(button, XtNcallback,
3253 (XtCallbackProc) MenuBarSelect,
3254 (caddr_t) mi->proc);
3261 CreatePieceMenu(name, color)
3268 ChessSquare selection;
3270 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3271 boardWidget, args, 0);
3273 for (i = 0; i < PIECE_MENU_SIZE; i++) {
3274 String item = pieceMenuStrings[color][i];
3276 if (strcmp(item, "----") == 0) {
3277 entry = XtCreateManagedWidget(item, smeLineObjectClass,
3280 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3281 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3283 selection = pieceMenuTranslation[color][i];
3284 XtAddCallback(entry, XtNcallback,
3285 (XtCallbackProc) PieceMenuSelect,
3286 (caddr_t) selection);
3287 if (selection == WhitePawn || selection == BlackPawn) {
3288 XtSetArg(args[0], XtNpopupOnEntry, entry);
3289 XtSetValues(menu, args, 1);
3302 ChessSquare selection;
3304 // whitePieceMenu = CreatePieceMenu("menuW", 0);
3305 // blackPieceMenu = CreatePieceMenu("menuB", 1);
3307 // XtRegisterGrabAction(PieceMenuPopup, True,
3308 // (unsigned)(ButtonPressMask|ButtonReleaseMask),
3309 // GrabModeAsync, GrabModeAsync);
3311 // XtSetArg(args[0], XtNlabel, _("Drop"));
3312 // dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
3313 // boardWidget, args, 1);
3314 // for (i = 0; i < DROP_MENU_SIZE; i++) {
3315 // String item = dropMenuStrings[i];
3317 // if (strcmp(item, "----") == 0) {
3318 // entry = XtCreateManagedWidget(item, smeLineObjectClass,
3319 // dropMenu, NULL, 0);
3321 // XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3322 // entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3323 // dropMenu, args, 1);
3324 // selection = dropMenuTranslation[i];
3325 // XtAddCallback(entry, XtNcallback,
3326 // (XtCallbackProc) DropMenuSelect,
3327 // (caddr_t) selection);
3332 void SetupDropMenu()
3340 for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
3341 entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
3342 p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
3343 dmEnables[i].piece);
3344 XtSetSensitive(entry, p != NULL || !appData.testLegality
3345 /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
3346 && !appData.icsActive));
3348 while (p && *p++ == dmEnables[i].piece) count++;
3349 snprintf(label, sizeof(label), "%s %d", dmEnables[i].widget, count);
3351 XtSetArg(args[j], XtNlabel, label); j++;
3352 XtSetValues(entry, args, j);
3356 void PieceMenuPopup(w, event, params, num_params)
3360 Cardinal *num_params;
3363 if (event->type != ButtonPress) return;
3364 if (errorUp) ErrorPopDown();
3368 whichMenu = params[0];
3370 case IcsPlayingWhite:
3371 case IcsPlayingBlack:
3373 case MachinePlaysWhite:
3374 case MachinePlaysBlack:
3375 if (appData.testLegality &&
3376 gameInfo.variant != VariantBughouse &&
3377 gameInfo.variant != VariantCrazyhouse) return;
3379 whichMenu = "menuD";
3385 if (((pmFromX = EventToSquare(event->xbutton.x, BOARD_WIDTH)) < 0) ||
3386 ((pmFromY = EventToSquare(event->xbutton.y, BOARD_HEIGHT)) < 0)) {
3387 pmFromX = pmFromY = -1;
3391 pmFromX = BOARD_WIDTH - 1 - pmFromX;
3393 pmFromY = BOARD_HEIGHT - 1 - pmFromY;
3395 XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
3398 static void PieceMenuSelect(w, piece, junk)
3403 if (pmFromX < 0 || pmFromY < 0) return;
3404 EditPositionMenuEvent(piece, pmFromX, pmFromY);
3407 static void DropMenuSelect(w, piece, junk)
3412 if (pmFromX < 0 || pmFromY < 0) return;
3413 DropMenuEvent(piece, pmFromX, pmFromY);
3416 void WhiteClock(w, event, prms, nprms)
3422 if (gameMode == EditPosition || gameMode == IcsExamining) {
3423 SetWhiteToPlayEvent();
3424 } else if (gameMode == IcsPlayingBlack || gameMode == MachinePlaysWhite) {
3429 void BlackClock(w, event, prms, nprms)
3435 if (gameMode == EditPosition || gameMode == IcsExamining) {
3436 SetBlackToPlayEvent();
3437 } else if (gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) {
3444 * If the user selects on a border boundary, return -1; if off the board,
3445 * return -2. Otherwise map the event coordinate to the square.
3447 int EventToSquare(x, limit)
3455 if ((x % (squareSize + lineGap)) >= squareSize)
3457 x /= (squareSize + lineGap);
3463 static void do_flash_delay(msec)
3469 static void drawHighlight(file, rank, line_type)
3470 int file, rank, line_type;
3475 if (lineGap == 0 || appData.blindfold) return;
3479 x = lineGap/2 + ((BOARD_WIDTH-1)-file) *
3480 (squareSize + lineGap);
3481 y = lineGap/2 + rank * (squareSize + lineGap);
3485 x = lineGap/2 + file * (squareSize + lineGap);
3486 y = lineGap/2 + ((BOARD_HEIGHT-1)-rank) *
3487 (squareSize + lineGap);
3491 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3493 /* draw the highlight */
3494 cairo_move_to (cr, x, y);
3495 cairo_rel_line_to (cr, 0,squareSize+lineGap);
3496 cairo_rel_line_to (cr, squareSize+lineGap,0);
3497 cairo_rel_line_to (cr, 0,-squareSize-lineGap);
3498 cairo_close_path (cr);
3500 cairo_set_line_width (cr, lineGap);
3503 /* TODO: use appdata colors */
3504 case LINE_TYPE_HIGHLIGHT:
3505 cairo_set_source_rgba (cr, 1, 1, 0, 1.0);
3508 cairo_set_source_rgba (cr, 1, 0, 0, 1.0);
3510 case LINE_TYPE_NORMAL:
3512 cairo_set_source_rgba (cr, 0, 1, 0, 1.0);
3523 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
3524 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
3527 SetHighlights(fromX, fromY, toX, toY)
3528 int fromX, fromY, toX, toY;
3530 if (hi1X != fromX || hi1Y != fromY)
3532 if (hi1X >= 0 && hi1Y >= 0)
3534 drawHighlight(hi1X, hi1Y, LINE_TYPE_NORMAL);
3536 if (fromX >= 0 && fromY >= 0)
3538 drawHighlight(fromX, fromY, LINE_TYPE_HIGHLIGHT);
3541 if (hi2X != toX || hi2Y != toY)
3543 if (hi2X >= 0 && hi2Y >= 0)
3545 drawHighlight(hi2X, hi2Y, LINE_TYPE_NORMAL);
3547 if (toX >= 0 && toY >= 0)
3549 drawHighlight(toX, toY, LINE_TYPE_HIGHLIGHT);
3563 SetHighlights(-1, -1, -1, -1);
3568 SetPremoveHighlights(fromX, fromY, toX, toY)
3569 int fromX, fromY, toX, toY;
3571 if (pm1X != fromX || pm1Y != fromY)
3573 if (pm1X >= 0 && pm1Y >= 0)
3575 drawHighlight(pm1X, pm1Y, LINE_TYPE_NORMAL);
3577 if (fromX >= 0 && fromY >= 0)
3579 drawHighlight(fromX, fromY, LINE_TYPE_PRE);
3582 if (pm2X != toX || pm2Y != toY)
3584 if (pm2X >= 0 && pm2Y >= 0)
3586 drawHighlight(pm2X, pm2Y, LINE_TYPE_NORMAL);
3588 if (toX >= 0 && toY >= 0)
3590 drawHighlight(toX, toY, LINE_TYPE_PRE);
3603 ClearPremoveHighlights()
3605 SetPremoveHighlights(-1, -1, -1, -1);
3608 static void BlankSquare(x, y, color, piece, dest)
3621 pb = SVGLightSquare;
3623 case 2: /* neutral */
3625 pb = SVGNeutralSquare;
3628 gdk_draw_pixbuf(GDK_WINDOW(GUI_Board->window),NULL,pb,0,0,x,y,-1,-1, GDK_RGB_DITHER_NORMAL, 0, 0);
3632 static void DrawPiece(piece, square_color, x, y, dest)
3634 int square_color, x, y;
3637 /* redraw background, since piece might be transparent in some areas */
3638 BlankSquare(x,y,square_color,piece,dest);
3641 gdk_draw_pixbuf(GDK_WINDOW(GUI_Board->window),NULL,
3642 GDK_PIXBUF(SVGpieces[piece]),0,0,x,y,-1,-1,
3643 GDK_RGB_DITHER_NORMAL, 0, 0);
3647 /* [HR] determine square color depending on chess variant. */
3648 static int SquareColor(row, column)
3653 if (gameInfo.variant == VariantXiangqi) {
3654 if (column >= 3 && column <= 5 && row >= 0 && row <= 2) {
3656 } else if (column >= 3 && column <= 5 && row >= 7 && row <= 9) {
3658 } else if (row <= 4) {
3664 square_color = ((column + row) % 2) == 1;
3667 /* [hgm] holdings: next line makes all holdings squares light */
3668 if(column < BOARD_LEFT || column >= BOARD_RGHT) square_color = 1;
3670 return square_color;
3673 void DrawSquare(row, column, piece, do_flash)
3674 int row, column, do_flash;
3677 int square_color, x, y;
3682 /* Calculate delay in milliseconds (2-delays per complete flash) */
3683 flash_delay = 500 / appData.flashRate;
3685 /* calculate x and y coordinates from row and column */
3688 x = lineGap + ((BOARD_WIDTH-1)-column) *
3689 (squareSize + lineGap);
3690 y = lineGap + row * (squareSize + lineGap);
3694 x = lineGap + column * (squareSize + lineGap);
3695 y = lineGap + ((BOARD_HEIGHT-1)-row) *
3696 (squareSize + lineGap);
3699 square_color = SquareColor(row, column);
3701 // [HGM] holdings: blank out area between board and holdings
3702 if ( column == BOARD_LEFT-1 || column == BOARD_RGHT
3703 || (column == BOARD_LEFT-2 && row < BOARD_HEIGHT-gameInfo.holdingsSize)
3704 || (column == BOARD_RGHT+1 && row >= gameInfo.holdingsSize) )
3706 BlankSquare(x, y, 2, EmptySquare, xBoardWindow);
3708 // [HGM] print piece counts next to holdings
3709 string[1] = NULLCHAR;
3712 cairo_text_extents_t extents;
3717 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3719 string[0] = '0' + piece;
3721 /* TODO this has to go into the font-selection */
3722 cairo_select_font_face (cr, "Sans",
3723 CAIRO_FONT_SLANT_NORMAL,
3724 CAIRO_FONT_WEIGHT_NORMAL);
3726 cairo_set_font_size (cr, 12.0);
3727 cairo_text_extents (cr, string, &extents);
3729 if (column == (flipView ? BOARD_LEFT-1 : BOARD_RGHT) )
3731 xpos= x + squareSize - extents.width - 2;
3732 ypos= y + extents.y_bearing + 1;
3734 if (column == (flipView ? BOARD_RGHT : BOARD_LEFT-1) && piece > 1)
3737 ypos = y + extents.y_bearing + 1;
3740 /* TODO mono mode? */
3741 cairo_move_to (cr, xpos, ypos);
3742 cairo_text_path (cr, string);
3743 cairo_set_source_rgb (cr, 1.0, 1.0, 1);
3744 cairo_fill_preserve (cr);
3745 cairo_set_source_rgb (cr, 0, 0, 0);
3746 cairo_set_line_width (cr, 0.1);
3755 /* square on the board */
3756 if (piece == EmptySquare || appData.blindfold)
3758 BlankSquare(x, y, square_color, piece, xBoardWindow);
3762 if (do_flash && appData.flashCount > 0)
3764 for (i=0; i<appData.flashCount; ++i)
3767 DrawPiece(piece, square_color, x, y, xBoardWindow);
3768 do_flash_delay(flash_delay);
3770 BlankSquare(x, y, square_color, piece, xBoardWindow);
3771 do_flash_delay(flash_delay);
3774 DrawPiece(piece, square_color, x, y, xBoardWindow);
3778 /* show coordinates if necessary */
3779 if(appData.showCoords)
3781 cairo_text_extents_t extents;
3785 /* TODO this has to go into the font-selection */
3786 cairo_select_font_face (cr, "Sans",
3787 CAIRO_FONT_SLANT_NORMAL,
3788 CAIRO_FONT_WEIGHT_NORMAL);
3789 cairo_set_font_size (cr, 12.0);
3791 string[1] = NULLCHAR;
3794 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3796 if (row == (flipView ? BOARD_HEIGHT-1 : 0) &&
3797 column >= BOARD_LEFT && column < BOARD_RGHT)
3799 string[0] = 'a' + column - BOARD_LEFT;
3800 cairo_text_extents (cr, string, &extents);
3802 xpos = x + squareSize - extents.width - 2;
3803 ypos = y + squareSize - extents.height - extents.y_bearing - 1;
3805 if (appData.monoMode)
3812 cairo_move_to (cr, xpos, ypos);
3813 cairo_text_path (cr, string);
3814 cairo_set_source_rgb (cr, 0.0, 0.0, 0);
3815 cairo_fill_preserve (cr);
3816 cairo_set_source_rgb (cr, 0, 1.0, 0);
3817 cairo_set_line_width (cr, 0.1);
3820 if ( column == (flipView ? BOARD_RGHT-1 : BOARD_LEFT))
3823 string[0] = ONE + row;
3824 cairo_text_extents (cr, string, &extents);
3827 ypos = y + extents.height + 1;
3829 if (appData.monoMode)
3836 cairo_move_to (cr, xpos, ypos);
3837 cairo_text_path (cr, string);
3838 cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
3839 cairo_fill_preserve (cr);
3840 cairo_set_source_rgb (cr, 0, 0, 1.0);
3841 cairo_set_line_width (cr, 0.1);
3853 /* Returns 1 if there are "too many" differences between b1 and b2
3854 (i.e. more than 1 move was made) */
3855 static int too_many_diffs(b1, b2)
3861 for (i=0; i<BOARD_HEIGHT; ++i) {
3862 for (j=0; j<BOARD_WIDTH; ++j) {
3863 if (b1[i][j] != b2[i][j]) {
3864 if (++c > 4) /* Castling causes 4 diffs */
3873 /* Matrix describing castling maneuvers */
3874 /* Row, ColRookFrom, ColKingFrom, ColRookTo, ColKingTo */
3875 static int castling_matrix[4][5] = {
3876 { 0, 0, 4, 3, 2 }, /* 0-0-0, white */
3877 { 0, 7, 4, 5, 6 }, /* 0-0, white */
3878 { 7, 0, 4, 3, 2 }, /* 0-0-0, black */
3879 { 7, 7, 4, 5, 6 } /* 0-0, black */
3882 /* Checks whether castling occurred. If it did, *rrow and *rcol
3883 are set to the destination (row,col) of the rook that moved.
3885 Returns 1 if castling occurred, 0 if not.
3887 Note: Only handles a max of 1 castling move, so be sure
3888 to call too_many_diffs() first.
3890 static int check_castle_draw(newb, oldb, rrow, rcol)
3897 /* For each type of castling... */
3898 for (i=0; i<4; ++i) {
3899 r = castling_matrix[i];
3901 /* Check the 4 squares involved in the castling move */
3903 for (j=1; j<=4; ++j) {
3904 if (newb[r[0]][r[j]] == oldb[r[0]][r[j]]) {
3911 /* All 4 changed, so it must be a castling move */
3920 static int damage[BOARD_SIZE][BOARD_SIZE];
3923 * event handler for redrawing the board
3925 void DrawPosition( repaint, board)
3926 /*Boolean*/int repaint;
3930 static int lastFlipView = 0;
3931 static int lastBoardValid = 0;
3932 static Board lastBoard;
3935 if (board == NULL) {
3936 if (!lastBoardValid) return;
3939 if (!lastBoardValid || lastFlipView != flipView) {
3940 // XtSetArg(args[0], XtNleftBitmap, (flipView ? xMarkPixmap : None));
3941 // XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flip View"),
3946 * It would be simpler to clear the window with XClearWindow()
3947 * but this causes a very distracting flicker.
3950 if (!repaint && lastBoardValid && lastFlipView == flipView)
3952 /* If too much changes (begin observing new game, etc.), don't
3954 do_flash = too_many_diffs(board, lastBoard) ? 0 : 1;
3956 /* Special check for castling so we don't flash both the king
3957 and the rook (just flash the king). */
3960 if (check_castle_draw(board, lastBoard, &rrow, &rcol))
3962 /* Draw rook with NO flashing. King will be drawn flashing later */
3963 DrawSquare(rrow, rcol, board[rrow][rcol], 0);
3964 lastBoard[rrow][rcol] = board[rrow][rcol];
3968 /* First pass -- Draw (newly) empty squares and repair damage.
3969 This prevents you from having a piece show up twice while it
3970 is flashing on its new square */
3971 for (i = 0; i < BOARD_HEIGHT; i++)
3972 for (j = 0; j < BOARD_WIDTH; j++)
3973 if ((board[i][j] != lastBoard[i][j] && board[i][j] == EmptySquare)
3976 DrawSquare(i, j, board[i][j], 0);
3977 damage[i][j] = False;
3980 /* Second pass -- Draw piece(s) in new position and flash them */
3981 for (i = 0; i < BOARD_HEIGHT; i++)
3982 for (j = 0; j < BOARD_WIDTH; j++)
3983 if (board[i][j] != lastBoard[i][j])
3985 DrawSquare(i, j, board[i][j], do_flash);
3997 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3999 cairo_set_line_width (cr, lineGap);
4001 /* TODO: use appdata colors */
4002 cairo_set_source_rgba (cr, 0, 1, 0, 1.0);
4006 for (i = 0; i < BOARD_HEIGHT + 1; i++)
4009 x2 = lineGap + BOARD_WIDTH * (squareSize + lineGap);
4010 y1 = y2 = lineGap / 2 + (i * (squareSize + lineGap));
4012 cairo_move_to (cr, x1, y1);
4013 cairo_rel_line_to (cr, x2,0);
4017 for (j = 0; j < BOARD_WIDTH + 1; j++)
4020 y2 = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
4021 x1 = x2 = lineGap / 2 + (j * (squareSize + lineGap));
4023 cairo_move_to (cr, x1, y1);
4024 cairo_rel_line_to (cr, 0, y2);
4033 for (i = 0; i < BOARD_HEIGHT; i++)
4034 for (j = 0; j < BOARD_WIDTH; j++)
4036 DrawSquare(i, j, board[i][j], 0);
4037 damage[i][j] = False;
4041 CopyBoard(lastBoard, board);
4043 lastFlipView = flipView;
4045 /* Draw highlights */
4046 if (pm1X >= 0 && pm1Y >= 0)
4048 drawHighlight(pm1X, pm1Y, LINE_TYPE_PRE);
4050 if (pm2X >= 0 && pm2Y >= 0)
4052 drawHighlight(pm2X, pm2Y, LINE_TYPE_PRE);
4054 if (hi1X >= 0 && hi1Y >= 0)
4056 drawHighlight(hi1X, hi1Y, LINE_TYPE_HIGHLIGHT);
4058 if (hi2X >= 0 && hi2Y >= 0)
4060 drawHighlight(hi2X, hi2Y, LINE_TYPE_HIGHLIGHT);
4063 /* If piece being dragged around board, must redraw that too */
4070 * event handler for parsing user moves
4072 // [HGM] This routine will need quite some reworking. Although the backend still supports the old
4073 // way of doing things, by calling UserMoveEvent() to test the legality of the move and then perform
4074 // it at the end, and doing all kind of preliminary tests here (e.g. to weed out self-captures), it
4075 // should be made to use the new way, of calling UserMoveTest early to determine the legality of the
4076 // move, (which will weed out the illegal selfcaptures and moves into the holdings, and flag promotions),
4077 // and at the end FinishMove() to perform the move after optional promotion popups.
4078 // For now I patched it to allow self-capture with King, and suppress clicks between board and holdings.
4079 void HandleUserMove(w, event, prms, nprms)
4086 Boolean saveAnimate;
4087 static int second = 0, promotionChoice = 0;
4090 if (w != boardWidget || errorExitStatus != -1) return;
4092 x = EventToSquare(event->xbutton.x, BOARD_WIDTH);
4093 y = EventToSquare(event->xbutton.y, BOARD_HEIGHT);
4094 if (!flipView && y >= 0) {
4095 y = BOARD_HEIGHT - 1 - y;
4097 if (flipView && x >= 0) {
4098 x = BOARD_WIDTH - 1 - x;
4101 if(promotionChoice) { // we are waiting for a click to indicate promotion piece
4102 if(event->type == ButtonRelease) return; // ignore upclick of click-click destination
4103 promotionChoice = FALSE; // only one chance: if click not OK it is interpreted as cancel
4104 if(appData.debugMode) fprintf(debugFP, "promotion click, x=%d, y=%d\n", x, y);
4105 if(gameInfo.holdingsWidth &&
4106 (WhiteOnMove(currentMove)
4107 ? x == BOARD_WIDTH-1 && y < gameInfo.holdingsSize && y > 0
4108 : x == 0 && y >= BOARD_HEIGHT - gameInfo.holdingsSize && y < BOARD_HEIGHT-1) ) {
4109 // click in right holdings, for determining promotion piece
4110 ChessSquare p = boards[currentMove][y][x];
4111 if(appData.debugMode) fprintf(debugFP, "square contains %d\n", (int)p);
4112 if(p != EmptySquare) {
4113 FinishMove(NormalMove, fromX, fromY, toX, toY, ToLower(PieceToChar(p)));
4118 DrawPosition(FALSE, boards[currentMove]);
4121 if (event->type == ButtonPress) ErrorPopDown();
4124 if (event->type == ButtonPress) {
4125 // XtPopdown(promotionShell);
4126 // XtDestroyWidget(promotionShell);
4127 promotionUp = False;
4135 /* [HGM] holdings: next 5 lines: ignore all clicks between board and holdings */
4136 if(event->type == ButtonPress
4137 && ( x == BOARD_LEFT-1 ||
4139 (x == BOARD_LEFT-2 && y < BOARD_HEIGHT-gameInfo.holdingsSize ) ||
4140 (x == BOARD_RGHT+1 && y >= gameInfo.holdingsSize)) )
4144 if (event->type == ButtonPress) {
4145 /* First square, prepare to drag */
4146 if (OKToStartUserMove(x, y)) {
4150 DragPieceBegin(event->xbutton.x, event->xbutton.y);
4151 if (appData.highlightDragging) {
4152 SetHighlights(x, y, -1, -1);
4160 if (event->type == ButtonRelease && x == fromX && y == fromY) {
4161 /* Click on single square in stead of drag-drop */
4162 DragPieceEnd(event->xbutton.x, event->xbutton.y);
4163 if (appData.animateDragging) {
4164 /* Undo animation damage if any */
4165 DrawPosition(FALSE, NULL);
4168 /* Second up/down in same square; just abort move */
4173 ClearPremoveHighlights();
4175 /* First upclick in same square; start click-click mode */
4176 SetHighlights(x, y, -1, -1);
4181 moveType = UserMoveTest(fromX, fromY, x, y, NULLCHAR, event->type == ButtonRelease);
4183 if (moveType == Comment) { // kludge for indicating capture-own on Press
4184 /* Clicked again on same color piece -- changed his mind */
4185 /* note that re-clicking same square always hits same color piece */
4186 second = (x == fromX && y == fromY);
4187 if (appData.highlightDragging) {
4188 SetHighlights(x, y, -1, -1);
4192 if (OKToStartUserMove(x, y)) {
4195 DragPieceBegin(event->xbutton.x, event->xbutton.y);
4200 if(moveType == AmbiguousMove) { // kludge to indicate edit-position move
4203 DragPieceEnd(event->xbutton.x, event->xbutton.y);
4204 DrawPosition(FALSE, boards[currentMove]);
4208 /* Complete move; (x,y) is now different from (fromX, fromY) on both Press and Release */
4211 saveAnimate = appData.animate;
4212 if (event->type == ButtonPress) {
4213 /* Finish clickclick move */
4214 if (appData.animate || appData.highlightLastMove) {
4215 SetHighlights(fromX, fromY, toX, toY);
4220 /* Finish drag move */
4221 if (appData.highlightLastMove) {
4222 SetHighlights(fromX, fromY, toX, toY);
4226 DragPieceEnd(event->xbutton.x, event->xbutton.y);
4227 /* Don't animate move and drag both */
4228 appData.animate = FALSE;
4230 if (moveType == WhitePromotionKnight || moveType == BlackPromotionKnight ||
4231 (moveType == WhitePromotionQueen || moveType == BlackPromotionQueen) &&
4232 appData.alwaysPromoteToQueen) { // promotion, but no choice
4233 FinishMove(moveType, fromX, fromY, toX, toY, 'q');
4235 if (moveType == WhitePromotionQueen || moveType == BlackPromotionQueen ) {
4236 SetHighlights(fromX, fromY, toX, toY);
4237 if(gameInfo.variant == VariantSuper || gameInfo.variant == VariantGreat) {
4238 // [HGM] super: promotion to captured piece selected from holdings
4239 ChessSquare p = boards[currentMove][fromY][fromX], q = boards[currentMove][toY][toX];
4240 promotionChoice = TRUE;
4241 // kludge follows to temporarily execute move on display, without promoting yet
4242 boards[currentMove][fromY][fromX] = EmptySquare; // move Pawn to 8th rank
4243 boards[currentMove][toY][toX] = p;
4244 DrawPosition(FALSE, boards[currentMove]);
4245 boards[currentMove][fromY][fromX] = p; // take back, but display stays
4246 boards[currentMove][toY][toX] = q;
4247 DisplayMessage("Click in holdings to choose piece", "");
4251 goto skipClearingFrom; // the skipped stuff is done asynchronously by PromotionCallback
4253 if(moveType != ImpossibleMove) { // valid move, but no promotion
4254 FinishMove(moveType, fromX, fromY, toX, toY, NULLCHAR);
4255 } else { // invalid move; could have set premove
4258 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
4259 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
4262 appData.animate = saveAnimate;
4263 if (appData.animate || appData.animateDragging) {
4264 /* Undo animation damage if needed */
4265 DrawPosition(FALSE, NULL);
4269 void AnimateUserMove (Widget w, XEvent * event,
4270 String * params, Cardinal * nParams)
4272 DragPieceMove(event->xmotion.x, event->xmotion.y);
4275 Widget CommentCreate(name, text, mutable, callback, lines)
4277 int /*Boolean*/ mutable;
4278 XtCallbackProc callback;
4282 Widget shell, layout, form, edit, b_ok, b_cancel, b_clear, b_close, b_edit;
4287 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4288 XtGetValues(boardWidget, args, j);
4291 XtSetArg(args[j], XtNresizable, True); j++;
4294 XtCreatePopupShell(name, topLevelShellWidgetClass,
4295 shellWidget, args, j);
4298 XtCreatePopupShell(name, transientShellWidgetClass,
4299 shellWidget, args, j);
4302 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
4303 layoutArgs, XtNumber(layoutArgs));
4305 XtCreateManagedWidget("form", formWidgetClass, layout,
4306 formArgs, XtNumber(formArgs));
4310 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
4311 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
4313 XtSetArg(args[j], XtNstring, text); j++;
4314 XtSetArg(args[j], XtNtop, XtChainTop); j++;
4315 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4316 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4317 XtSetArg(args[j], XtNright, XtChainRight); j++;
4318 XtSetArg(args[j], XtNresizable, True); j++;
4319 XtSetArg(args[j], XtNwidth, bw_width); j++; /*force wider than buttons*/
4320 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
4321 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
4322 XtSetArg(args[j], XtNautoFill, True); j++;
4323 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
4325 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
4329 XtSetArg(args[j], XtNfromVert, edit); j++;
4330 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4331 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4332 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4333 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4335 XtCreateManagedWidget(_("ok"), commandWidgetClass, form, args, j);
4336 XtAddCallback(b_ok, XtNcallback, callback, (XtPointer) 0);
4339 XtSetArg(args[j], XtNfromVert, edit); j++;
4340 XtSetArg(args[j], XtNfromHoriz, b_ok); j++;
4341 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4342 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4343 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4344 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4346 XtCreateManagedWidget(_("cancel"), commandWidgetClass, form, args, j);
4347 XtAddCallback(b_cancel, XtNcallback, callback, (XtPointer) 0);
4350 XtSetArg(args[j], XtNfromVert, edit); j++;
4351 XtSetArg(args[j], XtNfromHoriz, b_cancel); j++;
4352 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4353 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4354 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4355 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4357 XtCreateManagedWidget(_("clear"), commandWidgetClass, form, args, j);
4358 XtAddCallback(b_clear, XtNcallback, callback, (XtPointer) 0);
4361 XtSetArg(args[j], XtNfromVert, edit); j++;
4362 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4363 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4364 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4365 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4367 XtCreateManagedWidget(_("close"), commandWidgetClass, form, args, j);
4368 XtAddCallback(b_close, XtNcallback, callback, (XtPointer) 0);
4371 XtSetArg(args[j], XtNfromVert, edit); j++;
4372 XtSetArg(args[j], XtNfromHoriz, b_close); j++;
4373 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4374 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4375 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4376 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4378 XtCreateManagedWidget(_("edit"), commandWidgetClass, form, args, j);
4379 XtAddCallback(b_edit, XtNcallback, callback, (XtPointer) 0);
4382 XtRealizeWidget(shell);
4384 if (commentX == -1) {
4387 Dimension pw_height;
4388 Dimension ew_height;
4391 XtSetArg(args[j], XtNheight, &ew_height); j++;
4392 XtGetValues(edit, args, j);
4395 XtSetArg(args[j], XtNheight, &pw_height); j++;
4396 XtGetValues(shell, args, j);
4397 commentH = pw_height + (lines - 1) * ew_height;
4398 commentW = bw_width - 16;
4400 XSync(xDisplay, False);
4402 /* This code seems to tickle an X bug if it is executed too soon
4403 after xboard starts up. The coordinates get transformed as if
4404 the main window was positioned at (0, 0).
4406 XtTranslateCoords(shellWidget,
4407 (bw_width - commentW) / 2, 0 - commentH / 2,
4408 &commentX, &commentY);
4410 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
4411 RootWindowOfScreen(XtScreen(shellWidget)),
4412 (bw_width - commentW) / 2, 0 - commentH / 2,
4417 if (commentY < 0) commentY = 0; /*avoid positioning top offscreen*/
4420 XtSetArg(args[j], XtNheight, commentH); j++;
4421 XtSetArg(args[j], XtNwidth, commentW); j++;
4422 XtSetArg(args[j], XtNx, commentX); j++;
4423 XtSetArg(args[j], XtNy, commentY); j++;
4424 XtSetValues(shell, args, j);
4425 XtSetKeyboardFocus(shell, edit);
4430 /* Used for analysis window and ICS input window */
4431 Widget MiscCreate(name, text, mutable, callback, lines)
4433 int /*Boolean*/ mutable;
4434 XtCallbackProc callback;
4438 Widget shell, layout, form, edit;
4440 Dimension bw_width, pw_height, ew_height, w, h;
4446 XtSetArg(args[j], XtNresizable, True); j++;
4449 XtCreatePopupShell(name, topLevelShellWidgetClass,
4450 shellWidget, args, j);
4453 XtCreatePopupShell(name, transientShellWidgetClass,
4454 shellWidget, args, j);
4457 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
4458 layoutArgs, XtNumber(layoutArgs));
4460 XtCreateManagedWidget("form", formWidgetClass, layout,
4461 formArgs, XtNumber(formArgs));
4465 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
4466 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
4468 XtSetArg(args[j], XtNstring, text); j++;
4469 XtSetArg(args[j], XtNtop, XtChainTop); j++;
4470 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4471 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4472 XtSetArg(args[j], XtNright, XtChainRight); j++;
4473 XtSetArg(args[j], XtNresizable, True); j++;
4474 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
4475 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
4476 XtSetArg(args[j], XtNautoFill, True); j++;
4477 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
4479 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
4481 XtRealizeWidget(shell);
4484 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4485 XtGetValues(boardWidget, args, j);
4488 XtSetArg(args[j], XtNheight, &ew_height); j++;
4489 XtGetValues(edit, args, j);
4492 XtSetArg(args[j], XtNheight, &pw_height); j++;
4493 XtGetValues(shell, args, j);
4494 h = pw_height + (lines - 1) * ew_height;
4497 XSync(xDisplay, False);
4499 /* This code seems to tickle an X bug if it is executed too soon
4500 after xboard starts up. The coordinates get transformed as if
4501 the main window was positioned at (0, 0).
4503 XtTranslateCoords(shellWidget, (bw_width - w) / 2, 0 - h / 2, &x, &y);
4505 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
4506 RootWindowOfScreen(XtScreen(shellWidget)),
4507 (bw_width - w) / 2, 0 - h / 2, &xx, &yy, &junk);
4511 if (y < 0) y = 0; /*avoid positioning top offscreen*/
4514 XtSetArg(args[j], XtNheight, h); j++;
4515 XtSetArg(args[j], XtNwidth, w); j++;
4516 XtSetArg(args[j], XtNx, x); j++;
4517 XtSetArg(args[j], XtNy, y); j++;
4518 XtSetValues(shell, args, j);
4524 static int savedIndex; /* gross that this is global */
4526 void EditCommentPopUp(index, title, text)
4535 if (text == NULL) text = "";
4537 if (editShell == NULL) {
4539 CommentCreate(title, text, True, EditCommentCallback, 4);
4540 XtRealizeWidget(editShell);
4541 CatchDeleteWindow(editShell, "EditCommentPopDown");
4543 edit = XtNameToWidget(editShell, "*form.text");
4545 XtSetArg(args[j], XtNstring, text); j++;
4546 XtSetValues(edit, args, j);
4548 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4549 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4550 XtSetValues(editShell, args, j);
4553 XtPopup(editShell, XtGrabNone);
4557 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
4558 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
4562 void EditCommentCallback(w, client_data, call_data)
4564 XtPointer client_data, call_data;
4572 XtSetArg(args[j], XtNlabel, &name); j++;
4573 XtGetValues(w, args, j);
4575 if (strcmp(name, _("ok")) == 0) {
4576 edit = XtNameToWidget(editShell, "*form.text");
4578 XtSetArg(args[j], XtNstring, &val); j++;
4579 XtGetValues(edit, args, j);
4580 ReplaceComment(savedIndex, val);
4581 EditCommentPopDown();
4582 } else if (strcmp(name, _("cancel")) == 0) {
4583 EditCommentPopDown();
4584 } else if (strcmp(name, _("clear")) == 0) {
4585 edit = XtNameToWidget(editShell, "*form.text");
4586 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
4587 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
4591 void EditCommentPopDown()
4596 if (!editUp) return;
4598 XtSetArg(args[j], XtNx, &commentX); j++;
4599 XtSetArg(args[j], XtNy, &commentY); j++;
4600 XtSetArg(args[j], XtNheight, &commentH); j++;
4601 XtSetArg(args[j], XtNwidth, &commentW); j++;
4602 XtGetValues(editShell, args, j);
4603 XtPopdown(editShell);
4606 XtSetArg(args[j], XtNleftBitmap, None); j++;
4607 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
4611 void ICSInputBoxPopUp()
4616 char *title = _("ICS Input");
4619 if (ICSInputShell == NULL) {
4620 ICSInputShell = MiscCreate(title, "", True, NULL, 1);
4621 tr = XtParseTranslationTable(ICSInputTranslations);
4622 edit = XtNameToWidget(ICSInputShell, "*form.text");
4623 XtOverrideTranslations(edit, tr);
4624 XtRealizeWidget(ICSInputShell);
4625 CatchDeleteWindow(ICSInputShell, "ICSInputBoxPopDown");
4628 edit = XtNameToWidget(ICSInputShell, "*form.text");
4630 XtSetArg(args[j], XtNstring, ""); j++;
4631 XtSetValues(edit, args, j);
4633 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4634 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4635 XtSetValues(ICSInputShell, args, j);
4638 XtPopup(ICSInputShell, XtGrabNone);
4639 XtSetKeyboardFocus(ICSInputShell, edit);
4641 ICSInputBoxUp = True;
4643 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
4644 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
4648 void ICSInputSendText()
4655 edit = XtNameToWidget(ICSInputShell, "*form.text");
4657 XtSetArg(args[j], XtNstring, &val); j++;
4658 XtGetValues(edit, args, j);
4659 SendMultiLineToICS(val);
4660 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
4661 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
4664 void ICSInputBoxPopDown()
4669 if (!ICSInputBoxUp) return;
4671 XtPopdown(ICSInputShell);
4672 ICSInputBoxUp = False;
4674 XtSetArg(args[j], XtNleftBitmap, None); j++;
4675 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
4679 void CommentPopUp(title, text)
4686 if (commentShell == NULL) {
4688 CommentCreate(title, text, False, CommentCallback, 4);
4689 XtRealizeWidget(commentShell);
4690 CatchDeleteWindow(commentShell, "CommentPopDown");
4692 edit = XtNameToWidget(commentShell, "*form.text");
4694 XtSetArg(args[j], XtNstring, text); j++;
4695 XtSetValues(edit, args, j);
4697 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4698 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4699 XtSetValues(commentShell, args, j);
4702 XtPopup(commentShell, XtGrabNone);
4703 XSync(xDisplay, False);
4708 void AnalysisPopUp(title, text)
4715 if (analysisShell == NULL) {
4716 analysisShell = MiscCreate(title, text, False, NULL, 4);
4717 XtRealizeWidget(analysisShell);
4718 CatchDeleteWindow(analysisShell, "AnalysisPopDown");
4721 edit = XtNameToWidget(analysisShell, "*form.text");
4723 XtSetArg(args[j], XtNstring, text); j++;
4724 XtSetValues(edit, args, j);
4726 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4727 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4728 XtSetValues(analysisShell, args, j);
4732 XtPopup(analysisShell, XtGrabNone);
4734 XSync(xDisplay, False);
4739 void CommentCallback(w, client_data, call_data)
4741 XtPointer client_data, call_data;
4748 XtSetArg(args[j], XtNlabel, &name); j++;
4749 XtGetValues(w, args, j);
4751 if (strcmp(name, _("close")) == 0) {
4753 } else if (strcmp(name, _("edit")) == 0) {
4760 void CommentPopDown()
4765 if (!commentUp) return;
4767 XtSetArg(args[j], XtNx, &commentX); j++;
4768 XtSetArg(args[j], XtNy, &commentY); j++;
4769 XtSetArg(args[j], XtNwidth, &commentW); j++;
4770 XtSetArg(args[j], XtNheight, &commentH); j++;
4771 XtGetValues(commentShell, args, j);
4772 XtPopdown(commentShell);
4773 XSync(xDisplay, False);
4777 void AnalysisPopDown()
4779 if (!analysisUp) return;
4780 XtPopdown(analysisShell);
4781 XSync(xDisplay, False);
4783 if (appData.icsEngineAnalyze) ExitAnalyzeMode(); /* [DM] icsEngineAnalyze */
4787 void FileNamePopUp(label, def, proc, openMode)
4794 Widget popup, layout, dialog, edit;
4800 fileProc = proc; /* I can't see a way not */
4801 fileOpenMode = openMode; /* to use globals here */
4804 XtSetArg(args[i], XtNresizable, True); i++;
4805 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
4806 XtSetArg(args[i], XtNtitle, XtNewString(_("File name prompt"))); i++;
4807 fileNameShell = popup =
4808 XtCreatePopupShell("File name prompt", transientShellWidgetClass,
4809 shellWidget, args, i);
4812 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
4813 layoutArgs, XtNumber(layoutArgs));
4816 XtSetArg(args[i], XtNlabel, label); i++;
4817 XtSetArg(args[i], XtNvalue, def); i++;
4818 XtSetArg(args[i], XtNborderWidth, 0); i++;
4819 dialog = XtCreateManagedWidget("fileName", dialogWidgetClass,
4822 XawDialogAddButton(dialog, _("ok"), FileNameCallback, (XtPointer) dialog);
4823 XawDialogAddButton(dialog, _("cancel"), FileNameCallback,
4824 (XtPointer) dialog);
4826 XtRealizeWidget(popup);
4827 CatchDeleteWindow(popup, "FileNamePopDown");
4829 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
4830 &x, &y, &win_x, &win_y, &mask);
4832 XtSetArg(args[0], XtNx, x - 10);
4833 XtSetArg(args[1], XtNy, y - 30);
4834 XtSetValues(popup, args, 2);
4836 XtPopup(popup, XtGrabExclusive);
4839 edit = XtNameToWidget(dialog, "*value");
4840 XtSetKeyboardFocus(popup, edit);
4843 void FileNamePopDown()
4845 if (!filenameUp) return;
4846 XtPopdown(fileNameShell);
4847 XtDestroyWidget(fileNameShell);
4852 void FileNameCallback(w, client_data, call_data)
4854 XtPointer client_data, call_data;
4859 XtSetArg(args[0], XtNlabel, &name);
4860 XtGetValues(w, args, 1);
4862 if (strcmp(name, _("cancel")) == 0) {
4867 FileNameAction(w, NULL, NULL, NULL);
4870 void FileNameAction(w, event, prms, nprms)
4882 name = XawDialogGetValueString(w = XtParent(w));
4884 if ((name != NULL) && (*name != NULLCHAR)) {
4886 XtPopdown(w = XtParent(XtParent(w)));
4890 p = strrchr(buf, ' ');
4897 fullname = ExpandPathName(buf);
4899 ErrorPopUp(_("Error"), _("Can't open file"), FALSE);
4902 f = fopen(fullname, fileOpenMode);
4904 DisplayError(_("Failed to open file"), errno);
4906 (void) (*fileProc)(f, index, buf);
4913 XtPopdown(w = XtParent(XtParent(w)));
4919 void PromotionPopUp()
4922 Widget dialog, layout;
4924 Dimension bw_width, pw_width;
4928 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4929 XtGetValues(boardWidget, args, j);
4932 XtSetArg(args[j], XtNresizable, True); j++;
4933 XtSetArg(args[j], XtNtitle, XtNewString(_("Promotion"))); j++;
4935 XtCreatePopupShell("Promotion", transientShellWidgetClass,
4936 shellWidget, args, j);
4938 XtCreateManagedWidget(layoutName, formWidgetClass, promotionShell,
4939 layoutArgs, XtNumber(layoutArgs));
4942 XtSetArg(args[j], XtNlabel, _("Promote to what?")); j++;
4943 XtSetArg(args[j], XtNborderWidth, 0); j++;
4944 dialog = XtCreateManagedWidget("promotion", dialogWidgetClass,
4947 if(gameInfo.variant != VariantShogi) {
4948 XawDialogAddButton(dialog, _("Queen"), PromotionCallback,
4949 (XtPointer) dialog);
4950 XawDialogAddButton(dialog, _("Rook"), PromotionCallback,
4951 (XtPointer) dialog);
4952 XawDialogAddButton(dialog, _("Bishop"), PromotionCallback,
4953 (XtPointer) dialog);
4954 XawDialogAddButton(dialog, _("Knight"), PromotionCallback,
4955 (XtPointer) dialog);
4956 if (!appData.testLegality || gameInfo.variant == VariantSuicide ||
4957 gameInfo.variant == VariantGiveaway) {
4958 XawDialogAddButton(dialog, _("King"), PromotionCallback,
4959 (XtPointer) dialog);
4961 if(gameInfo.variant == VariantCapablanca ||
4962 gameInfo.variant == VariantGothic ||
4963 gameInfo.variant == VariantCapaRandom) {
4964 XawDialogAddButton(dialog, _("Archbishop"), PromotionCallback,
4965 (XtPointer) dialog);
4966 XawDialogAddButton(dialog, _("Chancellor"), PromotionCallback,
4967 (XtPointer) dialog);
4969 } else // [HGM] shogi
4971 XawDialogAddButton(dialog, _("Promote"), PromotionCallback,
4972 (XtPointer) dialog);
4973 XawDialogAddButton(dialog, _("Defer"), PromotionCallback,
4974 (XtPointer) dialog);
4976 XawDialogAddButton(dialog, _("cancel"), PromotionCallback,
4977 (XtPointer) dialog);
4979 XtRealizeWidget(promotionShell);
4980 CatchDeleteWindow(promotionShell, "PromotionPopDown");
4983 XtSetArg(args[j], XtNwidth, &pw_width); j++;
4984 XtGetValues(promotionShell, args, j);
4986 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
4987 lineGap + squareSize/3 +
4988 ((toY == BOARD_HEIGHT-1) ^ (flipView) ?
4989 0 : 6*(squareSize + lineGap)), &x, &y);
4992 XtSetArg(args[j], XtNx, x); j++;
4993 XtSetArg(args[j], XtNy, y); j++;
4994 XtSetValues(promotionShell, args, j);
4996 XtPopup(promotionShell, XtGrabNone);
5001 void PromotionPopDown()
5003 if (!promotionUp) return;
5004 XtPopdown(promotionShell);
5005 XtDestroyWidget(promotionShell);
5006 promotionUp = False;
5009 void PromotionCallback(w, client_data, call_data)
5011 XtPointer client_data, call_data;
5017 XtSetArg(args[0], XtNlabel, &name);
5018 XtGetValues(w, args, 1);
5022 if (fromX == -1) return;
5024 if (strcmp(name, _("cancel")) == 0) {
5028 } else if (strcmp(name, _("Knight")) == 0) {
5030 } else if (strcmp(name, _("Promote")) == 0) {
5032 } else if (strcmp(name, _("Defer")) == 0) {
5035 promoChar = ToLower(name[0]);
5038 FinishMove(NormalMove, fromX, fromY, toX, toY, promoChar);
5040 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
5041 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
5046 void ErrorCallback(w, client_data, call_data)
5048 XtPointer client_data, call_data;
5051 XtPopdown(w = XtParent(XtParent(XtParent(w))));
5053 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5059 if (!errorUp) return;
5063 gtk_widget_destroy(GTK_WIDGET(GUI_Error));
5065 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5070 void ErrorPopUp(title, label, modal)
5071 char *title, *label;
5074 GUI_Error = gtk_message_dialog_new(GTK_WINDOW(GUI_Window),
5075 GTK_DIALOG_DESTROY_WITH_PARENT,
5080 gtk_window_set_title(GTK_WINDOW(GUI_Error),(gchar *) title);
5083 gtk_dialog_run(GTK_DIALOG(GUI_Error));
5084 gtk_widget_destroy(GTK_WIDGET(GUI_Error));
5088 g_signal_connect_swapped (GUI_Error, "response",
5089 G_CALLBACK (ErrorPopDownProc),
5092 gtk_widget_show(GTK_WIDGET(GUI_Error));
5098 /* Disable all user input other than deleting the window */
5099 static int frozen = 0;
5103 /* Grab by a widget that doesn't accept input */
5104 // XtAddGrab(messageWidget, TRUE, FALSE);
5108 /* Undo a FreezeUI */
5111 if (!frozen) return;
5112 // XtRemoveGrab(messageWidget);
5116 char *ModeToWidgetName(mode)
5120 case BeginningOfGame:
5121 if (appData.icsActive)
5122 return "menuMode.ICS Client";
5123 else if (appData.noChessProgram ||
5124 *appData.cmailGameName != NULLCHAR)
5125 return "menuMode.Edit Game";
5127 return "menuMode.Machine Black";
5128 case MachinePlaysBlack:
5129 return "menuMode.Machine Black";
5130 case MachinePlaysWhite:
5131 return "menuMode.Machine White";
5133 return "menuMode.Analysis Mode";
5135 return "menuMode.Analyze File";
5136 case TwoMachinesPlay:
5137 return "menuMode.Two Machines";
5139 return "menuMode.Edit Game";
5140 case PlayFromGameFile:
5141 return "menuFile.Load Game";
5143 return "menuMode.Edit Position";
5145 return "menuMode.Training";
5146 case IcsPlayingWhite:
5147 case IcsPlayingBlack:
5151 return "menuMode.ICS Client";
5158 void ModeHighlight()
5160 static int oldPausing = FALSE;
5161 static GameMode oldmode = (GameMode) -1;
5164 // todo this toggling of the pause button doesn't seem to work?
5165 // e.g. select pause from buttonbar doesn't activate menumode.pause
5167 // if (!boardWidget || !XtIsRealized(boardWidget)) return;
5169 if (pausing != oldPausing) {
5170 oldPausing = pausing;
5171 gtk_button_set_relief(GTK_BUTTON (gtk_builder_get_object (builder, "menuMode.Pause")),pausing?GTK_RELIEF_NORMAL:GTK_RELIEF_NONE);
5172 /* toggle background color in showbuttonbar */
5173 if (appData.showButtonBar) {
5175 gtk_button_pressed(GTK_BUTTON (gtk_builder_get_object (builder, "buttonbar.Pause")));
5177 gtk_button_released(GTK_BUTTON (gtk_builder_get_object (builder, "buttonbar.Pause")));
5182 wname = ModeToWidgetName(oldmode);
5184 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, wname)),True);
5188 /* Maybe all the enables should be handled here, not just this one */
5189 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuMode.Training")),
5190 gameMode == Training || gameMode == PlayFromGameFile);
5195 * Button/menu procedures
5198 int LoadGamePopUp(f, gameNumber, title)
5203 cmailMsgLoaded = FALSE;
5205 if (gameNumber == 0)
5207 int error = GameListBuild(f);
5211 DisplayError(_("Cannot build game list"), error);
5213 else if (!ListEmpty(&gameList)
5214 && ((ListGame *) gameList.tailPred)->number > 1)
5216 GameListPopUp(f, title);
5224 return LoadGame(f, gameNumber, title, FALSE);
5228 void LoadNextPositionProc(w, event, prms, nprms)
5237 void LoadPrevPositionProc(w, event, prms, nprms)
5246 void ReloadPositionProc(w, event, prms, nprms)
5255 void LoadPositionProc(w, event, prms, nprms)
5261 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
5264 FileNamePopUp(_("Load position file name?"), "", LoadPosition, "rb");
5267 void SaveGameProc(w, event, prms, nprms)
5273 FileNamePopUp(_("Save game file name?"),
5274 DefaultFileName(appData.oldSaveStyle ? "game" : "pgn"),
5278 void SavePositionProc(w, event, prms, nprms)
5284 FileNamePopUp(_("Save position file name?"),
5285 DefaultFileName(appData.oldSaveStyle ? "pos" : "fen"),
5289 void ReloadCmailMsgProc(w, event, prms, nprms)
5295 ReloadCmailMsgEvent(FALSE);
5298 void MailMoveProc(w, event, prms, nprms)
5307 /* this variable is shared between CopyPositionProc and SendPositionSelection */
5308 static char *selected_fen_position=NULL;
5311 SendPositionSelection(Widget w, Atom *selection, Atom *target,
5312 Atom *type_return, XtPointer *value_return,
5313 unsigned long *length_return, int *format_return)
5315 char *selection_tmp;
5317 if (!selected_fen_position) return False; /* should never happen */
5318 if (*target == XA_STRING){
5319 /* note: since no XtSelectionDoneProc was registered, Xt will
5320 * automatically call XtFree on the value returned. So have to
5321 * make a copy of it allocated with XtMalloc */
5322 selection_tmp= XtMalloc(strlen(selected_fen_position)+16);
5323 strcpy(selection_tmp, selected_fen_position);
5325 *value_return=selection_tmp;
5326 *length_return=strlen(selection_tmp);
5327 *type_return=XA_STRING;
5328 *format_return = 8; /* bits per byte */
5335 /* note: when called from menu all parameters are NULL, so no clue what the
5336 * Widget which was clicked on was, or what the click event was
5338 void CopyPositionProc(w, event, prms, nprms)
5346 if (selected_fen_position) free(selected_fen_position);
5347 selected_fen_position = (char *)PositionToFEN(currentMove, NULL);
5348 if (!selected_fen_position) return;
5349 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
5351 SendPositionSelection,
5352 NULL/* lose_ownership_proc */ ,
5353 NULL/* transfer_done_proc */);
5355 free(selected_fen_position);
5356 selected_fen_position=NULL;
5360 /* function called when the data to Paste is ready */
5362 PastePositionCB(Widget w, XtPointer client_data, Atom *selection,
5363 Atom *type, XtPointer value, unsigned long *len, int *format)
5366 if (value==NULL || *len==0) return; /* nothing had been selected to copy */
5367 fenstr[*len]='\0'; /* normally this string is terminated, but be safe */
5368 EditPositionPasteFEN(fenstr);
5372 /* called when Paste Position button is pressed,
5373 * all parameters will be NULL */
5374 void PastePositionProc(w, event, prms, nprms)
5380 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
5381 /* (XtSelectionCallbackProc) */ PastePositionCB,
5382 NULL, /* client_data passed to PastePositionCB */
5384 /* better to use the time field from the event that triggered the
5385 * call to this function, but that isn't trivial to get
5393 SendGameSelection(Widget w, Atom *selection, Atom *target,
5394 Atom *type_return, XtPointer *value_return,
5395 unsigned long *length_return, int *format_return)
5397 char *selection_tmp;
5399 if (*target == XA_STRING){
5400 FILE* f = fopen(gameCopyFilename, "r");
5403 if (f == NULL) return False;
5407 selection_tmp = XtMalloc(len + 1);
5408 count = fread(selection_tmp, 1, len, f);
5410 XtFree(selection_tmp);
5413 selection_tmp[len] = NULLCHAR;
5414 *value_return = selection_tmp;
5415 *length_return = len;
5416 *type_return = XA_STRING;
5417 *format_return = 8; /* bits per byte */
5424 /* note: when called from menu all parameters are NULL, so no clue what the
5425 * Widget which was clicked on was, or what the click event was
5427 void CopyGameProc(w, event, prms, nprms)
5435 ret = SaveGameToFile(gameCopyFilename, FALSE);
5438 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
5441 NULL/* lose_ownership_proc */ ,
5442 NULL/* transfer_done_proc */);
5445 /* function called when the data to Paste is ready */
5447 PasteGameCB(Widget w, XtPointer client_data, Atom *selection,
5448 Atom *type, XtPointer value, unsigned long *len, int *format)
5451 if (value == NULL || *len == 0) {
5452 return; /* nothing had been selected to copy */
5454 f = fopen(gamePasteFilename, "w");
5456 DisplayError(_("Can't open temp file"), errno);
5459 fwrite(value, 1, *len, f);
5462 LoadGameFromFile(gamePasteFilename, 0, gamePasteFilename, TRUE);
5465 /* called when Paste Game button is pressed,
5466 * all parameters will be NULL */
5467 void PasteGameProc(w, event, prms, nprms)
5473 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
5474 /* (XtSelectionCallbackProc) */ PasteGameCB,
5475 NULL, /* client_data passed to PasteGameCB */
5477 /* better to use the time field from the event that triggered the
5478 * call to this function, but that isn't trivial to get
5488 SaveGameProc(NULL, NULL, NULL, NULL);
5491 void AnalyzeModeProc(w, event, prms, nprms)
5499 if (!first.analysisSupport) {
5500 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
5501 DisplayError(buf, 0);
5504 /* [DM] icsEngineAnalyze [HGM] This is horrible code; reverse the gameMode and isEngineAnalyze tests! */
5505 if (appData.icsActive) {
5506 if (gameMode != IcsObserving) {
5507 sprintf(buf,_("You are not observing a game"));
5508 DisplayError(buf, 0);
5510 if (appData.icsEngineAnalyze) {
5511 if (appData.debugMode)
5512 fprintf(debugFP, _("Found unexpected active ICS engine analyze \n"));
5518 /* if enable, use want disable icsEngineAnalyze */
5519 if (appData.icsEngineAnalyze) {
5524 appData.icsEngineAnalyze = TRUE;
5525 if (appData.debugMode)
5526 fprintf(debugFP, _("ICS engine analyze starting... \n"));
5528 if (!appData.showThinking)
5529 ShowThinkingProc(NULL,NULL);
5534 void AnalyzeFileProc(w, event, prms, nprms)
5540 if (!first.analysisSupport) {
5542 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
5543 DisplayError(buf, 0);
5548 if (!appData.showThinking)
5549 ShowThinkingProc(NULL,NULL);
5552 FileNamePopUp(_("File to analyze"), "", LoadGamePopUp, "rb");
5553 AnalysisPeriodicEvent(1);
5557 void EditGameProc(w, event, prms, nprms)
5566 void EditPositionProc(w, event, prms, nprms)
5572 EditPositionEvent();
5575 void TrainingProc(w, event, prms, nprms)
5584 void EditCommentProc(w, event, prms, nprms)
5591 EditCommentPopDown();
5597 void IcsInputBoxProc(w, event, prms, nprms)
5603 if (ICSInputBoxUp) {
5604 ICSInputBoxPopDown();
5611 void EnterKeyProc(w, event, prms, nprms)
5617 if (ICSInputBoxUp == True)
5621 void AlwaysQueenProc(w, event, prms, nprms)
5629 appData.alwaysPromoteToQueen = !appData.alwaysPromoteToQueen;
5631 if (appData.alwaysPromoteToQueen) {
5632 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5634 XtSetArg(args[0], XtNleftBitmap, None);
5636 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
5640 void AnimateDraggingProc(w, event, prms, nprms)
5648 appData.animateDragging = !appData.animateDragging;
5650 if (appData.animateDragging) {
5651 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5654 XtSetArg(args[0], XtNleftBitmap, None);
5656 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Dragging"),
5660 void AnimateMovingProc(w, event, prms, nprms)
5668 appData.animate = !appData.animate;
5670 if (appData.animate) {
5671 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5674 XtSetArg(args[0], XtNleftBitmap, None);
5676 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
5680 void AutocommProc(w, event, prms, nprms)
5688 appData.autoComment = !appData.autoComment;
5690 if (appData.autoComment) {
5691 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5693 XtSetArg(args[0], XtNleftBitmap, None);
5695 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
5700 void AutoflagProc(w, event, prms, nprms)
5708 appData.autoCallFlag = !appData.autoCallFlag;
5710 if (appData.autoCallFlag) {
5711 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5713 XtSetArg(args[0], XtNleftBitmap, None);
5715 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
5719 void AutoflipProc(w, event, prms, nprms)
5727 appData.autoFlipView = !appData.autoFlipView;
5729 if (appData.autoFlipView) {
5730 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5732 XtSetArg(args[0], XtNleftBitmap, None);
5734 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flip View"),
5738 void AutobsProc(w, event, prms, nprms)
5746 appData.autoObserve = !appData.autoObserve;
5748 if (appData.autoObserve) {
5749 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5751 XtSetArg(args[0], XtNleftBitmap, None);
5753 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
5757 void AutoraiseProc(w, event, prms, nprms)
5765 appData.autoRaiseBoard = !appData.autoRaiseBoard;
5767 if (appData.autoRaiseBoard) {
5768 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5770 XtSetArg(args[0], XtNleftBitmap, None);
5772 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Raise Board"),
5776 void AutosaveProc(w, event, prms, nprms)
5784 appData.autoSaveGames = !appData.autoSaveGames;
5786 if (appData.autoSaveGames) {
5787 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5789 XtSetArg(args[0], XtNleftBitmap, None);
5791 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
5795 void BlindfoldProc(w, event, prms, nprms)
5803 appData.blindfold = !appData.blindfold;
5805 if (appData.blindfold) {
5806 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5808 XtSetArg(args[0], XtNleftBitmap, None);
5810 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Blindfold"),
5813 DrawPosition(True, NULL);
5816 void TestLegalityProc(w, event, prms, nprms)
5824 appData.testLegality = !appData.testLegality;
5826 if (appData.testLegality) {
5827 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5829 XtSetArg(args[0], XtNleftBitmap, None);
5831 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Test Legality"),
5836 void FlashMovesProc(w, event, prms, nprms)
5844 if (appData.flashCount == 0) {
5845 appData.flashCount = 3;
5847 appData.flashCount = -appData.flashCount;
5850 if (appData.flashCount > 0) {
5851 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5853 XtSetArg(args[0], XtNleftBitmap, None);
5855 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flash Moves"),
5860 void HighlightDraggingProc(w, event, prms, nprms)
5868 appData.highlightDragging = !appData.highlightDragging;
5870 if (appData.highlightDragging) {
5871 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5873 XtSetArg(args[0], XtNleftBitmap, None);
5875 XtSetValues(XtNameToWidget(menuBarWidget,
5876 "menuOptions.Highlight Dragging"), args, 1);
5880 void HighlightLastMoveProc(w, event, prms, nprms)
5888 appData.highlightLastMove = !appData.highlightLastMove;
5890 if (appData.highlightLastMove) {
5891 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5893 XtSetArg(args[0], XtNleftBitmap, None);
5895 XtSetValues(XtNameToWidget(menuBarWidget,
5896 "menuOptions.Highlight Last Move"), args, 1);
5899 void IcsAlarmProc(w, event, prms, nprms)
5907 appData.icsAlarm = !appData.icsAlarm;
5909 if (appData.icsAlarm) {
5910 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5912 XtSetArg(args[0], XtNleftBitmap, None);
5914 XtSetValues(XtNameToWidget(menuBarWidget,
5915 "menuOptions.ICS Alarm"), args, 1);
5918 void MoveSoundProc(w, event, prms, nprms)
5926 appData.ringBellAfterMoves = !appData.ringBellAfterMoves;
5928 if (appData.ringBellAfterMoves) {
5929 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5931 XtSetArg(args[0], XtNleftBitmap, None);
5933 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
5938 void OldSaveStyleProc(w, event, prms, nprms)
5946 appData.oldSaveStyle = !appData.oldSaveStyle;
5948 if (appData.oldSaveStyle) {
5949 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5951 XtSetArg(args[0], XtNleftBitmap, None);
5953 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Old Save Style"),
5957 void PeriodicUpdatesProc(w, event, prms, nprms)
5965 PeriodicUpdatesEvent(!appData.periodicUpdates);
5967 if (appData.periodicUpdates) {
5968 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5970 XtSetArg(args[0], XtNleftBitmap, None);
5972 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Periodic Updates"),
5976 void PonderNextMoveProc(w, event, prms, nprms)
5984 PonderNextMoveEvent(!appData.ponderNextMove);
5986 if (appData.ponderNextMove) {
5987 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5989 XtSetArg(args[0], XtNleftBitmap, None);
5991 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Ponder Next Move"),
5995 void PopupExitMessageProc(w, event, prms, nprms)
6003 appData.popupExitMessage = !appData.popupExitMessage;
6005 if (appData.popupExitMessage) {
6006 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6008 XtSetArg(args[0], XtNleftBitmap, None);
6010 XtSetValues(XtNameToWidget(menuBarWidget,
6011 "menuOptions.Popup Exit Message"), args, 1);
6014 void PopupMoveErrorsProc(w, event, prms, nprms)
6022 appData.popupMoveErrors = !appData.popupMoveErrors;
6024 if (appData.popupMoveErrors) {
6025 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6027 XtSetArg(args[0], XtNleftBitmap, None);
6029 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Popup Move Errors"),
6033 void PremoveProc(w, event, prms, nprms)
6041 appData.premove = !appData.premove;
6043 if (appData.premove) {
6044 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6046 XtSetArg(args[0], XtNleftBitmap, None);
6048 XtSetValues(XtNameToWidget(menuBarWidget,
6049 "menuOptions.Premove"), args, 1);
6052 void QuietPlayProc(w, event, prms, nprms)
6060 appData.quietPlay = !appData.quietPlay;
6062 if (appData.quietPlay) {
6063 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6065 XtSetArg(args[0], XtNleftBitmap, None);
6067 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Quiet Play"),
6071 void DebugProc(w, event, prms, nprms)
6077 appData.debugMode = !appData.debugMode;
6080 void AboutGameProc(w, event, prms, nprms)
6089 void NothingProc(w, event, prms, nprms)
6098 void Iconify(w, event, prms, nprms)
6107 XtSetArg(args[0], XtNiconic, True);
6108 XtSetValues(shellWidget, args, 1);
6111 void DisplayMessage(message, extMessage)
6112 gchar *message, *extMessage;
6119 snprintf(buf, sizeof(buf), "%s %s", message, extMessage);
6122 message = extMessage;
6125 gtk_label_set_text( GTK_LABEL(gtk_builder_get_object (builder, "Messages")),message);
6130 void DisplayTitle(text)
6133 gchar title[MSG_SIZ];
6135 if (text == NULL) text = "";
6137 if (appData.titleInWindow)
6142 if (*text != NULLCHAR)
6144 strcpy(title, text);
6146 else if (appData.icsActive)
6148 snprintf(title, sizeof(title), "%s: %s", programName, appData.icsHost);
6150 else if (appData.cmailGameName[0] != NULLCHAR)
6152 snprintf(title,sizeof(title), "%s: %s", programName, "CMail");
6154 // [HGM] license: This stuff should really be done in back-end, but WinBoard already had a pop-up for it
6156 else if (gameInfo.variant == VariantGothic)
6158 strcpy(title, GOTHIC);
6162 else if (gameInfo.variant == VariantFalcon)
6164 strcpy(title, FALCON);
6167 else if (appData.noChessProgram)
6169 strcpy(title, programName);
6173 snprintf(title,sizeof(title), "%s: %s", programName, first.tidy);
6175 gtk_window_set_title(GTK_WINDOW(GUI_Window),title);
6181 void DisplayError(message, error)
6188 if (appData.debugMode || appData.matchMode) {
6189 fprintf(stderr, "%s: %s\n", programName, message);
6192 if (appData.debugMode || appData.matchMode) {
6193 fprintf(stderr, "%s: %s: %s\n",
6194 programName, message, strerror(error));
6196 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
6199 ErrorPopUp(_("Error"), message, FALSE);
6203 void DisplayMoveError(message)
6208 DrawPosition(FALSE, NULL);
6209 if (appData.debugMode || appData.matchMode) {
6210 fprintf(stderr, "%s: %s\n", programName, message);
6212 if (appData.popupMoveErrors) {
6213 ErrorPopUp(_("Error"), message, FALSE);
6215 DisplayMessage(message, "");
6220 void DisplayFatalError(message, error, status)
6226 errorExitStatus = status;
6228 fprintf(stderr, "%s: %s\n", programName, message);
6230 fprintf(stderr, "%s: %s: %s\n",
6231 programName, message, strerror(error));
6232 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
6235 if (appData.popupExitMessage && boardWidget && XtIsRealized(boardWidget)) {
6236 ErrorPopUp(status ? _("Fatal Error") : _("Exiting"), message, TRUE);
6242 void DisplayInformation(message)
6246 ErrorPopUp(_("Information"), message, TRUE);
6249 void DisplayNote(message)
6253 ErrorPopUp(_("Note"), message, FALSE);
6257 NullXErrorCheck(dpy, error_event)
6259 XErrorEvent *error_event;
6264 void DisplayIcsInteractionTitle(message)
6267 if (oldICSInteractionTitle == NULL) {
6268 /* Magic to find the old window title, adapted from vim */
6269 char *wina = getenv("WINDOWID");
6271 Window win = (Window) atoi(wina);
6272 Window root, parent, *children;
6273 unsigned int nchildren;
6274 int (*oldHandler)() = XSetErrorHandler(NullXErrorCheck);
6276 if (XFetchName(xDisplay, win, &oldICSInteractionTitle)) break;
6277 if (!XQueryTree(xDisplay, win, &root, &parent,
6278 &children, &nchildren)) break;
6279 if (children) XFree((void *)children);
6280 if (parent == root || parent == 0) break;
6283 XSetErrorHandler(oldHandler);
6285 if (oldICSInteractionTitle == NULL) {
6286 oldICSInteractionTitle = "xterm";
6289 printf("\033]0;%s\007", message);
6293 char pendingReplyPrefix[MSG_SIZ];
6294 ProcRef pendingReplyPR;
6296 void AskQuestionProc(w, event, prms, nprms)
6303 fprintf(stderr, _("AskQuestionProc needed 4 parameters, got %d\n"),
6307 AskQuestionEvent(prms[0], prms[1], prms[2], prms[3]);
6310 void AskQuestionPopDown()
6312 if (!askQuestionUp) return;
6313 XtPopdown(askQuestionShell);
6314 XtDestroyWidget(askQuestionShell);
6315 askQuestionUp = False;
6318 void AskQuestionReplyAction(w, event, prms, nprms)
6328 reply = XawDialogGetValueString(w = XtParent(w));
6329 strcpy(buf, pendingReplyPrefix);
6330 if (*buf) strcat(buf, " ");
6333 OutputToProcess(pendingReplyPR, buf, strlen(buf), &err);
6334 AskQuestionPopDown();
6336 if (err) DisplayFatalError(_("Error writing to chess program"), err, 0);
6339 void AskQuestionCallback(w, client_data, call_data)
6341 XtPointer client_data, call_data;
6346 XtSetArg(args[0], XtNlabel, &name);
6347 XtGetValues(w, args, 1);
6349 if (strcmp(name, _("cancel")) == 0) {
6350 AskQuestionPopDown();
6352 AskQuestionReplyAction(w, NULL, NULL, NULL);
6356 void AskQuestion(title, question, replyPrefix, pr)
6357 char *title, *question, *replyPrefix;
6361 Widget popup, layout, dialog, edit;
6367 strcpy(pendingReplyPrefix, replyPrefix);
6368 pendingReplyPR = pr;
6371 XtSetArg(args[i], XtNresizable, True); i++;
6372 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
6373 askQuestionShell = popup =
6374 XtCreatePopupShell(title, transientShellWidgetClass,
6375 shellWidget, args, i);
6378 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
6379 layoutArgs, XtNumber(layoutArgs));
6382 XtSetArg(args[i], XtNlabel, question); i++;
6383 XtSetArg(args[i], XtNvalue, ""); i++;
6384 XtSetArg(args[i], XtNborderWidth, 0); i++;
6385 dialog = XtCreateManagedWidget("question", dialogWidgetClass,
6388 XawDialogAddButton(dialog, _("enter"), AskQuestionCallback,
6389 (XtPointer) dialog);
6390 XawDialogAddButton(dialog, _("cancel"), AskQuestionCallback,
6391 (XtPointer) dialog);
6393 XtRealizeWidget(popup);
6394 CatchDeleteWindow(popup, "AskQuestionPopDown");
6396 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
6397 &x, &y, &win_x, &win_y, &mask);
6399 XtSetArg(args[0], XtNx, x - 10);
6400 XtSetArg(args[1], XtNy, y - 30);
6401 XtSetValues(popup, args, 2);
6403 XtPopup(popup, XtGrabExclusive);
6404 askQuestionUp = True;
6406 edit = XtNameToWidget(dialog, "*value");
6407 XtSetKeyboardFocus(popup, edit);
6415 if (*name == NULLCHAR) {
6417 } else if (strcmp(name, "$") == 0) {
6418 putc(BELLCHAR, stderr);
6421 snprintf(buf, sizeof(buf), "%s '%s' &", appData.soundProgram, name);
6429 PlaySound(appData.soundMove);
6435 PlaySound(appData.soundIcsWin);
6441 PlaySound(appData.soundIcsLoss);
6447 PlaySound(appData.soundIcsDraw);
6451 PlayIcsUnfinishedSound()
6453 PlaySound(appData.soundIcsUnfinished);
6459 PlaySound(appData.soundIcsAlarm);
6465 system("stty echo");
6471 system("stty -echo");
6475 Colorize(cc, continuation)
6480 int count, outCount, error;
6482 if (textColors[(int)cc].bg > 0) {
6483 if (textColors[(int)cc].fg > 0) {
6484 sprintf(buf, "\033[0;%d;%d;%dm", textColors[(int)cc].attr,
6485 textColors[(int)cc].fg, textColors[(int)cc].bg);
6487 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
6488 textColors[(int)cc].bg);
6491 if (textColors[(int)cc].fg > 0) {
6492 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
6493 textColors[(int)cc].fg);
6495 sprintf(buf, "\033[0;%dm", textColors[(int)cc].attr);
6498 count = strlen(buf);
6499 outCount = OutputToProcess(NoProc, buf, count, &error);
6500 if (outCount < count) {
6501 DisplayFatalError(_("Error writing to display"), error, 1);
6504 if (continuation) return;
6507 PlaySound(appData.soundShout);
6510 PlaySound(appData.soundSShout);
6513 PlaySound(appData.soundChannel1);
6516 PlaySound(appData.soundChannel);
6519 PlaySound(appData.soundKibitz);
6522 PlaySound(appData.soundTell);
6524 case ColorChallenge:
6525 PlaySound(appData.soundChallenge);
6528 PlaySound(appData.soundRequest);
6531 PlaySound(appData.soundSeek);
6542 return getpwuid(getuid())->pw_name;
6545 static char *ExpandPathName(path)
6548 static char static_buf[2000];
6549 char *d, *s, buf[2000];
6555 while (*s && isspace(*s))
6564 if (*(s+1) == '/') {
6565 strcpy(d, getpwuid(getuid())->pw_dir);
6570 *strchr(buf, '/') = 0;
6571 pwd = getpwnam(buf);
6574 fprintf(stderr, _("ERROR: Unknown user %s (in path %s)\n"),
6578 strcpy(d, pwd->pw_dir);
6579 strcat(d, strchr(s+1, '/'));
6590 static char host_name[MSG_SIZ];
6592 #if HAVE_GETHOSTNAME
6593 gethostname(host_name, MSG_SIZ);
6595 #else /* not HAVE_GETHOSTNAME */
6596 # if HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H
6597 sysinfo(SI_HOSTNAME, host_name, MSG_SIZ);
6599 # else /* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
6601 # endif/* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
6602 #endif /* not HAVE_GETHOSTNAME */
6605 guint delayedEventTimerTag = 0;
6606 DelayedEventCallback delayedEventCallback = 0;
6609 FireDelayedEvent(data)
6613 g_source_remove(delayedEventTimerTag);
6614 delayedEventTimerTag = 0;
6617 delayedEventCallback();
6623 ScheduleDelayedEvent(cb, millisec)
6624 DelayedEventCallback cb; guint millisec;
6626 if(delayedEventTimerTag && delayedEventCallback == cb)
6627 // [HGM] alive: replace, rather than add or flush identical event
6628 g_source_remove(delayedEventTimerTag);
6629 delayedEventCallback = cb;
6630 delayedEventTimerTag = g_timeout_add(millisec,(GSourceFunc) FireDelayedEvent, NULL);
6634 DelayedEventCallback
6637 if (delayedEventTimerTag)
6639 return delayedEventCallback;
6648 CancelDelayedEvent()
6650 if (delayedEventTimerTag)
6652 g_source_remove(delayedEventTimerTag);
6653 delayedEventTimerTag = 0;
6659 guint loadGameTimerTag = 0;
6661 int LoadGameTimerRunning()
6663 return loadGameTimerTag != 0;
6666 int StopLoadGameTimer()
6668 if (loadGameTimerTag != 0) {
6669 g_source_remove(loadGameTimerTag);
6670 loadGameTimerTag = 0;
6678 LoadGameTimerCallback(data)
6682 g_source_remove(loadGameTimerTag);
6683 loadGameTimerTag = 0;
6690 StartLoadGameTimer(millisec)
6694 g_timeout_add( millisec, (GSourceFunc) LoadGameTimerCallback, NULL);
6698 guint analysisClockTag = 0;
6701 AnalysisClockCallback(data)
6704 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile
6705 || appData.icsEngineAnalyze)
6707 AnalysisPeriodicEvent(0);
6708 return 1; /* keep on going */
6710 return 0; /* stop timer */
6714 StartAnalysisClock()
6717 g_timeout_add( 2000,(GSourceFunc) AnalysisClockCallback, NULL);
6721 guint clockTimerTag = 0;
6723 int ClockTimerRunning()
6725 return clockTimerTag != 0;
6728 int StopClockTimer()
6730 if (clockTimerTag != 0)
6732 g_source_remove(clockTimerTag);
6743 ClockTimerCallback(data)
6747 g_source_remove(clockTimerTag);
6755 StartClockTimer(millisec)
6758 clockTimerTag = g_timeout_add(millisec,(GSourceFunc) ClockTimerCallback,NULL);
6763 DisplayTimerLabel(w, color, timer, highlight)
6772 if (appData.clockMode) {
6773 sprintf(buf, "%s: %s", color, TimeString(timer));
6775 sprintf(buf, "%s ", color);
6777 gtk_label_set_text(GTK_LABEL(w),buf);
6779 /* check for low time warning */
6780 // Pixel foregroundOrWarningColor = timerForegroundPixel;
6783 // appData.lowTimeWarning &&
6784 // (timer / 1000) < appData.icsAlarmTime)
6785 // foregroundOrWarningColor = lowTimeWarningColor;
6787 // if (appData.clockMode) {
6788 // sprintf(buf, "%s: %s", color, TimeString(timer));
6789 // XtSetArg(args[0], XtNlabel, buf);
6791 // sprintf(buf, "%s ", color);
6792 // XtSetArg(args[0], XtNlabel, buf);
6797 // XtSetArg(args[1], XtNbackground, foregroundOrWarningColor);
6798 // XtSetArg(args[2], XtNforeground, timerBackgroundPixel);
6800 // XtSetArg(args[1], XtNbackground, timerBackgroundPixel);
6801 // XtSetArg(args[2], XtNforeground, foregroundOrWarningColor);
6804 // XtSetValues(w, args, 3);
6809 DisplayWhiteClock(timeRemaining, highlight)
6813 if(appData.noGUI) return;
6815 DisplayTimerLabel(GUI_Whiteclock, _("White"), timeRemaining, highlight);
6816 if (highlight && WindowIcon == BlackIcon)
6818 WindowIcon = WhiteIcon;
6819 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
6824 DisplayBlackClock(timeRemaining, highlight)
6828 if(appData.noGUI) return;
6830 DisplayTimerLabel(GUI_Blackclock, _("Black"), timeRemaining, highlight);
6831 if (highlight && WindowIcon == WhiteIcon)
6833 WindowIcon = BlackIcon;
6834 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
6852 int StartChildProcess(cmdLine, dir, pr)
6859 int to_prog[2], from_prog[2];
6863 if (appData.debugMode) {
6864 fprintf(stderr, "StartChildProcess (dir=\"%s\") %s\n",dir, cmdLine);
6867 /* We do NOT feed the cmdLine to the shell; we just
6868 parse it into blank-separated arguments in the
6869 most simple-minded way possible.
6872 strcpy(buf, cmdLine);
6877 if (p == NULL) break;
6882 SetUpChildIO(to_prog, from_prog);
6884 if ((pid = fork()) == 0) {
6886 // [HGM] PSWBTM: made order resistant against case where fd of created pipe was 0 or 1
6887 close(to_prog[1]); // first close the unused pipe ends
6888 close(from_prog[0]);
6889 dup2(to_prog[0], 0); // to_prog was created first, nd is the only one to use 0 or 1
6890 dup2(from_prog[1], 1);
6891 if(to_prog[0] >= 2) close(to_prog[0]); // if 0 or 1, the dup2 already cosed the original
6892 close(from_prog[1]); // and closing again loses one of the pipes!
6893 if(fileno(stderr) >= 2) // better safe than sorry...
6894 dup2(1, fileno(stderr)); /* force stderr to the pipe */
6896 if (dir[0] != NULLCHAR && chdir(dir) != 0) {
6901 nice(appData.niceEngines); // [HGM] nice: adjust priority of engine proc
6903 execvp(argv[0], argv);
6905 /* If we get here, exec failed */
6910 /* Parent process */
6912 close(from_prog[1]);
6914 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
6917 cp->fdFrom = from_prog[0];
6918 cp->fdTo = to_prog[1];
6923 // [HGM] kill: implement the 'hard killing' of AS's Winboard_x
6924 static RETSIGTYPE AlarmCallBack(int n)
6930 DestroyChildProcess(pr, signalType)
6934 ChildProc *cp = (ChildProc *) pr;
6936 if (cp->kind != CPReal) return;
6938 if (signalType == 10) { // [HGM] kill: if it does not terminate in 3 sec, kill
6939 signal(SIGALRM, AlarmCallBack);
6941 if(wait((int *) 0) == -1) { // process does not terminate on its own accord
6942 kill(cp->pid, SIGKILL); // kill it forcefully
6943 wait((int *) 0); // and wait again
6947 kill(cp->pid, signalType == 9 ? SIGKILL : SIGTERM); // [HGM] kill: use hard kill if so requested
6949 /* Process is exiting either because of the kill or because of
6950 a quit command sent by the backend; either way, wait for it to die.
6959 InterruptChildProcess(pr)
6962 ChildProc *cp = (ChildProc *) pr;
6964 if (cp->kind != CPReal) return;
6965 (void) kill(cp->pid, SIGINT); /* stop it thinking */
6968 int OpenTelnet(host, port, pr)
6973 char cmdLine[MSG_SIZ];
6975 if (port[0] == NULLCHAR) {
6976 snprintf(cmdLine, sizeof(cmdLine), "%s %s", appData.telnetProgram, host);
6978 snprintf(cmdLine, sizeof(cmdLine), "%s %s %s", appData.telnetProgram, host, port);
6980 return StartChildProcess(cmdLine, "", pr);
6983 int OpenTCP(host, port, pr)
6989 DisplayFatalError(_("Socket support is not configured in"), 0, 2);
6990 #else /* !OMIT_SOCKETS */
6992 struct sockaddr_in sa;
6994 unsigned short uport;
6997 if ((s = socket(AF_INET, SOCK_STREAM, 6)) < 0) {
7001 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
7002 sa.sin_family = AF_INET;
7003 sa.sin_addr.s_addr = INADDR_ANY;
7004 uport = (unsigned short) 0;
7005 sa.sin_port = htons(uport);
7006 if (bind(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)) < 0) {
7010 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
7011 if (!(hp = gethostbyname(host))) {
7013 if (sscanf(host, "%d.%d.%d.%d", &b0, &b1, &b2, &b3) == 4) {
7014 hp = (struct hostent *) calloc(1, sizeof(struct hostent));
7015 hp->h_addrtype = AF_INET;
7017 hp->h_addr_list = (char **) calloc(2, sizeof(char *));
7018 hp->h_addr_list[0] = (char *) malloc(4);
7019 hp->h_addr_list[0][0] = b0;
7020 hp->h_addr_list[0][1] = b1;
7021 hp->h_addr_list[0][2] = b2;
7022 hp->h_addr_list[0][3] = b3;
7027 sa.sin_family = hp->h_addrtype;
7028 uport = (unsigned short) atoi(port);
7029 sa.sin_port = htons(uport);
7030 memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);
7032 if (connect(s, (struct sockaddr *) &sa,
7033 sizeof(struct sockaddr_in)) < 0) {
7037 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7044 #endif /* !OMIT_SOCKETS */
7049 int OpenCommPort(name, pr)
7056 fd = open(name, 2, 0);
7057 if (fd < 0) return errno;
7059 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7069 int OpenLoopback(pr)
7075 SetUpChildIO(to, from);
7077 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7080 cp->fdFrom = to[0]; /* note not from[0]; we are doing a loopback */
7087 int OpenRcmd(host, user, cmd, pr)
7088 char *host, *user, *cmd;
7091 DisplayFatalError(_("internal rcmd not implemented for Unix"), 0, 1);
7095 #define INPUT_SOURCE_BUF_SIZE 8192
7104 char buf[INPUT_SOURCE_BUF_SIZE];
7109 DoInputCallback(io,cond,data)
7114 /* read input from one of the input source (for example a chess program, ICS, etc).
7115 * and call a function that will handle the input
7118 int count; /* how many bytes did we read */
7122 /* All information (callback function, file descriptor, etc) is
7123 * saved in an InputSource structure
7125 InputSource *is = (InputSource *) data;
7129 count = read(is->fd, is->unused,
7130 INPUT_SOURCE_BUF_SIZE - (is->unused - is->buf));
7134 (is->func)(is, is->closure, is->buf, count, count ? errno : 0);
7137 is->unused += count;
7139 /* break input into lines and call the callback function on each
7142 while (p < is->unused)
7144 q = memchr(p, '\n', is->unused - p);
7145 if (q == NULL) break;
7147 (is->func)(is, is->closure, p, q - p, 0);
7150 /* remember not yet used part of the buffer */
7152 while (p < is->unused)
7160 /* read maximum length of input buffer and send the whole buffer
7161 * to the callback function
7163 count = read(is->fd, is->buf, INPUT_SOURCE_BUF_SIZE);
7168 (is->func)(is, is->closure, is->buf, count, error);
7174 InputSourceRef AddInputSource(pr, lineByLine, func, closure)
7181 GIOChannel *channel;
7182 ChildProc *cp = (ChildProc *) pr;
7184 is = (InputSource *) calloc(1, sizeof(InputSource));
7185 is->lineByLine = lineByLine;
7189 is->fd = fileno(stdin);
7191 is->kind = cp->kind;
7192 is->fd = cp->fdFrom;
7195 is->unused = is->buf;
7199 // is->xid = XtAppAddInput(appContext, is->fd,
7200 // (XtPointer) (XtInputReadMask),
7201 // (XtInputCallbackProc) DoInputCallback,
7205 /* TODO: will this work on windows?*/
7206 printf("DEBUG: fd=%d %d\n",is->fd,is);
7208 channel = g_io_channel_unix_new(is->fd);
7209 g_io_channel_set_close_on_unref (channel, TRUE);
7210 is->sid = g_io_add_watch(channel, G_IO_IN,(GIOFunc) DoInputCallback, is);
7211 is->closure = closure;
7212 return (InputSourceRef) is;
7216 RemoveInputSource(isr)
7219 InputSource *is = (InputSource *) isr;
7221 if (is->sid == 0) return;
7222 g_source_remove(is->sid);
7227 int OutputToProcess(pr, message, count, outError)
7233 ChildProc *cp = (ChildProc *) pr;
7237 outCount = fwrite(message, 1, count, stdout);
7239 outCount = write(cp->fdTo, message, count);
7249 /* Output message to process, with "ms" milliseconds of delay
7250 between each character. This is needed when sending the logon
7251 script to ICC, which for some reason doesn't like the
7252 instantaneous send. */
7253 int OutputToProcessDelayed(pr, message, count, outError, msdelay)
7260 ChildProc *cp = (ChildProc *) pr;
7265 r = write(cp->fdTo, message++, 1);
7278 /**** Animation code by Hugh Fisher, DCS, ANU.
7280 Known problem: if a window overlapping the board is
7281 moved away while a piece is being animated underneath,
7282 the newly exposed area won't be updated properly.
7283 I can live with this.
7285 Known problem: if you look carefully at the animation
7286 of pieces in mono mode, they are being drawn as solid
7287 shapes without interior detail while moving. Fixing
7288 this would be a major complication for minimal return.
7291 /* Masks for XPM pieces. Black and white pieces can have
7292 different shapes, but in the interest of retaining my
7293 sanity pieces must have the same outline on both light
7294 and dark squares, and all pieces must use the same
7295 background square colors/images. */
7297 static int xpmDone = 0;
7300 CreateAnimMasks (pieceDepth)
7307 unsigned long plane;
7310 /* just return for gtk at the moment */
7313 /* Need a bitmap just to get a GC with right depth */
7314 buf = XCreatePixmap(xDisplay, xBoardWindow,
7316 values.foreground = 1;
7317 values.background = 0;
7318 /* Don't use XtGetGC, not read only */
7319 maskGC = XCreateGC(xDisplay, buf,
7320 GCForeground | GCBackground, &values);
7321 XFreePixmap(xDisplay, buf);
7323 buf = XCreatePixmap(xDisplay, xBoardWindow,
7324 squareSize, squareSize, pieceDepth);
7325 values.foreground = XBlackPixel(xDisplay, xScreen);
7326 values.background = XWhitePixel(xDisplay, xScreen);
7327 bufGC = XCreateGC(xDisplay, buf,
7328 GCForeground | GCBackground, &values);
7330 for (piece = WhitePawn; piece <= BlackKing; piece++) {
7331 /* Begin with empty mask */
7332 if(!xpmDone) // [HGM] pieces: keep using existing
7333 xpmMask[piece] = XCreatePixmap(xDisplay, xBoardWindow,
7334 squareSize, squareSize, 1);
7335 XSetFunction(xDisplay, maskGC, GXclear);
7336 XFillRectangle(xDisplay, xpmMask[piece], maskGC,
7337 0, 0, squareSize, squareSize);
7339 /* Take a copy of the piece */
7344 XSetFunction(xDisplay, bufGC, GXcopy);
7345 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn],
7347 0, 0, squareSize, squareSize, 0, 0);
7349 /* XOR the background (light) over the piece */
7350 XSetFunction(xDisplay, bufGC, GXxor);
7352 XCopyArea(xDisplay, xpmLightSquare, buf, bufGC,
7353 0, 0, squareSize, squareSize, 0, 0);
7355 XSetForeground(xDisplay, bufGC, lightSquareColor);
7356 XFillRectangle(xDisplay, buf, bufGC, 0, 0, squareSize, squareSize);
7359 /* We now have an inverted piece image with the background
7360 erased. Construct mask by just selecting all the non-zero
7361 pixels - no need to reconstruct the original image. */
7362 XSetFunction(xDisplay, maskGC, GXor);
7364 /* Might be quicker to download an XImage and create bitmap
7365 data from it rather than this N copies per piece, but it
7366 only takes a fraction of a second and there is a much
7367 longer delay for loading the pieces. */
7368 for (n = 0; n < pieceDepth; n ++) {
7369 XCopyPlane(xDisplay, buf, xpmMask[piece], maskGC,
7370 0, 0, squareSize, squareSize,
7376 XFreePixmap(xDisplay, buf);
7377 XFreeGC(xDisplay, bufGC);
7378 XFreeGC(xDisplay, maskGC);
7382 InitAnimState (anim, info)
7384 XWindowAttributes * info;
7389 /* Each buffer is square size, same depth as window */
7390 // anim->saveBuf = XCreatePixmap(xDisplay, xBoardWindow,
7391 // squareSize, squareSize, info->depth);
7392 // anim->newBuf = XCreatePixmap(xDisplay, xBoardWindow,
7393 // squareSize, squareSize, info->depth);
7395 // /* Create a plain GC for blitting */
7396 // mask = GCForeground | GCBackground | GCFunction |
7397 // GCPlaneMask | GCGraphicsExposures;
7398 // values.foreground = XBlackPixel(xDisplay, xScreen);
7399 // values.background = XWhitePixel(xDisplay, xScreen);
7400 // values.function = GXcopy;
7401 // values.plane_mask = AllPlanes;
7402 // values.graphics_exposures = False;
7403 // anim->blitGC = XCreateGC(xDisplay, xBoardWindow, mask, &values);
7405 // /* Piece will be copied from an existing context at
7406 // the start of each new animation/drag. */
7407 // anim->pieceGC = XCreateGC(xDisplay, xBoardWindow, 0, &values);
7409 // /* Outline will be a read-only copy of an existing */
7410 // anim->outlineGC = None;
7416 static VariantClass old = (VariantClass) -1; // [HGM] pieces: redo every time variant changes
7417 XWindowAttributes info;
7419 /* for gtk at the moment just ... */
7422 if (xpmDone && gameInfo.variant == old) return;
7423 if(xpmDone) old = gameInfo.variant; // first time pieces might not be created yet
7424 // XGetWindowAttributes(xDisplay, xBoardWindow, &info);
7426 // InitAnimState(&game, &info);
7427 // InitAnimState(&player, &info);
7429 /* For XPM pieces, we need bitmaps to use as masks. */
7431 // CreateAnimMasks(info.depth);
7437 static Boolean frameWaiting;
7439 static RETSIGTYPE FrameAlarm (sig)
7442 frameWaiting = False;
7443 /* In case System-V style signals. Needed?? */
7444 signal(SIGALRM, FrameAlarm);
7451 struct itimerval delay;
7453 XSync(xDisplay, False);
7456 frameWaiting = True;
7457 signal(SIGALRM, FrameAlarm);
7458 delay.it_interval.tv_sec =
7459 delay.it_value.tv_sec = time / 1000;
7460 delay.it_interval.tv_usec =
7461 delay.it_value.tv_usec = (time % 1000) * 1000;
7462 setitimer(ITIMER_REAL, &delay, NULL);
7463 while (frameWaiting) pause();
7464 delay.it_interval.tv_sec = delay.it_value.tv_sec = 0;
7465 delay.it_interval.tv_usec = delay.it_value.tv_usec = 0;
7466 setitimer(ITIMER_REAL, &delay, NULL);
7476 // XSync(xDisplay, False);
7478 usleep(time * 1000);
7483 /* Convert board position to corner of screen rect and color */
7486 ScreenSquare(column, row, pt, color)
7487 int column; int row; XPoint * pt; int * color;
7490 pt->x = lineGap + ((BOARD_WIDTH-1)-column) * (squareSize + lineGap);
7491 pt->y = lineGap + row * (squareSize + lineGap);
7493 pt->x = lineGap + column * (squareSize + lineGap);
7494 pt->y = lineGap + ((BOARD_HEIGHT-1)-row) * (squareSize + lineGap);
7496 *color = SquareColor(row, column);
7499 /* Convert window coords to square */
7502 BoardSquare(x, y, column, row)
7503 int x; int y; int * column; int * row;
7505 *column = EventToSquare(x, BOARD_WIDTH);
7506 if (flipView && *column >= 0)
7507 *column = BOARD_WIDTH - 1 - *column;
7508 *row = EventToSquare(y, BOARD_HEIGHT);
7509 if (!flipView && *row >= 0)
7510 *row = BOARD_HEIGHT - 1 - *row;
7515 #undef Max /* just in case */
7517 #define Max(a, b) ((a) > (b) ? (a) : (b))
7518 #define Min(a, b) ((a) < (b) ? (a) : (b))
7521 SetRect(rect, x, y, width, height)
7522 XRectangle * rect; int x; int y; int width; int height;
7526 rect->width = width;
7527 rect->height = height;
7530 /* Test if two frames overlap. If they do, return
7531 intersection rect within old and location of
7532 that rect within new. */
7535 Intersect(old, new, size, area, pt)
7536 XPoint * old; XPoint * new;
7537 int size; XRectangle * area; XPoint * pt;
7539 if (old->x > new->x + size || new->x > old->x + size ||
7540 old->y > new->y + size || new->y > old->y + size) {
7543 SetRect(area, Max(new->x - old->x, 0), Max(new->y - old->y, 0),
7544 size - abs(old->x - new->x), size - abs(old->y - new->y));
7545 pt->x = Max(old->x - new->x, 0);
7546 pt->y = Max(old->y - new->y, 0);
7551 /* For two overlapping frames, return the rect(s)
7552 in the old that do not intersect with the new. */
7555 CalcUpdateRects(old, new, size, update, nUpdates)
7556 XPoint * old; XPoint * new; int size;
7557 XRectangle update[]; int * nUpdates;
7561 /* If old = new (shouldn't happen) then nothing to draw */
7562 if (old->x == new->x && old->y == new->y) {
7566 /* Work out what bits overlap. Since we know the rects
7567 are the same size we don't need a full intersect calc. */
7569 /* Top or bottom edge? */
7570 if (new->y > old->y) {
7571 SetRect(&(update[count]), old->x, old->y, size, new->y - old->y);
7573 } else if (old->y > new->y) {
7574 SetRect(&(update[count]), old->x, old->y + size - (old->y - new->y),
7575 size, old->y - new->y);
7578 /* Left or right edge - don't overlap any update calculated above. */
7579 if (new->x > old->x) {
7580 SetRect(&(update[count]), old->x, Max(new->y, old->y),
7581 new->x - old->x, size - abs(new->y - old->y));
7583 } else if (old->x > new->x) {
7584 SetRect(&(update[count]), new->x + size, Max(new->y, old->y),
7585 old->x - new->x, size - abs(new->y - old->y));
7592 /* Generate a series of frame coords from start->mid->finish.
7593 The movement rate doubles until the half way point is
7594 reached, then halves back down to the final destination,
7595 which gives a nice slow in/out effect. The algorithmn
7596 may seem to generate too many intermediates for short
7597 moves, but remember that the purpose is to attract the
7598 viewers attention to the piece about to be moved and
7599 then to where it ends up. Too few frames would be less
7603 Tween(start, mid, finish, factor, frames, nFrames)
7604 XPoint * start; XPoint * mid;
7605 XPoint * finish; int factor;
7606 XPoint frames[]; int * nFrames;
7608 int fraction, n, count;
7612 /* Slow in, stepping 1/16th, then 1/8th, ... */
7614 for (n = 0; n < factor; n++)
7616 for (n = 0; n < factor; n++) {
7617 frames[count].x = start->x + (mid->x - start->x) / fraction;
7618 frames[count].y = start->y + (mid->y - start->y) / fraction;
7620 fraction = fraction / 2;
7624 frames[count] = *mid;
7627 /* Slow out, stepping 1/2, then 1/4, ... */
7629 for (n = 0; n < factor; n++) {
7630 frames[count].x = finish->x - (finish->x - mid->x) / fraction;
7631 frames[count].y = finish->y - (finish->y - mid->y) / fraction;
7633 fraction = fraction * 2;
7638 /* Draw a piece on the screen without disturbing what's there */
7641 SelectGCMask(piece, clip, outline, mask)
7642 ChessSquare piece; GC * clip; GC * outline; Pixmap * mask;
7646 /* Bitmap for piece being moved. */
7647 if (appData.monoMode) {
7648 *mask = *pieceToSolid(piece);
7649 } else if (useImages) {
7651 *mask = xpmMask[piece];
7653 *mask = ximMaskPm[piece];
7656 *mask = *pieceToSolid(piece);
7659 /* GC for piece being moved. Square color doesn't matter, but
7660 since it gets modified we make a copy of the original. */
7662 if (appData.monoMode)
7667 if (appData.monoMode)
7672 // XCopyGC(xDisplay, source, 0xFFFFFFFF, *clip);
7674 /* Outline only used in mono mode and is not modified */
7676 *outline = bwPieceGC;
7678 *outline = wbPieceGC;
7682 OverlayPiece(piece, clip, outline, dest)
7683 ChessSquare piece; GC clip; GC outline; Drawable dest;
7688 /* Draw solid rectangle which will be clipped to shape of piece */
7689 // XFillRectangle(xDisplay, dest, clip,
7690 // 0, 0, squareSize, squareSize)
7692 if (appData.monoMode)
7693 /* Also draw outline in contrasting color for black
7694 on black / white on white cases */
7695 // XCopyPlane(xDisplay, *pieceToOutline(piece), dest, outline,
7696 // 0, 0, squareSize, squareSize, 0, 0, 1)
7699 /* Copy the piece */
7704 // XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
7706 // 0, 0, squareSize, squareSize,
7711 /* Animate the movement of a single piece */
7714 BeginAnimation(anim, piece, startColor, start)
7722 /* The old buffer is initialised with the start square (empty) */
7723 BlankSquare(0, 0, startColor, EmptySquare, anim->saveBuf);
7724 anim->prevFrame = *start;
7726 /* The piece will be drawn using its own bitmap as a matte */
7727 // SelectGCMask(piece, &anim->pieceGC, &anim->outlineGC, &mask);
7728 // XSetClipMask(xDisplay, anim->pieceGC, mask);
7732 AnimationFrame(anim, frame, piece)
7737 XRectangle updates[4];
7742 /* Save what we are about to draw into the new buffer */
7743 // XCopyArea(xDisplay, xBoardWindow, anim->newBuf, anim->blitGC,
7744 // frame->x, frame->y, squareSize, squareSize,
7747 /* Erase bits of the previous frame */
7748 if (Intersect(&anim->prevFrame, frame, squareSize, &overlap, &pt)) {
7749 /* Where the new frame overlapped the previous,
7750 the contents in newBuf are wrong. */
7751 // XCopyArea(xDisplay, anim->saveBuf, anim->newBuf, anim->blitGC,
7752 // overlap.x, overlap.y,
7753 // overlap.width, overlap.height,
7755 /* Repaint the areas in the old that don't overlap new */
7756 CalcUpdateRects(&anim->prevFrame, frame, squareSize, updates, &count);
7757 for (i = 0; i < count; i++)
7758 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
7759 // updates[i].x - anim->prevFrame.x,
7760 // updates[i].y - anim->prevFrame.y,
7761 // updates[i].width, updates[i].height,
7762 // updates[i].x, updates[i].y)
7765 /* Easy when no overlap */
7766 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
7767 // 0, 0, squareSize, squareSize,
7768 // anim->prevFrame.x, anim->prevFrame.y);
7771 /* Save this frame for next time round */
7772 // XCopyArea(xDisplay, anim->newBuf, anim->saveBuf, anim->blitGC,
7773 // 0, 0, squareSize, squareSize,
7775 anim->prevFrame = *frame;
7777 /* Draw piece over original screen contents, not current,
7778 and copy entire rect. Wipes out overlapping piece images. */
7779 OverlayPiece(piece, anim->pieceGC, anim->outlineGC, anim->newBuf);
7780 // XCopyArea(xDisplay, anim->newBuf, xBoardWindow, anim->blitGC,
7781 // 0, 0, squareSize, squareSize,
7782 // frame->x, frame->y);
7786 EndAnimation (anim, finish)
7790 XRectangle updates[4];
7795 /* The main code will redraw the final square, so we
7796 only need to erase the bits that don't overlap. */
7797 if (Intersect(&anim->prevFrame, finish, squareSize, &overlap, &pt)) {
7798 CalcUpdateRects(&anim->prevFrame, finish, squareSize, updates, &count);
7799 for (i = 0; i < count; i++)
7800 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
7801 // updates[i].x - anim->prevFrame.x,
7802 // updates[i].y - anim->prevFrame.y,
7803 // updates[i].width, updates[i].height,
7804 // updates[i].x, updates[i].y)
7807 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
7808 // 0, 0, squareSize, squareSize,
7809 // anim->prevFrame.x, anim->prevFrame.y);
7814 FrameSequence(anim, piece, startColor, start, finish, frames, nFrames)
7816 ChessSquare piece; int startColor;
7817 XPoint * start; XPoint * finish;
7818 XPoint frames[]; int nFrames;
7822 BeginAnimation(anim, piece, startColor, start);
7823 for (n = 0; n < nFrames; n++) {
7824 AnimationFrame(anim, &(frames[n]), piece);
7825 FrameDelay(appData.animSpeed);
7827 EndAnimation(anim, finish);
7830 /* Main control logic for deciding what to animate and how */
7833 AnimateMove(board, fromX, fromY, toX, toY)
7842 XPoint start, finish, mid;
7843 XPoint frames[kFactor * 2 + 1];
7844 int nFrames, startColor, endColor;
7846 /* Are we animating? */
7847 if (!appData.animate || appData.blindfold)
7850 if(board[toY][toX] == WhiteRook && board[fromY][fromX] == WhiteKing ||
7851 board[toY][toX] == BlackRook && board[fromY][fromX] == BlackKing)
7852 return; // [HGM] FRC: no animtion of FRC castlings, as to-square is not true to-square
7854 if (fromY < 0 || fromX < 0 || toX < 0 || toY < 0) return;
7855 piece = board[fromY][fromX];
7856 if (piece >= EmptySquare) return;
7861 hop = (piece == WhiteKnight || piece == BlackKnight);
7864 if (appData.debugMode) {
7865 fprintf(debugFP, hop ? _("AnimateMove: piece %d hops from %d,%d to %d,%d \n") :
7866 _("AnimateMove: piece %d slides from %d,%d to %d,%d \n"),
7867 piece, fromX, fromY, toX, toY); }
7869 ScreenSquare(fromX, fromY, &start, &startColor);
7870 ScreenSquare(toX, toY, &finish, &endColor);
7873 /* Knight: make diagonal movement then straight */
7874 if (abs(toY - fromY) < abs(toX - fromX)) {
7875 mid.x = start.x + (finish.x - start.x) / 2;
7879 mid.y = start.y + (finish.y - start.y) / 2;
7882 mid.x = start.x + (finish.x - start.x) / 2;
7883 mid.y = start.y + (finish.y - start.y) / 2;
7886 /* Don't use as many frames for very short moves */
7887 if (abs(toY - fromY) + abs(toX - fromX) <= 2)
7888 Tween(&start, &mid, &finish, kFactor - 1, frames, &nFrames);
7890 Tween(&start, &mid, &finish, kFactor, frames, &nFrames);
7891 FrameSequence(&game, piece, startColor, &start, &finish, frames, nFrames);
7893 /* Be sure end square is redrawn */
7894 damage[toY][toX] = True;
7898 DragPieceBegin(x, y)
7901 int boardX, boardY, color;
7904 /* Are we animating? */
7905 if (!appData.animateDragging || appData.blindfold)
7908 /* Figure out which square we start in and the
7909 mouse position relative to top left corner. */
7910 BoardSquare(x, y, &boardX, &boardY);
7911 player.startBoardX = boardX;
7912 player.startBoardY = boardY;
7913 ScreenSquare(boardX, boardY, &corner, &color);
7914 player.startSquare = corner;
7915 player.startColor = color;
7916 /* As soon as we start dragging, the piece will jump slightly to
7917 be centered over the mouse pointer. */
7918 player.mouseDelta.x = squareSize/2;
7919 player.mouseDelta.y = squareSize/2;
7920 /* Initialise animation */
7921 player.dragPiece = PieceForSquare(boardX, boardY);
7923 if (player.dragPiece >= 0 && player.dragPiece < EmptySquare) {
7924 player.dragActive = True;
7925 BeginAnimation(&player, player.dragPiece, color, &corner);
7926 /* Mark this square as needing to be redrawn. Note that
7927 we don't remove the piece though, since logically (ie
7928 as seen by opponent) the move hasn't been made yet. */
7929 if(boardX == BOARD_RGHT+1 && PieceForSquare(boardX-1, boardY) > 1 ||
7930 boardX == BOARD_LEFT-2 && PieceForSquare(boardX+1, boardY) > 1)
7931 // XCopyArea(xDisplay, xBoardWindow, player.saveBuf, player.blitGC,
7932 // corner.x, corner.y, squareSize, squareSize,
7933 // 0, 0); // [HGM] zh: unstack in stead of grab
7934 damage[boardY][boardX] = True;
7936 player.dragActive = False;
7946 /* Are we animating? */
7947 if (!appData.animateDragging || appData.blindfold)
7951 if (! player.dragActive)
7953 /* Move piece, maintaining same relative position
7954 of mouse within square */
7955 corner.x = x - player.mouseDelta.x;
7956 corner.y = y - player.mouseDelta.y;
7957 AnimationFrame(&player, &corner, player.dragPiece);
7959 if (appData.highlightDragging) {
7961 BoardSquare(x, y, &boardX, &boardY);
7962 SetHighlights(fromX, fromY, boardX, boardY);
7971 int boardX, boardY, color;
7974 /* Are we animating? */
7975 if (!appData.animateDragging || appData.blindfold)
7979 if (! player.dragActive)
7981 /* Last frame in sequence is square piece is
7982 placed on, which may not match mouse exactly. */
7983 BoardSquare(x, y, &boardX, &boardY);
7984 ScreenSquare(boardX, boardY, &corner, &color);
7985 EndAnimation(&player, &corner);
7987 /* Be sure end square is redrawn */
7988 damage[boardY][boardX] = True;
7990 /* This prevents weird things happening with fast successive
7991 clicks which on my Sun at least can cause motion events
7992 without corresponding press/release. */
7993 player.dragActive = False;
7996 /* Handle expose event while piece being dragged */
8001 if (!player.dragActive || appData.blindfold)
8004 /* What we're doing: logically, the move hasn't been made yet,
8005 so the piece is still in it's original square. But visually
8006 it's being dragged around the board. So we erase the square
8007 that the piece is on and draw it at the last known drag point. */
8008 BlankSquare(player.startSquare.x, player.startSquare.y,
8009 player.startColor, EmptySquare, xBoardWindow);
8010 AnimationFrame(&player, &player.prevFrame, player.dragPiece);
8011 damage[player.startBoardY][player.startBoardX] = TRUE;
8015 SetProgramStats( FrontEndProgramStats * stats )
8018 // [HGM] done, but perhaps backend should call this directly?
8019 EngineOutputUpdate( stats );