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 IcsClientProc P((Widget w, XEvent *event, String *prms,
322 void EditGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
323 void EditPositionProc P((Widget w, XEvent *event,
324 String *prms, Cardinal *nprms));
325 void TrainingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
326 void EditCommentProc P((Widget w, XEvent *event,
327 String *prms, Cardinal *nprms));
328 void IcsInputBoxProc P((Widget w, XEvent *event,
329 String *prms, Cardinal *nprms));
330 void EnterKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
331 void BackwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
332 void ForwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
333 void ToStartProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
334 void ToEndProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
335 void RevertProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
336 void TruncateGameProc P((Widget w, XEvent *event, String *prms,
338 void RetractMoveProc P((Widget w, XEvent *event, String *prms,
340 void AlwaysQueenProc P((Widget w, XEvent *event, String *prms,
342 void AnimateDraggingProc P((Widget w, XEvent *event, String *prms,
344 void AnimateMovingProc P((Widget w, XEvent *event, String *prms,
346 void AutocommProc P((Widget w, XEvent *event, String *prms,
348 void AutoflagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
349 void AutoflipProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
350 void AutobsProc P((Widget w, XEvent *event, String *prms,
352 void AutoraiseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
353 void AutosaveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
354 void BlindfoldProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
355 void FlashMovesProc P((Widget w, XEvent *event, String *prms,
357 void FlipViewProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
358 void GetMoveListProc P((Widget w, XEvent *event, String *prms,
360 void HighlightDraggingProc P((Widget w, XEvent *event, String *prms,
362 void HighlightLastMoveProc P((Widget w, XEvent *event, String *prms,
364 void MoveSoundProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
365 void IcsAlarmProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
366 void OldSaveStyleProc P((Widget w, XEvent *event, String *prms,
368 void PeriodicUpdatesProc P((Widget w, XEvent *event, String *prms,
370 void PonderNextMoveProc P((Widget w, XEvent *event, String *prms,
372 void PopupMoveErrorsProc P((Widget w, XEvent *event, String *prms,
374 void PopupExitMessageProc P((Widget w, XEvent *event, String *prms,
376 void PremoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
377 void QuietPlayProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
378 void ShowThinkingProc P((Widget w, XEvent *event, String *prms,
380 void HideThinkingProc P((Widget w, XEvent *event, String *prms,
382 void TestLegalityProc P((Widget w, XEvent *event, String *prms,
384 void InfoProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
385 void ManProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
386 void HintProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
387 void BookProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
388 void AboutGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
389 void DebugProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
390 void NothingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
391 void Iconify P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
392 void DisplayMove P((int moveNumber));
393 void DisplayTitle P((char *title));
394 void ICSInitScript P((void));
395 int LoadGamePopUp P((FILE *f, int gameNumber, char *title));
396 void ErrorPopUp P((char *title, char *text, int modal));
397 void ErrorPopDown P((void));
398 static char *ExpandPathName P((char *path));
399 static void CreateAnimVars P((void));
400 void DragPieceBegin P((int x, int y));
401 static void DragPieceMove P((int x, int y));
402 void DragPieceEnd P((int x, int y));
403 static void DrawDragPiece P((void));
404 char *ModeToWidgetName P((GameMode mode));
405 void EngineOutputUpdate( FrontEndProgramStats * stats );
406 void ShuffleMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
407 void EngineMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
408 void UciMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
409 void TimeControlProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
410 void NewVariantProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
411 void FirstSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
412 void SecondSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
413 void ShufflePopDown P(());
414 void EnginePopDown P(());
415 void UciPopDown P(());
416 void TimeControlPopDown P(());
417 void NewVariantPopDown P(());
418 void SettingsPopDown P(());
419 void SetMenuEnables P((Enables *enab));
422 * XBoard depends on Xt R4 or higher
424 int xtVersion = XtSpecificationRelease;
429 Pixel lightSquareColor, darkSquareColor, whitePieceColor, blackPieceColor,
430 jailSquareColor, highlightSquareColor, premoveHighlightColor;
431 Pixel lowTimeWarningColor;
433 #define LINE_TYPE_NORMAL 0
434 #define LINE_TYPE_HIGHLIGHT 1
435 #define LINE_TYPE_PRE 2
438 GC lightSquareGC, darkSquareGC, jailSquareGC, wdPieceGC, wlPieceGC,
439 bdPieceGC, blPieceGC, wbPieceGC, bwPieceGC, coordGC,
440 wjPieceGC, bjPieceGC;
441 Pixmap iconPixmap, wIconPixmap, bIconPixmap, xMarkPixmap;
442 Widget shellWidget, layoutWidget, formWidget, boardWidget, messageWidget,
443 whiteTimerWidget, blackTimerWidget, titleWidget, widgetList[16],
444 commentShell, promotionShell, whitePieceMenu, blackPieceMenu, dropMenu,
445 menuBarWidget, buttonBarWidget, editShell, errorShell, analysisShell,
446 ICSInputShell, fileNameShell, askQuestionShell;
447 Font clockFontID, coordFontID, countFontID;
448 XFontStruct *clockFontStruct, *coordFontStruct, *countFontStruct;
449 XtAppContext appContext;
451 char *oldICSInteractionTitle;
455 char installDir[] = "."; // [HGM] UCI: needed for UCI; probably needs run-time initializtion
457 Position commentX = -1, commentY = -1;
458 Dimension commentW, commentH;
460 int squareSize, smallLayout = 0, tinyLayout = 0,
461 marginW, marginH, // [HGM] for run-time resizing
462 fromX = -1, fromY = -1, toX, toY, commentUp = False, analysisUp = False,
463 ICSInputBoxUp = False, askQuestionUp = False,
464 filenameUp = False, promotionUp = False, pmFromX = -1, pmFromY = -1,
465 editUp = False, errorUp = False, errorExitStatus = -1, lineGap;
466 Pixel timerForegroundPixel, timerBackgroundPixel;
467 Pixel buttonForegroundPixel, buttonBackgroundPixel;
468 char *chessDir, *programName, *programVersion,
469 *gameCopyFilename, *gamePasteFilename;
473 Pixmap pieceBitmap[2][(int)BlackPawn];
474 Pixmap pieceBitmap2[2][(int)BlackPawn+4]; /* [HGM] pieces */
475 Pixmap xpmPieceBitmap[4][(int)BlackPawn]; /* LL, LD, DL, DD actually used*/
476 Pixmap xpmPieceBitmap2[4][(int)BlackPawn+4]; /* LL, LD, DL, DD set to select from */
477 Pixmap xpmLightSquare, xpmDarkSquare, xpmJailSquare;
478 int useImages=0, useImageSqs;
479 XImage *ximPieceBitmap[4][(int)BlackPawn+4]; /* LL, LD, DL, DD */
480 Pixmap ximMaskPm[(int)BlackPawn]; /* clipmasks, used for XIM pieces */
481 Pixmap ximMaskPm2[(int)BlackPawn+4]; /* clipmasks, used for XIM pieces */
482 XImage *ximLightSquare, *ximDarkSquare;
485 #define pieceToSolid(piece) &pieceBitmap[SOLID][(piece) % (int)BlackPawn]
486 #define pieceToOutline(piece) &pieceBitmap[OUTLINE][(piece) % (int)BlackPawn]
488 #define White(piece) ((int)(piece) < (int)BlackPawn)
490 /* Variables for doing smooth animation. This whole thing
491 would be much easier if the board was double-buffered,
492 but that would require a fairly major rewrite. */
497 GC blitGC, pieceGC, outlineGC;
498 XPoint startSquare, prevFrame, mouseDelta;
502 int startBoardX, startBoardY;
505 /* There can be two pieces being animated at once: a player
506 can begin dragging a piece before the remote opponent has moved. */
508 static AnimState game, player;
510 /* Bitmaps for use as masks when drawing XPM pieces.
511 Need one for each black and white piece. */
512 static Pixmap xpmMask[BlackKing + 1];
514 /* This magic number is the number of intermediate frames used
515 in each half of the animation. For short moves it's reduced
516 by 1. The total number of frames will be factor * 2 + 1. */
519 SizeDefaults sizeDefaults[] = SIZE_DEFAULTS;
521 Enables icsEnables[] = {
522 { "menuFile.Mail Move", False },
523 { "menuFile.Reload CMail Message", False },
524 { "menuMode.Machine Black", False },
525 { "menuMode.Machine White", False },
526 { "menuMode.Analysis Mode", False },
527 { "menuMode.Analyze File", False },
528 { "menuMode.Two Machines", False },
530 { "menuHelp.Hint", False },
531 { "menuHelp.Book", False },
532 { "menuStep.Move Now", False },
533 { "menuOptions.Periodic Updates", False },
534 { "menuOptions.Hide Thinking", False },
535 { "menuOptions.Ponder Next Move", False },
540 Enables ncpEnables[] = {
541 { "menuFile.Mail Move", False },
542 { "menuFile.Reload CMail Message", False },
543 { "menuMode.Machine White", False },
544 { "menuMode.Machine Black", False },
545 { "menuMode.Analysis Mode", False },
546 { "menuMode.Analyze File", False },
547 { "menuMode.Two Machines", False },
548 { "menuMode.ICS Client", False },
549 { "menuMode.ICS Input Box", False },
551 { "menuStep.Revert", False },
552 { "menuStep.Move Now", False },
553 { "menuStep.Retract Move", False },
554 { "menuOptions.Auto Comment", False },
555 { "menuOptions.Auto Flag", False },
556 { "menuOptions.Auto Flip View", False },
557 { "menuOptions.Auto Observe", False },
558 { "menuOptions.Auto Raise Board", False },
559 { "menuOptions.Get Move List", False },
560 { "menuOptions.ICS Alarm", False },
561 { "menuOptions.Move Sound", False },
562 { "menuOptions.Quiet Play", False },
563 { "menuOptions.Hide Thinking", False },
564 { "menuOptions.Periodic Updates", False },
565 { "menuOptions.Ponder Next Move", False },
566 { "menuHelp.Hint", False },
567 { "menuHelp.Book", False },
571 Enables gnuEnables[] = {
572 { "menuMode.ICS Client", False },
573 { "menuMode.ICS Input Box", False },
574 { "menuAction.Accept", False },
575 { "menuAction.Decline", False },
576 { "menuAction.Rematch", False },
577 { "menuAction.Adjourn", False },
578 { "menuAction.Stop Examining", False },
579 { "menuAction.Stop Observing", False },
580 { "menuStep.Revert", False },
581 { "menuOptions.Auto Comment", False },
582 { "menuOptions.Auto Observe", False },
583 { "menuOptions.Auto Raise Board", False },
584 { "menuOptions.Get Move List", False },
585 { "menuOptions.Premove", False },
586 { "menuOptions.Quiet Play", False },
588 /* The next two options rely on SetCmailMode being called *after* */
589 /* SetGNUMode so that when GNU is being used to give hints these */
590 /* menu options are still available */
592 { "menuFile.Mail Move", False },
593 { "menuFile.Reload CMail Message", False },
597 Enables cmailEnables[] = {
599 { "menuAction.Call Flag", False },
600 { "menuAction.Draw", True },
601 { "menuAction.Adjourn", False },
602 { "menuAction.Abort", False },
603 { "menuAction.Stop Observing", False },
604 { "menuAction.Stop Examining", False },
605 { "menuFile.Mail Move", True },
606 { "menuFile.Reload CMail Message", True },
610 Enables trainingOnEnables[] = {
611 { "menuMode.Edit Comment", False },
612 { "menuMode.Pause", False },
613 { "menuStep.Forward", False },
614 { "menuStep.Backward", False },
615 { "menuStep.Forward to End", False },
616 { "menuStep.Back to Start", False },
617 { "menuStep.Move Now", False },
618 { "menuStep.Truncate Game", False },
622 Enables trainingOffEnables[] = {
623 { "menuMode.Edit Comment", True },
624 { "menuMode.Pause", True },
625 { "menuStep.Forward", True },
626 { "menuStep.Backward", True },
627 { "menuStep.Forward to End", True },
628 { "menuStep.Back to Start", True },
629 { "menuStep.Move Now", True },
630 { "menuStep.Truncate Game", True },
634 Enables machineThinkingEnables[] = {
635 { "menuFile.Load Game", False },
636 { "menuFile.Load Next Game", False },
637 { "menuFile.Load Previous Game", False },
638 { "menuFile.Reload Same Game", False },
639 { "menuFile.Paste Game", False },
640 { "menuFile.Load Position", False },
641 { "menuFile.Load Next Position", False },
642 { "menuFile.Load Previous Position", False },
643 { "menuFile.Reload Same Position", False },
644 { "menuFile.Paste Position", False },
645 { "menuMode.Machine White", False },
646 { "menuMode.Machine Black", False },
647 { "menuMode.Two Machines", False },
648 { "menuStep.Retract Move", False },
652 Enables userThinkingEnables[] = {
653 { "menuFile.Load Game", True },
654 { "menuFile.Load Next Game", True },
655 { "menuFile.Load Previous Game", True },
656 { "menuFile.Reload Same Game", True },
657 { "menuFile.Paste Game", True },
658 { "menuFile.Load Position", True },
659 { "menuFile.Load Next Position", True },
660 { "menuFile.Load Previous Position", True },
661 { "menuFile.Reload Same Position", True },
662 { "menuFile.Paste Position", True },
663 { "menuMode.Machine White", True },
664 { "menuMode.Machine Black", True },
665 { "menuMode.Two Machines", True },
666 { "menuStep.Retract Move", True },
672 MenuItem fileMenu[] = {
673 {N_("New Shuffle Game ..."), ShuffleMenuProc},
674 {N_("New Variant ..."), NewVariantProc}, // [HGM] variant: not functional yet
675 {"----", NothingProc},
676 {N_("Save Game"), SaveGameProc},
677 {"----", NothingProc},
678 {N_("Copy Game"), CopyGameProc},
679 {N_("Paste Game"), PasteGameProc},
680 {"----", NothingProc},
681 {N_("Load Position"), LoadPositionProc},
682 {N_("Load Next Position"), LoadNextPositionProc},
683 {N_("Load Previous Position"), LoadPrevPositionProc},
684 {N_("Reload Same Position"), ReloadPositionProc},
685 {N_("Save Position"), SavePositionProc},
686 {"----", NothingProc},
687 {N_("Copy Position"), CopyPositionProc},
688 {N_("Paste Position"), PastePositionProc},
689 {"----", NothingProc},
690 {N_("Mail Move"), MailMoveProc},
691 {N_("Reload CMail Message"), ReloadCmailMsgProc},
692 {"----", NothingProc},
696 MenuItem modeMenu[] = {
697 // {N_("Machine White"), MachineWhiteProc},
698 // {N_("Machine Black"), MachineBlackProc},
699 // {N_("Two Machines"), TwoMachinesProc},
700 {N_("Analysis Mode"), AnalyzeModeProc},
701 {N_("Analyze File"), AnalyzeFileProc },
702 {N_("ICS Client"), IcsClientProc},
703 {N_("Edit Game"), EditGameProc},
704 {N_("Edit Position"), EditPositionProc},
705 {N_("Training"), TrainingProc},
706 {"----", NothingProc},
707 {N_("Show Engine Output"), EngineOutputProc},
708 {N_("Show Evaluation Graph"), NothingProc}, // [HGM] evalgr: not functional yet
709 {N_("Show Game List"), ShowGameListProc},
710 {"Show Move History", HistoryShowProc}, // [HGM] hist: activate 4.2.7 code
711 {"----", NothingProc},
712 {N_("Edit Tags"), EditTagsProc},
713 {N_("Edit Comment"), EditCommentProc},
714 {N_("ICS Input Box"), IcsInputBoxProc},
718 MenuItem stepMenu[] = {
719 {N_("Backward"), BackwardProc},
720 {N_("Forward"), ForwardProc},
721 {N_("Back to Start"), ToStartProc},
722 {N_("Forward to End"), ToEndProc},
723 {N_("Revert"), RevertProc},
724 {N_("Truncate Game"), TruncateGameProc},
725 {"----", NothingProc},
726 // {N_("Move Now"), MoveNowProc},
727 {N_("Retract Move"), RetractMoveProc},
731 MenuItem optionsMenu[] = {
732 {N_("Flip View"), FlipViewProc},
733 {"----", NothingProc},
734 {N_("Adjudications ..."), EngineMenuProc},
735 {N_("General Settings ..."), UciMenuProc},
736 {N_("Engine #1 Settings ..."), FirstSettingsProc},
737 {N_("Engine #2 Settings ..."), SecondSettingsProc},
738 {N_("Time Control ..."), TimeControlProc},
739 {"----", NothingProc},
740 {N_("Always Queen"), AlwaysQueenProc},
741 {N_("Animate Dragging"), AnimateDraggingProc},
742 {N_("Animate Moving"), AnimateMovingProc},
743 {N_("Auto Comment"), AutocommProc},
744 {N_("Auto Flag"), AutoflagProc},
745 {N_("Auto Flip View"), AutoflipProc},
746 {N_("Auto Observe"), AutobsProc},
747 {N_("Auto Raise Board"), AutoraiseProc},
748 {N_("Auto Save"), AutosaveProc},
749 {N_("Blindfold"), BlindfoldProc},
750 {N_("Flash Moves"), FlashMovesProc},
751 {N_("Get Move List"), GetMoveListProc},
753 {N_("Highlight Dragging"), HighlightDraggingProc},
755 {N_("Highlight Last Move"), HighlightLastMoveProc},
756 {N_("Move Sound"), MoveSoundProc},
757 {N_("ICS Alarm"), IcsAlarmProc},
758 {N_("Old Save Style"), OldSaveStyleProc},
759 {N_("Periodic Updates"), PeriodicUpdatesProc},
760 {N_("Ponder Next Move"), PonderNextMoveProc},
761 {N_("Popup Exit Message"), PopupExitMessageProc},
762 {N_("Popup Move Errors"), PopupMoveErrorsProc},
763 {N_("Premove"), PremoveProc},
764 {N_("Quiet Play"), QuietPlayProc},
765 {N_("Hide Thinking"), HideThinkingProc},
766 {N_("Test Legality"), TestLegalityProc},
770 MenuItem helpMenu[] = {
771 {N_("Info XBoard"), InfoProc},
772 {N_("Man XBoard"), ManProc},
773 {"----", NothingProc},
774 {N_("Hint"), HintProc},
775 {N_("Book"), BookProc},
776 {"----", NothingProc},
781 {N_("File"), fileMenu},
782 {N_("Mode"), modeMenu},
783 {N_("Step"), stepMenu},
784 {N_("Options"), optionsMenu},
785 {N_("Help"), helpMenu},
789 #define PAUSE_BUTTON N_("P")
790 MenuItem buttonBar[] = {
793 // {PAUSE_BUTTON, PauseProc},
799 #define PIECE_MENU_SIZE 18
800 String pieceMenuStrings[2][PIECE_MENU_SIZE] = {
801 { N_("White"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
802 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
803 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
804 N_("Empty square"), N_("Clear board") },
805 { N_("Black"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
806 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
807 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
808 N_("Empty square"), N_("Clear board") }
810 /* must be in same order as PieceMenuStrings! */
811 ChessSquare pieceMenuTranslation[2][PIECE_MENU_SIZE] = {
812 { WhitePlay, (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
813 WhiteRook, WhiteQueen, WhiteKing, (ChessSquare) 0, WhiteAlfil,
814 WhiteCannon, WhiteAngel, WhiteMarshall, (ChessSquare) 0,
815 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
816 { BlackPlay, (ChessSquare) 0, BlackPawn, BlackKnight, BlackBishop,
817 BlackRook, BlackQueen, BlackKing, (ChessSquare) 0, BlackAlfil,
818 BlackCannon, BlackAngel, BlackMarshall, (ChessSquare) 0,
819 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
822 #define DROP_MENU_SIZE 6
823 String dropMenuStrings[DROP_MENU_SIZE] = {
824 "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"), N_("Queen")
826 /* must be in same order as PieceMenuStrings! */
827 ChessSquare dropMenuTranslation[DROP_MENU_SIZE] = {
828 (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
829 WhiteRook, WhiteQueen
837 DropMenuEnables dmEnables[] = {
855 { XtNborderWidth, 0 },
856 { XtNdefaultDistance, 0 },
860 { XtNborderWidth, 0 },
861 { XtNresizable, (XtArgVal) True },
865 { XtNborderWidth, 0 },
871 { XtNjustify, (XtArgVal) XtJustifyRight },
872 { XtNlabel, (XtArgVal) "..." },
873 { XtNresizable, (XtArgVal) True },
874 { XtNresize, (XtArgVal) False }
877 Arg messageArgs[] = {
878 { XtNjustify, (XtArgVal) XtJustifyLeft },
879 { XtNlabel, (XtArgVal) "..." },
880 { XtNresizable, (XtArgVal) True },
881 { XtNresize, (XtArgVal) False }
885 { XtNborderWidth, 0 },
886 { XtNjustify, (XtArgVal) XtJustifyLeft }
889 XtResource clientResources[] = {
890 { "whitePieceColor", "whitePieceColor", XtRString, sizeof(String),
891 XtOffset(AppDataPtr, whitePieceColor), XtRString,
893 { "blackPieceColor", "blackPieceColor", XtRString, sizeof(String),
894 XtOffset(AppDataPtr, blackPieceColor), XtRString,
896 { "lightSquareColor", "lightSquareColor", XtRString,
897 sizeof(String), XtOffset(AppDataPtr, lightSquareColor),
898 XtRString, LIGHT_SQUARE_COLOR },
899 { "darkSquareColor", "darkSquareColor", XtRString, sizeof(String),
900 XtOffset(AppDataPtr, darkSquareColor), XtRString,
902 { "highlightSquareColor", "highlightSquareColor", XtRString,
903 sizeof(String), XtOffset(AppDataPtr, highlightSquareColor),
904 XtRString, HIGHLIGHT_SQUARE_COLOR },
905 { "premoveHighlightColor", "premoveHighlightColor", XtRString,
906 sizeof(String), XtOffset(AppDataPtr, premoveHighlightColor),
907 XtRString, PREMOVE_HIGHLIGHT_COLOR },
908 { "movesPerSession", "movesPerSession", XtRInt, sizeof(int),
909 XtOffset(AppDataPtr, movesPerSession), XtRImmediate,
910 (XtPointer) MOVES_PER_SESSION },
911 { "timeIncrement", "timeIncrement", XtRInt, sizeof(int),
912 XtOffset(AppDataPtr, timeIncrement), XtRImmediate,
913 (XtPointer) TIME_INCREMENT },
914 { "initString", "initString", XtRString, sizeof(String),
915 XtOffset(AppDataPtr, initString), XtRString, INIT_STRING },
916 { "secondInitString", "secondInitString", XtRString, sizeof(String),
917 XtOffset(AppDataPtr, secondInitString), XtRString, INIT_STRING },
918 { "firstComputerString", "firstComputerString", XtRString,
919 sizeof(String), XtOffset(AppDataPtr, firstComputerString), XtRString,
921 { "secondComputerString", "secondComputerString", XtRString,
922 sizeof(String), XtOffset(AppDataPtr, secondComputerString), XtRString,
924 { "firstChessProgram", "firstChessProgram", XtRString,
925 sizeof(String), XtOffset(AppDataPtr, firstChessProgram),
926 XtRString, FIRST_CHESS_PROGRAM },
927 { "secondChessProgram", "secondChessProgram", XtRString,
928 sizeof(String), XtOffset(AppDataPtr, secondChessProgram),
929 XtRString, SECOND_CHESS_PROGRAM },
930 { "firstPlaysBlack", "firstPlaysBlack", XtRBoolean,
931 sizeof(Boolean), XtOffset(AppDataPtr, firstPlaysBlack),
932 XtRImmediate, (XtPointer) False },
933 { "noChessProgram", "noChessProgram", XtRBoolean,
934 sizeof(Boolean), XtOffset(AppDataPtr, noChessProgram),
935 XtRImmediate, (XtPointer) False },
936 { "firstHost", "firstHost", XtRString, sizeof(String),
937 XtOffset(AppDataPtr, firstHost), XtRString, FIRST_HOST },
938 { "secondHost", "secondHost", XtRString, sizeof(String),
939 XtOffset(AppDataPtr, secondHost), XtRString, SECOND_HOST },
940 { "firstDirectory", "firstDirectory", XtRString, sizeof(String),
941 XtOffset(AppDataPtr, firstDirectory), XtRString, "." },
942 { "secondDirectory", "secondDirectory", XtRString, sizeof(String),
943 XtOffset(AppDataPtr, secondDirectory), XtRString, "." },
944 { "bitmapDirectory", "bitmapDirectory", XtRString,
945 sizeof(String), XtOffset(AppDataPtr, bitmapDirectory),
947 { "remoteShell", "remoteShell", XtRString, sizeof(String),
948 XtOffset(AppDataPtr, remoteShell), XtRString, REMOTE_SHELL },
949 { "remoteUser", "remoteUser", XtRString, sizeof(String),
950 XtOffset(AppDataPtr, remoteUser), XtRString, "" },
951 { "timeDelay", "timeDelay", XtRFloat, sizeof(float),
952 XtOffset(AppDataPtr, timeDelay), XtRString,
953 (XtPointer) TIME_DELAY_QUOTE },
954 { "timeControl", "timeControl", XtRString, sizeof(String),
955 XtOffset(AppDataPtr, timeControl), XtRString,
956 (XtPointer) TIME_CONTROL },
957 { "internetChessServerMode", "internetChessServerMode",
958 XtRBoolean, sizeof(Boolean),
959 XtOffset(AppDataPtr, icsActive), XtRImmediate,
961 { "internetChessServerHost", "internetChessServerHost",
962 XtRString, sizeof(String),
963 XtOffset(AppDataPtr, icsHost),
964 XtRString, (XtPointer) ICS_HOST },
965 { "internetChessServerPort", "internetChessServerPort",
966 XtRString, sizeof(String),
967 XtOffset(AppDataPtr, icsPort), XtRString,
968 (XtPointer) ICS_PORT },
969 { "internetChessServerCommPort", "internetChessServerCommPort",
970 XtRString, sizeof(String),
971 XtOffset(AppDataPtr, icsCommPort), XtRString,
973 { "internetChessServerLogonScript", "internetChessServerLogonScript",
974 XtRString, sizeof(String),
975 XtOffset(AppDataPtr, icsLogon), XtRString,
977 { "internetChessServerHelper", "internetChessServerHelper",
978 XtRString, sizeof(String),
979 XtOffset(AppDataPtr, icsHelper), XtRString, "" },
980 { "internetChessServerInputBox", "internetChessServerInputBox",
981 XtRBoolean, sizeof(Boolean),
982 XtOffset(AppDataPtr, icsInputBox), XtRImmediate,
984 { "icsAlarm", "icsAlarm",
985 XtRBoolean, sizeof(Boolean),
986 XtOffset(AppDataPtr, icsAlarm), XtRImmediate,
988 { "icsAlarmTime", "icsAlarmTime",
990 XtOffset(AppDataPtr, icsAlarmTime), XtRImmediate,
992 { "useTelnet", "useTelnet", XtRBoolean, sizeof(Boolean),
993 XtOffset(AppDataPtr, useTelnet), XtRImmediate,
995 { "telnetProgram", "telnetProgram", XtRString, sizeof(String),
996 XtOffset(AppDataPtr, telnetProgram), XtRString, TELNET_PROGRAM },
997 { "gateway", "gateway", XtRString, sizeof(String),
998 XtOffset(AppDataPtr, gateway), XtRString, "" },
999 { "loadGameFile", "loadGameFile", XtRString, sizeof(String),
1000 XtOffset(AppDataPtr, loadGameFile), XtRString, "" },
1001 { "loadGameIndex", "loadGameIndex",
1002 XtRInt, sizeof(int),
1003 XtOffset(AppDataPtr, loadGameIndex), XtRImmediate,
1005 { "saveGameFile", "saveGameFile", XtRString, sizeof(String),
1006 XtOffset(AppDataPtr, saveGameFile), XtRString, "" },
1007 { "autoRaiseBoard", "autoRaiseBoard", XtRBoolean,
1008 sizeof(Boolean), XtOffset(AppDataPtr, autoRaiseBoard),
1009 XtRImmediate, (XtPointer) True },
1010 { "autoSaveGames", "autoSaveGames", XtRBoolean,
1011 sizeof(Boolean), XtOffset(AppDataPtr, autoSaveGames),
1012 XtRImmediate, (XtPointer) False },
1013 { "blindfold", "blindfold", XtRBoolean,
1014 sizeof(Boolean), XtOffset(AppDataPtr, blindfold),
1015 XtRImmediate, (XtPointer) False },
1016 { "loadPositionFile", "loadPositionFile", XtRString,
1017 sizeof(String), XtOffset(AppDataPtr, loadPositionFile),
1019 { "loadPositionIndex", "loadPositionIndex",
1020 XtRInt, sizeof(int),
1021 XtOffset(AppDataPtr, loadPositionIndex), XtRImmediate,
1023 { "savePositionFile", "savePositionFile", XtRString,
1024 sizeof(String), XtOffset(AppDataPtr, savePositionFile),
1026 { "matchMode", "matchMode", XtRBoolean, sizeof(Boolean),
1027 XtOffset(AppDataPtr, matchMode), XtRImmediate, (XtPointer) False },
1028 { "matchGames", "matchGames", XtRInt, sizeof(int),
1029 XtOffset(AppDataPtr, matchGames), XtRImmediate,
1031 { "monoMode", "monoMode", XtRBoolean, sizeof(Boolean),
1032 XtOffset(AppDataPtr, monoMode), XtRImmediate,
1033 (XtPointer) False },
1034 { "debugMode", "debugMode", XtRBoolean, sizeof(Boolean),
1035 XtOffset(AppDataPtr, debugMode), XtRImmediate,
1036 (XtPointer) False },
1037 { "clockMode", "clockMode", XtRBoolean, sizeof(Boolean),
1038 XtOffset(AppDataPtr, clockMode), XtRImmediate,
1040 { "boardSize", "boardSize", XtRString, sizeof(String),
1041 XtOffset(AppDataPtr, boardSize), XtRString, "" },
1042 { "searchTime", "searchTime", XtRString, sizeof(String),
1043 XtOffset(AppDataPtr, searchTime), XtRString,
1045 { "searchDepth", "searchDepth", XtRInt, sizeof(int),
1046 XtOffset(AppDataPtr, searchDepth), XtRImmediate,
1048 { "showCoords", "showCoords", XtRBoolean, sizeof(Boolean),
1049 XtOffset(AppDataPtr, showCoords), XtRImmediate,
1050 (XtPointer) False },
1051 { "showJail", "showJail", XtRInt, sizeof(int),
1052 XtOffset(AppDataPtr, showJail), XtRImmediate,
1054 { "showThinking", "showThinking", XtRBoolean, sizeof(Boolean),
1055 XtOffset(AppDataPtr, showThinking), XtRImmediate,
1057 { "ponderNextMove", "ponderNextMove", XtRBoolean, sizeof(Boolean),
1058 XtOffset(AppDataPtr, ponderNextMove), XtRImmediate,
1060 { "periodicUpdates", "periodicUpdates", XtRBoolean, sizeof(Boolean),
1061 XtOffset(AppDataPtr, periodicUpdates), XtRImmediate,
1063 { "clockFont", "clockFont", XtRString, sizeof(String),
1064 XtOffset(AppDataPtr, clockFont), XtRString, CLOCK_FONT },
1065 { "coordFont", "coordFont", XtRString, sizeof(String),
1066 XtOffset(AppDataPtr, coordFont), XtRString, COORD_FONT },
1067 { "font", "font", XtRString, sizeof(String),
1068 XtOffset(AppDataPtr, font), XtRString, DEFAULT_FONT },
1069 { "ringBellAfterMoves", "ringBellAfterMoves",
1070 XtRBoolean, sizeof(Boolean),
1071 XtOffset(AppDataPtr, ringBellAfterMoves),
1072 XtRImmediate, (XtPointer) False },
1073 { "autoCallFlag", "autoCallFlag", XtRBoolean,
1074 sizeof(Boolean), XtOffset(AppDataPtr, autoCallFlag),
1075 XtRImmediate, (XtPointer) False },
1076 { "autoFlipView", "autoFlipView", XtRBoolean,
1077 sizeof(Boolean), XtOffset(AppDataPtr, autoFlipView),
1078 XtRImmediate, (XtPointer) True },
1079 { "autoObserve", "autoObserve", XtRBoolean,
1080 sizeof(Boolean), XtOffset(AppDataPtr, autoObserve),
1081 XtRImmediate, (XtPointer) False },
1082 { "autoComment", "autoComment", XtRBoolean,
1083 sizeof(Boolean), XtOffset(AppDataPtr, autoComment),
1084 XtRImmediate, (XtPointer) False },
1085 { "getMoveList", "getMoveList", XtRBoolean,
1086 sizeof(Boolean), XtOffset(AppDataPtr, getMoveList),
1087 XtRImmediate, (XtPointer) True },
1089 { "highlightDragging", "highlightDragging", XtRBoolean,
1090 sizeof(Boolean), XtOffset(AppDataPtr, highlightDragging),
1091 XtRImmediate, (XtPointer) False },
1093 { "highlightLastMove", "highlightLastMove", XtRBoolean,
1094 sizeof(Boolean), XtOffset(AppDataPtr, highlightLastMove),
1095 XtRImmediate, (XtPointer) False },
1096 { "premove", "premove", XtRBoolean,
1097 sizeof(Boolean), XtOffset(AppDataPtr, premove),
1098 XtRImmediate, (XtPointer) True },
1099 { "testLegality", "testLegality", XtRBoolean,
1100 sizeof(Boolean), XtOffset(AppDataPtr, testLegality),
1101 XtRImmediate, (XtPointer) True },
1102 { "flipView", "flipView", XtRBoolean,
1103 sizeof(Boolean), XtOffset(AppDataPtr, flipView),
1104 XtRImmediate, (XtPointer) False },
1105 { "cmail", "cmailGameName", XtRString, sizeof(String),
1106 XtOffset(AppDataPtr, cmailGameName), XtRString, "" },
1107 { "alwaysPromoteToQueen", "alwaysPromoteToQueen", XtRBoolean,
1108 sizeof(Boolean), XtOffset(AppDataPtr, alwaysPromoteToQueen),
1109 XtRImmediate, (XtPointer) False },
1110 { "oldSaveStyle", "oldSaveStyle", XtRBoolean,
1111 sizeof(Boolean), XtOffset(AppDataPtr, oldSaveStyle),
1112 XtRImmediate, (XtPointer) False },
1113 { "quietPlay", "quietPlay", XtRBoolean,
1114 sizeof(Boolean), XtOffset(AppDataPtr, quietPlay),
1115 XtRImmediate, (XtPointer) False },
1116 { "titleInWindow", "titleInWindow", XtRBoolean,
1117 sizeof(Boolean), XtOffset(AppDataPtr, titleInWindow),
1118 XtRImmediate, (XtPointer) False },
1119 { "localLineEditing", "localLineEditing", XtRBoolean,
1120 sizeof(Boolean), XtOffset(AppDataPtr, localLineEditing),
1121 XtRImmediate, (XtPointer) True }, /* not implemented, must be True */
1123 { "zippyTalk", "zippyTalk", XtRBoolean,
1124 sizeof(Boolean), XtOffset(AppDataPtr, zippyTalk),
1125 XtRImmediate, (XtPointer) ZIPPY_TALK },
1126 { "zippyPlay", "zippyPlay", XtRBoolean,
1127 sizeof(Boolean), XtOffset(AppDataPtr, zippyPlay),
1128 XtRImmediate, (XtPointer) ZIPPY_PLAY },
1129 { "zippyLines", "zippyLines", XtRString, sizeof(String),
1130 XtOffset(AppDataPtr, zippyLines), XtRString, ZIPPY_LINES },
1131 { "zippyPinhead", "zippyPinhead", XtRString, sizeof(String),
1132 XtOffset(AppDataPtr, zippyPinhead), XtRString, ZIPPY_PINHEAD },
1133 { "zippyPassword", "zippyPassword", XtRString, sizeof(String),
1134 XtOffset(AppDataPtr, zippyPassword), XtRString, ZIPPY_PASSWORD },
1135 { "zippyPassword2", "zippyPassword2", XtRString, sizeof(String),
1136 XtOffset(AppDataPtr, zippyPassword2), XtRString, ZIPPY_PASSWORD2 },
1137 { "zippyWrongPassword", "zippyWrongPassword", XtRString, sizeof(String),
1138 XtOffset(AppDataPtr, zippyWrongPassword), XtRString,
1139 ZIPPY_WRONG_PASSWORD },
1140 { "zippyAcceptOnly", "zippyAcceptOnly", XtRString, sizeof(String),
1141 XtOffset(AppDataPtr, zippyAcceptOnly), XtRString, ZIPPY_ACCEPT_ONLY },
1142 { "zippyUseI", "zippyUseI", XtRBoolean,
1143 sizeof(Boolean), XtOffset(AppDataPtr, zippyUseI),
1144 XtRImmediate, (XtPointer) ZIPPY_USE_I },
1145 { "zippyBughouse", "zippyBughouse", XtRInt,
1146 sizeof(int), XtOffset(AppDataPtr, zippyBughouse),
1147 XtRImmediate, (XtPointer) ZIPPY_BUGHOUSE },
1148 { "zippyNoplayCrafty", "zippyNoplayCrafty", XtRBoolean,
1149 sizeof(Boolean), XtOffset(AppDataPtr, zippyNoplayCrafty),
1150 XtRImmediate, (XtPointer) ZIPPY_NOPLAY_CRAFTY },
1151 { "zippyGameEnd", "zippyGameEnd", XtRString, sizeof(String),
1152 XtOffset(AppDataPtr, zippyGameEnd), XtRString, ZIPPY_GAME_END },
1153 { "zippyGameStart", "zippyGameStart", XtRString, sizeof(String),
1154 XtOffset(AppDataPtr, zippyGameStart), XtRString, ZIPPY_GAME_START },
1155 { "zippyAdjourn", "zippyAdjourn", XtRBoolean,
1156 sizeof(Boolean), XtOffset(AppDataPtr, zippyAdjourn),
1157 XtRImmediate, (XtPointer) ZIPPY_ADJOURN },
1158 { "zippyAbort", "zippyAbort", XtRBoolean,
1159 sizeof(Boolean), XtOffset(AppDataPtr, zippyAbort),
1160 XtRImmediate, (XtPointer) ZIPPY_ABORT },
1161 { "zippyVariants", "zippyVariants", XtRString, sizeof(String),
1162 XtOffset(AppDataPtr, zippyVariants), XtRString, ZIPPY_VARIANTS },
1163 { "zippyMaxGames", "zippyMaxGames", XtRInt, sizeof(int),
1164 XtOffset(AppDataPtr, zippyMaxGames), XtRImmediate,
1165 (XtPointer) ZIPPY_MAX_GAMES },
1166 { "zippyReplayTimeout", "zippyReplayTimeout", XtRInt, sizeof(int),
1167 XtOffset(AppDataPtr, zippyReplayTimeout), XtRImmediate,
1168 (XtPointer) ZIPPY_REPLAY_TIMEOUT },
1169 { "zippyShortGame", "zippyShortGame", XtRInt, sizeof(int),
1170 XtOffset(AppDataPtr, zippyShortGame), XtRImmediate,
1173 { "flashCount", "flashCount", XtRInt, sizeof(int),
1174 XtOffset(AppDataPtr, flashCount), XtRImmediate,
1175 (XtPointer) FLASH_COUNT },
1176 { "flashRate", "flashRate", XtRInt, sizeof(int),
1177 XtOffset(AppDataPtr, flashRate), XtRImmediate,
1178 (XtPointer) FLASH_RATE },
1179 { "pixmapDirectory", "pixmapDirectory", XtRString,
1180 sizeof(String), XtOffset(AppDataPtr, pixmapDirectory),
1182 { "msLoginDelay", "msLoginDelay", XtRInt, sizeof(int),
1183 XtOffset(AppDataPtr, msLoginDelay), XtRImmediate,
1184 (XtPointer) MS_LOGIN_DELAY },
1185 { "colorizeMessages", "colorizeMessages", XtRBoolean,
1186 sizeof(Boolean), XtOffset(AppDataPtr, colorize),
1187 XtRImmediate, (XtPointer) False },
1188 { "colorShout", "colorShout", XtRString,
1189 sizeof(String), XtOffset(AppDataPtr, colorShout),
1190 XtRString, COLOR_SHOUT },
1191 { "colorSShout", "colorSShout", XtRString,
1192 sizeof(String), XtOffset(AppDataPtr, colorSShout),
1193 XtRString, COLOR_SSHOUT },
1194 { "colorChannel1", "colorChannel1", XtRString,
1195 sizeof(String), XtOffset(AppDataPtr, colorChannel1),
1196 XtRString, COLOR_CHANNEL1 },
1197 { "colorChannel", "colorChannel", XtRString,
1198 sizeof(String), XtOffset(AppDataPtr, colorChannel),
1199 XtRString, COLOR_CHANNEL },
1200 { "colorKibitz", "colorKibitz", XtRString,
1201 sizeof(String), XtOffset(AppDataPtr, colorKibitz),
1202 XtRString, COLOR_KIBITZ },
1203 { "colorTell", "colorTell", XtRString,
1204 sizeof(String), XtOffset(AppDataPtr, colorTell),
1205 XtRString, COLOR_TELL },
1206 { "colorChallenge", "colorChallenge", XtRString,
1207 sizeof(String), XtOffset(AppDataPtr, colorChallenge),
1208 XtRString, COLOR_CHALLENGE },
1209 { "colorRequest", "colorRequest", XtRString,
1210 sizeof(String), XtOffset(AppDataPtr, colorRequest),
1211 XtRString, COLOR_REQUEST },
1212 { "colorSeek", "colorSeek", XtRString,
1213 sizeof(String), XtOffset(AppDataPtr, colorSeek),
1214 XtRString, COLOR_SEEK },
1215 { "colorNormal", "colorNormal", XtRString,
1216 sizeof(String), XtOffset(AppDataPtr, colorNormal),
1217 XtRString, COLOR_NORMAL },
1218 { "soundProgram", "soundProgram", XtRString,
1219 sizeof(String), XtOffset(AppDataPtr, soundProgram),
1220 XtRString, "play" },
1221 { "soundShout", "soundShout", XtRString,
1222 sizeof(String), XtOffset(AppDataPtr, soundShout),
1224 { "soundSShout", "soundSShout", XtRString,
1225 sizeof(String), XtOffset(AppDataPtr, soundSShout),
1227 { "soundChannel1", "soundChannel1", XtRString,
1228 sizeof(String), XtOffset(AppDataPtr, soundChannel1),
1230 { "soundChannel", "soundChannel", XtRString,
1231 sizeof(String), XtOffset(AppDataPtr, soundChannel),
1233 { "soundKibitz", "soundKibitz", XtRString,
1234 sizeof(String), XtOffset(AppDataPtr, soundKibitz),
1236 { "soundTell", "soundTell", XtRString,
1237 sizeof(String), XtOffset(AppDataPtr, soundTell),
1239 { "soundChallenge", "soundChallenge", XtRString,
1240 sizeof(String), XtOffset(AppDataPtr, soundChallenge),
1242 { "soundRequest", "soundRequest", XtRString,
1243 sizeof(String), XtOffset(AppDataPtr, soundRequest),
1245 { "soundSeek", "soundSeek", XtRString,
1246 sizeof(String), XtOffset(AppDataPtr, soundSeek),
1248 { "soundMove", "soundMove", XtRString,
1249 sizeof(String), XtOffset(AppDataPtr, soundMove),
1251 { "soundIcsWin", "soundIcsWin", XtRString,
1252 sizeof(String), XtOffset(AppDataPtr, soundIcsWin),
1254 { "soundIcsLoss", "soundIcsLoss", XtRString,
1255 sizeof(String), XtOffset(AppDataPtr, soundIcsLoss),
1257 { "soundIcsDraw", "soundIcsDraw", XtRString,
1258 sizeof(String), XtOffset(AppDataPtr, soundIcsDraw),
1260 { "soundIcsUnfinished", "soundIcsUnfinished", XtRString,
1261 sizeof(String), XtOffset(AppDataPtr, soundIcsUnfinished),
1263 { "soundIcsAlarm", "soundIcsAlarm", XtRString,
1264 sizeof(String), XtOffset(AppDataPtr, soundIcsAlarm),
1266 { "reuseFirst", "reuseFirst", XtRBoolean,
1267 sizeof(Boolean), XtOffset(AppDataPtr, reuseFirst),
1268 XtRImmediate, (XtPointer) True },
1269 { "reuseSecond", "reuseSecond", XtRBoolean,
1270 sizeof(Boolean), XtOffset(AppDataPtr, reuseSecond),
1271 XtRImmediate, (XtPointer) True },
1272 { "animateDragging", "animateDragging", XtRBoolean,
1273 sizeof(Boolean), XtOffset(AppDataPtr, animateDragging),
1274 XtRImmediate, (XtPointer) True },
1275 { "animateMoving", "animateMoving", XtRBoolean,
1276 sizeof(Boolean), XtOffset(AppDataPtr, animate),
1277 XtRImmediate, (XtPointer) True },
1278 { "animateSpeed", "animateSpeed", XtRInt,
1279 sizeof(int), XtOffset(AppDataPtr, animSpeed),
1280 XtRImmediate, (XtPointer)10 },
1281 { "popupExitMessage", "popupExitMessage", XtRBoolean,
1282 sizeof(Boolean), XtOffset(AppDataPtr, popupExitMessage),
1283 XtRImmediate, (XtPointer) True },
1284 { "popupMoveErrors", "popupMoveErrors", XtRBoolean,
1285 sizeof(Boolean), XtOffset(AppDataPtr, popupMoveErrors),
1286 XtRImmediate, (XtPointer) False },
1287 { "fontSizeTolerance", "fontSizeTolerance", XtRInt,
1288 sizeof(int), XtOffset(AppDataPtr, fontSizeTolerance),
1289 XtRImmediate, (XtPointer)4 },
1290 { "initialMode", "initialMode", XtRString,
1291 sizeof(String), XtOffset(AppDataPtr, initialMode),
1292 XtRImmediate, (XtPointer) "" },
1293 { "variant", "variant", XtRString,
1294 sizeof(String), XtOffset(AppDataPtr, variant),
1295 XtRImmediate, (XtPointer) "normal" },
1296 { "firstProtocolVersion", "firstProtocolVersion", XtRInt,
1297 sizeof(int), XtOffset(AppDataPtr, firstProtocolVersion),
1298 XtRImmediate, (XtPointer)PROTOVER },
1299 { "secondProtocolVersion", "secondProtocolVersion", XtRInt,
1300 sizeof(int), XtOffset(AppDataPtr, secondProtocolVersion),
1301 XtRImmediate, (XtPointer)PROTOVER },
1302 { "showButtonBar", "showButtonBar", XtRBoolean,
1303 sizeof(Boolean), XtOffset(AppDataPtr, showButtonBar),
1304 XtRImmediate, (XtPointer) True },
1305 { "lowTimeWarningColor", "lowTimeWarningColor", XtRString,
1306 sizeof(String), XtOffset(AppDataPtr, lowTimeWarningColor),
1307 XtRString, COLOR_LOWTIMEWARNING },
1308 { "lowTimeWarning", "lowTimeWarning", XtRBoolean,
1309 sizeof(Boolean), XtOffset(AppDataPtr, lowTimeWarning),
1310 XtRImmediate, (XtPointer) False },
1311 {"icsEngineAnalyze", "icsEngineAnalyze", XtRBoolean, /* [DM] icsEngineAnalyze */
1312 sizeof(Boolean), XtOffset(AppDataPtr, icsEngineAnalyze),
1313 XtRImmediate, (XtPointer) False },
1314 { "firstScoreAbs", "firstScoreAbs", XtRBoolean,
1315 sizeof(Boolean), XtOffset(AppDataPtr, firstScoreIsAbsolute),
1316 XtRImmediate, (XtPointer) False },
1317 { "secondScoreAbs", "secondScoreAbs", XtRBoolean,
1318 sizeof(Boolean), XtOffset(AppDataPtr, secondScoreIsAbsolute),
1319 XtRImmediate, (XtPointer) False },
1320 { "pgnExtendedInfo", "pgnExtendedInfo", XtRBoolean,
1321 sizeof(Boolean), XtOffset(AppDataPtr, saveExtendedInfoInPGN),
1322 XtRImmediate, (XtPointer) False },
1323 { "hideThinkingFromHuman", "hideThinkingFromHuman", XtRBoolean,
1324 sizeof(Boolean), XtOffset(AppDataPtr, hideThinkingFromHuman),
1325 XtRImmediate, (XtPointer) True },
1326 { "adjudicateLossThreshold", "adjudicateLossThreshold", XtRInt,
1327 sizeof(int), XtOffset(AppDataPtr, adjudicateLossThreshold),
1328 XtRImmediate, (XtPointer) 0},
1329 { "pgnEventHeader", "pgnEventHeader", XtRString,
1330 sizeof(String), XtOffset(AppDataPtr, pgnEventHeader),
1331 XtRImmediate, (XtPointer) "Computer Chess Game" },
1332 { "defaultFrcPosition", "defaultFrcPositon", XtRInt,
1333 sizeof(int), XtOffset(AppDataPtr, defaultFrcPosition),
1334 XtRImmediate, (XtPointer) -1},
1335 { "gameListTags", "gameListTags", XtRString,
1336 sizeof(String), XtOffset(AppDataPtr, gameListTags),
1337 XtRImmediate, (XtPointer) GLT_DEFAULT_TAGS },
1339 // [HGM] 4.3.xx options
1340 { "boardWidth", "boardWidth", XtRInt,
1341 sizeof(int), XtOffset(AppDataPtr, NrFiles),
1342 XtRImmediate, (XtPointer) -1},
1343 { "boardHeight", "boardHeight", XtRInt,
1344 sizeof(int), XtOffset(AppDataPtr, NrRanks),
1345 XtRImmediate, (XtPointer) -1},
1346 { "matchPause", "matchPause", XtRInt,
1347 sizeof(int), XtOffset(AppDataPtr, matchPause),
1348 XtRImmediate, (XtPointer) 10000},
1349 { "holdingsSize", "holdingsSize", XtRInt,
1350 sizeof(int), XtOffset(AppDataPtr, holdingsSize),
1351 XtRImmediate, (XtPointer) -1},
1352 { "flipBlack", "flipBlack", XtRBoolean,
1353 sizeof(Boolean), XtOffset(AppDataPtr, upsideDown),
1354 XtRImmediate, (XtPointer) False},
1355 { "allWhite", "allWhite", XtRBoolean,
1356 sizeof(Boolean), XtOffset(AppDataPtr, allWhite),
1357 XtRImmediate, (XtPointer) False},
1358 { "pieceToCharTable", "pieceToCharTable", XtRString,
1359 sizeof(String), XtOffset(AppDataPtr, pieceToCharTable),
1360 XtRImmediate, (XtPointer) 0},
1361 { "alphaRank", "alphaRank", XtRBoolean,
1362 sizeof(Boolean), XtOffset(AppDataPtr, alphaRank),
1363 XtRImmediate, (XtPointer) False},
1364 { "testClaims", "testClaims", XtRBoolean,
1365 sizeof(Boolean), XtOffset(AppDataPtr, testClaims),
1366 XtRImmediate, (XtPointer) True},
1367 { "checkMates", "checkMates", XtRBoolean,
1368 sizeof(Boolean), XtOffset(AppDataPtr, checkMates),
1369 XtRImmediate, (XtPointer) True},
1370 { "materialDraws", "materialDraws", XtRBoolean,
1371 sizeof(Boolean), XtOffset(AppDataPtr, materialDraws),
1372 XtRImmediate, (XtPointer) True},
1373 { "trivialDraws", "trivialDraws", XtRBoolean,
1374 sizeof(Boolean), XtOffset(AppDataPtr, trivialDraws),
1375 XtRImmediate, (XtPointer) False},
1376 { "ruleMoves", "ruleMoves", XtRInt,
1377 sizeof(int), XtOffset(AppDataPtr, ruleMoves),
1378 XtRImmediate, (XtPointer) 51},
1379 { "repeatsToDraw", "repeatsToDraw", XtRInt,
1380 sizeof(int), XtOffset(AppDataPtr, drawRepeats),
1381 XtRImmediate, (XtPointer) 6},
1382 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1383 sizeof(int), XtOffset(AppDataPtr, engineComments),
1384 XtRImmediate, (XtPointer) 1},
1385 { "userName", "userName", XtRString,
1386 sizeof(int), XtOffset(AppDataPtr, userName),
1387 XtRImmediate, (XtPointer) 0},
1388 { "autoKibitz", "autoKibitz", XtRBoolean,
1389 sizeof(Boolean), XtOffset(AppDataPtr, autoKibitz),
1390 XtRImmediate, (XtPointer) False},
1391 { "firstTimeOdds", "firstTimeOdds", XtRInt,
1392 sizeof(int), XtOffset(AppDataPtr, firstTimeOdds),
1393 XtRImmediate, (XtPointer) 1},
1394 { "secondTimeOdds", "secondTimeOdds", XtRInt,
1395 sizeof(int), XtOffset(AppDataPtr, secondTimeOdds),
1396 XtRImmediate, (XtPointer) 1},
1397 { "timeOddsMode", "timeOddsMode", XtRInt,
1398 sizeof(int), XtOffset(AppDataPtr, timeOddsMode),
1399 XtRImmediate, (XtPointer) 0},
1400 { "firstAccumulateTC", "firstAccumulateTC", XtRInt,
1401 sizeof(int), XtOffset(AppDataPtr, firstAccumulateTC),
1402 XtRImmediate, (XtPointer) 1},
1403 { "secondAccumulateTC", "secondAccumulateTC", XtRInt,
1404 sizeof(int), XtOffset(AppDataPtr, secondAccumulateTC),
1405 XtRImmediate, (XtPointer) 1},
1406 { "firstNPS", "firstNPS", XtRInt,
1407 sizeof(int), XtOffset(AppDataPtr, firstNPS),
1408 XtRImmediate, (XtPointer) -1},
1409 { "secondNPS", "secondNPS", XtRInt,
1410 sizeof(int), XtOffset(AppDataPtr, secondNPS),
1411 XtRImmediate, (XtPointer) -1},
1412 { "serverMoves", "serverMoves", XtRString,
1413 sizeof(String), XtOffset(AppDataPtr, serverMovesName),
1414 XtRImmediate, (XtPointer) 0},
1415 { "serverPause", "serverPause", XtRInt,
1416 sizeof(int), XtOffset(AppDataPtr, serverPause),
1417 XtRImmediate, (XtPointer) 0},
1418 { "suppressLoadMoves", "suppressLoadMoves", XtRBoolean,
1419 sizeof(Boolean), XtOffset(AppDataPtr, suppressLoadMoves),
1420 XtRImmediate, (XtPointer) False},
1421 { "userName", "userName", XtRString,
1422 sizeof(String), XtOffset(AppDataPtr, userName),
1423 XtRImmediate, (XtPointer) 0},
1424 { "egtFormats", "egtFormats", XtRString,
1425 sizeof(String), XtOffset(AppDataPtr, egtFormats),
1426 XtRImmediate, (XtPointer) 0},
1427 { "rewindIndex", "rewindIndex", XtRInt,
1428 sizeof(int), XtOffset(AppDataPtr, rewindIndex),
1429 XtRImmediate, (XtPointer) 0},
1430 { "sameColorGames", "sameColorGames", XtRInt,
1431 sizeof(int), XtOffset(AppDataPtr, sameColorGames),
1432 XtRImmediate, (XtPointer) 0},
1433 { "smpCores", "smpCores", XtRInt,
1434 sizeof(int), XtOffset(AppDataPtr, smpCores),
1435 XtRImmediate, (XtPointer) 1},
1436 { "niceEngines", "niceEngines", XtRInt,
1437 sizeof(int), XtOffset(AppDataPtr, niceEngines),
1438 XtRImmediate, (XtPointer) 0},
1439 { "nameOfDebugFile", "nameOfDebugFile", XtRString,
1440 sizeof(String), XtOffset(AppDataPtr, nameOfDebugFile),
1441 XtRImmediate, (XtPointer) "xboard.debug"},
1442 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1443 sizeof(int), XtOffset(AppDataPtr, engineComments),
1444 XtRImmediate, (XtPointer) 0},
1445 { "noGUI", "noGUI", XtRBoolean,
1446 sizeof(Boolean), XtOffset(AppDataPtr, noGUI),
1447 XtRImmediate, (XtPointer) 0},
1448 { "firstOptions", "firstOptions", XtRString,
1449 sizeof(String), XtOffset(AppDataPtr, firstOptions),
1450 XtRImmediate, (XtPointer) "" },
1451 { "secondOptions", "secondOptions", XtRString,
1452 sizeof(String), XtOffset(AppDataPtr, secondOptions),
1453 XtRImmediate, (XtPointer) "" },
1454 { "firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XtRString,
1455 sizeof(String), XtOffset(AppDataPtr, fenOverride1),
1456 XtRImmediate, (XtPointer) 0 },
1457 { "secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XtRString,
1458 sizeof(String), XtOffset(AppDataPtr, fenOverride2),
1459 XtRImmediate, (XtPointer) 0 },
1461 // [HGM] Winboard_x UCI options
1462 { "firstIsUCI", "firstIsUCI", XtRBoolean,
1463 sizeof(Boolean), XtOffset(AppDataPtr, firstIsUCI),
1464 XtRImmediate, (XtPointer) False},
1465 { "secondIsUCI", "secondIsUCI", XtRBoolean,
1466 sizeof(Boolean), XtOffset(AppDataPtr, secondIsUCI),
1467 XtRImmediate, (XtPointer) False},
1468 { "firstHasOwnBookUCI", "firstHasOwnBookUCI", XtRBoolean,
1469 sizeof(Boolean), XtOffset(AppDataPtr, firstHasOwnBookUCI),
1470 XtRImmediate, (XtPointer) True},
1471 { "secondHasOwnBookUCI", "secondHasOwnBookUCI", XtRBoolean,
1472 sizeof(Boolean), XtOffset(AppDataPtr, secondHasOwnBookUCI),
1473 XtRImmediate, (XtPointer) True},
1474 { "usePolyglotBook", "usePolyglotBook", XtRBoolean,
1475 sizeof(Boolean), XtOffset(AppDataPtr, usePolyglotBook),
1476 XtRImmediate, (XtPointer) False},
1477 { "defaultHashSize", "defaultHashSize", XtRInt,
1478 sizeof(int), XtOffset(AppDataPtr, defaultHashSize),
1479 XtRImmediate, (XtPointer) 64},
1480 { "defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XtRInt,
1481 sizeof(int), XtOffset(AppDataPtr, defaultCacheSizeEGTB),
1482 XtRImmediate, (XtPointer) 4},
1483 { "polyglotDir", "polyglotDir", XtRString,
1484 sizeof(String), XtOffset(AppDataPtr, polyglotDir),
1485 XtRImmediate, (XtPointer) "." },
1486 { "polyglotBook", "polyglotBook", XtRString,
1487 sizeof(String), XtOffset(AppDataPtr, polyglotBook),
1488 XtRImmediate, (XtPointer) "" },
1489 { "defaultPathEGTB", "defaultPathEGTB", XtRString,
1490 sizeof(String), XtOffset(AppDataPtr, defaultPathEGTB),
1491 XtRImmediate, (XtPointer) "/usr/local/share/egtb"},
1492 { "delayBeforeQuit", "delayBeforeQuit", XtRInt,
1493 sizeof(int), XtOffset(AppDataPtr, delayBeforeQuit),
1494 XtRImmediate, (XtPointer) 0},
1495 { "delayAfterQuit", "delayAfterQuit", XtRInt,
1496 sizeof(int), XtOffset(AppDataPtr, delayAfterQuit),
1497 XtRImmediate, (XtPointer) 0},
1500 XrmOptionDescRec shellOptions[] = {
1501 { "-whitePieceColor", "whitePieceColor", XrmoptionSepArg, NULL },
1502 { "-blackPieceColor", "blackPieceColor", XrmoptionSepArg, NULL },
1503 { "-lightSquareColor", "lightSquareColor", XrmoptionSepArg, NULL },
1504 { "-darkSquareColor", "darkSquareColor", XrmoptionSepArg, NULL },
1505 { "-highlightSquareColor", "highlightSquareColor", XrmoptionSepArg, NULL },
1506 { "-premoveHighlightColor", "premoveHighlightColor", XrmoptionSepArg,NULL},
1507 { "-movesPerSession", "movesPerSession", XrmoptionSepArg, NULL },
1508 { "-mps", "movesPerSession", XrmoptionSepArg, NULL },
1509 { "-timeIncrement", "timeIncrement", XrmoptionSepArg, NULL },
1510 { "-inc", "timeIncrement", XrmoptionSepArg, NULL },
1511 { "-initString", "initString", XrmoptionSepArg, NULL },
1512 { "-firstInitString", "initString", XrmoptionSepArg, NULL },
1513 { "-secondInitString", "secondInitString", XrmoptionSepArg, NULL },
1514 { "-firstComputerString", "firstComputerString", XrmoptionSepArg, NULL },
1515 { "-secondComputerString", "secondComputerString", XrmoptionSepArg, NULL },
1516 { "-firstChessProgram", "firstChessProgram", XrmoptionSepArg, NULL },
1517 { "-fcp", "firstChessProgram", XrmoptionSepArg, NULL },
1518 { "-secondChessProgram", "secondChessProgram", XrmoptionSepArg, NULL },
1519 { "-scp", "secondChessProgram", XrmoptionSepArg, NULL },
1520 { "-firstPlaysBlack", "firstPlaysBlack", XrmoptionSepArg, NULL },
1521 { "-fb", "firstPlaysBlack", XrmoptionNoArg, "True" },
1522 { "-xfb", "firstPlaysBlack", XrmoptionNoArg, "False" },
1523 { "-noChessProgram", "noChessProgram", XrmoptionSepArg, NULL },
1524 { "-ncp", "noChessProgram", XrmoptionNoArg, "True" },
1525 { "-xncp", "noChessProgram", XrmoptionNoArg, "False" },
1526 { "-firstHost", "firstHost", XrmoptionSepArg, NULL },
1527 { "-fh", "firstHost", XrmoptionSepArg, NULL },
1528 { "-secondHost", "secondHost", XrmoptionSepArg, NULL },
1529 { "-sh", "secondHost", XrmoptionSepArg, NULL },
1530 { "-firstDirectory", "firstDirectory", XrmoptionSepArg, NULL },
1531 { "-fd", "firstDirectory", XrmoptionSepArg, NULL },
1532 { "-secondDirectory", "secondDirectory", XrmoptionSepArg, NULL },
1533 { "-sd", "secondDirectory", XrmoptionSepArg, NULL },
1534 { "-bitmapDirectory", "bitmapDirectory", XrmoptionSepArg, NULL },
1535 { "-bm", "bitmapDirectory", XrmoptionSepArg, NULL },
1536 { "-remoteShell", "remoteShell", XrmoptionSepArg, NULL },
1537 { "-rsh", "remoteShell", XrmoptionSepArg, NULL },
1538 { "-remoteUser", "remoteUser", XrmoptionSepArg, NULL },
1539 { "-ruser", "remoteUser", XrmoptionSepArg, NULL },
1540 { "-timeDelay", "timeDelay", XrmoptionSepArg, NULL },
1541 { "-td", "timeDelay", XrmoptionSepArg, NULL },
1542 { "-timeControl", "timeControl", XrmoptionSepArg, NULL },
1543 { "-tc", "timeControl", XrmoptionSepArg, NULL },
1544 { "-internetChessServerMode", "internetChessServerMode",
1545 XrmoptionSepArg, NULL },
1546 { "-ics", "internetChessServerMode", XrmoptionNoArg, "True" },
1547 { "-xics", "internetChessServerMode", XrmoptionNoArg, "False" },
1548 { "-internetChessServerHost", "internetChessServerHost",
1549 XrmoptionSepArg, NULL },
1550 { "-icshost", "internetChessServerHost", XrmoptionSepArg, NULL },
1551 { "-internetChessServerPort", "internetChessServerPort",
1552 XrmoptionSepArg, NULL },
1553 { "-icsport", "internetChessServerPort", XrmoptionSepArg, NULL },
1554 { "-internetChessServerCommPort", "internetChessServerCommPort",
1555 XrmoptionSepArg, NULL },
1556 { "-icscomm", "internetChessServerCommPort", XrmoptionSepArg, NULL },
1557 { "-internetChessServerLogonScript", "internetChessServerLogonScript",
1558 XrmoptionSepArg, NULL },
1559 { "-icslogon", "internetChessServerLogonScript", XrmoptionSepArg, NULL },
1560 { "-internetChessServerHelper", "internetChessServerHelper",
1561 XrmoptionSepArg, NULL },
1562 { "-icshelper", "internetChessServerHelper", XrmoptionSepArg, NULL },
1563 { "-internetChessServerInputBox", "internetChessServerInputBox",
1564 XrmoptionSepArg, NULL },
1565 { "-icsinput", "internetChessServerInputBox", XrmoptionNoArg, "True" },
1566 { "-xicsinput", "internetChessServerInputBox", XrmoptionNoArg, "False" },
1567 { "-icsAlarm", "icsAlarm", XrmoptionSepArg, NULL },
1568 { "-alarm", "icsAlarm", XrmoptionNoArg, "True" },
1569 { "-xalarm", "icsAlarm", XrmoptionNoArg, "False" },
1570 { "-icsAlarmTime", "icsAlarmTime", XrmoptionSepArg, NULL },
1571 { "-useTelnet", "useTelnet", XrmoptionSepArg, NULL },
1572 { "-telnet", "useTelnet", XrmoptionNoArg, "True" },
1573 { "-xtelnet", "useTelnet", XrmoptionNoArg, "False" },
1574 { "-telnetProgram", "telnetProgram", XrmoptionSepArg, NULL },
1575 { "-gateway", "gateway", XrmoptionSepArg, NULL },
1576 { "-loadGameFile", "loadGameFile", XrmoptionSepArg, NULL },
1577 { "-lgf", "loadGameFile", XrmoptionSepArg, NULL },
1578 { "-loadGameIndex", "loadGameIndex", XrmoptionSepArg, NULL },
1579 { "-lgi", "loadGameIndex", XrmoptionSepArg, NULL },
1580 { "-saveGameFile", "saveGameFile", XrmoptionSepArg, NULL },
1581 { "-sgf", "saveGameFile", XrmoptionSepArg, NULL },
1582 { "-autoSaveGames", "autoSaveGames", XrmoptionSepArg, NULL },
1583 { "-autosave", "autoSaveGames", XrmoptionNoArg, "True" },
1584 { "-xautosave", "autoSaveGames", XrmoptionNoArg, "False" },
1585 { "-autoRaiseBoard", "autoRaiseBoard", XrmoptionSepArg, NULL },
1586 { "-autoraise", "autoRaiseBoard", XrmoptionNoArg, "True" },
1587 { "-xautoraise", "autoRaiseBoard", XrmoptionNoArg, "False" },
1588 { "-blindfold", "blindfold", XrmoptionSepArg, NULL },
1589 { "-blind", "blindfold", XrmoptionNoArg, "True" },
1590 { "-xblind", "blindfold", XrmoptionNoArg, "False" },
1591 { "-loadPositionFile", "loadPositionFile", XrmoptionSepArg, NULL },
1592 { "-lpf", "loadPositionFile", XrmoptionSepArg, NULL },
1593 { "-loadPositionIndex", "loadPositionIndex", XrmoptionSepArg, NULL },
1594 { "-lpi", "loadPositionIndex", XrmoptionSepArg, NULL },
1595 { "-savePositionFile", "savePositionFile", XrmoptionSepArg, NULL },
1596 { "-spf", "savePositionFile", XrmoptionSepArg, NULL },
1597 { "-matchMode", "matchMode", XrmoptionSepArg, NULL },
1598 { "-mm", "matchMode", XrmoptionNoArg, "True" },
1599 { "-xmm", "matchMode", XrmoptionNoArg, "False" },
1600 { "-matchGames", "matchGames", XrmoptionSepArg, NULL },
1601 { "-mg", "matchGames", XrmoptionSepArg, NULL },
1602 { "-monoMode", "monoMode", XrmoptionSepArg, NULL },
1603 { "-mono", "monoMode", XrmoptionNoArg, "True" },
1604 { "-xmono", "monoMode", XrmoptionNoArg, "False" },
1605 { "-debugMode", "debugMode", XrmoptionSepArg, NULL },
1606 { "-debug", "debugMode", XrmoptionNoArg, "True" },
1607 { "-xdebug", "debugMode", XrmoptionNoArg, "False" },
1608 { "-clockMode", "clockMode", XrmoptionSepArg, NULL },
1609 { "-clock", "clockMode", XrmoptionNoArg, "True" },
1610 { "-xclock", "clockMode", XrmoptionNoArg, "False" },
1611 { "-boardSize", "boardSize", XrmoptionSepArg, NULL },
1612 { "-size", "boardSize", XrmoptionSepArg, NULL },
1613 { "-searchTime", "searchTime", XrmoptionSepArg, NULL },
1614 { "-st", "searchTime", XrmoptionSepArg, NULL },
1615 { "-searchDepth", "searchDepth", XrmoptionSepArg, NULL },
1616 { "-depth", "searchDepth", XrmoptionSepArg, NULL },
1617 { "-showCoords", "showCoords", XrmoptionSepArg, NULL },
1618 { "-coords", "showCoords", XrmoptionNoArg, "True" },
1619 { "-xcoords", "showCoords", XrmoptionNoArg, "False" },
1621 { "-showJail", "showJail", XrmoptionSepArg, NULL },
1622 { "-jail", "showJail", XrmoptionNoArg, "1" },
1623 { "-sidejail", "showJail", XrmoptionNoArg, "2" },
1624 { "-xjail", "showJail", XrmoptionNoArg, "0" },
1626 { "-showThinking", "showThinking", XrmoptionSepArg, NULL },
1627 { "-thinking", "showThinking", XrmoptionNoArg, "True" },
1628 { "-xthinking", "showThinking", XrmoptionNoArg, "False" },
1629 { "-ponderNextMove", "ponderNextMove", XrmoptionSepArg, NULL },
1630 { "-ponder", "ponderNextMove", XrmoptionNoArg, "True" },
1631 { "-xponder", "ponderNextMove", XrmoptionNoArg, "False" },
1632 { "-periodicUpdates", "periodicUpdates", XrmoptionSepArg, NULL },
1633 { "-periodic", "periodicUpdates", XrmoptionNoArg, "True" },
1634 { "-xperiodic", "periodicUpdates", XrmoptionNoArg, "False" },
1635 { "-clockFont", "clockFont", XrmoptionSepArg, NULL },
1636 { "-coordFont", "coordFont", XrmoptionSepArg, NULL },
1637 { "-font", "font", XrmoptionSepArg, NULL },
1638 { "-ringBellAfterMoves", "ringBellAfterMoves", XrmoptionSepArg, NULL },
1639 { "-bell", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1640 { "-xbell", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1641 { "-movesound", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1642 { "-xmovesound", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1643 { "-autoCallFlag", "autoCallFlag", XrmoptionSepArg, NULL },
1644 { "-autoflag", "autoCallFlag", XrmoptionNoArg, "True" },
1645 { "-xautoflag", "autoCallFlag", XrmoptionNoArg, "False" },
1646 { "-autoFlipView", "autoFlipView", XrmoptionSepArg, NULL },
1647 { "-autoflip", "autoFlipView", XrmoptionNoArg, "True" },
1648 { "-xautoflip", "autoFlipView", XrmoptionNoArg, "False" },
1649 { "-autoObserve", "autoObserve", XrmoptionSepArg, NULL },
1650 { "-autobs", "autoObserve", XrmoptionNoArg, "True" },
1651 { "-xautobs", "autoObserve", XrmoptionNoArg, "False" },
1652 { "-autoComment", "autoComment", XrmoptionSepArg, NULL },
1653 { "-autocomm", "autoComment", XrmoptionNoArg, "True" },
1654 { "-xautocomm", "autoComment", XrmoptionNoArg, "False" },
1655 { "-getMoveList", "getMoveList", XrmoptionSepArg, NULL },
1656 { "-moves", "getMoveList", XrmoptionNoArg, "True" },
1657 { "-xmoves", "getMoveList", XrmoptionNoArg, "False" },
1659 { "-highlightDragging", "highlightDragging", XrmoptionSepArg, NULL },
1660 { "-highdrag", "highlightDragging", XrmoptionNoArg, "True" },
1661 { "-xhighdrag", "highlightDragging", XrmoptionNoArg, "False" },
1663 { "-highlightLastMove", "highlightLastMove", XrmoptionSepArg, NULL },
1664 { "-highlight", "highlightLastMove", XrmoptionNoArg, "True" },
1665 { "-xhighlight", "highlightLastMove", XrmoptionNoArg, "False" },
1666 { "-premove", "premove", XrmoptionSepArg, NULL },
1667 { "-pre", "premove", XrmoptionNoArg, "True" },
1668 { "-xpre", "premove", XrmoptionNoArg, "False" },
1669 { "-testLegality", "testLegality", XrmoptionSepArg, NULL },
1670 { "-legal", "testLegality", XrmoptionNoArg, "True" },
1671 { "-xlegal", "testLegality", XrmoptionNoArg, "False" },
1672 { "-flipView", "flipView", XrmoptionSepArg, NULL },
1673 { "-flip", "flipView", XrmoptionNoArg, "True" },
1674 { "-xflip", "flipView", XrmoptionNoArg, "False" },
1675 { "-cmail", "cmailGameName", XrmoptionSepArg, NULL },
1676 { "-alwaysPromoteToQueen", "alwaysPromoteToQueen",
1677 XrmoptionSepArg, NULL },
1678 { "-queen", "alwaysPromoteToQueen", XrmoptionNoArg, "True" },
1679 { "-xqueen", "alwaysPromoteToQueen", XrmoptionNoArg, "False" },
1680 { "-oldSaveStyle", "oldSaveStyle", XrmoptionSepArg, NULL },
1681 { "-oldsave", "oldSaveStyle", XrmoptionNoArg, "True" },
1682 { "-xoldsave", "oldSaveStyle", XrmoptionNoArg, "False" },
1683 { "-quietPlay", "quietPlay", XrmoptionSepArg, NULL },
1684 { "-quiet", "quietPlay", XrmoptionNoArg, "True" },
1685 { "-xquiet", "quietPlay", XrmoptionNoArg, "False" },
1686 { "-titleInWindow", "titleInWindow", XrmoptionSepArg, NULL },
1687 { "-title", "titleInWindow", XrmoptionNoArg, "True" },
1688 { "-xtitle", "titleInWindow", XrmoptionNoArg, "False" },
1690 { "-zippyTalk", "zippyTalk", XrmoptionSepArg, NULL },
1691 { "-zt", "zippyTalk", XrmoptionNoArg, "True" },
1692 { "-xzt", "zippyTalk", XrmoptionNoArg, "False" },
1693 { "-zippyPlay", "zippyPlay", XrmoptionSepArg, NULL },
1694 { "-zp", "zippyPlay", XrmoptionNoArg, "True" },
1695 { "-xzp", "zippyPlay", XrmoptionNoArg, "False" },
1696 { "-zippyLines", "zippyLines", XrmoptionSepArg, NULL },
1697 { "-zippyPinhead", "zippyPinhead", XrmoptionSepArg, NULL },
1698 { "-zippyPassword", "zippyPassword", XrmoptionSepArg, NULL },
1699 { "-zippyPassword2", "zippyPassword2", XrmoptionSepArg, NULL },
1700 { "-zippyWrongPassword", "zippyWrongPassword", XrmoptionSepArg, NULL },
1701 { "-zippyAcceptOnly", "zippyAcceptOnly", XrmoptionSepArg, NULL },
1702 { "-zippyUseI", "zippyUseI", XrmoptionSepArg, NULL },
1703 { "-zui", "zippyUseI", XrmoptionNoArg, "True" },
1704 { "-xzui", "zippyUseI", XrmoptionNoArg, "False" },
1705 { "-zippyBughouse", "zippyBughouse", XrmoptionSepArg, NULL },
1706 { "-zippyNoplayCrafty", "zippyNoplayCrafty", XrmoptionSepArg, NULL },
1707 { "-znc", "zippyNoplayCrafty", XrmoptionNoArg, "True" },
1708 { "-xznc", "zippyNoplayCrafty", XrmoptionNoArg, "False" },
1709 { "-zippyGameEnd", "zippyGameEnd", XrmoptionSepArg, NULL },
1710 { "-zippyGameStart", "zippyGameStart", XrmoptionSepArg, NULL },
1711 { "-zippyAdjourn", "zippyAdjourn", XrmoptionSepArg, NULL },
1712 { "-zadj", "zippyAdjourn", XrmoptionNoArg, "True" },
1713 { "-xzadj", "zippyAdjourn", XrmoptionNoArg, "False" },
1714 { "-zippyAbort", "zippyAbort", XrmoptionSepArg, NULL },
1715 { "-zab", "zippyAbort", XrmoptionNoArg, "True" },
1716 { "-xzab", "zippyAbort", XrmoptionNoArg, "False" },
1717 { "-zippyVariants", "zippyVariants", XrmoptionSepArg, NULL },
1718 { "-zippyMaxGames", "zippyMaxGames", XrmoptionSepArg, NULL },
1719 { "-zippyReplayTimeout", "zippyReplayTimeout", XrmoptionSepArg, NULL },
1720 { "-zippyShortGame", "zippyShortGame", XrmoptionSepArg, NULL },
1722 { "-flashCount", "flashCount", XrmoptionSepArg, NULL },
1723 { "-flash", "flashCount", XrmoptionNoArg, "3" },
1724 { "-xflash", "flashCount", XrmoptionNoArg, "0" },
1725 { "-flashRate", "flashRate", XrmoptionSepArg, NULL },
1726 { "-pixmapDirectory", "pixmapDirectory", XrmoptionSepArg, NULL },
1727 { "-msLoginDelay", "msLoginDelay", XrmoptionSepArg, NULL },
1728 { "-pixmap", "pixmapDirectory", XrmoptionSepArg, NULL },
1729 { "-colorizeMessages", "colorizeMessages", XrmoptionSepArg, NULL },
1730 { "-colorize", "colorizeMessages", XrmoptionNoArg, "True" },
1731 { "-xcolorize", "colorizeMessages", XrmoptionNoArg, "False" },
1732 { "-colorShout", "colorShout", XrmoptionSepArg, NULL },
1733 { "-colorSShout", "colorSShout", XrmoptionSepArg, NULL },
1734 { "-colorCShout", "colorSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1735 { "-colorChannel1", "colorChannel1", XrmoptionSepArg, NULL },
1736 { "-colorChannel", "colorChannel", XrmoptionSepArg, NULL },
1737 { "-colorKibitz", "colorKibitz", XrmoptionSepArg, NULL },
1738 { "-colorTell", "colorTell", XrmoptionSepArg, NULL },
1739 { "-colorChallenge", "colorChallenge", XrmoptionSepArg, NULL },
1740 { "-colorRequest", "colorRequest", XrmoptionSepArg, NULL },
1741 { "-colorSeek", "colorSeek", XrmoptionSepArg, NULL },
1742 { "-colorNormal", "colorNormal", XrmoptionSepArg, NULL },
1743 { "-soundProgram", "soundProgram", XrmoptionSepArg, NULL },
1744 { "-soundShout", "soundShout", XrmoptionSepArg, NULL },
1745 { "-soundSShout", "soundSShout", XrmoptionSepArg, NULL },
1746 { "-soundCShout", "soundSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1747 { "-soundChannel1", "soundChannel1", XrmoptionSepArg, NULL },
1748 { "-soundChannel", "soundChannel", XrmoptionSepArg, NULL },
1749 { "-soundKibitz", "soundKibitz", XrmoptionSepArg, NULL },
1750 { "-soundTell", "soundTell", XrmoptionSepArg, NULL },
1751 { "-soundChallenge", "soundChallenge", XrmoptionSepArg, NULL },
1752 { "-soundRequest", "soundRequest", XrmoptionSepArg, NULL },
1753 { "-soundSeek", "soundSeek", XrmoptionSepArg, NULL },
1754 { "-soundMove", "soundMove", XrmoptionSepArg, NULL },
1755 { "-soundIcsWin", "soundIcsWin", XrmoptionSepArg, NULL },
1756 { "-soundIcsLoss", "soundIcsLoss", XrmoptionSepArg, NULL },
1757 { "-soundIcsDraw", "soundIcsDraw", XrmoptionSepArg, NULL },
1758 { "-soundIcsUnfinished", "soundIcsUnfinished", XrmoptionSepArg, NULL },
1759 { "-soundIcsAlarm", "soundIcsAlarm", XrmoptionSepArg, NULL },
1760 { "-reuseFirst", "reuseFirst", XrmoptionSepArg, NULL },
1761 { "-reuseChessPrograms", "reuseFirst", XrmoptionSepArg, NULL }, /*compat*/
1762 { "-reuse", "reuseFirst", XrmoptionNoArg, "True" },
1763 { "-xreuse", "reuseFirst", XrmoptionNoArg, "False" },
1764 { "-reuseSecond", "reuseSecond", XrmoptionSepArg, NULL },
1765 { "-reuse2", "reuseSecond", XrmoptionNoArg, "True" },
1766 { "-xreuse2", "reuseSecond", XrmoptionNoArg, "False" },
1767 { "-animateMoving", "animateMoving", XrmoptionSepArg, NULL },
1768 { "-animate", "animateMoving", XrmoptionNoArg, "True" },
1769 { "-xanimate", "animateMoving", XrmoptionNoArg, "False" },
1770 { "-animateDragging", "animateDragging", XrmoptionSepArg, NULL },
1771 { "-drag", "animateDragging", XrmoptionNoArg, "True" },
1772 { "-xdrag", "animateDragging", XrmoptionNoArg, "False" },
1773 { "-animateSpeed", "animateSpeed", XrmoptionSepArg, NULL },
1774 { "-popupExitMessage", "popupExitMessage", XrmoptionSepArg, NULL },
1775 { "-exit", "popupExitMessage", XrmoptionNoArg, "True" },
1776 { "-xexit", "popupExitMessage", XrmoptionNoArg, "False" },
1777 { "-popupMoveErrors", "popupMoveErrors", XrmoptionSepArg, NULL },
1778 { "-popup", "popupMoveErrors", XrmoptionNoArg, "True" },
1779 { "-xpopup", "popupMoveErrors", XrmoptionNoArg, "False" },
1780 { "-fontSizeTolerance", "fontSizeTolerance", XrmoptionSepArg, NULL },
1781 { "-initialMode", "initialMode", XrmoptionSepArg, NULL },
1782 { "-mode", "initialMode", XrmoptionSepArg, NULL },
1783 { "-variant", "variant", XrmoptionSepArg, NULL },
1784 { "-firstProtocolVersion", "firstProtocolVersion", XrmoptionSepArg, NULL },
1785 { "-secondProtocolVersion","secondProtocolVersion",XrmoptionSepArg, NULL },
1786 { "-showButtonBar", "showButtonBar", XrmoptionSepArg, NULL },
1787 { "-buttons", "showButtonBar", XrmoptionNoArg, "True" },
1788 { "-xbuttons", "showButtonBar", XrmoptionNoArg, "False" },
1789 { "-lowTimeWarningColor", "lowTimeWarningColor", XrmoptionSepArg, NULL },
1790 { "-lowTimeWarning", "lowTimeWarning", XrmoptionSepArg, NULL },
1791 /* [AS,HR] New features */
1792 { "-firstScoreAbs", "firstScoreAbs", XrmoptionSepArg, NULL },
1793 { "-secondScoreAbs", "secondScoreAbs", XrmoptionSepArg, NULL },
1794 { "-pgnExtendedInfo", "pgnExtendedInfo", XrmoptionSepArg, NULL },
1795 { "-hideThinkingFromHuman", "hideThinkingFromHuman", XrmoptionSepArg, NULL },
1796 { "-adjudicateLossThreshold", "adjudicateLossThreshold", XrmoptionSepArg, NULL },
1797 { "-pgnEventHeader", "pgnEventHeader", XrmoptionSepArg, NULL },
1798 { "-firstIsUCI", "firstIsUCI", XrmoptionSepArg, NULL },
1799 { "-secondIsUCI", "secondIsUCI", XrmoptionSepArg, NULL },
1800 { "-fUCI", "firstIsUCI", XrmoptionNoArg, "True" },
1801 { "-sUCI", "secondIsUCI", XrmoptionNoArg, "True" },
1802 { "-firstHasOwnBookUCI", "firstHasOwnBookUCI", XrmoptionSepArg, NULL },
1803 { "-secondHasOwnBookUCI", "secondHasOwnBookUCI", XrmoptionSepArg, NULL },
1804 { "-fNoOwnBookUCI", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1805 { "-sNoOwnBookUCI", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1806 { "-firstXBook", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1807 { "-secondXBook", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1808 { "-polyglotDir", "polyglotDir", XrmoptionSepArg, NULL },
1809 { "-usePolyglotBook", "usePolyglotBook", XrmoptionSepArg, NULL },
1810 { "-polyglotBook", "polyglotBook", XrmoptionSepArg, NULL },
1811 { "-defaultHashSize", "defaultHashSize", XrmoptionSepArg, NULL },
1812 { "-defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XrmoptionSepArg, NULL },
1813 { "-defaultPathEGTB", "defaultPathEGTB", XrmoptionSepArg, NULL },
1814 { "-defaultFrcPosition", "defaultFrcPosition", XrmoptionSepArg, NULL },
1815 { "-gameListTags", "gameListTags", XrmoptionSepArg, NULL },
1816 // [HGM] I am sure AS added many more options, but we have to fish them out, from the list in winboard.c
1818 /* [HGM,HR] User-selectable board size */
1819 { "-boardWidth", "boardWidth", XrmoptionSepArg, NULL },
1820 { "-boardHeight", "boardHeight", XrmoptionSepArg, NULL },
1821 { "-matchPause", "matchPause", XrmoptionSepArg, NULL },
1823 /* [HGM] new arguments of 4.3.xx. All except first three are back-end options, which should work immediately */
1824 { "-holdingsSize", "holdingsSize", XrmoptionSepArg, NULL }, // requires extensive front-end changes to work
1825 { "-flipBlack", "flipBlack", XrmoptionSepArg, NULL }, // requires front-end changes to work
1826 { "-allWhite", "allWhite", XrmoptionSepArg, NULL }, // requires front-end changes to work
1827 { "-pieceToCharTable", "pieceToCharTable", XrmoptionSepArg, NULL },
1828 { "-alphaRank", "alphaRank", XrmoptionSepArg, NULL },
1829 { "-testClaims", "testClaims", XrmoptionSepArg, NULL },
1830 { "-checkMates", "checkMates", XrmoptionSepArg, NULL },
1831 { "-materialDraws", "materialDraws", XrmoptionSepArg, NULL },
1832 { "-trivialDraws", "trivialDraws", XrmoptionSepArg, NULL },
1833 { "-ruleMoves", "ruleMoves", XrmoptionSepArg, NULL },
1834 { "-repeatsToDraw", "repeatsToDraw", XrmoptionSepArg, NULL },
1835 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1836 { "-userName", "userName", XrmoptionSepArg, NULL },
1837 { "-autoKibitz", "autoKibitz", XrmoptionNoArg, "True" },
1838 { "-firstTimeOdds", "firstTimeOdds", XrmoptionSepArg, NULL },
1839 { "-secondTimeOdds", "secondTimeOdds", XrmoptionSepArg, NULL },
1840 { "-timeOddsMode", "timeOddsMode", XrmoptionSepArg, NULL },
1841 { "-firstAccumulateTC", "firstAccumulateTC", XrmoptionSepArg, NULL },
1842 { "-secondAccumulateTC", "secondAccumulateTC", XrmoptionSepArg, NULL },
1843 { "-firstNPS", "firstNPS", XrmoptionSepArg, NULL },
1844 { "-secondNPS", "secondNPS", XrmoptionSepArg, NULL },
1845 { "-serverMoves", "serverMoves", XrmoptionSepArg, NULL },
1846 { "-serverPause", "serverPause", XrmoptionSepArg, NULL },
1847 { "-suppressLoadMoves", "suppressLoadMoves", XrmoptionSepArg, NULL },
1848 { "-egtFormats", "egtFormats", XrmoptionSepArg, NULL },
1849 { "-userName", "userName", XrmoptionSepArg, NULL },
1850 { "-smpCores", "smpCores", XrmoptionSepArg, NULL },
1851 { "-sameColorGames", "sameColorGames", XrmoptionSepArg, NULL },
1852 { "-rewindIndex", "rewindIndex", XrmoptionSepArg, NULL },
1853 { "-niceEngines", "niceEngines", XrmoptionSepArg, NULL },
1854 { "-delayBeforeQuit", "delayBeforeQuit", XrmoptionSepArg, NULL },
1855 { "-delayAfterQuit", "delayAfterQuit", XrmoptionSepArg, NULL },
1856 { "-nameOfDebugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1857 { "-debugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1858 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1859 { "-noGUI", "noGUI", XrmoptionNoArg, "True" },
1860 { "-firstOptions", "firstOptions", XrmoptionSepArg, NULL },
1861 { "-secondOptions", "secondOptions", XrmoptionSepArg, NULL },
1862 { "-firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1863 { "-secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1867 XtActionsRec boardActions[] = {
1868 { "HandleUserMove", HandleUserMove },
1869 { "AnimateUserMove", AnimateUserMove },
1870 { "FileNameAction", FileNameAction },
1871 { "AskQuestionProc", AskQuestionProc },
1872 { "AskQuestionReplyAction", AskQuestionReplyAction },
1873 { "PieceMenuPopup", PieceMenuPopup },
1874 { "WhiteClock", WhiteClock },
1875 { "BlackClock", BlackClock },
1876 { "Iconify", Iconify },
1877 { "LoadSelectedProc", LoadSelectedProc },
1878 { "LoadPositionProc", LoadPositionProc },
1879 { "LoadNextPositionProc", LoadNextPositionProc },
1880 { "LoadPrevPositionProc", LoadPrevPositionProc },
1881 { "ReloadPositionProc", ReloadPositionProc },
1882 { "CopyPositionProc", CopyPositionProc },
1883 { "PastePositionProc", PastePositionProc },
1884 { "CopyGameProc", CopyGameProc },
1885 { "PasteGameProc", PasteGameProc },
1886 { "SaveGameProc", SaveGameProc },
1887 { "SavePositionProc", SavePositionProc },
1888 { "MailMoveProc", MailMoveProc },
1889 { "ReloadCmailMsgProc", ReloadCmailMsgProc },
1890 // { "MachineWhiteProc", MachineWhiteProc },
1891 // { "MachineBlackProc", MachineBlackProc },
1892 { "AnalysisModeProc", AnalyzeModeProc },
1893 { "AnalyzeFileProc", AnalyzeFileProc },
1894 // { "TwoMachinesProc", TwoMachinesProc },
1895 { "IcsClientProc", IcsClientProc },
1896 { "EditGameProc", EditGameProc },
1897 { "EditPositionProc", EditPositionProc },
1898 { "TrainingProc", EditPositionProc },
1899 { "EngineOutputProc", EngineOutputProc}, // [HGM] Winboard_x engine-output window
1900 { "ShowGameListProc", ShowGameListProc },
1901 { "ShowMoveListProc", HistoryShowProc},
1902 { "EditTagsProc", EditCommentProc },
1903 { "EditCommentProc", EditCommentProc },
1904 { "IcsAlarmProc", IcsAlarmProc },
1905 { "IcsInputBoxProc", IcsInputBoxProc },
1906 // { "AcceptProc", AcceptProc },
1907 // { "DeclineProc", DeclineProc },
1908 // { "RematchProc", RematchProc },
1909 // { "CallFlagProc", CallFlagProc },
1910 // { "DrawProc", DrawProc },
1911 // { "AdjournProc", AdjournProc },
1912 // { "AbortProc", AbortProc },
1913 // { "ResignProc", ResignProc },
1914 // { "AdjuWhiteProc", AdjuWhiteProc },
1915 // { "AdjuBlackProc", AdjuBlackProc },
1916 // { "AdjuDrawProc", AdjuDrawProc },
1917 { "EnterKeyProc", EnterKeyProc },
1918 // { "StopObservingProc", StopObservingProc },
1919 // { "StopExaminingProc", StopExaminingProc },
1920 { "BackwardProc", BackwardProc },
1921 { "ForwardProc", ForwardProc },
1922 { "ToStartProc", ToStartProc },
1923 { "ToEndProc", ToEndProc },
1924 { "RevertProc", RevertProc },
1925 { "TruncateGameProc", TruncateGameProc },
1926 // { "MoveNowProc", MoveNowProc },
1927 { "RetractMoveProc", RetractMoveProc },
1928 { "AlwaysQueenProc", AlwaysQueenProc },
1929 { "AnimateDraggingProc", AnimateDraggingProc },
1930 { "AnimateMovingProc", AnimateMovingProc },
1931 { "AutoflagProc", AutoflagProc },
1932 { "AutoflipProc", AutoflipProc },
1933 { "AutobsProc", AutobsProc },
1934 { "AutoraiseProc", AutoraiseProc },
1935 { "AutosaveProc", AutosaveProc },
1936 { "BlindfoldProc", BlindfoldProc },
1937 { "FlashMovesProc", FlashMovesProc },
1938 { "FlipViewProc", FlipViewProc },
1939 { "GetMoveListProc", GetMoveListProc },
1941 { "HighlightDraggingProc", HighlightDraggingProc },
1943 { "HighlightLastMoveProc", HighlightLastMoveProc },
1944 { "IcsAlarmProc", IcsAlarmProc },
1945 { "MoveSoundProc", MoveSoundProc },
1946 { "OldSaveStyleProc", OldSaveStyleProc },
1947 { "PeriodicUpdatesProc", PeriodicUpdatesProc },
1948 { "PonderNextMoveProc", PonderNextMoveProc },
1949 { "PopupExitMessageProc", PopupExitMessageProc },
1950 { "PopupMoveErrorsProc", PopupMoveErrorsProc },
1951 { "PremoveProc", PremoveProc },
1952 { "QuietPlayProc", QuietPlayProc },
1953 { "ShowThinkingProc", ShowThinkingProc },
1954 { "HideThinkingProc", HideThinkingProc },
1955 { "TestLegalityProc", TestLegalityProc },
1956 { "InfoProc", InfoProc },
1957 { "ManProc", ManProc },
1958 { "HintProc", HintProc },
1959 { "BookProc", BookProc },
1960 { "AboutGameProc", AboutGameProc },
1961 { "DebugProc", DebugProc },
1962 { "NothingProc", NothingProc },
1963 { "CommentPopDown", (XtActionProc) CommentPopDown },
1964 { "EditCommentPopDown", (XtActionProc) EditCommentPopDown },
1965 { "TagsPopDown", (XtActionProc) TagsPopDown },
1966 { "ErrorPopDown", (XtActionProc) ErrorPopDown },
1967 { "ICSInputBoxPopDown", (XtActionProc) ICSInputBoxPopDown },
1968 { "AnalysisPopDown", (XtActionProc) AnalysisPopDown },
1969 { "FileNamePopDown", (XtActionProc) FileNamePopDown },
1970 { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown },
1971 { "GameListPopDown", (XtActionProc) GameListPopDown },
1972 { "PromotionPopDown", (XtActionProc) PromotionPopDown },
1973 { "HistoryPopDown", (XtActionProc) HistoryPopDown },
1974 { "EngineOutputPopDown", (XtActionProc) EngineOutputPopDown },
1975 { "ShufflePopDown", (XtActionProc) ShufflePopDown },
1976 { "EnginePopDown", (XtActionProc) EnginePopDown },
1977 { "UciPopDown", (XtActionProc) UciPopDown },
1978 { "TimeControlPopDown", (XtActionProc) TimeControlPopDown },
1979 { "NewVariantPopDown", (XtActionProc) NewVariantPopDown },
1980 { "SettingsPopDown", (XtActionProc) SettingsPopDown },
1984 char ICSInputTranslations[] =
1985 "<Key>Return: EnterKeyProc() \n";
1987 String xboardResources[] = {
1988 "*fileName*value.translations: #override\\n <Key>Return: FileNameAction()",
1989 "*question*value.translations: #override\\n <Key>Return: AskQuestionReplyAction()",
1990 "*errorpopup*translations: #override\\n <Key>Return: ErrorPopDown()",
1994 static char *cnames[9] = { "black", "red", "green", "yellow", "blue",
1995 "magenta", "cyan", "white" };
1999 TextColors textColors[(int)NColorClasses];
2001 /* String is: "fg, bg, attr". Which is 0, 1, 2 */
2003 parse_color(str, which)
2007 char *p, buf[100], *d;
2010 if (strlen(str) > 99) /* watch bounds on buf */
2015 for (i=0; i<which; ++i) {
2022 /* Could be looking at something like:
2024 .. in which case we want to stop on a comma also */
2025 while (*p && *p != ',' && !isalpha(*p) && !isdigit(*p))
2029 return -1; /* Use default for empty field */
2032 if (which == 2 || isdigit(*p))
2035 while (*p && isalpha(*p))
2040 for (i=0; i<8; ++i) {
2041 if (!StrCaseCmp(buf, cnames[i]))
2042 return which? (i+40) : (i+30);
2044 if (!StrCaseCmp(buf, "default")) return -1;
2046 fprintf(stderr, _("%s: unrecognized color %s\n"), programName, buf);
2051 parse_cpair(cc, str)
2055 if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {
2056 fprintf(stderr, _("%s: can't parse foreground color in `%s'\n"),
2061 /* bg and attr are optional */
2062 textColors[(int)cc].bg = parse_color(str, 1);
2063 if ((textColors[(int)cc].attr = parse_color(str, 2)) < 0) {
2064 textColors[(int)cc].attr = 0;
2070 /* Arrange to catch delete-window events */
2071 Atom wm_delete_window;
2073 CatchDeleteWindow(Widget w, String procname)
2076 XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
2077 snprintf(buf, sizeof(buf), "<Message>WM_PROTOCOLS: %s() \n", procname);
2078 XtAugmentTranslations(w, XtParseTranslationTable(buf));
2084 /* this should raise the board to the top */
2085 gtk_window_present(GTK_WINDOW(GUI_Window));
2090 // eventually, all layout determining code should go into a subroutine, but until then IDSIZE remains undefined
2092 #define BoardSize int
2093 void InitDrawingSizes(BoardSize boardSize, int flags)
2094 { // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
2095 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2097 XtGeometryResult gres;
2100 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2101 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2103 timerWidth = (boardWidth - sep) / 2;
2105 if (appData.titleInWindow)
2110 w = boardWidth - 2*bor;
2114 w = boardWidth - w - sep - 2*bor - 2; // WIDTH_FUDGE
2118 if(!formWidget) return;
2121 * Inhibit shell resizing.
2124 // [HGM] pieces: tailor piece bitmaps to needs of specific variant
2127 for(i=0; i<4; i++) {
2129 for(p=0; p<=(int)WhiteKing; p++)
2130 xpmPieceBitmap[i][p] = xpmPieceBitmap2[i][p]; // defaults
2131 if(gameInfo.variant == VariantShogi) {
2132 xpmPieceBitmap[i][(int)WhiteCannon] = xpmPieceBitmap2[i][(int)WhiteKing+1];
2133 xpmPieceBitmap[i][(int)WhiteNightrider] = xpmPieceBitmap2[i][(int)WhiteKing+2];
2134 xpmPieceBitmap[i][(int)WhiteSilver] = xpmPieceBitmap2[i][(int)WhiteKing+3];
2135 xpmPieceBitmap[i][(int)WhiteGrasshopper] = xpmPieceBitmap2[i][(int)WhiteKing+4];
2136 xpmPieceBitmap[i][(int)WhiteQueen] = xpmPieceBitmap2[i][(int)WhiteLance];
2139 if(gameInfo.variant == VariantGothic) {
2140 xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteSilver];
2144 // [HGM] why are thee ximMasks used at all? the ximPieceBitmaps seem to be never used!
2145 for(p=0; p<=(int)WhiteKing; p++)
2146 ximMaskPm[p] = ximMaskPm2[p]; // defaults
2147 if(gameInfo.variant == VariantShogi) {
2148 ximMaskPm[(int)WhiteCannon] = ximMaskPm2[(int)WhiteKing+1];
2149 ximMaskPm[(int)WhiteNightrider] = ximMaskPm2[(int)WhiteKing+2];
2150 ximMaskPm[(int)WhiteSilver] = ximMaskPm2[(int)WhiteKing+3];
2151 ximMaskPm[(int)WhiteGrasshopper] = ximMaskPm2[(int)WhiteKing+4];
2152 ximMaskPm[(int)WhiteQueen] = ximMaskPm2[(int)WhiteLance];
2155 if(gameInfo.variant == VariantGothic) {
2156 ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[i][(int)WhiteSilver];
2162 for(i=0; i<2; i++) {
2164 for(p=0; p<=(int)WhiteKing; p++)
2165 pieceBitmap[i][p] = pieceBitmap2[i][p]; // defaults
2166 if(gameInfo.variant == VariantShogi) {
2167 pieceBitmap[i][(int)WhiteCannon] = pieceBitmap2[i][(int)WhiteKing+1];
2168 pieceBitmap[i][(int)WhiteNightrider] = pieceBitmap2[i][(int)WhiteKing+2];
2169 pieceBitmap[i][(int)WhiteSilver] = pieceBitmap2[i][(int)WhiteKing+3];
2170 pieceBitmap[i][(int)WhiteGrasshopper] = pieceBitmap2[i][(int)WhiteKing+4];
2171 pieceBitmap[i][(int)WhiteQueen] = pieceBitmap2[i][(int)WhiteLance];
2174 if(gameInfo.variant == VariantGothic) {
2175 pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteSilver];
2191 int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
2192 XSetWindowAttributes window_attributes;
2194 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2195 XrmValue vFrom, vTo;
2196 XtGeometryResult gres;
2199 int forceMono = False;
2203 // [HGM] before anything else, expand any indirection files amongst options
2204 char *argvCopy[1000]; // 1000 seems enough
2205 char newArgs[10000]; // holds actual characters
2208 srandom(time(0)); // [HGM] book: make random truly random
2211 for(i=0; i<argc; i++) {
2212 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2213 //fprintf(stderr, "arg %s\n", argv[i]);
2214 if(argv[i][0] != '@') argvCopy[j++] = argv[i]; else {
2216 FILE *f = fopen(argv[i]+1, "rb");
2217 if(f == NULL) { fprintf(stderr, _("ignore %s\n"), argv[i]); continue; } // do not expand non-existing
2218 argvCopy[j++] = newArgs + k; // get ready for first argument from file
2219 while((c = fgetc(f)) != EOF) { // each line of file inserts 1 argument in the list
2221 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2222 newArgs[k++] = 0; // terminate current arg
2223 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2224 argvCopy[j++] = newArgs + k; // get ready for next
2226 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2239 if(appData.debugMode,1) { // OK, appData is not initialized here yet...
2240 for(i=0; i<argc; i++) fprintf(stderr, "argv[%2d] = '%s'\n", i, argv[i]);
2246 setbuf(stdout, NULL);
2247 setbuf(stderr, NULL);
2250 programName = strrchr(argv[0], '/');
2251 if (programName == NULL)
2252 programName = argv[0];
2257 XtSetLanguageProc(NULL, NULL, NULL);
2258 bindtextdomain(PACKAGE, LOCALEDIR);
2259 textdomain(PACKAGE);
2263 XtAppInitialize(&appContext, "XBoard", shellOptions,
2264 XtNumber(shellOptions),
2265 &argc, argv, xboardResources, NULL, 0);
2269 gtk_init (&argc, &argv);
2271 /* parse glade file to build widgets */
2273 builder = gtk_builder_new ();
2274 gtk_builder_add_from_file (builder, "gtk-interface.xml", NULL);
2276 /* test if everything worked ok */
2278 GUI_Window = GTK_WIDGET (gtk_builder_get_object (builder, "MainWindow"));
2279 if(!GUI_Window) printf("Error: gtk_builder didn't work!\n");
2280 GUI_Board = GTK_WIDGET (gtk_builder_get_object (builder, "Board"));
2281 if(!GUI_Board) printf("Error: gtk_builder didn't work!\n");
2282 GUI_Whiteclock = GTK_WIDGET (gtk_builder_get_object (builder, "WhiteClock"));
2283 if(!GUI_Whiteclock) printf("Error: gtk_builder didn't work!\n");
2284 GUI_Blackclock = GTK_WIDGET (gtk_builder_get_object (builder, "BlackClock"));
2285 if(!GUI_Blackclock) printf("Error: gtk_builder didn't work!\n");
2287 gtk_builder_connect_signals (builder, NULL);
2289 // don't unref the builder, since we use it to get references to widgets
2290 // g_object_unref (G_OBJECT (builder));
2292 /* end parse glade file */
2296 fprintf(stderr, _("%s: unrecognized argument %s\n"),
2297 programName, argv[1]);
2298 fprintf(stderr, "Recognized options:\n");
2299 for(i = 0; i < XtNumber(shellOptions); i++)
2301 j = fprintf(stderr, " %s%s", shellOptions[i].option,
2302 (shellOptions[i].argKind == XrmoptionSepArg
2304 if (i++ < XtNumber(shellOptions))
2306 fprintf(stderr, "%*c%s%s\n", 40 - j, ' ',
2307 shellOptions[i].option,
2308 (shellOptions[i].argKind == XrmoptionSepArg
2313 fprintf(stderr, "\n");
2319 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL)
2325 if (chdir(chessDir) != 0)
2327 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
2334 if (p == NULL) p = "/tmp";
2335 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
2336 gameCopyFilename = (char*) malloc(i);
2337 gamePasteFilename = (char*) malloc(i);
2338 snprintf(gameCopyFilename,i, "%s/.xboard%05uc.pgn", p, getpid());
2339 snprintf(gamePasteFilename,i, "%s/.xboard%05up.pgn", p, getpid());
2341 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
2342 clientResources, XtNumber(clientResources),
2345 if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) {
2346 /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */
2347 if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL) {
2348 printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile);
2351 setbuf(debugFP, NULL);
2354 /* [HGM,HR] make sure board size is acceptable */
2355 if(appData.NrFiles > BOARD_SIZE ||
2356 appData.NrRanks > BOARD_SIZE )
2357 DisplayFatalError(_("Recompile with BOARD_SIZE > 12, to support this size"), 0, 2);
2360 /* This feature does not work; animation needs a rewrite */
2361 appData.highlightDragging = FALSE;
2365 xDisplay = XtDisplay(shellWidget);
2366 xScreen = DefaultScreen(xDisplay);
2367 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
2369 gameInfo.variant = StringToVariant(appData.variant);
2370 InitPosition(FALSE);
2374 * Determine boardSize
2376 gameInfo.boardWidth = gameInfo.boardHeight = 8; // [HGM] boardsize: make sure we start as 8x8
2379 // [HGM] as long as we have not created the possibility to change size while running, start with requested size
2380 gameInfo.boardWidth = appData.NrFiles > 0 ? appData.NrFiles : 8;
2381 gameInfo.boardHeight = appData.NrRanks > 0 ? appData.NrRanks : 8;
2382 gameInfo.holdingsWidth = appData.holdingsSize > 0 ? 2 : 0;
2387 InitDrawingSizes(-1, 0); // [HGM] initsize: make this into a subroutine
2389 if (isdigit(appData.boardSize[0])) {
2390 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
2391 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
2392 &fontPxlSize, &smallLayout, &tinyLayout);
2394 fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
2395 programName, appData.boardSize);
2399 /* Find some defaults; use the nearest known size */
2400 SizeDefaults *szd, *nearest;
2401 int distance = 99999;
2402 nearest = szd = sizeDefaults;
2403 while (szd->name != NULL) {
2404 if (abs(szd->squareSize - squareSize) < distance) {
2406 distance = abs(szd->squareSize - squareSize);
2407 if (distance == 0) break;
2411 if (i < 2) lineGap = nearest->lineGap;
2412 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
2413 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
2414 if (i < 5) fontPxlSize = nearest->fontPxlSize;
2415 if (i < 6) smallLayout = nearest->smallLayout;
2416 if (i < 7) tinyLayout = nearest->tinyLayout;
2419 SizeDefaults *szd = sizeDefaults;
2420 if (*appData.boardSize == NULLCHAR) {
2421 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize ||
2422 DisplayHeight(xDisplay, xScreen) < szd->minScreenSize) {
2425 if (szd->name == NULL) szd--;
2427 while (szd->name != NULL &&
2428 StrCaseCmp(szd->name, appData.boardSize) != 0) szd++;
2429 if (szd->name == NULL) {
2430 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
2431 programName, appData.boardSize);
2435 squareSize = szd->squareSize;
2436 lineGap = szd->lineGap;
2437 clockFontPxlSize = szd->clockFontPxlSize;
2438 coordFontPxlSize = szd->coordFontPxlSize;
2439 fontPxlSize = szd->fontPxlSize;
2440 smallLayout = szd->smallLayout;
2441 tinyLayout = szd->tinyLayout;
2444 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2445 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2446 if (appData.showJail == 1) {
2447 /* Jail on top and bottom */
2448 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2449 XtSetArg(boardArgs[2], XtNheight,
2450 boardHeight + 2*(lineGap + squareSize));
2451 } else if (appData.showJail == 2) {
2453 XtSetArg(boardArgs[1], XtNwidth,
2454 boardWidth + 2*(lineGap + squareSize));
2455 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2458 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2459 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2463 * Determine what fonts to use.
2465 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
2466 clockFontID = XLoadFont(xDisplay, appData.clockFont);
2467 clockFontStruct = XQueryFont(xDisplay, clockFontID);
2468 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
2469 coordFontID = XLoadFont(xDisplay, appData.coordFont);
2470 coordFontStruct = XQueryFont(xDisplay, coordFontID);
2471 appData.font = FindFont(appData.font, fontPxlSize);
2472 countFontID = XLoadFont(xDisplay, appData.coordFont); // [HGM] holdings
2473 countFontStruct = XQueryFont(xDisplay, countFontID);
2474 // appData.font = FindFont(appData.font, fontPxlSize);
2476 xdb = XtDatabase(xDisplay);
2477 XrmPutStringResource(&xdb, "*font", appData.font);
2480 * Detect if there are not enough colors available and adapt.
2482 if (DefaultDepth(xDisplay, xScreen) <= 2) {
2483 appData.monoMode = True;
2486 if (!appData.monoMode) {
2487 vFrom.addr = (caddr_t) appData.lightSquareColor;
2488 vFrom.size = strlen(appData.lightSquareColor);
2489 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2490 if (vTo.addr == NULL) {
2491 appData.monoMode = True;
2494 lightSquareColor = *(Pixel *) vTo.addr;
2497 if (!appData.monoMode) {
2498 vFrom.addr = (caddr_t) appData.darkSquareColor;
2499 vFrom.size = strlen(appData.darkSquareColor);
2500 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2501 if (vTo.addr == NULL) {
2502 appData.monoMode = True;
2505 darkSquareColor = *(Pixel *) vTo.addr;
2508 if (!appData.monoMode) {
2509 vFrom.addr = (caddr_t) appData.whitePieceColor;
2510 vFrom.size = strlen(appData.whitePieceColor);
2511 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2512 if (vTo.addr == NULL) {
2513 appData.monoMode = True;
2516 whitePieceColor = *(Pixel *) vTo.addr;
2519 if (!appData.monoMode) {
2520 vFrom.addr = (caddr_t) appData.blackPieceColor;
2521 vFrom.size = strlen(appData.blackPieceColor);
2522 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2523 if (vTo.addr == NULL) {
2524 appData.monoMode = True;
2527 blackPieceColor = *(Pixel *) vTo.addr;
2531 if (!appData.monoMode) {
2532 vFrom.addr = (caddr_t) appData.highlightSquareColor;
2533 vFrom.size = strlen(appData.highlightSquareColor);
2534 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2535 if (vTo.addr == NULL) {
2536 appData.monoMode = True;
2539 highlightSquareColor = *(Pixel *) vTo.addr;
2543 if (!appData.monoMode) {
2544 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
2545 vFrom.size = strlen(appData.premoveHighlightColor);
2546 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2547 if (vTo.addr == NULL) {
2548 appData.monoMode = True;
2551 premoveHighlightColor = *(Pixel *) vTo.addr;
2556 fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2559 if (appData.bitmapDirectory == NULL ||
2560 appData.bitmapDirectory[0] == NULLCHAR)
2561 appData.bitmapDirectory = DEF_BITMAP_DIR;
2564 if (appData.lowTimeWarning && !appData.monoMode) {
2565 vFrom.addr = (caddr_t) appData.lowTimeWarningColor;
2566 vFrom.size = strlen(appData.lowTimeWarningColor);
2567 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2568 if (vTo.addr == NULL)
2569 appData.monoMode = True;
2571 lowTimeWarningColor = *(Pixel *) vTo.addr;
2574 if (appData.monoMode && appData.debugMode) {
2575 fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2576 (unsigned long) XWhitePixel(xDisplay, xScreen),
2577 (unsigned long) XBlackPixel(xDisplay, xScreen));
2580 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
2581 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
2582 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
2583 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
2584 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
2585 parse_cpair(ColorTell, appData.colorTell) < 0 ||
2586 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
2587 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
2588 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
2589 parse_cpair(ColorNormal, appData.colorNormal) < 0)
2591 if (appData.colorize) {
2593 _("%s: can't parse color names; disabling colorization\n"),
2596 appData.colorize = FALSE;
2598 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2599 textColors[ColorNone].attr = 0;
2601 // XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2607 layoutName = "tinyLayout";
2608 } else if (smallLayout) {
2609 layoutName = "smallLayout";
2611 layoutName = "normalLayout";
2614 if (appData.titleInWindow) {
2615 /* todo check what this appdata does */
2618 if (appData.showButtonBar) {
2619 /* TODO hide button bar if requested */
2623 * gtk set properties of widgets
2626 /* set board size */
2627 gtk_widget_set_size_request(GTK_WIDGET(GUI_Board),
2628 boardWidth,boardHeight);
2630 /* end gtk set properties of widgets */
2632 if (appData.titleInWindow)
2637 if (appData.showButtonBar)
2644 if (appData.showButtonBar)
2653 // [HGM] it seems the layout code ends here, but perhaps the color stuff is size independent and would
2654 // not need to go into InitDrawingSizes().
2657 /* set some checkboxes in the menu according to appData */
2659 if (appData.alwaysPromoteToQueen)
2660 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Always Queen")),TRUE);
2662 if (appData.animateDragging)
2663 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Animate Dragging")),TRUE);
2665 if (appData.animate)
2666 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Animate Moving")),TRUE);
2668 if (appData.autoComment)
2669 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Comment")),TRUE);
2671 if (appData.autoCallFlag)
2672 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Flag")),TRUE);
2674 if (appData.autoFlipView)
2675 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Flip View")),TRUE);
2677 if (appData.autoObserve)
2678 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Observe")),TRUE);
2680 if (appData.autoRaiseBoard)
2681 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Raise Board")),TRUE);
2683 if (appData.autoSaveGames)
2684 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Save")),TRUE);
2686 if (appData.saveGameFile[0] != NULLCHAR)
2688 /* Can't turn this off from menu */
2689 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Save")),TRUE);
2690 gtk_action_set_sensitive(GTK_ACTION (gtk_builder_get_object (builder, "menuOptions.Auto Save")),FALSE);
2693 if (appData.blindfold)
2694 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Blindfold")),TRUE);
2696 if (appData.flashCount > 0)
2697 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Flash Moves")),TRUE);
2699 if (appData.getMoveList)
2700 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Get Move List")),TRUE);
2703 if (appData.highlightDragging)
2704 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Highlight Dragging")),TRUE);
2707 if (appData.highlightLastMove)
2708 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Highlight Last Move")),TRUE);
2710 if (appData.icsAlarm)
2711 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.ICS Alarm")),TRUE);
2713 if (appData.ringBellAfterMoves)
2714 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Move Sound")),TRUE);
2716 if (appData.oldSaveStyle)
2717 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Old Save Style")),TRUE);
2719 if (appData.periodicUpdates)
2720 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Periodic Updates")),TRUE);
2722 if (appData.ponderNextMove)
2723 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Ponder Next Move")),TRUE);
2725 if (appData.popupExitMessage)
2726 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Popup Exit Message")),TRUE);
2728 if (appData.popupMoveErrors)
2729 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Popup Move Errors")),TRUE);
2731 if (appData.premove)
2732 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Premove")),TRUE);
2734 if (appData.quietPlay)
2735 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Quit Play")),TRUE);
2737 if (appData.showCoords)
2738 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Show Coords")),TRUE);
2740 if (appData.showThinking)
2741 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Show Thinking")),TRUE);
2743 if (appData.testLegality)
2744 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Test Legality")),TRUE);
2746 /* end setting check boxes */
2749 /* load square colors */
2750 SVGLightSquare = load_pixbuf("svg/LightSquare.svg",squareSize);
2751 SVGDarkSquare = load_pixbuf("svg/DarkSquare.svg",squareSize);
2752 SVGNeutralSquare = load_pixbuf("svg/NeutralSquare.svg",squareSize);
2754 /* use two icons to indicate if it is white's or black's turn */
2755 WhiteIcon = load_pixbuf("svg/icon_white.svg",0);
2756 BlackIcon = load_pixbuf("svg/icon_black.svg",0);
2757 WindowIcon = WhiteIcon;
2758 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
2760 /* do resizing to a fixed aspect ratio */
2765 GUI_SetAspectRatio(0.7);
2767 /* realize window */
2768 gtk_widget_show (GUI_Window);
2774 if (appData.animate || appData.animateDragging)
2779 if (errorExitStatus == -1) {
2780 if (appData.icsActive) {
2781 /* We now wait until we see "login:" from the ICS before
2782 sending the logon script (problems with timestamp otherwise) */
2783 /*ICSInitScript();*/
2784 if (appData.icsInputBox) ICSInputBoxPopUp();
2787 signal(SIGINT, IntSigHandler);
2788 signal(SIGTERM, IntSigHandler);
2789 if (*appData.cmailGameName != NULLCHAR) {
2790 signal(SIGUSR1, CmailSigHandler);
2793 gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes()
2797 * Create a cursor for the board widget.
2798 * (This needs to be called after the window has been created to have access to board-window)
2801 BoardCursor = gdk_cursor_new(GDK_HAND2);
2802 gdk_window_set_cursor(GUI_Board->window, BoardCursor);
2803 gdk_cursor_destroy(BoardCursor);
2808 if (appData.debugMode) fclose(debugFP); // [DM] debug
2815 if (appData.icsActive && oldICSInteractionTitle != NULL) {
2816 DisplayIcsInteractionTitle(oldICSInteractionTitle);
2818 unlink(gameCopyFilename);
2819 unlink(gamePasteFilename);
2830 CmailSigHandler(sig)
2836 signal(SIGUSR1, SIG_IGN); /* suspend handler */
2838 /* Activate call-back function CmailSigHandlerCallBack() */
2839 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
2841 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
2845 CmailSigHandlerCallBack(isr, closure, message, count, error)
2853 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
2855 /**** end signal code ****/
2865 f = fopen(appData.icsLogon, "r");
2871 strcat(buf, appData.icsLogon);
2872 f = fopen(buf, "r");
2876 ProcessICSInitScript(f);
2883 EditCommentPopDown();
2889 SetMenuEnables(enab)
2894 if (!builder) return;
2895 while (enab->name != NULL) {
2896 o = gtk_builder_get_object(builder, enab->name);
2897 if(GTK_IS_WIDGET(o))
2898 gtk_widget_set_sensitive(GTK_WIDGET (o),enab->value);
2901 if(GTK_IS_ACTION(o))
2902 gtk_action_set_sensitive(GTK_ACTION (o),enab->value);
2904 DisplayError(enab->name, 0);
2912 SetMenuEnables(icsEnables);
2915 if (appData.zippyPlay && !appData.noChessProgram) /* [DM] icsEngineAnalyze */
2916 {}; // XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
2923 SetMenuEnables(ncpEnables);
2929 SetMenuEnables(gnuEnables);
2935 SetMenuEnables(cmailEnables);
2941 SetMenuEnables(trainingOnEnables);
2942 if (appData.showButtonBar) {
2943 // XtSetSensitive(buttonBarWidget, False);
2949 SetTrainingModeOff()
2951 SetMenuEnables(trainingOffEnables);
2952 if (appData.showButtonBar) {
2953 // XtSetSensitive(buttonBarWidget, True);
2958 SetUserThinkingEnables()
2960 if (appData.noChessProgram) return;
2961 SetMenuEnables(userThinkingEnables);
2965 SetMachineThinkingEnables()
2967 if (appData.noChessProgram) return;
2968 SetMenuEnables(machineThinkingEnables);
2970 case MachinePlaysBlack:
2971 case MachinePlaysWhite:
2972 case TwoMachinesPlay:
2973 // XtSetSensitive(XtNameToWidget(menuBarWidget,
2974 // ModeToWidgetName(gameMode)), True);
2981 #define Abs(n) ((n)<0 ? -(n) : (n))
2984 * Find a font that matches "pattern" that is as close as
2985 * possible to the targetPxlSize. Prefer fonts that are k
2986 * pixels smaller to fonts that are k pixels larger. The
2987 * pattern must be in the X Consortium standard format,
2988 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
2989 * The return value should be freed with XtFree when no
2992 char *FindFont(pattern, targetPxlSize)
2996 char **fonts, *p, *best, *scalable, *scalableTail;
2997 int i, j, nfonts, minerr, err, pxlSize;
3000 char **missing_list;
3002 char *def_string, *base_fnt_lst, strInt[3];
3004 XFontStruct **fnt_list;
3006 base_fnt_lst = calloc(1, strlen(pattern) + 3);
3007 sprintf(strInt, "%d", targetPxlSize);
3008 p = strstr(pattern, "--");
3009 strncpy(base_fnt_lst, pattern, p - pattern + 2);
3010 strcat(base_fnt_lst, strInt);
3011 strcat(base_fnt_lst, strchr(p + 2, '-'));
3013 if ((fntSet = XCreateFontSet(xDisplay,
3017 &def_string)) == NULL) {
3019 fprintf(stderr, _("Unable to create font set.\n"));
3023 nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
3025 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
3027 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
3028 programName, pattern);
3036 for (i=0; i<nfonts; i++) {
3039 if (*p != '-') continue;
3041 if (*p == NULLCHAR) break;
3042 if (*p++ == '-') j++;
3044 if (j < 7) continue;
3047 scalable = fonts[i];
3050 err = pxlSize - targetPxlSize;
3051 if (Abs(err) < Abs(minerr) ||
3052 (minerr > 0 && err < 0 && -err == minerr)) {
3058 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
3059 /* If the error is too big and there is a scalable font,
3060 use the scalable font. */
3061 int headlen = scalableTail - scalable;
3062 p = (char *) XtMalloc(strlen(scalable) + 10);
3063 while (isdigit(*scalableTail)) scalableTail++;
3064 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
3066 p = (char *) XtMalloc(strlen(best) + 1);
3069 if (appData.debugMode) {
3070 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
3071 pattern, targetPxlSize, p);
3074 if (missing_count > 0)
3075 XFreeStringList(missing_list);
3076 XFreeFontSet(xDisplay, fntSet);
3078 XFreeFontNames(fonts);
3085 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
3086 | GCBackground | GCFunction | GCPlaneMask;
3087 XGCValues gc_values;
3090 gc_values.plane_mask = AllPlanes;
3091 gc_values.line_width = lineGap;
3092 gc_values.line_style = LineSolid;
3093 gc_values.function = GXcopy;
3095 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3096 gc_values.background = XWhitePixel(xDisplay, xScreen);
3097 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
3098 XSetFont(xDisplay, coordGC, coordFontID);
3100 if (appData.monoMode) {
3101 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3102 gc_values.background = XBlackPixel(xDisplay, xScreen);
3103 lightSquareGC = wbPieceGC
3104 = XtGetGC(shellWidget, value_mask, &gc_values);
3106 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3107 gc_values.background = XWhitePixel(xDisplay, xScreen);
3108 darkSquareGC = bwPieceGC
3109 = XtGetGC(shellWidget, value_mask, &gc_values);
3111 if (DefaultDepth(xDisplay, xScreen) == 1) {
3112 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3113 gc_values.function = GXcopyInverted;
3114 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3115 gc_values.function = GXcopy;
3116 if (XBlackPixel(xDisplay, xScreen) == 1) {
3117 bwPieceGC = darkSquareGC;
3118 wbPieceGC = copyInvertedGC;
3120 bwPieceGC = copyInvertedGC;
3121 wbPieceGC = lightSquareGC;
3125 gc_values.foreground = lightSquareColor;
3126 gc_values.background = darkSquareColor;
3127 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3129 gc_values.foreground = darkSquareColor;
3130 gc_values.background = lightSquareColor;
3131 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3133 gc_values.foreground = jailSquareColor;
3134 gc_values.background = jailSquareColor;
3135 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3137 gc_values.foreground = whitePieceColor;
3138 gc_values.background = darkSquareColor;
3139 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3141 gc_values.foreground = whitePieceColor;
3142 gc_values.background = lightSquareColor;
3143 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3145 gc_values.foreground = whitePieceColor;
3146 gc_values.background = jailSquareColor;
3147 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3149 gc_values.foreground = blackPieceColor;
3150 gc_values.background = darkSquareColor;
3151 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3153 gc_values.foreground = blackPieceColor;
3154 gc_values.background = lightSquareColor;
3155 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3157 gc_values.foreground = blackPieceColor;
3158 gc_values.background = jailSquareColor;
3159 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3166 WhitePawn, WhiteKnight, WhiteBishop, WhiteRook, WhiteQueen, WhiteKing,
3167 BlackPawn, BlackKnight, BlackBishop, BlackRook, BlackQueen, BlackKing,
3171 /* get some defaults going */
3172 for(i=WhitePawn; i<DemotePiece+1; i++)
3173 SVGpieces[i] = load_pixbuf("svg/NeutralSquare.svg",squareSize);
3176 SVGpieces[WhitePawn] = load_pixbuf("svg/WhitePawn.svg",squareSize);
3177 SVGpieces[WhiteKnight] = load_pixbuf("svg/WhiteKnight.svg",squareSize);
3178 SVGpieces[WhiteBishop] = load_pixbuf("svg/WhiteBishop.svg",squareSize);
3179 SVGpieces[WhiteRook] = load_pixbuf("svg/WhiteRook.svg",squareSize);
3180 SVGpieces[WhiteQueen] = load_pixbuf("svg/WhiteQueen.svg",squareSize);
3181 SVGpieces[WhiteKing] = load_pixbuf("svg/WhiteKing.svg",squareSize);
3183 SVGpieces[BlackPawn] = load_pixbuf("svg/BlackPawn.svg",squareSize);
3184 SVGpieces[BlackKnight] = load_pixbuf("svg/BlackKnight.svg",squareSize);
3185 SVGpieces[BlackBishop] = load_pixbuf("svg/BlackBishop.svg",squareSize);
3186 SVGpieces[BlackRook] = load_pixbuf("svg/BlackRook.svg",squareSize);
3187 SVGpieces[BlackQueen] = load_pixbuf("svg/BlackQueen.svg",squareSize);
3188 SVGpieces[BlackKing] = load_pixbuf("svg/BlackKing.svg",squareSize);
3194 static void MenuBarSelect(w, addr, index)
3199 XtActionProc proc = (XtActionProc) addr;
3201 (proc)(NULL, NULL, NULL, NULL);
3204 void CreateMenuBarPopup(parent, name, mb)
3214 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3217 XtSetArg(args[j], XtNleftMargin, 20); j++;
3218 XtSetArg(args[j], XtNrightMargin, 20); j++;
3220 while (mi->string != NULL) {
3221 if (strcmp(mi->string, "----") == 0) {
3222 entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
3225 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string)));
3226 entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass,
3228 XtAddCallback(entry, XtNcallback,
3229 (XtCallbackProc) MenuBarSelect,
3230 (caddr_t) mi->proc);
3236 Widget CreateMenuBar(mb)
3240 Widget anchor, menuBar;
3242 char menuName[MSG_SIZ];
3245 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3246 XtSetArg(args[j], XtNvSpace, 0); j++;
3247 XtSetArg(args[j], XtNborderWidth, 0); j++;
3248 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
3249 formWidget, args, j);
3251 while (mb->name != NULL) {
3252 strcpy(menuName, "menu");
3253 strcat(menuName, mb->name);
3255 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
3258 shortName[0] = _(mb->name)[0];
3259 shortName[1] = NULLCHAR;
3260 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
3263 XtSetArg(args[j], XtNlabel, XtNewString(_(mb->name))); j++;
3266 XtSetArg(args[j], XtNborderWidth, 0); j++;
3267 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
3269 CreateMenuBarPopup(menuBar, menuName, mb);
3275 Widget CreateButtonBar(mi)
3279 Widget button, buttonBar;
3283 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3285 XtSetArg(args[j], XtNhSpace, 0); j++;
3287 XtSetArg(args[j], XtNborderWidth, 0); j++;
3288 XtSetArg(args[j], XtNvSpace, 0); j++;
3289 buttonBar = XtCreateWidget("buttonBar", boxWidgetClass,
3290 formWidget, args, j);
3292 while (mi->string != NULL) {
3295 XtSetArg(args[j], XtNinternalWidth, 2); j++;
3296 XtSetArg(args[j], XtNborderWidth, 0); j++;
3298 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string))); j++;
3299 button = XtCreateManagedWidget(mi->string, commandWidgetClass,
3300 buttonBar, args, j);
3301 XtAddCallback(button, XtNcallback,
3302 (XtCallbackProc) MenuBarSelect,
3303 (caddr_t) mi->proc);
3310 CreatePieceMenu(name, color)
3317 ChessSquare selection;
3319 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3320 boardWidget, args, 0);
3322 for (i = 0; i < PIECE_MENU_SIZE; i++) {
3323 String item = pieceMenuStrings[color][i];
3325 if (strcmp(item, "----") == 0) {
3326 entry = XtCreateManagedWidget(item, smeLineObjectClass,
3329 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3330 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3332 selection = pieceMenuTranslation[color][i];
3333 XtAddCallback(entry, XtNcallback,
3334 (XtCallbackProc) PieceMenuSelect,
3335 (caddr_t) selection);
3336 if (selection == WhitePawn || selection == BlackPawn) {
3337 XtSetArg(args[0], XtNpopupOnEntry, entry);
3338 XtSetValues(menu, args, 1);
3351 ChessSquare selection;
3353 // whitePieceMenu = CreatePieceMenu("menuW", 0);
3354 // blackPieceMenu = CreatePieceMenu("menuB", 1);
3356 // XtRegisterGrabAction(PieceMenuPopup, True,
3357 // (unsigned)(ButtonPressMask|ButtonReleaseMask),
3358 // GrabModeAsync, GrabModeAsync);
3360 // XtSetArg(args[0], XtNlabel, _("Drop"));
3361 // dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
3362 // boardWidget, args, 1);
3363 // for (i = 0; i < DROP_MENU_SIZE; i++) {
3364 // String item = dropMenuStrings[i];
3366 // if (strcmp(item, "----") == 0) {
3367 // entry = XtCreateManagedWidget(item, smeLineObjectClass,
3368 // dropMenu, NULL, 0);
3370 // XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3371 // entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3372 // dropMenu, args, 1);
3373 // selection = dropMenuTranslation[i];
3374 // XtAddCallback(entry, XtNcallback,
3375 // (XtCallbackProc) DropMenuSelect,
3376 // (caddr_t) selection);
3381 void SetupDropMenu()
3389 for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
3390 entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
3391 p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
3392 dmEnables[i].piece);
3393 XtSetSensitive(entry, p != NULL || !appData.testLegality
3394 /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
3395 && !appData.icsActive));
3397 while (p && *p++ == dmEnables[i].piece) count++;
3398 snprintf(label, sizeof(label), "%s %d", dmEnables[i].widget, count);
3400 XtSetArg(args[j], XtNlabel, label); j++;
3401 XtSetValues(entry, args, j);
3405 void PieceMenuPopup(w, event, params, num_params)
3409 Cardinal *num_params;
3412 if (event->type != ButtonPress) return;
3413 if (errorUp) ErrorPopDown();
3417 whichMenu = params[0];
3419 case IcsPlayingWhite:
3420 case IcsPlayingBlack:
3422 case MachinePlaysWhite:
3423 case MachinePlaysBlack:
3424 if (appData.testLegality &&
3425 gameInfo.variant != VariantBughouse &&
3426 gameInfo.variant != VariantCrazyhouse) return;
3428 whichMenu = "menuD";
3434 if (((pmFromX = EventToSquare(event->xbutton.x, BOARD_WIDTH)) < 0) ||
3435 ((pmFromY = EventToSquare(event->xbutton.y, BOARD_HEIGHT)) < 0)) {
3436 pmFromX = pmFromY = -1;
3440 pmFromX = BOARD_WIDTH - 1 - pmFromX;
3442 pmFromY = BOARD_HEIGHT - 1 - pmFromY;
3444 XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
3447 static void PieceMenuSelect(w, piece, junk)
3452 if (pmFromX < 0 || pmFromY < 0) return;
3453 EditPositionMenuEvent(piece, pmFromX, pmFromY);
3456 static void DropMenuSelect(w, piece, junk)
3461 if (pmFromX < 0 || pmFromY < 0) return;
3462 DropMenuEvent(piece, pmFromX, pmFromY);
3465 void WhiteClock(w, event, prms, nprms)
3471 if (gameMode == EditPosition || gameMode == IcsExamining) {
3472 SetWhiteToPlayEvent();
3473 } else if (gameMode == IcsPlayingBlack || gameMode == MachinePlaysWhite) {
3478 void BlackClock(w, event, prms, nprms)
3484 if (gameMode == EditPosition || gameMode == IcsExamining) {
3485 SetBlackToPlayEvent();
3486 } else if (gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) {
3493 * If the user selects on a border boundary, return -1; if off the board,
3494 * return -2. Otherwise map the event coordinate to the square.
3496 int EventToSquare(x, limit)
3504 if ((x % (squareSize + lineGap)) >= squareSize)
3506 x /= (squareSize + lineGap);
3512 static void do_flash_delay(msec)
3518 static void drawHighlight(file, rank, line_type)
3519 int file, rank, line_type;
3524 if (lineGap == 0 || appData.blindfold) return;
3528 x = lineGap/2 + ((BOARD_WIDTH-1)-file) *
3529 (squareSize + lineGap);
3530 y = lineGap/2 + rank * (squareSize + lineGap);
3534 x = lineGap/2 + file * (squareSize + lineGap);
3535 y = lineGap/2 + ((BOARD_HEIGHT-1)-rank) *
3536 (squareSize + lineGap);
3540 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3542 /* draw the highlight */
3543 cairo_move_to (cr, x, y);
3544 cairo_rel_line_to (cr, 0,squareSize+lineGap);
3545 cairo_rel_line_to (cr, squareSize+lineGap,0);
3546 cairo_rel_line_to (cr, 0,-squareSize-lineGap);
3547 cairo_close_path (cr);
3549 cairo_set_line_width (cr, lineGap);
3552 /* TODO: use appdata colors */
3553 case LINE_TYPE_HIGHLIGHT:
3554 cairo_set_source_rgba (cr, 1, 1, 0, 1.0);
3557 cairo_set_source_rgba (cr, 1, 0, 0, 1.0);
3559 case LINE_TYPE_NORMAL:
3561 cairo_set_source_rgba (cr, 0, 1, 0, 1.0);
3572 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
3573 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
3576 SetHighlights(fromX, fromY, toX, toY)
3577 int fromX, fromY, toX, toY;
3579 if (hi1X != fromX || hi1Y != fromY)
3581 if (hi1X >= 0 && hi1Y >= 0)
3583 drawHighlight(hi1X, hi1Y, LINE_TYPE_NORMAL);
3585 if (fromX >= 0 && fromY >= 0)
3587 drawHighlight(fromX, fromY, LINE_TYPE_HIGHLIGHT);
3590 if (hi2X != toX || hi2Y != toY)
3592 if (hi2X >= 0 && hi2Y >= 0)
3594 drawHighlight(hi2X, hi2Y, LINE_TYPE_NORMAL);
3596 if (toX >= 0 && toY >= 0)
3598 drawHighlight(toX, toY, LINE_TYPE_HIGHLIGHT);
3612 SetHighlights(-1, -1, -1, -1);
3617 SetPremoveHighlights(fromX, fromY, toX, toY)
3618 int fromX, fromY, toX, toY;
3620 if (pm1X != fromX || pm1Y != fromY)
3622 if (pm1X >= 0 && pm1Y >= 0)
3624 drawHighlight(pm1X, pm1Y, LINE_TYPE_NORMAL);
3626 if (fromX >= 0 && fromY >= 0)
3628 drawHighlight(fromX, fromY, LINE_TYPE_PRE);
3631 if (pm2X != toX || pm2Y != toY)
3633 if (pm2X >= 0 && pm2Y >= 0)
3635 drawHighlight(pm2X, pm2Y, LINE_TYPE_NORMAL);
3637 if (toX >= 0 && toY >= 0)
3639 drawHighlight(toX, toY, LINE_TYPE_PRE);
3652 ClearPremoveHighlights()
3654 SetPremoveHighlights(-1, -1, -1, -1);
3657 static void BlankSquare(x, y, color, piece, dest)
3670 pb = SVGLightSquare;
3672 case 2: /* neutral */
3674 pb = SVGNeutralSquare;
3677 gdk_draw_pixbuf(GDK_WINDOW(GUI_Board->window),NULL,pb,0,0,x,y,-1,-1, GDK_RGB_DITHER_NORMAL, 0, 0);
3681 static void DrawPiece(piece, square_color, x, y, dest)
3683 int square_color, x, y;
3686 gdk_draw_pixbuf(GDK_WINDOW(GUI_Board->window),NULL,
3687 GDK_PIXBUF(SVGpieces[piece]),0,0,x,y,-1,-1,
3688 GDK_RGB_DITHER_NORMAL, 0, 0);
3692 /* [HR] determine square color depending on chess variant. */
3693 static int SquareColor(row, column)
3698 if (gameInfo.variant == VariantXiangqi) {
3699 if (column >= 3 && column <= 5 && row >= 0 && row <= 2) {
3701 } else if (column >= 3 && column <= 5 && row >= 7 && row <= 9) {
3703 } else if (row <= 4) {
3709 square_color = ((column + row) % 2) == 1;
3712 /* [hgm] holdings: next line makes all holdings squares light */
3713 if(column < BOARD_LEFT || column >= BOARD_RGHT) square_color = 1;
3715 return square_color;
3718 void DrawSquare(row, column, piece, do_flash)
3719 int row, column, do_flash;
3722 int square_color, x, y;
3727 /* Calculate delay in milliseconds (2-delays per complete flash) */
3728 flash_delay = 500 / appData.flashRate;
3730 /* calculate x and y coordinates from row and column */
3733 x = lineGap + ((BOARD_WIDTH-1)-column) *
3734 (squareSize + lineGap);
3735 y = lineGap + row * (squareSize + lineGap);
3739 x = lineGap + column * (squareSize + lineGap);
3740 y = lineGap + ((BOARD_HEIGHT-1)-row) *
3741 (squareSize + lineGap);
3744 square_color = SquareColor(row, column);
3746 // [HGM] holdings: blank out area between board and holdings
3747 if ( column == BOARD_LEFT-1 || column == BOARD_RGHT
3748 || (column == BOARD_LEFT-2 && row < BOARD_HEIGHT-gameInfo.holdingsSize)
3749 || (column == BOARD_RGHT+1 && row >= gameInfo.holdingsSize) )
3751 BlankSquare(x, y, 2, EmptySquare, xBoardWindow);
3753 // [HGM] print piece counts next to holdings
3754 string[1] = NULLCHAR;
3757 cairo_text_extents_t extents;
3762 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3764 string[0] = '0' + piece;
3766 /* TODO this has to go into the font-selection */
3767 cairo_select_font_face (cr, "Sans",
3768 CAIRO_FONT_SLANT_NORMAL,
3769 CAIRO_FONT_WEIGHT_NORMAL);
3771 cairo_set_font_size (cr, 12.0);
3772 cairo_text_extents (cr, string, &extents);
3774 if (column == (flipView ? BOARD_LEFT-1 : BOARD_RGHT) )
3776 xpos= x + squareSize - extents.width - 2;
3777 ypos= y + extents.y_bearing + 1;
3779 if (column == (flipView ? BOARD_RGHT : BOARD_LEFT-1) && piece > 1)
3782 ypos = y + extents.y_bearing + 1;
3785 /* TODO mono mode? */
3786 cairo_move_to (cr, xpos, ypos);
3787 cairo_text_path (cr, string);
3788 cairo_set_source_rgb (cr, 1.0, 1.0, 1);
3789 cairo_fill_preserve (cr);
3790 cairo_set_source_rgb (cr, 0, 0, 0);
3791 cairo_set_line_width (cr, 0.1);
3800 /* square on the board */
3801 if (piece == EmptySquare || appData.blindfold)
3803 BlankSquare(x, y, square_color, piece, xBoardWindow);
3807 if (do_flash && appData.flashCount > 0)
3809 for (i=0; i<appData.flashCount; ++i)
3812 DrawPiece(piece, square_color, x, y, xBoardWindow);
3813 do_flash_delay(flash_delay);
3815 BlankSquare(x, y, square_color, piece, xBoardWindow);
3816 do_flash_delay(flash_delay);
3819 DrawPiece(piece, square_color, x, y, xBoardWindow);
3823 /* show coordinates if necessary */
3824 if(appData.showCoords)
3826 cairo_text_extents_t extents;
3830 /* TODO this has to go into the font-selection */
3831 cairo_select_font_face (cr, "Sans",
3832 CAIRO_FONT_SLANT_NORMAL,
3833 CAIRO_FONT_WEIGHT_NORMAL);
3834 cairo_set_font_size (cr, 12.0);
3836 string[1] = NULLCHAR;
3839 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3841 if (row == (flipView ? BOARD_HEIGHT-1 : 0) &&
3842 column >= BOARD_LEFT && column < BOARD_RGHT)
3844 string[0] = 'a' + column - BOARD_LEFT;
3845 cairo_text_extents (cr, string, &extents);
3847 xpos = x + squareSize - extents.width - 2;
3848 ypos = y + squareSize - extents.height - extents.y_bearing - 1;
3850 if (appData.monoMode)
3857 cairo_move_to (cr, xpos, ypos);
3858 cairo_text_path (cr, string);
3859 cairo_set_source_rgb (cr, 0.0, 0.0, 0);
3860 cairo_fill_preserve (cr);
3861 cairo_set_source_rgb (cr, 0, 1.0, 0);
3862 cairo_set_line_width (cr, 0.1);
3865 if ( column == (flipView ? BOARD_RGHT-1 : BOARD_LEFT))
3868 string[0] = ONE + row;
3869 cairo_text_extents (cr, string, &extents);
3872 ypos = y + extents.height + 1;
3874 if (appData.monoMode)
3881 cairo_move_to (cr, xpos, ypos);
3882 cairo_text_path (cr, string);
3883 cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
3884 cairo_fill_preserve (cr);
3885 cairo_set_source_rgb (cr, 0, 0, 1.0);
3886 cairo_set_line_width (cr, 0.1);
3898 /* Returns 1 if there are "too many" differences between b1 and b2
3899 (i.e. more than 1 move was made) */
3900 static int too_many_diffs(b1, b2)
3906 for (i=0; i<BOARD_HEIGHT; ++i) {
3907 for (j=0; j<BOARD_WIDTH; ++j) {
3908 if (b1[i][j] != b2[i][j]) {
3909 if (++c > 4) /* Castling causes 4 diffs */
3918 /* Matrix describing castling maneuvers */
3919 /* Row, ColRookFrom, ColKingFrom, ColRookTo, ColKingTo */
3920 static int castling_matrix[4][5] = {
3921 { 0, 0, 4, 3, 2 }, /* 0-0-0, white */
3922 { 0, 7, 4, 5, 6 }, /* 0-0, white */
3923 { 7, 0, 4, 3, 2 }, /* 0-0-0, black */
3924 { 7, 7, 4, 5, 6 } /* 0-0, black */
3927 /* Checks whether castling occurred. If it did, *rrow and *rcol
3928 are set to the destination (row,col) of the rook that moved.
3930 Returns 1 if castling occurred, 0 if not.
3932 Note: Only handles a max of 1 castling move, so be sure
3933 to call too_many_diffs() first.
3935 static int check_castle_draw(newb, oldb, rrow, rcol)
3942 /* For each type of castling... */
3943 for (i=0; i<4; ++i) {
3944 r = castling_matrix[i];
3946 /* Check the 4 squares involved in the castling move */
3948 for (j=1; j<=4; ++j) {
3949 if (newb[r[0]][r[j]] == oldb[r[0]][r[j]]) {
3956 /* All 4 changed, so it must be a castling move */
3965 static int damage[BOARD_SIZE][BOARD_SIZE];
3968 * event handler for redrawing the board
3970 void DrawPosition( repaint, board)
3971 /*Boolean*/int repaint;
3975 static int lastFlipView = 0;
3976 static int lastBoardValid = 0;
3977 static Board lastBoard;
3980 if (board == NULL) {
3981 if (!lastBoardValid) return;
3984 if (!lastBoardValid || lastFlipView != flipView) {
3985 // XtSetArg(args[0], XtNleftBitmap, (flipView ? xMarkPixmap : None));
3986 // XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flip View"),
3991 * It would be simpler to clear the window with XClearWindow()
3992 * but this causes a very distracting flicker.
3995 if (!repaint && lastBoardValid && lastFlipView == flipView)
3997 /* If too much changes (begin observing new game, etc.), don't
3999 do_flash = too_many_diffs(board, lastBoard) ? 0 : 1;
4001 /* Special check for castling so we don't flash both the king
4002 and the rook (just flash the king). */
4005 if (check_castle_draw(board, lastBoard, &rrow, &rcol))
4007 /* Draw rook with NO flashing. King will be drawn flashing later */
4008 DrawSquare(rrow, rcol, board[rrow][rcol], 0);
4009 lastBoard[rrow][rcol] = board[rrow][rcol];
4013 /* First pass -- Draw (newly) empty squares and repair damage.
4014 This prevents you from having a piece show up twice while it
4015 is flashing on its new square */
4016 for (i = 0; i < BOARD_HEIGHT; i++)
4017 for (j = 0; j < BOARD_WIDTH; j++)
4018 if ((board[i][j] != lastBoard[i][j] && board[i][j] == EmptySquare)
4021 DrawSquare(i, j, board[i][j], 0);
4022 damage[i][j] = False;
4025 /* Second pass -- Draw piece(s) in new position and flash them */
4026 for (i = 0; i < BOARD_HEIGHT; i++)
4027 for (j = 0; j < BOARD_WIDTH; j++)
4028 if (board[i][j] != lastBoard[i][j])
4030 DrawSquare(i, j, board[i][j], do_flash);
4042 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
4044 cairo_set_line_width (cr, lineGap);
4046 /* TODO: use appdata colors */
4047 cairo_set_source_rgba (cr, 0, 1, 0, 1.0);
4051 for (i = 0; i < BOARD_HEIGHT + 1; i++)
4054 x2 = lineGap + BOARD_WIDTH * (squareSize + lineGap);
4055 y1 = y2 = lineGap / 2 + (i * (squareSize + lineGap));
4057 cairo_move_to (cr, x1, y1);
4058 cairo_rel_line_to (cr, x2,0);
4062 for (j = 0; j < BOARD_WIDTH + 1; j++)
4065 y2 = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
4066 x1 = x2 = lineGap / 2 + (j * (squareSize + lineGap));
4068 cairo_move_to (cr, x1, y1);
4069 cairo_rel_line_to (cr, 0, y2);
4078 for (i = 0; i < BOARD_HEIGHT; i++)
4079 for (j = 0; j < BOARD_WIDTH; j++)
4081 DrawSquare(i, j, board[i][j], 0);
4082 damage[i][j] = False;
4086 CopyBoard(lastBoard, board);
4088 lastFlipView = flipView;
4090 /* Draw highlights */
4091 if (pm1X >= 0 && pm1Y >= 0)
4093 drawHighlight(pm1X, pm1Y, LINE_TYPE_PRE);
4095 if (pm2X >= 0 && pm2Y >= 0)
4097 drawHighlight(pm2X, pm2Y, LINE_TYPE_PRE);
4099 if (hi1X >= 0 && hi1Y >= 0)
4101 drawHighlight(hi1X, hi1Y, LINE_TYPE_HIGHLIGHT);
4103 if (hi2X >= 0 && hi2Y >= 0)
4105 drawHighlight(hi2X, hi2Y, LINE_TYPE_HIGHLIGHT);
4108 /* If piece being dragged around board, must redraw that too */
4115 * event handler for parsing user moves
4117 // [HGM] This routine will need quite some reworking. Although the backend still supports the old
4118 // way of doing things, by calling UserMoveEvent() to test the legality of the move and then perform
4119 // it at the end, and doing all kind of preliminary tests here (e.g. to weed out self-captures), it
4120 // should be made to use the new way, of calling UserMoveTest early to determine the legality of the
4121 // move, (which will weed out the illegal selfcaptures and moves into the holdings, and flag promotions),
4122 // and at the end FinishMove() to perform the move after optional promotion popups.
4123 // For now I patched it to allow self-capture with King, and suppress clicks between board and holdings.
4124 void HandleUserMove(w, event, prms, nprms)
4131 Boolean saveAnimate;
4132 static int second = 0;
4134 if (w != boardWidget || errorExitStatus != -1) return;
4136 if (event->type == ButtonPress) ErrorPopDown();
4139 if (event->type == ButtonPress) {
4140 // XtPopdown(promotionShell);
4141 // XtDestroyWidget(promotionShell);
4142 promotionUp = False;
4150 x = EventToSquare(event->xbutton.x, BOARD_WIDTH);
4151 y = EventToSquare(event->xbutton.y, BOARD_HEIGHT);
4152 if (!flipView && y >= 0) {
4153 y = BOARD_HEIGHT - 1 - y;
4155 if (flipView && x >= 0) {
4156 x = BOARD_WIDTH - 1 - x;
4159 /* [HGM] holdings: next 5 lines: ignore all clicks between board and holdings */
4160 if(event->type == ButtonPress
4161 && ( x == BOARD_LEFT-1 ||
4163 (x == BOARD_LEFT-2 && y < BOARD_HEIGHT-gameInfo.holdingsSize ) ||
4164 (x == BOARD_RGHT+1 && y >= gameInfo.holdingsSize)) )
4168 if (event->type == ButtonPress) {
4170 if (OKToStartUserMove(x, y)) {
4174 DragPieceBegin(event->xbutton.x, event->xbutton.y);
4175 if (appData.highlightDragging) {
4176 SetHighlights(x, y, -1, -1);
4184 if (event->type == ButtonPress && gameMode != EditPosition &&
4189 /* Check if clicking again on the same color piece */
4190 fromP = boards[currentMove][fromY][fromX];
4191 toP = boards[currentMove][y][x];
4192 if ((WhitePawn <= fromP && fromP < WhiteKing && // [HGM] this test should go, as UserMoveTest now does it.
4193 WhitePawn <= toP && toP <= WhiteKing) || // For now I made it less critical by exempting King
4194 (BlackPawn <= fromP && fromP < BlackKing && // moves, to not interfere with FRC castlings.
4195 BlackPawn <= toP && toP <= BlackKing)) {
4196 /* Clicked again on same color piece -- changed his mind */
4197 second = (x == fromX && y == fromY);
4198 if (appData.highlightDragging) {
4199 SetHighlights(x, y, -1, -1);
4203 if (OKToStartUserMove(x, y)) {
4206 DragPieceBegin(event->xbutton.x, event->xbutton.y);
4212 if (event->type == ButtonRelease && x == fromX && y == fromY) {
4213 DragPieceEnd(event->xbutton.x, event->xbutton.y);
4214 if (appData.animateDragging) {
4215 /* Undo animation damage if any */
4216 DrawPosition(FALSE, NULL);
4219 /* Second up/down in same square; just abort move */
4224 ClearPremoveHighlights();
4226 /* First upclick in same square; start click-click mode */
4227 SetHighlights(x, y, -1, -1);
4232 /* Completed move */
4235 saveAnimate = appData.animate;
4236 if (event->type == ButtonPress) {
4237 /* Finish clickclick move */
4238 if (appData.animate || appData.highlightLastMove) {
4239 SetHighlights(fromX, fromY, toX, toY);
4244 /* Finish drag move */
4245 if (appData.highlightLastMove) {
4246 SetHighlights(fromX, fromY, toX, toY);
4250 DragPieceEnd(event->xbutton.x, event->xbutton.y);
4251 /* Don't animate move and drag both */
4252 appData.animate = FALSE;
4254 if (IsPromotion(fromX, fromY, toX, toY)) {
4255 if (appData.alwaysPromoteToQueen) {
4256 UserMoveEvent(fromX, fromY, toX, toY, 'q');
4257 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
4258 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
4261 SetHighlights(fromX, fromY, toX, toY);
4265 UserMoveEvent(fromX, fromY, toX, toY, NULLCHAR);
4266 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
4267 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
4270 appData.animate = saveAnimate;
4271 if (appData.animate || appData.animateDragging) {
4272 /* Undo animation damage if needed */
4273 DrawPosition(FALSE, NULL);
4277 void AnimateUserMove (Widget w, XEvent * event,
4278 String * params, Cardinal * nParams)
4280 DragPieceMove(event->xmotion.x, event->xmotion.y);
4283 Widget CommentCreate(name, text, mutable, callback, lines)
4285 int /*Boolean*/ mutable;
4286 XtCallbackProc callback;
4290 Widget shell, layout, form, edit, b_ok, b_cancel, b_clear, b_close, b_edit;
4295 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4296 XtGetValues(boardWidget, args, j);
4299 XtSetArg(args[j], XtNresizable, True); j++;
4302 XtCreatePopupShell(name, topLevelShellWidgetClass,
4303 shellWidget, args, j);
4306 XtCreatePopupShell(name, transientShellWidgetClass,
4307 shellWidget, args, j);
4310 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
4311 layoutArgs, XtNumber(layoutArgs));
4313 XtCreateManagedWidget("form", formWidgetClass, layout,
4314 formArgs, XtNumber(formArgs));
4318 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
4319 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
4321 XtSetArg(args[j], XtNstring, text); j++;
4322 XtSetArg(args[j], XtNtop, XtChainTop); j++;
4323 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4324 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4325 XtSetArg(args[j], XtNright, XtChainRight); j++;
4326 XtSetArg(args[j], XtNresizable, True); j++;
4327 XtSetArg(args[j], XtNwidth, bw_width); j++; /*force wider than buttons*/
4329 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
4331 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
4332 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
4334 XtSetArg(args[j], XtNautoFill, True); j++;
4335 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
4337 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
4341 XtSetArg(args[j], XtNfromVert, edit); j++;
4342 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4343 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4344 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4345 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4347 XtCreateManagedWidget(_("ok"), commandWidgetClass, form, args, j);
4348 XtAddCallback(b_ok, XtNcallback, callback, (XtPointer) 0);
4351 XtSetArg(args[j], XtNfromVert, edit); j++;
4352 XtSetArg(args[j], XtNfromHoriz, b_ok); j++;
4353 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4354 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4355 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4356 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4358 XtCreateManagedWidget(_("cancel"), commandWidgetClass, form, args, j);
4359 XtAddCallback(b_cancel, XtNcallback, callback, (XtPointer) 0);
4362 XtSetArg(args[j], XtNfromVert, edit); j++;
4363 XtSetArg(args[j], XtNfromHoriz, b_cancel); j++;
4364 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4365 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4366 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4367 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4369 XtCreateManagedWidget(_("clear"), commandWidgetClass, form, args, j);
4370 XtAddCallback(b_clear, XtNcallback, callback, (XtPointer) 0);
4373 XtSetArg(args[j], XtNfromVert, edit); j++;
4374 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4375 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4376 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4377 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4379 XtCreateManagedWidget(_("close"), commandWidgetClass, form, args, j);
4380 XtAddCallback(b_close, XtNcallback, callback, (XtPointer) 0);
4383 XtSetArg(args[j], XtNfromVert, edit); j++;
4384 XtSetArg(args[j], XtNfromHoriz, b_close); j++;
4385 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4386 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4387 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4388 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4390 XtCreateManagedWidget(_("edit"), commandWidgetClass, form, args, j);
4391 XtAddCallback(b_edit, XtNcallback, callback, (XtPointer) 0);
4394 XtRealizeWidget(shell);
4396 if (commentX == -1) {
4399 Dimension pw_height;
4400 Dimension ew_height;
4403 XtSetArg(args[j], XtNheight, &ew_height); j++;
4404 XtGetValues(edit, args, j);
4407 XtSetArg(args[j], XtNheight, &pw_height); j++;
4408 XtGetValues(shell, args, j);
4409 commentH = pw_height + (lines - 1) * ew_height;
4410 commentW = bw_width - 16;
4412 XSync(xDisplay, False);
4414 /* This code seems to tickle an X bug if it is executed too soon
4415 after xboard starts up. The coordinates get transformed as if
4416 the main window was positioned at (0, 0).
4418 XtTranslateCoords(shellWidget,
4419 (bw_width - commentW) / 2, 0 - commentH / 2,
4420 &commentX, &commentY);
4422 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
4423 RootWindowOfScreen(XtScreen(shellWidget)),
4424 (bw_width - commentW) / 2, 0 - commentH / 2,
4429 if (commentY < 0) commentY = 0; /*avoid positioning top offscreen*/
4432 XtSetArg(args[j], XtNheight, commentH); j++;
4433 XtSetArg(args[j], XtNwidth, commentW); j++;
4434 XtSetArg(args[j], XtNx, commentX); j++;
4435 XtSetArg(args[j], XtNy, commentY); j++;
4436 XtSetValues(shell, args, j);
4437 XtSetKeyboardFocus(shell, edit);
4442 /* Used for analysis window and ICS input window */
4443 Widget MiscCreate(name, text, mutable, callback, lines)
4445 int /*Boolean*/ mutable;
4446 XtCallbackProc callback;
4450 Widget shell, layout, form, edit;
4452 Dimension bw_width, pw_height, ew_height, w, h;
4458 XtSetArg(args[j], XtNresizable, True); j++;
4461 XtCreatePopupShell(name, topLevelShellWidgetClass,
4462 shellWidget, args, j);
4465 XtCreatePopupShell(name, transientShellWidgetClass,
4466 shellWidget, args, j);
4469 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
4470 layoutArgs, XtNumber(layoutArgs));
4472 XtCreateManagedWidget("form", formWidgetClass, layout,
4473 formArgs, XtNumber(formArgs));
4477 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
4478 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
4480 XtSetArg(args[j], XtNstring, text); j++;
4481 XtSetArg(args[j], XtNtop, XtChainTop); j++;
4482 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4483 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4484 XtSetArg(args[j], XtNright, XtChainRight); j++;
4485 XtSetArg(args[j], XtNresizable, True); j++;
4487 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
4489 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
4490 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
4492 XtSetArg(args[j], XtNautoFill, True); j++;
4493 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
4495 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
4497 XtRealizeWidget(shell);
4500 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4501 XtGetValues(boardWidget, args, j);
4504 XtSetArg(args[j], XtNheight, &ew_height); j++;
4505 XtGetValues(edit, args, j);
4508 XtSetArg(args[j], XtNheight, &pw_height); j++;
4509 XtGetValues(shell, args, j);
4510 h = pw_height + (lines - 1) * ew_height;
4513 XSync(xDisplay, False);
4515 /* This code seems to tickle an X bug if it is executed too soon
4516 after xboard starts up. The coordinates get transformed as if
4517 the main window was positioned at (0, 0).
4519 XtTranslateCoords(shellWidget, (bw_width - w) / 2, 0 - h / 2, &x, &y);
4521 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
4522 RootWindowOfScreen(XtScreen(shellWidget)),
4523 (bw_width - w) / 2, 0 - h / 2, &xx, &yy, &junk);
4527 if (y < 0) y = 0; /*avoid positioning top offscreen*/
4530 XtSetArg(args[j], XtNheight, h); j++;
4531 XtSetArg(args[j], XtNwidth, w); j++;
4532 XtSetArg(args[j], XtNx, x); j++;
4533 XtSetArg(args[j], XtNy, y); j++;
4534 XtSetValues(shell, args, j);
4540 static int savedIndex; /* gross that this is global */
4542 void EditCommentPopUp(index, title, text)
4551 if (text == NULL) text = "";
4553 if (editShell == NULL) {
4555 CommentCreate(title, text, True, EditCommentCallback, 4);
4556 XtRealizeWidget(editShell);
4557 CatchDeleteWindow(editShell, "EditCommentPopDown");
4559 edit = XtNameToWidget(editShell, "*form.text");
4561 XtSetArg(args[j], XtNstring, text); j++;
4562 XtSetValues(edit, args, j);
4564 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4565 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4566 XtSetValues(editShell, args, j);
4569 XtPopup(editShell, XtGrabNone);
4573 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
4574 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
4578 void EditCommentCallback(w, client_data, call_data)
4580 XtPointer client_data, call_data;
4588 XtSetArg(args[j], XtNlabel, &name); j++;
4589 XtGetValues(w, args, j);
4591 if (strcmp(name, _("ok")) == 0) {
4592 edit = XtNameToWidget(editShell, "*form.text");
4594 XtSetArg(args[j], XtNstring, &val); j++;
4595 XtGetValues(edit, args, j);
4596 ReplaceComment(savedIndex, val);
4597 EditCommentPopDown();
4598 } else if (strcmp(name, _("cancel")) == 0) {
4599 EditCommentPopDown();
4600 } else if (strcmp(name, _("clear")) == 0) {
4601 edit = XtNameToWidget(editShell, "*form.text");
4602 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
4603 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
4607 void EditCommentPopDown()
4612 if (!editUp) return;
4614 XtSetArg(args[j], XtNx, &commentX); j++;
4615 XtSetArg(args[j], XtNy, &commentY); j++;
4616 XtSetArg(args[j], XtNheight, &commentH); j++;
4617 XtSetArg(args[j], XtNwidth, &commentW); j++;
4618 XtGetValues(editShell, args, j);
4619 XtPopdown(editShell);
4622 XtSetArg(args[j], XtNleftBitmap, None); j++;
4623 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
4627 void ICSInputBoxPopUp()
4632 char *title = _("ICS Input");
4635 if (ICSInputShell == NULL) {
4636 ICSInputShell = MiscCreate(title, "", True, NULL, 1);
4637 tr = XtParseTranslationTable(ICSInputTranslations);
4638 edit = XtNameToWidget(ICSInputShell, "*form.text");
4639 XtOverrideTranslations(edit, tr);
4640 XtRealizeWidget(ICSInputShell);
4641 CatchDeleteWindow(ICSInputShell, "ICSInputBoxPopDown");
4644 edit = XtNameToWidget(ICSInputShell, "*form.text");
4646 XtSetArg(args[j], XtNstring, ""); j++;
4647 XtSetValues(edit, args, j);
4649 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4650 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4651 XtSetValues(ICSInputShell, args, j);
4654 XtPopup(ICSInputShell, XtGrabNone);
4655 XtSetKeyboardFocus(ICSInputShell, edit);
4657 ICSInputBoxUp = True;
4659 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
4660 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
4664 void ICSInputSendText()
4671 edit = XtNameToWidget(ICSInputShell, "*form.text");
4673 XtSetArg(args[j], XtNstring, &val); j++;
4674 XtGetValues(edit, args, j);
4675 SendMultiLineToICS(val);
4676 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
4677 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
4680 void ICSInputBoxPopDown()
4685 if (!ICSInputBoxUp) return;
4687 XtPopdown(ICSInputShell);
4688 ICSInputBoxUp = False;
4690 XtSetArg(args[j], XtNleftBitmap, None); j++;
4691 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
4695 void CommentPopUp(title, text)
4702 if (commentShell == NULL) {
4704 CommentCreate(title, text, False, CommentCallback, 4);
4705 XtRealizeWidget(commentShell);
4706 CatchDeleteWindow(commentShell, "CommentPopDown");
4708 edit = XtNameToWidget(commentShell, "*form.text");
4710 XtSetArg(args[j], XtNstring, text); j++;
4711 XtSetValues(edit, args, j);
4713 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4714 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4715 XtSetValues(commentShell, args, j);
4718 XtPopup(commentShell, XtGrabNone);
4719 XSync(xDisplay, False);
4724 void AnalysisPopUp(title, text)
4731 if (analysisShell == NULL) {
4732 analysisShell = MiscCreate(title, text, False, NULL, 4);
4733 XtRealizeWidget(analysisShell);
4734 CatchDeleteWindow(analysisShell, "AnalysisPopDown");
4737 edit = XtNameToWidget(analysisShell, "*form.text");
4739 XtSetArg(args[j], XtNstring, text); j++;
4740 XtSetValues(edit, args, j);
4742 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4743 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4744 XtSetValues(analysisShell, args, j);
4748 XtPopup(analysisShell, XtGrabNone);
4750 XSync(xDisplay, False);
4755 void CommentCallback(w, client_data, call_data)
4757 XtPointer client_data, call_data;
4764 XtSetArg(args[j], XtNlabel, &name); j++;
4765 XtGetValues(w, args, j);
4767 if (strcmp(name, _("close")) == 0) {
4769 } else if (strcmp(name, _("edit")) == 0) {
4776 void CommentPopDown()
4781 if (!commentUp) return;
4783 XtSetArg(args[j], XtNx, &commentX); j++;
4784 XtSetArg(args[j], XtNy, &commentY); j++;
4785 XtSetArg(args[j], XtNwidth, &commentW); j++;
4786 XtSetArg(args[j], XtNheight, &commentH); j++;
4787 XtGetValues(commentShell, args, j);
4788 XtPopdown(commentShell);
4789 XSync(xDisplay, False);
4793 void AnalysisPopDown()
4795 if (!analysisUp) return;
4796 XtPopdown(analysisShell);
4797 XSync(xDisplay, False);
4799 if (appData.icsEngineAnalyze) ExitAnalyzeMode(); /* [DM] icsEngineAnalyze */
4803 void FileNamePopUp(label, def, proc, openMode)
4810 Widget popup, layout, dialog, edit;
4816 fileProc = proc; /* I can't see a way not */
4817 fileOpenMode = openMode; /* to use globals here */
4820 XtSetArg(args[i], XtNresizable, True); i++;
4821 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
4822 XtSetArg(args[i], XtNtitle, XtNewString(_("File name prompt"))); i++;
4823 fileNameShell = popup =
4824 XtCreatePopupShell("File name prompt", transientShellWidgetClass,
4825 shellWidget, args, i);
4828 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
4829 layoutArgs, XtNumber(layoutArgs));
4832 XtSetArg(args[i], XtNlabel, label); i++;
4833 XtSetArg(args[i], XtNvalue, def); i++;
4834 XtSetArg(args[i], XtNborderWidth, 0); i++;
4835 dialog = XtCreateManagedWidget("fileName", dialogWidgetClass,
4838 XawDialogAddButton(dialog, _("ok"), FileNameCallback, (XtPointer) dialog);
4839 XawDialogAddButton(dialog, _("cancel"), FileNameCallback,
4840 (XtPointer) dialog);
4842 XtRealizeWidget(popup);
4843 CatchDeleteWindow(popup, "FileNamePopDown");
4845 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
4846 &x, &y, &win_x, &win_y, &mask);
4848 XtSetArg(args[0], XtNx, x - 10);
4849 XtSetArg(args[1], XtNy, y - 30);
4850 XtSetValues(popup, args, 2);
4852 XtPopup(popup, XtGrabExclusive);
4855 edit = XtNameToWidget(dialog, "*value");
4856 XtSetKeyboardFocus(popup, edit);
4859 void FileNamePopDown()
4861 if (!filenameUp) return;
4862 XtPopdown(fileNameShell);
4863 XtDestroyWidget(fileNameShell);
4868 void FileNameCallback(w, client_data, call_data)
4870 XtPointer client_data, call_data;
4875 XtSetArg(args[0], XtNlabel, &name);
4876 XtGetValues(w, args, 1);
4878 if (strcmp(name, _("cancel")) == 0) {
4883 FileNameAction(w, NULL, NULL, NULL);
4886 void FileNameAction(w, event, prms, nprms)
4898 name = XawDialogGetValueString(w = XtParent(w));
4900 if ((name != NULL) && (*name != NULLCHAR)) {
4902 XtPopdown(w = XtParent(XtParent(w)));
4906 p = strrchr(buf, ' ');
4913 fullname = ExpandPathName(buf);
4915 ErrorPopUp(_("Error"), _("Can't open file"), FALSE);
4918 f = fopen(fullname, fileOpenMode);
4920 DisplayError(_("Failed to open file"), errno);
4922 (void) (*fileProc)(f, index, buf);
4929 XtPopdown(w = XtParent(XtParent(w)));
4935 void PromotionPopUp()
4938 Widget dialog, layout;
4940 Dimension bw_width, pw_width;
4944 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4945 XtGetValues(boardWidget, args, j);
4948 XtSetArg(args[j], XtNresizable, True); j++;
4949 XtSetArg(args[j], XtNtitle, XtNewString(_("Promotion"))); j++;
4951 XtCreatePopupShell("Promotion", transientShellWidgetClass,
4952 shellWidget, args, j);
4954 XtCreateManagedWidget(layoutName, formWidgetClass, promotionShell,
4955 layoutArgs, XtNumber(layoutArgs));
4958 XtSetArg(args[j], XtNlabel, _("Promote to what?")); j++;
4959 XtSetArg(args[j], XtNborderWidth, 0); j++;
4960 dialog = XtCreateManagedWidget("promotion", dialogWidgetClass,
4963 if(gameInfo.variant != VariantShogi) {
4964 XawDialogAddButton(dialog, _("Queen"), PromotionCallback,
4965 (XtPointer) dialog);
4966 XawDialogAddButton(dialog, _("Rook"), PromotionCallback,
4967 (XtPointer) dialog);
4968 XawDialogAddButton(dialog, _("Bishop"), PromotionCallback,
4969 (XtPointer) dialog);
4970 XawDialogAddButton(dialog, _("Knight"), PromotionCallback,
4971 (XtPointer) dialog);
4972 if (!appData.testLegality || gameInfo.variant == VariantSuicide ||
4973 gameInfo.variant == VariantGiveaway) {
4974 XawDialogAddButton(dialog, _("King"), PromotionCallback,
4975 (XtPointer) dialog);
4977 if(gameInfo.variant == VariantCapablanca ||
4978 gameInfo.variant == VariantGothic ||
4979 gameInfo.variant == VariantCapaRandom) {
4980 XawDialogAddButton(dialog, _("Archbishop"), PromotionCallback,
4981 (XtPointer) dialog);
4982 XawDialogAddButton(dialog, _("Chancellor"), PromotionCallback,
4983 (XtPointer) dialog);
4985 } else // [HGM] shogi
4987 XawDialogAddButton(dialog, _("Promote"), PromotionCallback,
4988 (XtPointer) dialog);
4989 XawDialogAddButton(dialog, _("Defer"), PromotionCallback,
4990 (XtPointer) dialog);
4992 XawDialogAddButton(dialog, _("cancel"), PromotionCallback,
4993 (XtPointer) dialog);
4995 XtRealizeWidget(promotionShell);
4996 CatchDeleteWindow(promotionShell, "PromotionPopDown");
4999 XtSetArg(args[j], XtNwidth, &pw_width); j++;
5000 XtGetValues(promotionShell, args, j);
5002 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
5003 lineGap + squareSize/3 +
5004 ((toY == BOARD_HEIGHT-1) ^ (flipView) ?
5005 0 : 6*(squareSize + lineGap)), &x, &y);
5008 XtSetArg(args[j], XtNx, x); j++;
5009 XtSetArg(args[j], XtNy, y); j++;
5010 XtSetValues(promotionShell, args, j);
5012 XtPopup(promotionShell, XtGrabNone);
5017 void PromotionPopDown()
5019 if (!promotionUp) return;
5020 XtPopdown(promotionShell);
5021 XtDestroyWidget(promotionShell);
5022 promotionUp = False;
5025 void PromotionCallback(w, client_data, call_data)
5027 XtPointer client_data, call_data;
5033 XtSetArg(args[0], XtNlabel, &name);
5034 XtGetValues(w, args, 1);
5038 if (fromX == -1) return;
5040 if (strcmp(name, _("cancel")) == 0) {
5044 } else if (strcmp(name, _("Knight")) == 0) {
5046 } else if (strcmp(name, _("Promote")) == 0) {
5048 } else if (strcmp(name, _("Defer")) == 0) {
5051 promoChar = ToLower(name[0]);
5054 UserMoveEvent(fromX, fromY, toX, toY, promoChar);
5056 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
5057 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
5062 void ErrorCallback(w, client_data, call_data)
5064 XtPointer client_data, call_data;
5067 XtPopdown(w = XtParent(XtParent(XtParent(w))));
5069 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5075 if (!errorUp) return;
5079 gtk_widget_destroy(GTK_WIDGET(GUI_Error));
5081 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5086 void ErrorPopUp(title, label, modal)
5087 char *title, *label;
5090 GUI_Error = gtk_message_dialog_new(GTK_WINDOW(GUI_Window),
5091 GTK_DIALOG_DESTROY_WITH_PARENT,
5096 gtk_window_set_title(GTK_WINDOW(GUI_Error),(gchar *) title);
5099 gtk_dialog_run(GTK_DIALOG(GUI_Error));
5100 gtk_widget_destroy(GTK_WIDGET(GUI_Error));
5104 g_signal_connect_swapped (GUI_Error, "response",
5105 G_CALLBACK (ErrorPopDownProc),
5108 gtk_widget_show(GTK_WIDGET(GUI_Error));
5114 /* Disable all user input other than deleting the window */
5115 static int frozen = 0;
5119 /* Grab by a widget that doesn't accept input */
5120 // XtAddGrab(messageWidget, TRUE, FALSE);
5124 /* Undo a FreezeUI */
5127 if (!frozen) return;
5128 // XtRemoveGrab(messageWidget);
5132 char *ModeToWidgetName(mode)
5136 case BeginningOfGame:
5137 if (appData.icsActive)
5138 return "menuMode.ICS Client";
5139 else if (appData.noChessProgram ||
5140 *appData.cmailGameName != NULLCHAR)
5141 return "menuMode.Edit Game";
5143 return "menuMode.Machine Black";
5144 case MachinePlaysBlack:
5145 return "menuMode.Machine Black";
5146 case MachinePlaysWhite:
5147 return "menuMode.Machine White";
5149 return "menuMode.Analysis Mode";
5151 return "menuMode.Analyze File";
5152 case TwoMachinesPlay:
5153 return "menuMode.Two Machines";
5155 return "menuMode.Edit Game";
5156 case PlayFromGameFile:
5157 return "menuFile.Load Game";
5159 return "menuMode.Edit Position";
5161 return "menuMode.Training";
5162 case IcsPlayingWhite:
5163 case IcsPlayingBlack:
5167 return "menuMode.ICS Client";
5174 void ModeHighlight()
5176 static int oldPausing = FALSE;
5177 static GameMode oldmode = (GameMode) -1;
5180 // todo this toggling of the pause button doesn't seem to work?
5181 // e.g. select pause from buttonbar doesn't activate menumode.pause
5183 // if (!boardWidget || !XtIsRealized(boardWidget)) return;
5185 if (pausing != oldPausing) {
5186 oldPausing = pausing;
5187 gtk_button_set_relief(GTK_BUTTON (gtk_builder_get_object (builder, "menuMode.Pause")),pausing?GTK_RELIEF_NORMAL:GTK_RELIEF_NONE);
5188 /* toggle background color in showbuttonbar */
5189 if (appData.showButtonBar) {
5191 gtk_button_pressed(GTK_BUTTON (gtk_builder_get_object (builder, "buttonbar.Pause")));
5193 gtk_button_released(GTK_BUTTON (gtk_builder_get_object (builder, "buttonbar.Pause")));
5198 wname = ModeToWidgetName(oldmode);
5200 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, wname)),True);
5204 /* Maybe all the enables should be handled here, not just this one */
5205 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuMode.Training")),
5206 gameMode == Training || gameMode == PlayFromGameFile);
5211 * Button/menu procedures
5214 int LoadGamePopUp(f, gameNumber, title)
5219 cmailMsgLoaded = FALSE;
5220 if (gameNumber == 0) {
5221 int error = GameListBuild(f);
5223 DisplayError(_("Cannot build game list"), error);
5224 } else if (!ListEmpty(&gameList) &&
5225 ((ListGame *) gameList.tailPred)->number > 1) {
5226 GameListPopUp(f, title);
5232 return LoadGame(f, gameNumber, title, FALSE);
5236 void LoadNextPositionProc(w, event, prms, nprms)
5245 void LoadPrevPositionProc(w, event, prms, nprms)
5254 void ReloadPositionProc(w, event, prms, nprms)
5263 void LoadPositionProc(w, event, prms, nprms)
5269 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
5272 FileNamePopUp(_("Load position file name?"), "", LoadPosition, "rb");
5275 void SaveGameProc(w, event, prms, nprms)
5281 FileNamePopUp(_("Save game file name?"),
5282 DefaultFileName(appData.oldSaveStyle ? "game" : "pgn"),
5286 void SavePositionProc(w, event, prms, nprms)
5292 FileNamePopUp(_("Save position file name?"),
5293 DefaultFileName(appData.oldSaveStyle ? "pos" : "fen"),
5297 void ReloadCmailMsgProc(w, event, prms, nprms)
5303 ReloadCmailMsgEvent(FALSE);
5306 void MailMoveProc(w, event, prms, nprms)
5315 /* this variable is shared between CopyPositionProc and SendPositionSelection */
5316 static char *selected_fen_position=NULL;
5319 SendPositionSelection(Widget w, Atom *selection, Atom *target,
5320 Atom *type_return, XtPointer *value_return,
5321 unsigned long *length_return, int *format_return)
5323 char *selection_tmp;
5325 if (!selected_fen_position) return False; /* should never happen */
5326 if (*target == XA_STRING){
5327 /* note: since no XtSelectionDoneProc was registered, Xt will
5328 * automatically call XtFree on the value returned. So have to
5329 * make a copy of it allocated with XtMalloc */
5330 selection_tmp= XtMalloc(strlen(selected_fen_position)+16);
5331 strcpy(selection_tmp, selected_fen_position);
5333 *value_return=selection_tmp;
5334 *length_return=strlen(selection_tmp);
5335 *type_return=XA_STRING;
5336 *format_return = 8; /* bits per byte */
5343 /* note: when called from menu all parameters are NULL, so no clue what the
5344 * Widget which was clicked on was, or what the click event was
5346 void CopyPositionProc(w, event, prms, nprms)
5354 if (selected_fen_position) free(selected_fen_position);
5355 selected_fen_position = (char *)PositionToFEN(currentMove, NULL);
5356 if (!selected_fen_position) return;
5357 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
5359 SendPositionSelection,
5360 NULL/* lose_ownership_proc */ ,
5361 NULL/* transfer_done_proc */);
5363 free(selected_fen_position);
5364 selected_fen_position=NULL;
5368 /* function called when the data to Paste is ready */
5370 PastePositionCB(Widget w, XtPointer client_data, Atom *selection,
5371 Atom *type, XtPointer value, unsigned long *len, int *format)
5374 if (value==NULL || *len==0) return; /* nothing had been selected to copy */
5375 fenstr[*len]='\0'; /* normally this string is terminated, but be safe */
5376 EditPositionPasteFEN(fenstr);
5380 /* called when Paste Position button is pressed,
5381 * all parameters will be NULL */
5382 void PastePositionProc(w, event, prms, nprms)
5388 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
5389 /* (XtSelectionCallbackProc) */ PastePositionCB,
5390 NULL, /* client_data passed to PastePositionCB */
5392 /* better to use the time field from the event that triggered the
5393 * call to this function, but that isn't trivial to get
5401 SendGameSelection(Widget w, Atom *selection, Atom *target,
5402 Atom *type_return, XtPointer *value_return,
5403 unsigned long *length_return, int *format_return)
5405 char *selection_tmp;
5407 if (*target == XA_STRING){
5408 FILE* f = fopen(gameCopyFilename, "r");
5411 if (f == NULL) return False;
5415 selection_tmp = XtMalloc(len + 1);
5416 count = fread(selection_tmp, 1, len, f);
5418 XtFree(selection_tmp);
5421 selection_tmp[len] = NULLCHAR;
5422 *value_return = selection_tmp;
5423 *length_return = len;
5424 *type_return = XA_STRING;
5425 *format_return = 8; /* bits per byte */
5432 /* note: when called from menu all parameters are NULL, so no clue what the
5433 * Widget which was clicked on was, or what the click event was
5435 void CopyGameProc(w, event, prms, nprms)
5443 ret = SaveGameToFile(gameCopyFilename, FALSE);
5446 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
5449 NULL/* lose_ownership_proc */ ,
5450 NULL/* transfer_done_proc */);
5453 /* function called when the data to Paste is ready */
5455 PasteGameCB(Widget w, XtPointer client_data, Atom *selection,
5456 Atom *type, XtPointer value, unsigned long *len, int *format)
5459 if (value == NULL || *len == 0) {
5460 return; /* nothing had been selected to copy */
5462 f = fopen(gamePasteFilename, "w");
5464 DisplayError(_("Can't open temp file"), errno);
5467 fwrite(value, 1, *len, f);
5470 LoadGameFromFile(gamePasteFilename, 0, gamePasteFilename, TRUE);
5473 /* called when Paste Game button is pressed,
5474 * all parameters will be NULL */
5475 void PasteGameProc(w, event, prms, nprms)
5481 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
5482 /* (XtSelectionCallbackProc) */ PasteGameCB,
5483 NULL, /* client_data passed to PasteGameCB */
5485 /* better to use the time field from the event that triggered the
5486 * call to this function, but that isn't trivial to get
5496 SaveGameProc(NULL, NULL, NULL, NULL);
5499 void AnalyzeModeProc(w, event, prms, nprms)
5507 if (!first.analysisSupport) {
5508 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
5509 DisplayError(buf, 0);
5512 /* [DM] icsEngineAnalyze [HGM] This is horrible code; reverse the gameMode and isEngineAnalyze tests! */
5513 if (appData.icsActive) {
5514 if (gameMode != IcsObserving) {
5515 sprintf(buf,_("You are not observing a game"));
5516 DisplayError(buf, 0);
5518 if (appData.icsEngineAnalyze) {
5519 if (appData.debugMode)
5520 fprintf(debugFP, _("Found unexpected active ICS engine analyze \n"));
5526 /* if enable, use want disable icsEngineAnalyze */
5527 if (appData.icsEngineAnalyze) {
5532 appData.icsEngineAnalyze = TRUE;
5533 if (appData.debugMode)
5534 fprintf(debugFP, _("ICS engine analyze starting... \n"));
5536 if (!appData.showThinking)
5537 ShowThinkingProc(w,event,prms,nprms);
5542 void AnalyzeFileProc(w, event, prms, nprms)
5548 if (!first.analysisSupport) {
5550 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
5551 DisplayError(buf, 0);
5556 if (!appData.showThinking)
5557 ShowThinkingProc(w,event,prms,nprms);
5560 FileNamePopUp(_("File to analyze"), "", LoadGamePopUp, "rb");
5561 AnalysisPeriodicEvent(1);
5564 void IcsClientProc(w, event, prms, nprms)
5573 void EditGameProc(w, event, prms, nprms)
5582 void EditPositionProc(w, event, prms, nprms)
5588 EditPositionEvent();
5591 void TrainingProc(w, event, prms, nprms)
5600 void EditCommentProc(w, event, prms, nprms)
5607 EditCommentPopDown();
5613 void IcsInputBoxProc(w, event, prms, nprms)
5619 if (ICSInputBoxUp) {
5620 ICSInputBoxPopDown();
5627 void EnterKeyProc(w, event, prms, nprms)
5633 if (ICSInputBoxUp == True)
5638 void ForwardProc(w, event, prms, nprms)
5648 void BackwardProc(w, event, prms, nprms)
5657 void ToStartProc(w, event, prms, nprms)
5666 void ToEndProc(w, event, prms, nprms)
5675 void RevertProc(w, event, prms, nprms)
5684 void TruncateGameProc(w, event, prms, nprms)
5690 TruncateGameEvent();
5692 void RetractMoveProc(w, event, prms, nprms)
5701 void AlwaysQueenProc(w, event, prms, nprms)
5709 appData.alwaysPromoteToQueen = !appData.alwaysPromoteToQueen;
5711 if (appData.alwaysPromoteToQueen) {
5712 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5714 XtSetArg(args[0], XtNleftBitmap, None);
5716 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
5720 void AnimateDraggingProc(w, event, prms, nprms)
5728 appData.animateDragging = !appData.animateDragging;
5730 if (appData.animateDragging) {
5731 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5734 XtSetArg(args[0], XtNleftBitmap, None);
5736 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Dragging"),
5740 void AnimateMovingProc(w, event, prms, nprms)
5748 appData.animate = !appData.animate;
5750 if (appData.animate) {
5751 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5754 XtSetArg(args[0], XtNleftBitmap, None);
5756 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
5760 void AutocommProc(w, event, prms, nprms)
5768 appData.autoComment = !appData.autoComment;
5770 if (appData.autoComment) {
5771 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5773 XtSetArg(args[0], XtNleftBitmap, None);
5775 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
5780 void AutoflagProc(w, event, prms, nprms)
5788 appData.autoCallFlag = !appData.autoCallFlag;
5790 if (appData.autoCallFlag) {
5791 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5793 XtSetArg(args[0], XtNleftBitmap, None);
5795 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
5799 void AutoflipProc(w, event, prms, nprms)
5807 appData.autoFlipView = !appData.autoFlipView;
5809 if (appData.autoFlipView) {
5810 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5812 XtSetArg(args[0], XtNleftBitmap, None);
5814 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flip View"),
5818 void AutobsProc(w, event, prms, nprms)
5826 appData.autoObserve = !appData.autoObserve;
5828 if (appData.autoObserve) {
5829 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5831 XtSetArg(args[0], XtNleftBitmap, None);
5833 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
5837 void AutoraiseProc(w, event, prms, nprms)
5845 appData.autoRaiseBoard = !appData.autoRaiseBoard;
5847 if (appData.autoRaiseBoard) {
5848 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5850 XtSetArg(args[0], XtNleftBitmap, None);
5852 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Raise Board"),
5856 void AutosaveProc(w, event, prms, nprms)
5864 appData.autoSaveGames = !appData.autoSaveGames;
5866 if (appData.autoSaveGames) {
5867 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5869 XtSetArg(args[0], XtNleftBitmap, None);
5871 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
5875 void BlindfoldProc(w, event, prms, nprms)
5883 appData.blindfold = !appData.blindfold;
5885 if (appData.blindfold) {
5886 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5888 XtSetArg(args[0], XtNleftBitmap, None);
5890 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Blindfold"),
5893 DrawPosition(True, NULL);
5896 void TestLegalityProc(w, event, prms, nprms)
5904 appData.testLegality = !appData.testLegality;
5906 if (appData.testLegality) {
5907 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5909 XtSetArg(args[0], XtNleftBitmap, None);
5911 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Test Legality"),
5916 void FlashMovesProc(w, event, prms, nprms)
5924 if (appData.flashCount == 0) {
5925 appData.flashCount = 3;
5927 appData.flashCount = -appData.flashCount;
5930 if (appData.flashCount > 0) {
5931 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5933 XtSetArg(args[0], XtNleftBitmap, None);
5935 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flash Moves"),
5939 void FlipViewProc(w, event, prms, nprms)
5945 flipView = !flipView;
5946 DrawPosition(True, NULL);
5949 void GetMoveListProc(w, event, prms, nprms)
5957 appData.getMoveList = !appData.getMoveList;
5959 if (appData.getMoveList) {
5960 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5963 XtSetArg(args[0], XtNleftBitmap, None);
5965 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
5970 void HighlightDraggingProc(w, event, prms, nprms)
5978 appData.highlightDragging = !appData.highlightDragging;
5980 if (appData.highlightDragging) {
5981 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5983 XtSetArg(args[0], XtNleftBitmap, None);
5985 XtSetValues(XtNameToWidget(menuBarWidget,
5986 "menuOptions.Highlight Dragging"), args, 1);
5990 void HighlightLastMoveProc(w, event, prms, nprms)
5998 appData.highlightLastMove = !appData.highlightLastMove;
6000 if (appData.highlightLastMove) {
6001 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6003 XtSetArg(args[0], XtNleftBitmap, None);
6005 XtSetValues(XtNameToWidget(menuBarWidget,
6006 "menuOptions.Highlight Last Move"), args, 1);
6009 void IcsAlarmProc(w, event, prms, nprms)
6017 appData.icsAlarm = !appData.icsAlarm;
6019 if (appData.icsAlarm) {
6020 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6022 XtSetArg(args[0], XtNleftBitmap, None);
6024 XtSetValues(XtNameToWidget(menuBarWidget,
6025 "menuOptions.ICS Alarm"), args, 1);
6028 void MoveSoundProc(w, event, prms, nprms)
6036 appData.ringBellAfterMoves = !appData.ringBellAfterMoves;
6038 if (appData.ringBellAfterMoves) {
6039 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6041 XtSetArg(args[0], XtNleftBitmap, None);
6043 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
6048 void OldSaveStyleProc(w, event, prms, nprms)
6056 appData.oldSaveStyle = !appData.oldSaveStyle;
6058 if (appData.oldSaveStyle) {
6059 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6061 XtSetArg(args[0], XtNleftBitmap, None);
6063 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Old Save Style"),
6067 void PeriodicUpdatesProc(w, event, prms, nprms)
6075 PeriodicUpdatesEvent(!appData.periodicUpdates);
6077 if (appData.periodicUpdates) {
6078 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6080 XtSetArg(args[0], XtNleftBitmap, None);
6082 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Periodic Updates"),
6086 void PonderNextMoveProc(w, event, prms, nprms)
6094 PonderNextMoveEvent(!appData.ponderNextMove);
6096 if (appData.ponderNextMove) {
6097 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6099 XtSetArg(args[0], XtNleftBitmap, None);
6101 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Ponder Next Move"),
6105 void PopupExitMessageProc(w, event, prms, nprms)
6113 appData.popupExitMessage = !appData.popupExitMessage;
6115 if (appData.popupExitMessage) {
6116 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6118 XtSetArg(args[0], XtNleftBitmap, None);
6120 XtSetValues(XtNameToWidget(menuBarWidget,
6121 "menuOptions.Popup Exit Message"), args, 1);
6124 void PopupMoveErrorsProc(w, event, prms, nprms)
6132 appData.popupMoveErrors = !appData.popupMoveErrors;
6134 if (appData.popupMoveErrors) {
6135 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6137 XtSetArg(args[0], XtNleftBitmap, None);
6139 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Popup Move Errors"),
6143 void PremoveProc(w, event, prms, nprms)
6151 appData.premove = !appData.premove;
6153 if (appData.premove) {
6154 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6156 XtSetArg(args[0], XtNleftBitmap, None);
6158 XtSetValues(XtNameToWidget(menuBarWidget,
6159 "menuOptions.Premove"), args, 1);
6162 void QuietPlayProc(w, event, prms, nprms)
6170 appData.quietPlay = !appData.quietPlay;
6172 if (appData.quietPlay) {
6173 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6175 XtSetArg(args[0], XtNleftBitmap, None);
6177 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Quiet Play"),
6181 void ShowThinkingProc(w, event, prms, nprms)
6189 appData.showThinking = !appData.showThinking; // [HGM] thinking: tken out of ShowThinkingEvent
6190 ShowThinkingEvent();
6192 // [HGM] thinking: currently no suc menu item; replaced by Hide Thinking (From Human)
6193 if (appData.showThinking) {
6194 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6196 XtSetArg(args[0], XtNleftBitmap, None);
6198 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Thinking"),
6203 void HideThinkingProc(w, event, prms, nprms)
6211 appData.hideThinkingFromHuman = !appData.hideThinkingFromHuman; // [HGM] thinking: tken out of ShowThinkingEvent
6212 ShowThinkingEvent();
6214 if (appData.hideThinkingFromHuman) {
6215 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6217 XtSetArg(args[0], XtNleftBitmap, None);
6219 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
6223 void InfoProc(w, event, prms, nprms)
6230 snprintf(buf, sizeof(buf), "xterm -e info --directory %s --directory . -f %s &",
6235 void ManProc(w, event, prms, nprms)
6243 if (nprms && *nprms > 0)
6247 snprintf(buf, sizeof(buf), "xterm -e man %s &", name);
6251 void HintProc(w, event, prms, nprms)
6260 void BookProc(w, event, prms, nprms)
6269 void DebugProc(w, event, prms, nprms)
6275 appData.debugMode = !appData.debugMode;
6278 void AboutGameProc(w, event, prms, nprms)
6287 void NothingProc(w, event, prms, nprms)
6296 void Iconify(w, event, prms, nprms)
6305 XtSetArg(args[0], XtNiconic, True);
6306 XtSetValues(shellWidget, args, 1);
6309 void DisplayMessage(message, extMessage)
6310 gchar *message, *extMessage;
6317 snprintf(buf, sizeof(buf), "%s %s", message, extMessage);
6320 message = extMessage;
6323 gtk_label_set_text( GTK_LABEL(gtk_builder_get_object (builder, "Messages")),message);
6328 void DisplayTitle(text)
6331 gchar title[MSG_SIZ];
6333 if (text == NULL) text = "";
6335 if (appData.titleInWindow)
6340 if (*text != NULLCHAR)
6342 strcpy(title, text);
6344 else if (appData.icsActive)
6346 snprintf(title, sizeof(title), "%s: %s", programName, appData.icsHost);
6348 else if (appData.cmailGameName[0] != NULLCHAR)
6350 snprintf(title,sizeof(title), "%s: %s", programName, "CMail");
6352 // [HGM] license: This stuff should really be done in back-end, but WinBoard already had a pop-up for it
6354 else if (gameInfo.variant == VariantGothic)
6356 strcpy(title, GOTHIC);
6360 else if (gameInfo.variant == VariantFalcon)
6362 strcpy(title, FALCON);
6365 else if (appData.noChessProgram)
6367 strcpy(title, programName);
6371 snprintf(title,sizeof(title), "%s: %s", programName, first.tidy);
6373 gtk_window_set_title(GTK_WINDOW(GUI_Window),title);
6379 void DisplayError(message, error)
6386 if (appData.debugMode || appData.matchMode) {
6387 fprintf(stderr, "%s: %s\n", programName, message);
6390 if (appData.debugMode || appData.matchMode) {
6391 fprintf(stderr, "%s: %s: %s\n",
6392 programName, message, strerror(error));
6394 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
6397 ErrorPopUp(_("Error"), message, FALSE);
6401 void DisplayMoveError(message)
6406 DrawPosition(FALSE, NULL);
6407 if (appData.debugMode || appData.matchMode) {
6408 fprintf(stderr, "%s: %s\n", programName, message);
6410 if (appData.popupMoveErrors) {
6411 ErrorPopUp(_("Error"), message, FALSE);
6413 DisplayMessage(message, "");
6418 void DisplayFatalError(message, error, status)
6424 errorExitStatus = status;
6426 fprintf(stderr, "%s: %s\n", programName, message);
6428 fprintf(stderr, "%s: %s: %s\n",
6429 programName, message, strerror(error));
6430 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
6433 if (appData.popupExitMessage && boardWidget && XtIsRealized(boardWidget)) {
6434 ErrorPopUp(status ? _("Fatal Error") : _("Exiting"), message, TRUE);
6440 void DisplayInformation(message)
6444 ErrorPopUp(_("Information"), message, TRUE);
6447 void DisplayNote(message)
6451 ErrorPopUp(_("Note"), message, FALSE);
6455 NullXErrorCheck(dpy, error_event)
6457 XErrorEvent *error_event;
6462 void DisplayIcsInteractionTitle(message)
6465 if (oldICSInteractionTitle == NULL) {
6466 /* Magic to find the old window title, adapted from vim */
6467 char *wina = getenv("WINDOWID");
6469 Window win = (Window) atoi(wina);
6470 Window root, parent, *children;
6471 unsigned int nchildren;
6472 int (*oldHandler)() = XSetErrorHandler(NullXErrorCheck);
6474 if (XFetchName(xDisplay, win, &oldICSInteractionTitle)) break;
6475 if (!XQueryTree(xDisplay, win, &root, &parent,
6476 &children, &nchildren)) break;
6477 if (children) XFree((void *)children);
6478 if (parent == root || parent == 0) break;
6481 XSetErrorHandler(oldHandler);
6483 if (oldICSInteractionTitle == NULL) {
6484 oldICSInteractionTitle = "xterm";
6487 printf("\033]0;%s\007", message);
6491 char pendingReplyPrefix[MSG_SIZ];
6492 ProcRef pendingReplyPR;
6494 void AskQuestionProc(w, event, prms, nprms)
6501 fprintf(stderr, _("AskQuestionProc needed 4 parameters, got %d\n"),
6505 AskQuestionEvent(prms[0], prms[1], prms[2], prms[3]);
6508 void AskQuestionPopDown()
6510 if (!askQuestionUp) return;
6511 XtPopdown(askQuestionShell);
6512 XtDestroyWidget(askQuestionShell);
6513 askQuestionUp = False;
6516 void AskQuestionReplyAction(w, event, prms, nprms)
6526 reply = XawDialogGetValueString(w = XtParent(w));
6527 strcpy(buf, pendingReplyPrefix);
6528 if (*buf) strcat(buf, " ");
6531 OutputToProcess(pendingReplyPR, buf, strlen(buf), &err);
6532 AskQuestionPopDown();
6534 if (err) DisplayFatalError(_("Error writing to chess program"), err, 0);
6537 void AskQuestionCallback(w, client_data, call_data)
6539 XtPointer client_data, call_data;
6544 XtSetArg(args[0], XtNlabel, &name);
6545 XtGetValues(w, args, 1);
6547 if (strcmp(name, _("cancel")) == 0) {
6548 AskQuestionPopDown();
6550 AskQuestionReplyAction(w, NULL, NULL, NULL);
6554 void AskQuestion(title, question, replyPrefix, pr)
6555 char *title, *question, *replyPrefix;
6559 Widget popup, layout, dialog, edit;
6565 strcpy(pendingReplyPrefix, replyPrefix);
6566 pendingReplyPR = pr;
6569 XtSetArg(args[i], XtNresizable, True); i++;
6570 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
6571 askQuestionShell = popup =
6572 XtCreatePopupShell(title, transientShellWidgetClass,
6573 shellWidget, args, i);
6576 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
6577 layoutArgs, XtNumber(layoutArgs));
6580 XtSetArg(args[i], XtNlabel, question); i++;
6581 XtSetArg(args[i], XtNvalue, ""); i++;
6582 XtSetArg(args[i], XtNborderWidth, 0); i++;
6583 dialog = XtCreateManagedWidget("question", dialogWidgetClass,
6586 XawDialogAddButton(dialog, _("enter"), AskQuestionCallback,
6587 (XtPointer) dialog);
6588 XawDialogAddButton(dialog, _("cancel"), AskQuestionCallback,
6589 (XtPointer) dialog);
6591 XtRealizeWidget(popup);
6592 CatchDeleteWindow(popup, "AskQuestionPopDown");
6594 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
6595 &x, &y, &win_x, &win_y, &mask);
6597 XtSetArg(args[0], XtNx, x - 10);
6598 XtSetArg(args[1], XtNy, y - 30);
6599 XtSetValues(popup, args, 2);
6601 XtPopup(popup, XtGrabExclusive);
6602 askQuestionUp = True;
6604 edit = XtNameToWidget(dialog, "*value");
6605 XtSetKeyboardFocus(popup, edit);
6613 if (*name == NULLCHAR) {
6615 } else if (strcmp(name, "$") == 0) {
6616 putc(BELLCHAR, stderr);
6619 snprintf(buf, sizeof(buf), "%s '%s' &", appData.soundProgram, name);
6627 PlaySound(appData.soundMove);
6633 PlaySound(appData.soundIcsWin);
6639 PlaySound(appData.soundIcsLoss);
6645 PlaySound(appData.soundIcsDraw);
6649 PlayIcsUnfinishedSound()
6651 PlaySound(appData.soundIcsUnfinished);
6657 PlaySound(appData.soundIcsAlarm);
6663 system("stty echo");
6669 system("stty -echo");
6673 Colorize(cc, continuation)
6678 int count, outCount, error;
6680 if (textColors[(int)cc].bg > 0) {
6681 if (textColors[(int)cc].fg > 0) {
6682 sprintf(buf, "\033[0;%d;%d;%dm", textColors[(int)cc].attr,
6683 textColors[(int)cc].fg, textColors[(int)cc].bg);
6685 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
6686 textColors[(int)cc].bg);
6689 if (textColors[(int)cc].fg > 0) {
6690 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
6691 textColors[(int)cc].fg);
6693 sprintf(buf, "\033[0;%dm", textColors[(int)cc].attr);
6696 count = strlen(buf);
6697 outCount = OutputToProcess(NoProc, buf, count, &error);
6698 if (outCount < count) {
6699 DisplayFatalError(_("Error writing to display"), error, 1);
6702 if (continuation) return;
6705 PlaySound(appData.soundShout);
6708 PlaySound(appData.soundSShout);
6711 PlaySound(appData.soundChannel1);
6714 PlaySound(appData.soundChannel);
6717 PlaySound(appData.soundKibitz);
6720 PlaySound(appData.soundTell);
6722 case ColorChallenge:
6723 PlaySound(appData.soundChallenge);
6726 PlaySound(appData.soundRequest);
6729 PlaySound(appData.soundSeek);
6740 return getpwuid(getuid())->pw_name;
6743 static char *ExpandPathName(path)
6746 static char static_buf[2000];
6747 char *d, *s, buf[2000];
6753 while (*s && isspace(*s))
6762 if (*(s+1) == '/') {
6763 strcpy(d, getpwuid(getuid())->pw_dir);
6768 *strchr(buf, '/') = 0;
6769 pwd = getpwnam(buf);
6772 fprintf(stderr, _("ERROR: Unknown user %s (in path %s)\n"),
6776 strcpy(d, pwd->pw_dir);
6777 strcat(d, strchr(s+1, '/'));
6788 static char host_name[MSG_SIZ];
6790 #if HAVE_GETHOSTNAME
6791 gethostname(host_name, MSG_SIZ);
6793 #else /* not HAVE_GETHOSTNAME */
6794 # if HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H
6795 sysinfo(SI_HOSTNAME, host_name, MSG_SIZ);
6797 # else /* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
6799 # endif/* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
6800 #endif /* not HAVE_GETHOSTNAME */
6803 gint delayedEventTimerTag = 0;
6804 DelayedEventCallback delayedEventCallback = 0;
6807 FireDelayedEvent(data)
6810 delayedEventTimerTag = 0;
6811 delayedEventCallback();
6815 ScheduleDelayedEvent(cb, millisec)
6816 DelayedEventCallback cb; long millisec;
6818 delayedEventCallback = cb;
6819 delayedEventTimerTag = gtk_timeout_add(millisec,(GtkFunction) FireDelayedEvent, NULL);
6822 DelayedEventCallback
6825 if (delayedEventTimerTag)
6827 return delayedEventCallback;
6836 CancelDelayedEvent()
6838 if (delayedEventTimerTag)
6840 gtk_timeout_remove(delayedEventTimerTag);
6841 delayedEventTimerTag = 0;
6847 gint loadGameTimerTag = 0;
6849 int LoadGameTimerRunning()
6851 return loadGameTimerTag != 0;
6854 int StopLoadGameTimer()
6856 if (loadGameTimerTag != 0) {
6857 gtk_timeout_remove(loadGameTimerTag);
6858 loadGameTimerTag = 0;
6866 LoadGameTimerCallback(data)
6869 loadGameTimerTag = 0;
6874 StartLoadGameTimer(millisec)
6878 gtk_timeout_add( millisec, (GtkFunction) LoadGameTimerCallback, NULL);
6881 gint analysisClockTag = 0;
6884 AnalysisClockCallback(data)
6887 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile
6888 || appData.icsEngineAnalyze)
6890 AnalysisPeriodicEvent(0);
6891 StartAnalysisClock();
6896 StartAnalysisClock()
6899 gtk_timeout_add( 2000,(GtkFunction) AnalysisClockCallback, NULL);
6902 gint clockTimerTag = 0;
6904 int ClockTimerRunning()
6906 return clockTimerTag != 0;
6909 int StopClockTimer()
6911 if (clockTimerTag != 0)
6913 gtk_timeout_remove(clockTimerTag);
6924 ClockTimerCallback(data)
6933 StartClockTimer(millisec)
6936 clockTimerTag = gtk_timeout_add(millisec,(GtkFunction) ClockTimerCallback,NULL);
6941 DisplayTimerLabel(w, color, timer, highlight)
6950 if (appData.clockMode) {
6951 sprintf(buf, "%s: %s", color, TimeString(timer));
6953 sprintf(buf, "%s ", color);
6955 gtk_label_set_text(GTK_LABEL(w),buf);
6957 /* check for low time warning */
6958 // Pixel foregroundOrWarningColor = timerForegroundPixel;
6961 // appData.lowTimeWarning &&
6962 // (timer / 1000) < appData.icsAlarmTime)
6963 // foregroundOrWarningColor = lowTimeWarningColor;
6965 // if (appData.clockMode) {
6966 // sprintf(buf, "%s: %s", color, TimeString(timer));
6967 // XtSetArg(args[0], XtNlabel, buf);
6969 // sprintf(buf, "%s ", color);
6970 // XtSetArg(args[0], XtNlabel, buf);
6975 // XtSetArg(args[1], XtNbackground, foregroundOrWarningColor);
6976 // XtSetArg(args[2], XtNforeground, timerBackgroundPixel);
6978 // XtSetArg(args[1], XtNbackground, timerBackgroundPixel);
6979 // XtSetArg(args[2], XtNforeground, foregroundOrWarningColor);
6982 // XtSetValues(w, args, 3);
6987 DisplayWhiteClock(timeRemaining, highlight)
6991 if(appData.noGUI) return;
6993 DisplayTimerLabel(GUI_Whiteclock, _("White"), timeRemaining, highlight);
6994 if (highlight && WindowIcon == BlackIcon)
6996 WindowIcon = WhiteIcon;
6997 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
7002 DisplayBlackClock(timeRemaining, highlight)
7006 if(appData.noGUI) return;
7008 DisplayTimerLabel(GUI_Blackclock, _("Black"), timeRemaining, highlight);
7009 if (highlight && WindowIcon == WhiteIcon)
7011 WindowIcon = BlackIcon;
7012 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
7030 int StartChildProcess(cmdLine, dir, pr)
7037 int to_prog[2], from_prog[2];
7041 if (appData.debugMode) {
7042 fprintf(stderr, "StartChildProcess (dir=\"%s\") %s\n",dir, cmdLine);
7045 /* We do NOT feed the cmdLine to the shell; we just
7046 parse it into blank-separated arguments in the
7047 most simple-minded way possible.
7050 strcpy(buf, cmdLine);
7055 if (p == NULL) break;
7060 SetUpChildIO(to_prog, from_prog);
7062 if ((pid = fork()) == 0) {
7064 // [HGM] PSWBTM: made order resistant against case where fd of created pipe was 0 or 1
7065 close(to_prog[1]); // first close the unused pipe ends
7066 close(from_prog[0]);
7067 dup2(to_prog[0], 0); // to_prog was created first, nd is the only one to use 0 or 1
7068 dup2(from_prog[1], 1);
7069 if(to_prog[0] >= 2) close(to_prog[0]); // if 0 or 1, the dup2 already cosed the original
7070 close(from_prog[1]); // and closing again loses one of the pipes!
7071 if(fileno(stderr) >= 2) // better safe than sorry...
7072 dup2(1, fileno(stderr)); /* force stderr to the pipe */
7074 if (dir[0] != NULLCHAR && chdir(dir) != 0) {
7079 nice(appData.niceEngines); // [HGM] nice: adjust priority of engine proc
7081 execvp(argv[0], argv);
7083 /* If we get here, exec failed */
7088 /* Parent process */
7090 close(from_prog[1]);
7092 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7095 cp->fdFrom = from_prog[0];
7096 cp->fdTo = to_prog[1];
7101 // [HGM] kill: implement the 'hard killing' of AS's Winboard_x
7102 static RETSIGTYPE AlarmCallBack(int n)
7108 DestroyChildProcess(pr, signalType)
7112 ChildProc *cp = (ChildProc *) pr;
7114 if (cp->kind != CPReal) return;
7116 if (signalType == 10) { // [HGM] kill: if it does not terminate in 3 sec, kill
7117 signal(SIGALRM, AlarmCallBack);
7119 if(wait((int *) 0) == -1) { // process does not terminate on its own accord
7120 kill(cp->pid, SIGKILL); // kill it forcefully
7121 wait((int *) 0); // and wait again
7125 kill(cp->pid, signalType == 9 ? SIGKILL : SIGTERM); // [HGM] kill: use hard kill if so requested
7127 /* Process is exiting either because of the kill or because of
7128 a quit command sent by the backend; either way, wait for it to die.
7137 InterruptChildProcess(pr)
7140 ChildProc *cp = (ChildProc *) pr;
7142 if (cp->kind != CPReal) return;
7143 (void) kill(cp->pid, SIGINT); /* stop it thinking */
7146 int OpenTelnet(host, port, pr)
7151 char cmdLine[MSG_SIZ];
7153 if (port[0] == NULLCHAR) {
7154 snprintf(cmdLine, sizeof(cmdLine), "%s %s", appData.telnetProgram, host);
7156 snprintf(cmdLine, sizeof(cmdLine), "%s %s %s", appData.telnetProgram, host, port);
7158 return StartChildProcess(cmdLine, "", pr);
7161 int OpenTCP(host, port, pr)
7167 DisplayFatalError(_("Socket support is not configured in"), 0, 2);
7168 #else /* !OMIT_SOCKETS */
7170 struct sockaddr_in sa;
7172 unsigned short uport;
7175 if ((s = socket(AF_INET, SOCK_STREAM, 6)) < 0) {
7179 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
7180 sa.sin_family = AF_INET;
7181 sa.sin_addr.s_addr = INADDR_ANY;
7182 uport = (unsigned short) 0;
7183 sa.sin_port = htons(uport);
7184 if (bind(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)) < 0) {
7188 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
7189 if (!(hp = gethostbyname(host))) {
7191 if (sscanf(host, "%d.%d.%d.%d", &b0, &b1, &b2, &b3) == 4) {
7192 hp = (struct hostent *) calloc(1, sizeof(struct hostent));
7193 hp->h_addrtype = AF_INET;
7195 hp->h_addr_list = (char **) calloc(2, sizeof(char *));
7196 hp->h_addr_list[0] = (char *) malloc(4);
7197 hp->h_addr_list[0][0] = b0;
7198 hp->h_addr_list[0][1] = b1;
7199 hp->h_addr_list[0][2] = b2;
7200 hp->h_addr_list[0][3] = b3;
7205 sa.sin_family = hp->h_addrtype;
7206 uport = (unsigned short) atoi(port);
7207 sa.sin_port = htons(uport);
7208 memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);
7210 if (connect(s, (struct sockaddr *) &sa,
7211 sizeof(struct sockaddr_in)) < 0) {
7215 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7222 #endif /* !OMIT_SOCKETS */
7227 int OpenCommPort(name, pr)
7234 fd = open(name, 2, 0);
7235 if (fd < 0) return errno;
7237 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7247 int OpenLoopback(pr)
7253 SetUpChildIO(to, from);
7255 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7258 cp->fdFrom = to[0]; /* note not from[0]; we are doing a loopback */
7265 int OpenRcmd(host, user, cmd, pr)
7266 char *host, *user, *cmd;
7269 DisplayFatalError(_("internal rcmd not implemented for Unix"), 0, 1);
7273 #define INPUT_SOURCE_BUF_SIZE 8192
7282 char buf[INPUT_SOURCE_BUF_SIZE];
7287 DoInputCallback(closure, source, xid)
7292 InputSource *is = (InputSource *) closure;
7297 if (is->lineByLine) {
7298 count = read(is->fd, is->unused,
7299 INPUT_SOURCE_BUF_SIZE - (is->unused - is->buf));
7301 (is->func)(is, is->closure, is->buf, count, count ? errno : 0);
7304 is->unused += count;
7306 while (p < is->unused) {
7307 q = memchr(p, '\n', is->unused - p);
7308 if (q == NULL) break;
7310 (is->func)(is, is->closure, p, q - p, 0);
7314 while (p < is->unused) {
7319 count = read(is->fd, is->buf, INPUT_SOURCE_BUF_SIZE);
7324 (is->func)(is, is->closure, is->buf, count, error);
7328 InputSourceRef AddInputSource(pr, lineByLine, func, closure)
7335 ChildProc *cp = (ChildProc *) pr;
7337 is = (InputSource *) calloc(1, sizeof(InputSource));
7338 is->lineByLine = lineByLine;
7342 is->fd = fileno(stdin);
7344 is->kind = cp->kind;
7345 is->fd = cp->fdFrom;
7348 is->unused = is->buf;
7351 is->xid = XtAppAddInput(appContext, is->fd,
7352 (XtPointer) (XtInputReadMask),
7353 (XtInputCallbackProc) DoInputCallback,
7355 is->closure = closure;
7356 return (InputSourceRef) is;
7360 RemoveInputSource(isr)
7363 InputSource *is = (InputSource *) isr;
7365 if (is->xid == 0) return;
7366 XtRemoveInput(is->xid);
7370 int OutputToProcess(pr, message, count, outError)
7376 ChildProc *cp = (ChildProc *) pr;
7380 outCount = fwrite(message, 1, count, stdout);
7382 outCount = write(cp->fdTo, message, count);
7392 /* Output message to process, with "ms" milliseconds of delay
7393 between each character. This is needed when sending the logon
7394 script to ICC, which for some reason doesn't like the
7395 instantaneous send. */
7396 int OutputToProcessDelayed(pr, message, count, outError, msdelay)
7403 ChildProc *cp = (ChildProc *) pr;
7408 r = write(cp->fdTo, message++, 1);
7421 /**** Animation code by Hugh Fisher, DCS, ANU.
7423 Known problem: if a window overlapping the board is
7424 moved away while a piece is being animated underneath,
7425 the newly exposed area won't be updated properly.
7426 I can live with this.
7428 Known problem: if you look carefully at the animation
7429 of pieces in mono mode, they are being drawn as solid
7430 shapes without interior detail while moving. Fixing
7431 this would be a major complication for minimal return.
7434 /* Masks for XPM pieces. Black and white pieces can have
7435 different shapes, but in the interest of retaining my
7436 sanity pieces must have the same outline on both light
7437 and dark squares, and all pieces must use the same
7438 background square colors/images. */
7440 static int xpmDone = 0;
7443 CreateAnimMasks (pieceDepth)
7450 unsigned long plane;
7453 /* just return for gtk at the moment */
7456 /* Need a bitmap just to get a GC with right depth */
7457 buf = XCreatePixmap(xDisplay, xBoardWindow,
7459 values.foreground = 1;
7460 values.background = 0;
7461 /* Don't use XtGetGC, not read only */
7462 maskGC = XCreateGC(xDisplay, buf,
7463 GCForeground | GCBackground, &values);
7464 XFreePixmap(xDisplay, buf);
7466 buf = XCreatePixmap(xDisplay, xBoardWindow,
7467 squareSize, squareSize, pieceDepth);
7468 values.foreground = XBlackPixel(xDisplay, xScreen);
7469 values.background = XWhitePixel(xDisplay, xScreen);
7470 bufGC = XCreateGC(xDisplay, buf,
7471 GCForeground | GCBackground, &values);
7473 for (piece = WhitePawn; piece <= BlackKing; piece++) {
7474 /* Begin with empty mask */
7475 if(!xpmDone) // [HGM] pieces: keep using existing
7476 xpmMask[piece] = XCreatePixmap(xDisplay, xBoardWindow,
7477 squareSize, squareSize, 1);
7478 XSetFunction(xDisplay, maskGC, GXclear);
7479 XFillRectangle(xDisplay, xpmMask[piece], maskGC,
7480 0, 0, squareSize, squareSize);
7482 /* Take a copy of the piece */
7487 XSetFunction(xDisplay, bufGC, GXcopy);
7488 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn],
7490 0, 0, squareSize, squareSize, 0, 0);
7492 /* XOR the background (light) over the piece */
7493 XSetFunction(xDisplay, bufGC, GXxor);
7495 XCopyArea(xDisplay, xpmLightSquare, buf, bufGC,
7496 0, 0, squareSize, squareSize, 0, 0);
7498 XSetForeground(xDisplay, bufGC, lightSquareColor);
7499 XFillRectangle(xDisplay, buf, bufGC, 0, 0, squareSize, squareSize);
7502 /* We now have an inverted piece image with the background
7503 erased. Construct mask by just selecting all the non-zero
7504 pixels - no need to reconstruct the original image. */
7505 XSetFunction(xDisplay, maskGC, GXor);
7507 /* Might be quicker to download an XImage and create bitmap
7508 data from it rather than this N copies per piece, but it
7509 only takes a fraction of a second and there is a much
7510 longer delay for loading the pieces. */
7511 for (n = 0; n < pieceDepth; n ++) {
7512 XCopyPlane(xDisplay, buf, xpmMask[piece], maskGC,
7513 0, 0, squareSize, squareSize,
7519 XFreePixmap(xDisplay, buf);
7520 XFreeGC(xDisplay, bufGC);
7521 XFreeGC(xDisplay, maskGC);
7525 InitAnimState (anim, info)
7527 XWindowAttributes * info;
7532 /* Each buffer is square size, same depth as window */
7533 // anim->saveBuf = XCreatePixmap(xDisplay, xBoardWindow,
7534 // squareSize, squareSize, info->depth);
7535 // anim->newBuf = XCreatePixmap(xDisplay, xBoardWindow,
7536 // squareSize, squareSize, info->depth);
7538 // /* Create a plain GC for blitting */
7539 // mask = GCForeground | GCBackground | GCFunction |
7540 // GCPlaneMask | GCGraphicsExposures;
7541 // values.foreground = XBlackPixel(xDisplay, xScreen);
7542 // values.background = XWhitePixel(xDisplay, xScreen);
7543 // values.function = GXcopy;
7544 // values.plane_mask = AllPlanes;
7545 // values.graphics_exposures = False;
7546 // anim->blitGC = XCreateGC(xDisplay, xBoardWindow, mask, &values);
7548 // /* Piece will be copied from an existing context at
7549 // the start of each new animation/drag. */
7550 // anim->pieceGC = XCreateGC(xDisplay, xBoardWindow, 0, &values);
7552 // /* Outline will be a read-only copy of an existing */
7553 // anim->outlineGC = None;
7559 static VariantClass old = (VariantClass) -1; // [HGM] pieces: redo every time variant changes
7560 XWindowAttributes info;
7562 /* for gtk at the moment just ... */
7565 if (xpmDone && gameInfo.variant == old) return;
7566 if(xpmDone) old = gameInfo.variant; // first time pieces might not be created yet
7567 // XGetWindowAttributes(xDisplay, xBoardWindow, &info);
7569 // InitAnimState(&game, &info);
7570 // InitAnimState(&player, &info);
7572 /* For XPM pieces, we need bitmaps to use as masks. */
7574 // CreateAnimMasks(info.depth);
7580 static Boolean frameWaiting;
7582 static RETSIGTYPE FrameAlarm (sig)
7585 frameWaiting = False;
7586 /* In case System-V style signals. Needed?? */
7587 signal(SIGALRM, FrameAlarm);
7594 struct itimerval delay;
7596 XSync(xDisplay, False);
7599 frameWaiting = True;
7600 signal(SIGALRM, FrameAlarm);
7601 delay.it_interval.tv_sec =
7602 delay.it_value.tv_sec = time / 1000;
7603 delay.it_interval.tv_usec =
7604 delay.it_value.tv_usec = (time % 1000) * 1000;
7605 setitimer(ITIMER_REAL, &delay, NULL);
7607 /* Ugh -- busy-wait! --tpm */
7608 while (frameWaiting);
7610 while (frameWaiting) pause();
7612 delay.it_interval.tv_sec = delay.it_value.tv_sec = 0;
7613 delay.it_interval.tv_usec = delay.it_value.tv_usec = 0;
7614 setitimer(ITIMER_REAL, &delay, NULL);
7624 // XSync(xDisplay, False);
7626 usleep(time * 1000);
7631 /* Convert board position to corner of screen rect and color */
7634 ScreenSquare(column, row, pt, color)
7635 int column; int row; XPoint * pt; int * color;
7638 pt->x = lineGap + ((BOARD_WIDTH-1)-column) * (squareSize + lineGap);
7639 pt->y = lineGap + row * (squareSize + lineGap);
7641 pt->x = lineGap + column * (squareSize + lineGap);
7642 pt->y = lineGap + ((BOARD_HEIGHT-1)-row) * (squareSize + lineGap);
7644 *color = SquareColor(row, column);
7647 /* Convert window coords to square */
7650 BoardSquare(x, y, column, row)
7651 int x; int y; int * column; int * row;
7653 *column = EventToSquare(x, BOARD_WIDTH);
7654 if (flipView && *column >= 0)
7655 *column = BOARD_WIDTH - 1 - *column;
7656 *row = EventToSquare(y, BOARD_HEIGHT);
7657 if (!flipView && *row >= 0)
7658 *row = BOARD_HEIGHT - 1 - *row;
7663 #undef Max /* just in case */
7665 #define Max(a, b) ((a) > (b) ? (a) : (b))
7666 #define Min(a, b) ((a) < (b) ? (a) : (b))
7669 SetRect(rect, x, y, width, height)
7670 XRectangle * rect; int x; int y; int width; int height;
7674 rect->width = width;
7675 rect->height = height;
7678 /* Test if two frames overlap. If they do, return
7679 intersection rect within old and location of
7680 that rect within new. */
7683 Intersect(old, new, size, area, pt)
7684 XPoint * old; XPoint * new;
7685 int size; XRectangle * area; XPoint * pt;
7687 if (old->x > new->x + size || new->x > old->x + size ||
7688 old->y > new->y + size || new->y > old->y + size) {
7691 SetRect(area, Max(new->x - old->x, 0), Max(new->y - old->y, 0),
7692 size - abs(old->x - new->x), size - abs(old->y - new->y));
7693 pt->x = Max(old->x - new->x, 0);
7694 pt->y = Max(old->y - new->y, 0);
7699 /* For two overlapping frames, return the rect(s)
7700 in the old that do not intersect with the new. */
7703 CalcUpdateRects(old, new, size, update, nUpdates)
7704 XPoint * old; XPoint * new; int size;
7705 XRectangle update[]; int * nUpdates;
7709 /* If old = new (shouldn't happen) then nothing to draw */
7710 if (old->x == new->x && old->y == new->y) {
7714 /* Work out what bits overlap. Since we know the rects
7715 are the same size we don't need a full intersect calc. */
7717 /* Top or bottom edge? */
7718 if (new->y > old->y) {
7719 SetRect(&(update[count]), old->x, old->y, size, new->y - old->y);
7721 } else if (old->y > new->y) {
7722 SetRect(&(update[count]), old->x, old->y + size - (old->y - new->y),
7723 size, old->y - new->y);
7726 /* Left or right edge - don't overlap any update calculated above. */
7727 if (new->x > old->x) {
7728 SetRect(&(update[count]), old->x, Max(new->y, old->y),
7729 new->x - old->x, size - abs(new->y - old->y));
7731 } else if (old->x > new->x) {
7732 SetRect(&(update[count]), new->x + size, Max(new->y, old->y),
7733 old->x - new->x, size - abs(new->y - old->y));
7740 /* Generate a series of frame coords from start->mid->finish.
7741 The movement rate doubles until the half way point is
7742 reached, then halves back down to the final destination,
7743 which gives a nice slow in/out effect. The algorithmn
7744 may seem to generate too many intermediates for short
7745 moves, but remember that the purpose is to attract the
7746 viewers attention to the piece about to be moved and
7747 then to where it ends up. Too few frames would be less
7751 Tween(start, mid, finish, factor, frames, nFrames)
7752 XPoint * start; XPoint * mid;
7753 XPoint * finish; int factor;
7754 XPoint frames[]; int * nFrames;
7756 int fraction, n, count;
7760 /* Slow in, stepping 1/16th, then 1/8th, ... */
7762 for (n = 0; n < factor; n++)
7764 for (n = 0; n < factor; n++) {
7765 frames[count].x = start->x + (mid->x - start->x) / fraction;
7766 frames[count].y = start->y + (mid->y - start->y) / fraction;
7768 fraction = fraction / 2;
7772 frames[count] = *mid;
7775 /* Slow out, stepping 1/2, then 1/4, ... */
7777 for (n = 0; n < factor; n++) {
7778 frames[count].x = finish->x - (finish->x - mid->x) / fraction;
7779 frames[count].y = finish->y - (finish->y - mid->y) / fraction;
7781 fraction = fraction * 2;
7786 /* Draw a piece on the screen without disturbing what's there */
7789 SelectGCMask(piece, clip, outline, mask)
7790 ChessSquare piece; GC * clip; GC * outline; Pixmap * mask;
7794 /* Bitmap for piece being moved. */
7795 if (appData.monoMode) {
7796 *mask = *pieceToSolid(piece);
7797 } else if (useImages) {
7799 *mask = xpmMask[piece];
7801 *mask = ximMaskPm[piece];
7804 *mask = *pieceToSolid(piece);
7807 /* GC for piece being moved. Square color doesn't matter, but
7808 since it gets modified we make a copy of the original. */
7810 if (appData.monoMode)
7815 if (appData.monoMode)
7820 // XCopyGC(xDisplay, source, 0xFFFFFFFF, *clip);
7822 /* Outline only used in mono mode and is not modified */
7824 *outline = bwPieceGC;
7826 *outline = wbPieceGC;
7830 OverlayPiece(piece, clip, outline, dest)
7831 ChessSquare piece; GC clip; GC outline; Drawable dest;
7836 /* Draw solid rectangle which will be clipped to shape of piece */
7837 // XFillRectangle(xDisplay, dest, clip,
7838 // 0, 0, squareSize, squareSize)
7840 if (appData.monoMode)
7841 /* Also draw outline in contrasting color for black
7842 on black / white on white cases */
7843 // XCopyPlane(xDisplay, *pieceToOutline(piece), dest, outline,
7844 // 0, 0, squareSize, squareSize, 0, 0, 1)
7847 /* Copy the piece */
7852 // XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
7854 // 0, 0, squareSize, squareSize,
7859 /* Animate the movement of a single piece */
7862 BeginAnimation(anim, piece, startColor, start)
7870 /* The old buffer is initialised with the start square (empty) */
7871 BlankSquare(0, 0, startColor, EmptySquare, anim->saveBuf);
7872 anim->prevFrame = *start;
7874 /* The piece will be drawn using its own bitmap as a matte */
7875 // SelectGCMask(piece, &anim->pieceGC, &anim->outlineGC, &mask);
7876 // XSetClipMask(xDisplay, anim->pieceGC, mask);
7880 AnimationFrame(anim, frame, piece)
7885 XRectangle updates[4];
7890 /* Save what we are about to draw into the new buffer */
7891 // XCopyArea(xDisplay, xBoardWindow, anim->newBuf, anim->blitGC,
7892 // frame->x, frame->y, squareSize, squareSize,
7895 /* Erase bits of the previous frame */
7896 if (Intersect(&anim->prevFrame, frame, squareSize, &overlap, &pt)) {
7897 /* Where the new frame overlapped the previous,
7898 the contents in newBuf are wrong. */
7899 // XCopyArea(xDisplay, anim->saveBuf, anim->newBuf, anim->blitGC,
7900 // overlap.x, overlap.y,
7901 // overlap.width, overlap.height,
7903 /* Repaint the areas in the old that don't overlap new */
7904 CalcUpdateRects(&anim->prevFrame, frame, squareSize, updates, &count);
7905 for (i = 0; i < count; i++)
7906 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
7907 // updates[i].x - anim->prevFrame.x,
7908 // updates[i].y - anim->prevFrame.y,
7909 // updates[i].width, updates[i].height,
7910 // updates[i].x, updates[i].y)
7913 /* Easy when no overlap */
7914 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
7915 // 0, 0, squareSize, squareSize,
7916 // anim->prevFrame.x, anim->prevFrame.y);
7919 /* Save this frame for next time round */
7920 // XCopyArea(xDisplay, anim->newBuf, anim->saveBuf, anim->blitGC,
7921 // 0, 0, squareSize, squareSize,
7923 anim->prevFrame = *frame;
7925 /* Draw piece over original screen contents, not current,
7926 and copy entire rect. Wipes out overlapping piece images. */
7927 OverlayPiece(piece, anim->pieceGC, anim->outlineGC, anim->newBuf);
7928 // XCopyArea(xDisplay, anim->newBuf, xBoardWindow, anim->blitGC,
7929 // 0, 0, squareSize, squareSize,
7930 // frame->x, frame->y);
7934 EndAnimation (anim, finish)
7938 XRectangle updates[4];
7943 /* The main code will redraw the final square, so we
7944 only need to erase the bits that don't overlap. */
7945 if (Intersect(&anim->prevFrame, finish, squareSize, &overlap, &pt)) {
7946 CalcUpdateRects(&anim->prevFrame, finish, squareSize, updates, &count);
7947 for (i = 0; i < count; i++)
7948 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
7949 // updates[i].x - anim->prevFrame.x,
7950 // updates[i].y - anim->prevFrame.y,
7951 // updates[i].width, updates[i].height,
7952 // updates[i].x, updates[i].y)
7955 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
7956 // 0, 0, squareSize, squareSize,
7957 // anim->prevFrame.x, anim->prevFrame.y);
7962 FrameSequence(anim, piece, startColor, start, finish, frames, nFrames)
7964 ChessSquare piece; int startColor;
7965 XPoint * start; XPoint * finish;
7966 XPoint frames[]; int nFrames;
7970 BeginAnimation(anim, piece, startColor, start);
7971 for (n = 0; n < nFrames; n++) {
7972 AnimationFrame(anim, &(frames[n]), piece);
7973 FrameDelay(appData.animSpeed);
7975 EndAnimation(anim, finish);
7978 /* Main control logic for deciding what to animate and how */
7981 AnimateMove(board, fromX, fromY, toX, toY)
7990 XPoint start, finish, mid;
7991 XPoint frames[kFactor * 2 + 1];
7992 int nFrames, startColor, endColor;
7994 /* Are we animating? */
7995 if (!appData.animate || appData.blindfold)
7998 if(board[toY][toX] == WhiteRook && board[fromY][fromX] == WhiteKing ||
7999 board[toY][toX] == BlackRook && board[fromY][fromX] == BlackKing)
8000 return; // [HGM] FRC: no animtion of FRC castlings, as to-square is not true to-square
8002 if (fromY < 0 || fromX < 0 || toX < 0 || toY < 0) return;
8003 piece = board[fromY][fromX];
8004 if (piece >= EmptySquare) return;
8009 hop = (piece == WhiteKnight || piece == BlackKnight);
8012 if (appData.debugMode) {
8013 fprintf(debugFP, hop ? _("AnimateMove: piece %d hops from %d,%d to %d,%d \n") :
8014 _("AnimateMove: piece %d slides from %d,%d to %d,%d \n"),
8015 piece, fromX, fromY, toX, toY); }
8017 ScreenSquare(fromX, fromY, &start, &startColor);
8018 ScreenSquare(toX, toY, &finish, &endColor);
8021 /* Knight: make diagonal movement then straight */
8022 if (abs(toY - fromY) < abs(toX - fromX)) {
8023 mid.x = start.x + (finish.x - start.x) / 2;
8027 mid.y = start.y + (finish.y - start.y) / 2;
8030 mid.x = start.x + (finish.x - start.x) / 2;
8031 mid.y = start.y + (finish.y - start.y) / 2;
8034 /* Don't use as many frames for very short moves */
8035 if (abs(toY - fromY) + abs(toX - fromX) <= 2)
8036 Tween(&start, &mid, &finish, kFactor - 1, frames, &nFrames);
8038 Tween(&start, &mid, &finish, kFactor, frames, &nFrames);
8039 FrameSequence(&game, piece, startColor, &start, &finish, frames, nFrames);
8041 /* Be sure end square is redrawn */
8042 damage[toY][toX] = True;
8046 DragPieceBegin(x, y)
8049 int boardX, boardY, color;
8052 /* Are we animating? */
8053 if (!appData.animateDragging || appData.blindfold)
8056 /* Figure out which square we start in and the
8057 mouse position relative to top left corner. */
8058 BoardSquare(x, y, &boardX, &boardY);
8059 player.startBoardX = boardX;
8060 player.startBoardY = boardY;
8061 ScreenSquare(boardX, boardY, &corner, &color);
8062 player.startSquare = corner;
8063 player.startColor = color;
8065 /* Start from exactly where the piece is. This can be confusing
8066 if you start dragging far from the center of the square; most
8067 or all of the piece can be over a different square from the one
8068 the mouse pointer is in. */
8069 player.mouseDelta.x = x - corner.x;
8070 player.mouseDelta.y = y - corner.y;
8072 /* As soon as we start dragging, the piece will jump slightly to
8073 be centered over the mouse pointer. */
8074 player.mouseDelta.x = squareSize/2;
8075 player.mouseDelta.y = squareSize/2;
8077 /* Initialise animation */
8078 player.dragPiece = PieceForSquare(boardX, boardY);
8080 if (player.dragPiece >= 0 && player.dragPiece < EmptySquare) {
8081 player.dragActive = True;
8082 BeginAnimation(&player, player.dragPiece, color, &corner);
8083 /* Mark this square as needing to be redrawn. Note that
8084 we don't remove the piece though, since logically (ie
8085 as seen by opponent) the move hasn't been made yet. */
8086 if(boardX == BOARD_RGHT+1 && PieceForSquare(boardX-1, boardY) > 1 ||
8087 boardX == BOARD_LEFT-2 && PieceForSquare(boardX+1, boardY) > 1)
8088 // XCopyArea(xDisplay, xBoardWindow, player.saveBuf, player.blitGC,
8089 // corner.x, corner.y, squareSize, squareSize,
8090 // 0, 0); // [HGM] zh: unstack in stead of grab
8091 damage[boardY][boardX] = True;
8093 player.dragActive = False;
8103 /* Are we animating? */
8104 if (!appData.animateDragging || appData.blindfold)
8108 if (! player.dragActive)
8110 /* Move piece, maintaining same relative position
8111 of mouse within square */
8112 corner.x = x - player.mouseDelta.x;
8113 corner.y = y - player.mouseDelta.y;
8114 AnimationFrame(&player, &corner, player.dragPiece);
8116 if (appData.highlightDragging) {
8118 BoardSquare(x, y, &boardX, &boardY);
8119 SetHighlights(fromX, fromY, boardX, boardY);
8128 int boardX, boardY, color;
8131 /* Are we animating? */
8132 if (!appData.animateDragging || appData.blindfold)
8136 if (! player.dragActive)
8138 /* Last frame in sequence is square piece is
8139 placed on, which may not match mouse exactly. */
8140 BoardSquare(x, y, &boardX, &boardY);
8141 ScreenSquare(boardX, boardY, &corner, &color);
8142 EndAnimation(&player, &corner);
8144 /* Be sure end square is redrawn */
8145 damage[boardY][boardX] = True;
8147 /* This prevents weird things happening with fast successive
8148 clicks which on my Sun at least can cause motion events
8149 without corresponding press/release. */
8150 player.dragActive = False;
8153 /* Handle expose event while piece being dragged */
8158 if (!player.dragActive || appData.blindfold)
8161 /* What we're doing: logically, the move hasn't been made yet,
8162 so the piece is still in it's original square. But visually
8163 it's being dragged around the board. So we erase the square
8164 that the piece is on and draw it at the last known drag point. */
8165 BlankSquare(player.startSquare.x, player.startSquare.y,
8166 player.startColor, EmptySquare, xBoardWindow);
8167 AnimationFrame(&player, &player.prevFrame, player.dragPiece);
8168 damage[player.startBoardY][player.startBoardX] = TRUE;
8172 SetProgramStats( FrontEndProgramStats * stats )
8175 // [HGM] done, but perhaps backend should call this directly?
8176 EngineOutputUpdate( stats );