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)
238 int main P((int argc, char **argv));
239 RETSIGTYPE CmailSigHandler P((int sig));
240 RETSIGTYPE IntSigHandler P((int sig));
241 void CreateGCs P((void));
242 void CreateXIMPieces P((void));
243 void CreateXPMPieces P((void));
244 void CreatePieces P((void));
245 void CreatePieceMenus P((void));
246 Widget CreateMenuBar P((Menu *mb));
247 Widget CreateButtonBar P ((MenuItem *mi));
248 char *FindFont P((char *pattern, int targetPxlSize));
249 void PieceMenuPopup P((Widget w, XEvent *event,
250 String *params, Cardinal *num_params));
251 static void PieceMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
252 static void DropMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
253 int EventToSquare P((int x, int limit));
254 void DrawSquare P((int row, int column, ChessSquare piece, int do_flash));
255 void HandleUserMove P((Widget w, XEvent *event,
256 String *prms, Cardinal *nprms));
257 void AnimateUserMove P((Widget w, XEvent * event,
258 String * params, Cardinal * nParams));
259 void WhiteClock P((Widget w, XEvent *event,
260 String *prms, Cardinal *nprms));
261 void BlackClock P((Widget w, XEvent *event,
262 String *prms, Cardinal *nprms));
263 void DrawPositionProc P((Widget w, XEvent *event,
264 String *prms, Cardinal *nprms));
265 void CommentPopUp P((char *title, char *label));
266 void CommentPopDown P((void));
267 void CommentCallback P((Widget w, XtPointer client_data,
268 XtPointer call_data));
269 void ICSInputBoxPopUp P((void));
270 void ICSInputBoxPopDown P((void));
271 void FileNamePopUp P((char *label, char *def,
272 FileProc proc, char *openMode));
273 void FileNamePopDown P((void));
274 void FileNameCallback P((Widget w, XtPointer client_data,
275 XtPointer call_data));
276 void FileNameAction P((Widget w, XEvent *event,
277 String *prms, Cardinal *nprms));
278 void AskQuestionReplyAction P((Widget w, XEvent *event,
279 String *prms, Cardinal *nprms));
280 void AskQuestionProc P((Widget w, XEvent *event,
281 String *prms, Cardinal *nprms));
282 void AskQuestionPopDown P((void));
283 void PromotionPopUp P((void));
284 void PromotionPopDown P((void));
285 void PromotionCallback P((Widget w, XtPointer client_data,
286 XtPointer call_data));
287 void EditCommentPopDown P((void));
288 void EditCommentCallback P((Widget w, XtPointer client_data,
289 XtPointer call_data));
290 void SelectCommand P((Widget w, XtPointer client_data, XtPointer call_data));
291 void LoadPositionProc P((Widget w, XEvent *event,
292 String *prms, Cardinal *nprms));
293 void LoadNextPositionProc P((Widget w, XEvent *event, String *prms,
295 void LoadPrevPositionProc P((Widget w, XEvent *event, String *prms,
297 void ReloadPositionProc P((Widget w, XEvent *event, String *prms,
299 void CopyPositionProc P((Widget w, XEvent *event, String *prms,
301 void PastePositionProc P((Widget w, XEvent *event, String *prms,
303 void CopyGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
304 void PasteGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
305 void SaveGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
306 void SavePositionProc P((Widget w, XEvent *event,
307 String *prms, Cardinal *nprms));
308 void MailMoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
309 void ReloadCmailMsgProc P((Widget w, XEvent *event, String *prms,
311 void MachineBlackProc P((Widget w, XEvent *event, String *prms,
313 void MachineWhiteProc P((Widget w, XEvent *event,
314 String *prms, Cardinal *nprms));
315 void AnalyzeModeProc P((Widget w, XEvent *event,
316 String *prms, Cardinal *nprms));
317 void AnalyzeFileProc P((Widget w, XEvent *event,
318 String *prms, Cardinal *nprms));
319 void TwoMachinesProc P((Widget w, XEvent *event, String *prms,
321 void IcsClientProc P((Widget w, XEvent *event, String *prms,
323 void EditGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
324 void EditPositionProc P((Widget w, XEvent *event,
325 String *prms, Cardinal *nprms));
326 void TrainingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
327 void EditCommentProc P((Widget w, XEvent *event,
328 String *prms, Cardinal *nprms));
329 void IcsInputBoxProc P((Widget w, XEvent *event,
330 String *prms, Cardinal *nprms));
331 void AcceptProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
332 void DeclineProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
333 void RematchProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
334 void CallFlagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
335 void DrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
336 void AbortProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
337 void AdjournProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
338 void ResignProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
339 void AdjuWhiteProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
340 void AdjuBlackProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
341 void AdjuDrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
342 void EnterKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
343 void StopObservingProc P((Widget w, XEvent *event, String *prms,
345 void StopExaminingProc P((Widget w, XEvent *event, String *prms,
347 void BackwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
348 void ForwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
349 void ToStartProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
350 void ToEndProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
351 void RevertProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
352 void TruncateGameProc P((Widget w, XEvent *event, String *prms,
354 void RetractMoveProc P((Widget w, XEvent *event, String *prms,
356 void MoveNowProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
357 void AlwaysQueenProc P((Widget w, XEvent *event, String *prms,
359 void AnimateDraggingProc P((Widget w, XEvent *event, String *prms,
361 void AnimateMovingProc P((Widget w, XEvent *event, String *prms,
363 void AutocommProc P((Widget w, XEvent *event, String *prms,
365 void AutoflagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
366 void AutoflipProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
367 void AutobsProc P((Widget w, XEvent *event, String *prms,
369 void AutoraiseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
370 void AutosaveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
371 void BlindfoldProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
372 void FlashMovesProc P((Widget w, XEvent *event, String *prms,
374 void FlipViewProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
375 void GetMoveListProc P((Widget w, XEvent *event, String *prms,
377 void HighlightDraggingProc P((Widget w, XEvent *event, String *prms,
379 void HighlightLastMoveProc P((Widget w, XEvent *event, String *prms,
381 void MoveSoundProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
382 void IcsAlarmProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
383 void OldSaveStyleProc P((Widget w, XEvent *event, String *prms,
385 void PeriodicUpdatesProc P((Widget w, XEvent *event, String *prms,
387 void PonderNextMoveProc P((Widget w, XEvent *event, String *prms,
389 void PopupMoveErrorsProc P((Widget w, XEvent *event, String *prms,
391 void PopupExitMessageProc P((Widget w, XEvent *event, String *prms,
393 void PremoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
394 void QuietPlayProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
395 void ShowThinkingProc P((Widget w, XEvent *event, String *prms,
397 void HideThinkingProc P((Widget w, XEvent *event, String *prms,
399 void TestLegalityProc P((Widget w, XEvent *event, String *prms,
401 void InfoProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
402 void ManProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
403 void HintProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
404 void BookProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
405 void AboutGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
406 void DebugProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
407 void NothingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
408 void Iconify P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
409 void DisplayMove P((int moveNumber));
410 void DisplayTitle P((char *title));
411 void ICSInitScript P((void));
412 int LoadGamePopUp P((FILE *f, int gameNumber, char *title));
413 void ErrorPopUp P((char *title, char *text, int modal));
414 void ErrorPopDown P((void));
415 static char *ExpandPathName P((char *path));
416 static void CreateAnimVars P((void));
417 void DragPieceBegin P((int x, int y));
418 static void DragPieceMove P((int x, int y));
419 void DragPieceEnd P((int x, int y));
420 static void DrawDragPiece P((void));
421 char *ModeToWidgetName P((GameMode mode));
422 void EngineOutputUpdate( FrontEndProgramStats * stats );
423 void ShuffleMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
424 void EngineMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
425 void UciMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
426 void TimeControlProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
427 void NewVariantProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
428 void FirstSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
429 void SecondSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
430 void ShufflePopDown P(());
431 void EnginePopDown P(());
432 void UciPopDown P(());
433 void TimeControlPopDown P(());
434 void NewVariantPopDown P(());
435 void SettingsPopDown P(());
437 * XBoard depends on Xt R4 or higher
439 int xtVersion = XtSpecificationRelease;
444 Pixel lightSquareColor, darkSquareColor, whitePieceColor, blackPieceColor,
445 jailSquareColor, highlightSquareColor, premoveHighlightColor;
446 Pixel lowTimeWarningColor;
448 #define LINE_TYPE_NORMAL 0
449 #define LINE_TYPE_HIGHLIGHT 1
450 #define LINE_TYPE_PRE 2
453 GC lightSquareGC, darkSquareGC, jailSquareGC, wdPieceGC, wlPieceGC,
454 bdPieceGC, blPieceGC, wbPieceGC, bwPieceGC, coordGC,
455 wjPieceGC, bjPieceGC, countGC;
456 Pixmap iconPixmap, wIconPixmap, bIconPixmap, xMarkPixmap;
457 Widget shellWidget, layoutWidget, formWidget, boardWidget, messageWidget,
458 whiteTimerWidget, blackTimerWidget, titleWidget, widgetList[16],
459 commentShell, promotionShell, whitePieceMenu, blackPieceMenu, dropMenu,
460 menuBarWidget, buttonBarWidget, editShell, errorShell, analysisShell,
461 ICSInputShell, fileNameShell, askQuestionShell;
462 Font clockFontID, coordFontID, countFontID;
463 XFontStruct *clockFontStruct, *coordFontStruct, *countFontStruct;
464 XtAppContext appContext;
466 char *oldICSInteractionTitle;
470 char installDir[] = "."; // [HGM] UCI: needed for UCI; probably needs run-time initializtion
472 Position commentX = -1, commentY = -1;
473 Dimension commentW, commentH;
475 int squareSize, smallLayout = 0, tinyLayout = 0,
476 marginW, marginH, // [HGM] for run-time resizing
477 fromX = -1, fromY = -1, toX, toY, commentUp = False, analysisUp = False,
478 ICSInputBoxUp = False, askQuestionUp = False,
479 filenameUp = False, promotionUp = False, pmFromX = -1, pmFromY = -1,
480 editUp = False, errorUp = False, errorExitStatus = -1, lineGap;
481 Pixel timerForegroundPixel, timerBackgroundPixel;
482 Pixel buttonForegroundPixel, buttonBackgroundPixel;
483 char *chessDir, *programName, *programVersion,
484 *gameCopyFilename, *gamePasteFilename;
488 Pixmap pieceBitmap[2][(int)BlackPawn];
489 Pixmap pieceBitmap2[2][(int)BlackPawn+4]; /* [HGM] pieces */
490 Pixmap xpmPieceBitmap[4][(int)BlackPawn]; /* LL, LD, DL, DD actually used*/
491 Pixmap xpmPieceBitmap2[4][(int)BlackPawn+4]; /* LL, LD, DL, DD set to select from */
492 Pixmap xpmLightSquare, xpmDarkSquare, xpmJailSquare;
493 int useImages=0, useImageSqs;
494 XImage *ximPieceBitmap[4][(int)BlackPawn+4]; /* LL, LD, DL, DD */
495 Pixmap ximMaskPm[(int)BlackPawn]; /* clipmasks, used for XIM pieces */
496 Pixmap ximMaskPm2[(int)BlackPawn+4]; /* clipmasks, used for XIM pieces */
497 XImage *ximLightSquare, *ximDarkSquare;
500 #define pieceToSolid(piece) &pieceBitmap[SOLID][(piece) % (int)BlackPawn]
501 #define pieceToOutline(piece) &pieceBitmap[OUTLINE][(piece) % (int)BlackPawn]
503 #define White(piece) ((int)(piece) < (int)BlackPawn)
505 /* Variables for doing smooth animation. This whole thing
506 would be much easier if the board was double-buffered,
507 but that would require a fairly major rewrite. */
512 GC blitGC, pieceGC, outlineGC;
513 XPoint startSquare, prevFrame, mouseDelta;
517 int startBoardX, startBoardY;
520 /* There can be two pieces being animated at once: a player
521 can begin dragging a piece before the remote opponent has moved. */
523 static AnimState game, player;
525 /* Bitmaps for use as masks when drawing XPM pieces.
526 Need one for each black and white piece. */
527 static Pixmap xpmMask[BlackKing + 1];
529 /* This magic number is the number of intermediate frames used
530 in each half of the animation. For short moves it's reduced
531 by 1. The total number of frames will be factor * 2 + 1. */
534 SizeDefaults sizeDefaults[] = SIZE_DEFAULTS;
536 MenuItem fileMenu[] = {
537 {N_("New Shuffle Game ..."), ShuffleMenuProc},
538 {N_("New Variant ..."), NewVariantProc}, // [HGM] variant: not functional yet
539 {"----", NothingProc},
540 {N_("Save Game"), SaveGameProc},
541 {"----", NothingProc},
542 {N_("Copy Game"), CopyGameProc},
543 {N_("Paste Game"), PasteGameProc},
544 {"----", NothingProc},
545 {N_("Load Position"), LoadPositionProc},
546 {N_("Load Next Position"), LoadNextPositionProc},
547 {N_("Load Previous Position"), LoadPrevPositionProc},
548 {N_("Reload Same Position"), ReloadPositionProc},
549 {N_("Save Position"), SavePositionProc},
550 {"----", NothingProc},
551 {N_("Copy Position"), CopyPositionProc},
552 {N_("Paste Position"), PastePositionProc},
553 {"----", NothingProc},
554 {N_("Mail Move"), MailMoveProc},
555 {N_("Reload CMail Message"), ReloadCmailMsgProc},
556 {"----", NothingProc},
560 MenuItem modeMenu[] = {
561 {N_("Machine White"), MachineWhiteProc},
562 {N_("Machine Black"), MachineBlackProc},
563 {N_("Two Machines"), TwoMachinesProc},
564 {N_("Analysis Mode"), AnalyzeModeProc},
565 {N_("Analyze File"), AnalyzeFileProc },
566 {N_("ICS Client"), IcsClientProc},
567 {N_("Edit Game"), EditGameProc},
568 {N_("Edit Position"), EditPositionProc},
569 {N_("Training"), TrainingProc},
570 {"----", NothingProc},
571 {N_("Show Engine Output"), EngineOutputProc},
572 {N_("Show Evaluation Graph"), NothingProc}, // [HGM] evalgr: not functional yet
573 {N_("Show Game List"), ShowGameListProc},
574 {"Show Move History", HistoryShowProc}, // [HGM] hist: activate 4.2.7 code
575 {"----", NothingProc},
576 {N_("Edit Tags"), EditTagsProc},
577 {N_("Edit Comment"), EditCommentProc},
578 {N_("ICS Input Box"), IcsInputBoxProc},
582 MenuItem actionMenu[] = {
583 {N_("Accept"), AcceptProc},
584 {N_("Decline"), DeclineProc},
585 {N_("Rematch"), RematchProc},
586 {"----", NothingProc},
587 {N_("Call Flag"), CallFlagProc},
588 {N_("Draw"), DrawProc},
589 {N_("Adjourn"), AdjournProc},
590 {N_("Abort"), AbortProc},
591 {N_("Resign"), ResignProc},
592 {"----", NothingProc},
593 {N_("Stop Observing"), StopObservingProc},
594 {N_("Stop Examining"), StopExaminingProc},
595 {"----", NothingProc},
596 {N_("Adjudicate to White"), AdjuWhiteProc},
597 {N_("Adjudicate to Black"), AdjuBlackProc},
598 {N_("Adjudicate Draw"), AdjuDrawProc},
602 MenuItem stepMenu[] = {
603 {N_("Backward"), BackwardProc},
604 {N_("Forward"), ForwardProc},
605 {N_("Back to Start"), ToStartProc},
606 {N_("Forward to End"), ToEndProc},
607 {N_("Revert"), RevertProc},
608 {N_("Truncate Game"), TruncateGameProc},
609 {"----", NothingProc},
610 {N_("Move Now"), MoveNowProc},
611 {N_("Retract Move"), RetractMoveProc},
615 MenuItem optionsMenu[] = {
616 {N_("Flip View"), FlipViewProc},
617 {"----", NothingProc},
618 {N_("Adjudications ..."), EngineMenuProc},
619 {N_("General Settings ..."), UciMenuProc},
620 {N_("Engine #1 Settings ..."), FirstSettingsProc},
621 {N_("Engine #2 Settings ..."), SecondSettingsProc},
622 {N_("Time Control ..."), TimeControlProc},
623 {"----", NothingProc},
624 {N_("Always Queen"), AlwaysQueenProc},
625 {N_("Animate Dragging"), AnimateDraggingProc},
626 {N_("Animate Moving"), AnimateMovingProc},
627 {N_("Auto Comment"), AutocommProc},
628 {N_("Auto Flag"), AutoflagProc},
629 {N_("Auto Flip View"), AutoflipProc},
630 {N_("Auto Observe"), AutobsProc},
631 {N_("Auto Raise Board"), AutoraiseProc},
632 {N_("Auto Save"), AutosaveProc},
633 {N_("Blindfold"), BlindfoldProc},
634 {N_("Flash Moves"), FlashMovesProc},
635 {N_("Get Move List"), GetMoveListProc},
637 {N_("Highlight Dragging"), HighlightDraggingProc},
639 {N_("Highlight Last Move"), HighlightLastMoveProc},
640 {N_("Move Sound"), MoveSoundProc},
641 {N_("ICS Alarm"), IcsAlarmProc},
642 {N_("Old Save Style"), OldSaveStyleProc},
643 {N_("Periodic Updates"), PeriodicUpdatesProc},
644 {N_("Ponder Next Move"), PonderNextMoveProc},
645 {N_("Popup Exit Message"), PopupExitMessageProc},
646 {N_("Popup Move Errors"), PopupMoveErrorsProc},
647 {N_("Premove"), PremoveProc},
648 {N_("Quiet Play"), QuietPlayProc},
649 {N_("Hide Thinking"), HideThinkingProc},
650 {N_("Test Legality"), TestLegalityProc},
654 MenuItem helpMenu[] = {
655 {N_("Info XBoard"), InfoProc},
656 {N_("Man XBoard"), ManProc},
657 {"----", NothingProc},
658 {N_("Hint"), HintProc},
659 {N_("Book"), BookProc},
660 {"----", NothingProc},
665 {N_("File"), fileMenu},
666 {N_("Mode"), modeMenu},
667 {N_("Action"), actionMenu},
668 {N_("Step"), stepMenu},
669 {N_("Options"), optionsMenu},
670 {N_("Help"), helpMenu},
674 #define PAUSE_BUTTON N_("P")
675 MenuItem buttonBar[] = {
678 // {PAUSE_BUTTON, PauseProc},
684 #define PIECE_MENU_SIZE 18
685 String pieceMenuStrings[2][PIECE_MENU_SIZE] = {
686 { N_("White"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
687 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
688 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
689 N_("Empty square"), N_("Clear board") },
690 { N_("Black"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
691 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
692 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
693 N_("Empty square"), N_("Clear board") }
695 /* must be in same order as PieceMenuStrings! */
696 ChessSquare pieceMenuTranslation[2][PIECE_MENU_SIZE] = {
697 { WhitePlay, (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
698 WhiteRook, WhiteQueen, WhiteKing, (ChessSquare) 0, WhiteAlfil,
699 WhiteCannon, WhiteAngel, WhiteMarshall, (ChessSquare) 0,
700 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
701 { BlackPlay, (ChessSquare) 0, BlackPawn, BlackKnight, BlackBishop,
702 BlackRook, BlackQueen, BlackKing, (ChessSquare) 0, BlackAlfil,
703 BlackCannon, BlackAngel, BlackMarshall, (ChessSquare) 0,
704 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
707 #define DROP_MENU_SIZE 6
708 String dropMenuStrings[DROP_MENU_SIZE] = {
709 "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"), N_("Queen")
711 /* must be in same order as PieceMenuStrings! */
712 ChessSquare dropMenuTranslation[DROP_MENU_SIZE] = {
713 (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
714 WhiteRook, WhiteQueen
722 DropMenuEnables dmEnables[] = {
740 { XtNborderWidth, 0 },
741 { XtNdefaultDistance, 0 },
745 { XtNborderWidth, 0 },
746 { XtNresizable, (XtArgVal) True },
750 { XtNborderWidth, 0 },
756 { XtNjustify, (XtArgVal) XtJustifyRight },
757 { XtNlabel, (XtArgVal) "..." },
758 { XtNresizable, (XtArgVal) True },
759 { XtNresize, (XtArgVal) False }
762 Arg messageArgs[] = {
763 { XtNjustify, (XtArgVal) XtJustifyLeft },
764 { XtNlabel, (XtArgVal) "..." },
765 { XtNresizable, (XtArgVal) True },
766 { XtNresize, (XtArgVal) False }
770 { XtNborderWidth, 0 },
771 { XtNjustify, (XtArgVal) XtJustifyLeft }
774 XtResource clientResources[] = {
775 { "whitePieceColor", "whitePieceColor", XtRString, sizeof(String),
776 XtOffset(AppDataPtr, whitePieceColor), XtRString,
778 { "blackPieceColor", "blackPieceColor", XtRString, sizeof(String),
779 XtOffset(AppDataPtr, blackPieceColor), XtRString,
781 { "lightSquareColor", "lightSquareColor", XtRString,
782 sizeof(String), XtOffset(AppDataPtr, lightSquareColor),
783 XtRString, LIGHT_SQUARE_COLOR },
784 { "darkSquareColor", "darkSquareColor", XtRString, sizeof(String),
785 XtOffset(AppDataPtr, darkSquareColor), XtRString,
787 { "highlightSquareColor", "highlightSquareColor", XtRString,
788 sizeof(String), XtOffset(AppDataPtr, highlightSquareColor),
789 XtRString, HIGHLIGHT_SQUARE_COLOR },
790 { "premoveHighlightColor", "premoveHighlightColor", XtRString,
791 sizeof(String), XtOffset(AppDataPtr, premoveHighlightColor),
792 XtRString, PREMOVE_HIGHLIGHT_COLOR },
793 { "movesPerSession", "movesPerSession", XtRInt, sizeof(int),
794 XtOffset(AppDataPtr, movesPerSession), XtRImmediate,
795 (XtPointer) MOVES_PER_SESSION },
796 { "timeIncrement", "timeIncrement", XtRInt, sizeof(int),
797 XtOffset(AppDataPtr, timeIncrement), XtRImmediate,
798 (XtPointer) TIME_INCREMENT },
799 { "initString", "initString", XtRString, sizeof(String),
800 XtOffset(AppDataPtr, initString), XtRString, INIT_STRING },
801 { "secondInitString", "secondInitString", XtRString, sizeof(String),
802 XtOffset(AppDataPtr, secondInitString), XtRString, INIT_STRING },
803 { "firstComputerString", "firstComputerString", XtRString,
804 sizeof(String), XtOffset(AppDataPtr, firstComputerString), XtRString,
806 { "secondComputerString", "secondComputerString", XtRString,
807 sizeof(String), XtOffset(AppDataPtr, secondComputerString), XtRString,
809 { "firstChessProgram", "firstChessProgram", XtRString,
810 sizeof(String), XtOffset(AppDataPtr, firstChessProgram),
811 XtRString, FIRST_CHESS_PROGRAM },
812 { "secondChessProgram", "secondChessProgram", XtRString,
813 sizeof(String), XtOffset(AppDataPtr, secondChessProgram),
814 XtRString, SECOND_CHESS_PROGRAM },
815 { "firstPlaysBlack", "firstPlaysBlack", XtRBoolean,
816 sizeof(Boolean), XtOffset(AppDataPtr, firstPlaysBlack),
817 XtRImmediate, (XtPointer) False },
818 { "noChessProgram", "noChessProgram", XtRBoolean,
819 sizeof(Boolean), XtOffset(AppDataPtr, noChessProgram),
820 XtRImmediate, (XtPointer) False },
821 { "firstHost", "firstHost", XtRString, sizeof(String),
822 XtOffset(AppDataPtr, firstHost), XtRString, FIRST_HOST },
823 { "secondHost", "secondHost", XtRString, sizeof(String),
824 XtOffset(AppDataPtr, secondHost), XtRString, SECOND_HOST },
825 { "firstDirectory", "firstDirectory", XtRString, sizeof(String),
826 XtOffset(AppDataPtr, firstDirectory), XtRString, "." },
827 { "secondDirectory", "secondDirectory", XtRString, sizeof(String),
828 XtOffset(AppDataPtr, secondDirectory), XtRString, "." },
829 { "bitmapDirectory", "bitmapDirectory", XtRString,
830 sizeof(String), XtOffset(AppDataPtr, bitmapDirectory),
832 { "remoteShell", "remoteShell", XtRString, sizeof(String),
833 XtOffset(AppDataPtr, remoteShell), XtRString, REMOTE_SHELL },
834 { "remoteUser", "remoteUser", XtRString, sizeof(String),
835 XtOffset(AppDataPtr, remoteUser), XtRString, "" },
836 { "timeDelay", "timeDelay", XtRFloat, sizeof(float),
837 XtOffset(AppDataPtr, timeDelay), XtRString,
838 (XtPointer) TIME_DELAY_QUOTE },
839 { "timeControl", "timeControl", XtRString, sizeof(String),
840 XtOffset(AppDataPtr, timeControl), XtRString,
841 (XtPointer) TIME_CONTROL },
842 { "internetChessServerMode", "internetChessServerMode",
843 XtRBoolean, sizeof(Boolean),
844 XtOffset(AppDataPtr, icsActive), XtRImmediate,
846 { "internetChessServerHost", "internetChessServerHost",
847 XtRString, sizeof(String),
848 XtOffset(AppDataPtr, icsHost),
849 XtRString, (XtPointer) ICS_HOST },
850 { "internetChessServerPort", "internetChessServerPort",
851 XtRString, sizeof(String),
852 XtOffset(AppDataPtr, icsPort), XtRString,
853 (XtPointer) ICS_PORT },
854 { "internetChessServerCommPort", "internetChessServerCommPort",
855 XtRString, sizeof(String),
856 XtOffset(AppDataPtr, icsCommPort), XtRString,
858 { "internetChessServerLogonScript", "internetChessServerLogonScript",
859 XtRString, sizeof(String),
860 XtOffset(AppDataPtr, icsLogon), XtRString,
862 { "internetChessServerHelper", "internetChessServerHelper",
863 XtRString, sizeof(String),
864 XtOffset(AppDataPtr, icsHelper), XtRString, "" },
865 { "internetChessServerInputBox", "internetChessServerInputBox",
866 XtRBoolean, sizeof(Boolean),
867 XtOffset(AppDataPtr, icsInputBox), XtRImmediate,
869 { "icsAlarm", "icsAlarm",
870 XtRBoolean, sizeof(Boolean),
871 XtOffset(AppDataPtr, icsAlarm), XtRImmediate,
873 { "icsAlarmTime", "icsAlarmTime",
875 XtOffset(AppDataPtr, icsAlarmTime), XtRImmediate,
877 { "useTelnet", "useTelnet", XtRBoolean, sizeof(Boolean),
878 XtOffset(AppDataPtr, useTelnet), XtRImmediate,
880 { "telnetProgram", "telnetProgram", XtRString, sizeof(String),
881 XtOffset(AppDataPtr, telnetProgram), XtRString, TELNET_PROGRAM },
882 { "gateway", "gateway", XtRString, sizeof(String),
883 XtOffset(AppDataPtr, gateway), XtRString, "" },
884 { "loadGameFile", "loadGameFile", XtRString, sizeof(String),
885 XtOffset(AppDataPtr, loadGameFile), XtRString, "" },
886 { "loadGameIndex", "loadGameIndex",
888 XtOffset(AppDataPtr, loadGameIndex), XtRImmediate,
890 { "saveGameFile", "saveGameFile", XtRString, sizeof(String),
891 XtOffset(AppDataPtr, saveGameFile), XtRString, "" },
892 { "autoRaiseBoard", "autoRaiseBoard", XtRBoolean,
893 sizeof(Boolean), XtOffset(AppDataPtr, autoRaiseBoard),
894 XtRImmediate, (XtPointer) True },
895 { "autoSaveGames", "autoSaveGames", XtRBoolean,
896 sizeof(Boolean), XtOffset(AppDataPtr, autoSaveGames),
897 XtRImmediate, (XtPointer) False },
898 { "blindfold", "blindfold", XtRBoolean,
899 sizeof(Boolean), XtOffset(AppDataPtr, blindfold),
900 XtRImmediate, (XtPointer) False },
901 { "loadPositionFile", "loadPositionFile", XtRString,
902 sizeof(String), XtOffset(AppDataPtr, loadPositionFile),
904 { "loadPositionIndex", "loadPositionIndex",
906 XtOffset(AppDataPtr, loadPositionIndex), XtRImmediate,
908 { "savePositionFile", "savePositionFile", XtRString,
909 sizeof(String), XtOffset(AppDataPtr, savePositionFile),
911 { "matchMode", "matchMode", XtRBoolean, sizeof(Boolean),
912 XtOffset(AppDataPtr, matchMode), XtRImmediate, (XtPointer) False },
913 { "matchGames", "matchGames", XtRInt, sizeof(int),
914 XtOffset(AppDataPtr, matchGames), XtRImmediate,
916 { "monoMode", "monoMode", XtRBoolean, sizeof(Boolean),
917 XtOffset(AppDataPtr, monoMode), XtRImmediate,
919 { "debugMode", "debugMode", XtRBoolean, sizeof(Boolean),
920 XtOffset(AppDataPtr, debugMode), XtRImmediate,
922 { "clockMode", "clockMode", XtRBoolean, sizeof(Boolean),
923 XtOffset(AppDataPtr, clockMode), XtRImmediate,
925 { "boardSize", "boardSize", XtRString, sizeof(String),
926 XtOffset(AppDataPtr, boardSize), XtRString, "" },
927 { "searchTime", "searchTime", XtRString, sizeof(String),
928 XtOffset(AppDataPtr, searchTime), XtRString,
930 { "searchDepth", "searchDepth", XtRInt, sizeof(int),
931 XtOffset(AppDataPtr, searchDepth), XtRImmediate,
933 { "showCoords", "showCoords", XtRBoolean, sizeof(Boolean),
934 XtOffset(AppDataPtr, showCoords), XtRImmediate,
936 { "showJail", "showJail", XtRInt, sizeof(int),
937 XtOffset(AppDataPtr, showJail), XtRImmediate,
939 { "showThinking", "showThinking", XtRBoolean, sizeof(Boolean),
940 XtOffset(AppDataPtr, showThinking), XtRImmediate,
942 { "ponderNextMove", "ponderNextMove", XtRBoolean, sizeof(Boolean),
943 XtOffset(AppDataPtr, ponderNextMove), XtRImmediate,
945 { "periodicUpdates", "periodicUpdates", XtRBoolean, sizeof(Boolean),
946 XtOffset(AppDataPtr, periodicUpdates), XtRImmediate,
948 { "clockFont", "clockFont", XtRString, sizeof(String),
949 XtOffset(AppDataPtr, clockFont), XtRString, CLOCK_FONT },
950 { "coordFont", "coordFont", XtRString, sizeof(String),
951 XtOffset(AppDataPtr, coordFont), XtRString, COORD_FONT },
952 { "font", "font", XtRString, sizeof(String),
953 XtOffset(AppDataPtr, font), XtRString, DEFAULT_FONT },
954 { "ringBellAfterMoves", "ringBellAfterMoves",
955 XtRBoolean, sizeof(Boolean),
956 XtOffset(AppDataPtr, ringBellAfterMoves),
957 XtRImmediate, (XtPointer) False },
958 { "autoCallFlag", "autoCallFlag", XtRBoolean,
959 sizeof(Boolean), XtOffset(AppDataPtr, autoCallFlag),
960 XtRImmediate, (XtPointer) False },
961 { "autoFlipView", "autoFlipView", XtRBoolean,
962 sizeof(Boolean), XtOffset(AppDataPtr, autoFlipView),
963 XtRImmediate, (XtPointer) True },
964 { "autoObserve", "autoObserve", XtRBoolean,
965 sizeof(Boolean), XtOffset(AppDataPtr, autoObserve),
966 XtRImmediate, (XtPointer) False },
967 { "autoComment", "autoComment", XtRBoolean,
968 sizeof(Boolean), XtOffset(AppDataPtr, autoComment),
969 XtRImmediate, (XtPointer) False },
970 { "getMoveList", "getMoveList", XtRBoolean,
971 sizeof(Boolean), XtOffset(AppDataPtr, getMoveList),
972 XtRImmediate, (XtPointer) True },
974 { "highlightDragging", "highlightDragging", XtRBoolean,
975 sizeof(Boolean), XtOffset(AppDataPtr, highlightDragging),
976 XtRImmediate, (XtPointer) False },
978 { "highlightLastMove", "highlightLastMove", XtRBoolean,
979 sizeof(Boolean), XtOffset(AppDataPtr, highlightLastMove),
980 XtRImmediate, (XtPointer) False },
981 { "premove", "premove", XtRBoolean,
982 sizeof(Boolean), XtOffset(AppDataPtr, premove),
983 XtRImmediate, (XtPointer) True },
984 { "testLegality", "testLegality", XtRBoolean,
985 sizeof(Boolean), XtOffset(AppDataPtr, testLegality),
986 XtRImmediate, (XtPointer) True },
987 { "flipView", "flipView", XtRBoolean,
988 sizeof(Boolean), XtOffset(AppDataPtr, flipView),
989 XtRImmediate, (XtPointer) False },
990 { "cmail", "cmailGameName", XtRString, sizeof(String),
991 XtOffset(AppDataPtr, cmailGameName), XtRString, "" },
992 { "alwaysPromoteToQueen", "alwaysPromoteToQueen", XtRBoolean,
993 sizeof(Boolean), XtOffset(AppDataPtr, alwaysPromoteToQueen),
994 XtRImmediate, (XtPointer) False },
995 { "oldSaveStyle", "oldSaveStyle", XtRBoolean,
996 sizeof(Boolean), XtOffset(AppDataPtr, oldSaveStyle),
997 XtRImmediate, (XtPointer) False },
998 { "quietPlay", "quietPlay", XtRBoolean,
999 sizeof(Boolean), XtOffset(AppDataPtr, quietPlay),
1000 XtRImmediate, (XtPointer) False },
1001 { "titleInWindow", "titleInWindow", XtRBoolean,
1002 sizeof(Boolean), XtOffset(AppDataPtr, titleInWindow),
1003 XtRImmediate, (XtPointer) False },
1004 { "localLineEditing", "localLineEditing", XtRBoolean,
1005 sizeof(Boolean), XtOffset(AppDataPtr, localLineEditing),
1006 XtRImmediate, (XtPointer) True }, /* not implemented, must be True */
1008 { "zippyTalk", "zippyTalk", XtRBoolean,
1009 sizeof(Boolean), XtOffset(AppDataPtr, zippyTalk),
1010 XtRImmediate, (XtPointer) ZIPPY_TALK },
1011 { "zippyPlay", "zippyPlay", XtRBoolean,
1012 sizeof(Boolean), XtOffset(AppDataPtr, zippyPlay),
1013 XtRImmediate, (XtPointer) ZIPPY_PLAY },
1014 { "zippyLines", "zippyLines", XtRString, sizeof(String),
1015 XtOffset(AppDataPtr, zippyLines), XtRString, ZIPPY_LINES },
1016 { "zippyPinhead", "zippyPinhead", XtRString, sizeof(String),
1017 XtOffset(AppDataPtr, zippyPinhead), XtRString, ZIPPY_PINHEAD },
1018 { "zippyPassword", "zippyPassword", XtRString, sizeof(String),
1019 XtOffset(AppDataPtr, zippyPassword), XtRString, ZIPPY_PASSWORD },
1020 { "zippyPassword2", "zippyPassword2", XtRString, sizeof(String),
1021 XtOffset(AppDataPtr, zippyPassword2), XtRString, ZIPPY_PASSWORD2 },
1022 { "zippyWrongPassword", "zippyWrongPassword", XtRString, sizeof(String),
1023 XtOffset(AppDataPtr, zippyWrongPassword), XtRString,
1024 ZIPPY_WRONG_PASSWORD },
1025 { "zippyAcceptOnly", "zippyAcceptOnly", XtRString, sizeof(String),
1026 XtOffset(AppDataPtr, zippyAcceptOnly), XtRString, ZIPPY_ACCEPT_ONLY },
1027 { "zippyUseI", "zippyUseI", XtRBoolean,
1028 sizeof(Boolean), XtOffset(AppDataPtr, zippyUseI),
1029 XtRImmediate, (XtPointer) ZIPPY_USE_I },
1030 { "zippyBughouse", "zippyBughouse", XtRInt,
1031 sizeof(int), XtOffset(AppDataPtr, zippyBughouse),
1032 XtRImmediate, (XtPointer) ZIPPY_BUGHOUSE },
1033 { "zippyNoplayCrafty", "zippyNoplayCrafty", XtRBoolean,
1034 sizeof(Boolean), XtOffset(AppDataPtr, zippyNoplayCrafty),
1035 XtRImmediate, (XtPointer) ZIPPY_NOPLAY_CRAFTY },
1036 { "zippyGameEnd", "zippyGameEnd", XtRString, sizeof(String),
1037 XtOffset(AppDataPtr, zippyGameEnd), XtRString, ZIPPY_GAME_END },
1038 { "zippyGameStart", "zippyGameStart", XtRString, sizeof(String),
1039 XtOffset(AppDataPtr, zippyGameStart), XtRString, ZIPPY_GAME_START },
1040 { "zippyAdjourn", "zippyAdjourn", XtRBoolean,
1041 sizeof(Boolean), XtOffset(AppDataPtr, zippyAdjourn),
1042 XtRImmediate, (XtPointer) ZIPPY_ADJOURN },
1043 { "zippyAbort", "zippyAbort", XtRBoolean,
1044 sizeof(Boolean), XtOffset(AppDataPtr, zippyAbort),
1045 XtRImmediate, (XtPointer) ZIPPY_ABORT },
1046 { "zippyVariants", "zippyVariants", XtRString, sizeof(String),
1047 XtOffset(AppDataPtr, zippyVariants), XtRString, ZIPPY_VARIANTS },
1048 { "zippyMaxGames", "zippyMaxGames", XtRInt, sizeof(int),
1049 XtOffset(AppDataPtr, zippyMaxGames), XtRImmediate,
1050 (XtPointer) ZIPPY_MAX_GAMES },
1051 { "zippyReplayTimeout", "zippyReplayTimeout", XtRInt, sizeof(int),
1052 XtOffset(AppDataPtr, zippyReplayTimeout), XtRImmediate,
1053 (XtPointer) ZIPPY_REPLAY_TIMEOUT },
1054 { "zippyShortGame", "zippyShortGame", XtRInt, sizeof(int),
1055 XtOffset(AppDataPtr, zippyShortGame), XtRImmediate,
1058 { "flashCount", "flashCount", XtRInt, sizeof(int),
1059 XtOffset(AppDataPtr, flashCount), XtRImmediate,
1060 (XtPointer) FLASH_COUNT },
1061 { "flashRate", "flashRate", XtRInt, sizeof(int),
1062 XtOffset(AppDataPtr, flashRate), XtRImmediate,
1063 (XtPointer) FLASH_RATE },
1064 { "pixmapDirectory", "pixmapDirectory", XtRString,
1065 sizeof(String), XtOffset(AppDataPtr, pixmapDirectory),
1067 { "msLoginDelay", "msLoginDelay", XtRInt, sizeof(int),
1068 XtOffset(AppDataPtr, msLoginDelay), XtRImmediate,
1069 (XtPointer) MS_LOGIN_DELAY },
1070 { "colorizeMessages", "colorizeMessages", XtRBoolean,
1071 sizeof(Boolean), XtOffset(AppDataPtr, colorize),
1072 XtRImmediate, (XtPointer) False },
1073 { "colorShout", "colorShout", XtRString,
1074 sizeof(String), XtOffset(AppDataPtr, colorShout),
1075 XtRString, COLOR_SHOUT },
1076 { "colorSShout", "colorSShout", XtRString,
1077 sizeof(String), XtOffset(AppDataPtr, colorSShout),
1078 XtRString, COLOR_SSHOUT },
1079 { "colorChannel1", "colorChannel1", XtRString,
1080 sizeof(String), XtOffset(AppDataPtr, colorChannel1),
1081 XtRString, COLOR_CHANNEL1 },
1082 { "colorChannel", "colorChannel", XtRString,
1083 sizeof(String), XtOffset(AppDataPtr, colorChannel),
1084 XtRString, COLOR_CHANNEL },
1085 { "colorKibitz", "colorKibitz", XtRString,
1086 sizeof(String), XtOffset(AppDataPtr, colorKibitz),
1087 XtRString, COLOR_KIBITZ },
1088 { "colorTell", "colorTell", XtRString,
1089 sizeof(String), XtOffset(AppDataPtr, colorTell),
1090 XtRString, COLOR_TELL },
1091 { "colorChallenge", "colorChallenge", XtRString,
1092 sizeof(String), XtOffset(AppDataPtr, colorChallenge),
1093 XtRString, COLOR_CHALLENGE },
1094 { "colorRequest", "colorRequest", XtRString,
1095 sizeof(String), XtOffset(AppDataPtr, colorRequest),
1096 XtRString, COLOR_REQUEST },
1097 { "colorSeek", "colorSeek", XtRString,
1098 sizeof(String), XtOffset(AppDataPtr, colorSeek),
1099 XtRString, COLOR_SEEK },
1100 { "colorNormal", "colorNormal", XtRString,
1101 sizeof(String), XtOffset(AppDataPtr, colorNormal),
1102 XtRString, COLOR_NORMAL },
1103 { "soundProgram", "soundProgram", XtRString,
1104 sizeof(String), XtOffset(AppDataPtr, soundProgram),
1105 XtRString, "play" },
1106 { "soundShout", "soundShout", XtRString,
1107 sizeof(String), XtOffset(AppDataPtr, soundShout),
1109 { "soundSShout", "soundSShout", XtRString,
1110 sizeof(String), XtOffset(AppDataPtr, soundSShout),
1112 { "soundChannel1", "soundChannel1", XtRString,
1113 sizeof(String), XtOffset(AppDataPtr, soundChannel1),
1115 { "soundChannel", "soundChannel", XtRString,
1116 sizeof(String), XtOffset(AppDataPtr, soundChannel),
1118 { "soundKibitz", "soundKibitz", XtRString,
1119 sizeof(String), XtOffset(AppDataPtr, soundKibitz),
1121 { "soundTell", "soundTell", XtRString,
1122 sizeof(String), XtOffset(AppDataPtr, soundTell),
1124 { "soundChallenge", "soundChallenge", XtRString,
1125 sizeof(String), XtOffset(AppDataPtr, soundChallenge),
1127 { "soundRequest", "soundRequest", XtRString,
1128 sizeof(String), XtOffset(AppDataPtr, soundRequest),
1130 { "soundSeek", "soundSeek", XtRString,
1131 sizeof(String), XtOffset(AppDataPtr, soundSeek),
1133 { "soundMove", "soundMove", XtRString,
1134 sizeof(String), XtOffset(AppDataPtr, soundMove),
1136 { "soundIcsWin", "soundIcsWin", XtRString,
1137 sizeof(String), XtOffset(AppDataPtr, soundIcsWin),
1139 { "soundIcsLoss", "soundIcsLoss", XtRString,
1140 sizeof(String), XtOffset(AppDataPtr, soundIcsLoss),
1142 { "soundIcsDraw", "soundIcsDraw", XtRString,
1143 sizeof(String), XtOffset(AppDataPtr, soundIcsDraw),
1145 { "soundIcsUnfinished", "soundIcsUnfinished", XtRString,
1146 sizeof(String), XtOffset(AppDataPtr, soundIcsUnfinished),
1148 { "soundIcsAlarm", "soundIcsAlarm", XtRString,
1149 sizeof(String), XtOffset(AppDataPtr, soundIcsAlarm),
1151 { "reuseFirst", "reuseFirst", XtRBoolean,
1152 sizeof(Boolean), XtOffset(AppDataPtr, reuseFirst),
1153 XtRImmediate, (XtPointer) True },
1154 { "reuseSecond", "reuseSecond", XtRBoolean,
1155 sizeof(Boolean), XtOffset(AppDataPtr, reuseSecond),
1156 XtRImmediate, (XtPointer) True },
1157 { "animateDragging", "animateDragging", XtRBoolean,
1158 sizeof(Boolean), XtOffset(AppDataPtr, animateDragging),
1159 XtRImmediate, (XtPointer) True },
1160 { "animateMoving", "animateMoving", XtRBoolean,
1161 sizeof(Boolean), XtOffset(AppDataPtr, animate),
1162 XtRImmediate, (XtPointer) True },
1163 { "animateSpeed", "animateSpeed", XtRInt,
1164 sizeof(int), XtOffset(AppDataPtr, animSpeed),
1165 XtRImmediate, (XtPointer)10 },
1166 { "popupExitMessage", "popupExitMessage", XtRBoolean,
1167 sizeof(Boolean), XtOffset(AppDataPtr, popupExitMessage),
1168 XtRImmediate, (XtPointer) True },
1169 { "popupMoveErrors", "popupMoveErrors", XtRBoolean,
1170 sizeof(Boolean), XtOffset(AppDataPtr, popupMoveErrors),
1171 XtRImmediate, (XtPointer) False },
1172 { "fontSizeTolerance", "fontSizeTolerance", XtRInt,
1173 sizeof(int), XtOffset(AppDataPtr, fontSizeTolerance),
1174 XtRImmediate, (XtPointer)4 },
1175 { "initialMode", "initialMode", XtRString,
1176 sizeof(String), XtOffset(AppDataPtr, initialMode),
1177 XtRImmediate, (XtPointer) "" },
1178 { "variant", "variant", XtRString,
1179 sizeof(String), XtOffset(AppDataPtr, variant),
1180 XtRImmediate, (XtPointer) "normal" },
1181 { "firstProtocolVersion", "firstProtocolVersion", XtRInt,
1182 sizeof(int), XtOffset(AppDataPtr, firstProtocolVersion),
1183 XtRImmediate, (XtPointer)PROTOVER },
1184 { "secondProtocolVersion", "secondProtocolVersion", XtRInt,
1185 sizeof(int), XtOffset(AppDataPtr, secondProtocolVersion),
1186 XtRImmediate, (XtPointer)PROTOVER },
1187 { "showButtonBar", "showButtonBar", XtRBoolean,
1188 sizeof(Boolean), XtOffset(AppDataPtr, showButtonBar),
1189 XtRImmediate, (XtPointer) True },
1190 { "lowTimeWarningColor", "lowTimeWarningColor", XtRString,
1191 sizeof(String), XtOffset(AppDataPtr, lowTimeWarningColor),
1192 XtRString, COLOR_LOWTIMEWARNING },
1193 { "lowTimeWarning", "lowTimeWarning", XtRBoolean,
1194 sizeof(Boolean), XtOffset(AppDataPtr, lowTimeWarning),
1195 XtRImmediate, (XtPointer) False },
1196 {"icsEngineAnalyze", "icsEngineAnalyze", XtRBoolean, /* [DM] icsEngineAnalyze */
1197 sizeof(Boolean), XtOffset(AppDataPtr, icsEngineAnalyze),
1198 XtRImmediate, (XtPointer) False },
1199 { "firstScoreAbs", "firstScoreAbs", XtRBoolean,
1200 sizeof(Boolean), XtOffset(AppDataPtr, firstScoreIsAbsolute),
1201 XtRImmediate, (XtPointer) False },
1202 { "secondScoreAbs", "secondScoreAbs", XtRBoolean,
1203 sizeof(Boolean), XtOffset(AppDataPtr, secondScoreIsAbsolute),
1204 XtRImmediate, (XtPointer) False },
1205 { "pgnExtendedInfo", "pgnExtendedInfo", XtRBoolean,
1206 sizeof(Boolean), XtOffset(AppDataPtr, saveExtendedInfoInPGN),
1207 XtRImmediate, (XtPointer) False },
1208 { "hideThinkingFromHuman", "hideThinkingFromHuman", XtRBoolean,
1209 sizeof(Boolean), XtOffset(AppDataPtr, hideThinkingFromHuman),
1210 XtRImmediate, (XtPointer) True },
1211 { "adjudicateLossThreshold", "adjudicateLossThreshold", XtRInt,
1212 sizeof(int), XtOffset(AppDataPtr, adjudicateLossThreshold),
1213 XtRImmediate, (XtPointer) 0},
1214 { "pgnEventHeader", "pgnEventHeader", XtRString,
1215 sizeof(String), XtOffset(AppDataPtr, pgnEventHeader),
1216 XtRImmediate, (XtPointer) "Computer Chess Game" },
1217 { "defaultFrcPosition", "defaultFrcPositon", XtRInt,
1218 sizeof(int), XtOffset(AppDataPtr, defaultFrcPosition),
1219 XtRImmediate, (XtPointer) -1},
1220 { "gameListTags", "gameListTags", XtRString,
1221 sizeof(String), XtOffset(AppDataPtr, gameListTags),
1222 XtRImmediate, (XtPointer) GLT_DEFAULT_TAGS },
1224 // [HGM] 4.3.xx options
1225 { "boardWidth", "boardWidth", XtRInt,
1226 sizeof(int), XtOffset(AppDataPtr, NrFiles),
1227 XtRImmediate, (XtPointer) -1},
1228 { "boardHeight", "boardHeight", XtRInt,
1229 sizeof(int), XtOffset(AppDataPtr, NrRanks),
1230 XtRImmediate, (XtPointer) -1},
1231 { "matchPause", "matchPause", XtRInt,
1232 sizeof(int), XtOffset(AppDataPtr, matchPause),
1233 XtRImmediate, (XtPointer) 10000},
1234 { "holdingsSize", "holdingsSize", XtRInt,
1235 sizeof(int), XtOffset(AppDataPtr, holdingsSize),
1236 XtRImmediate, (XtPointer) -1},
1237 { "flipBlack", "flipBlack", XtRBoolean,
1238 sizeof(Boolean), XtOffset(AppDataPtr, upsideDown),
1239 XtRImmediate, (XtPointer) False},
1240 { "allWhite", "allWhite", XtRBoolean,
1241 sizeof(Boolean), XtOffset(AppDataPtr, allWhite),
1242 XtRImmediate, (XtPointer) False},
1243 { "pieceToCharTable", "pieceToCharTable", XtRString,
1244 sizeof(String), XtOffset(AppDataPtr, pieceToCharTable),
1245 XtRImmediate, (XtPointer) 0},
1246 { "alphaRank", "alphaRank", XtRBoolean,
1247 sizeof(Boolean), XtOffset(AppDataPtr, alphaRank),
1248 XtRImmediate, (XtPointer) False},
1249 { "testClaims", "testClaims", XtRBoolean,
1250 sizeof(Boolean), XtOffset(AppDataPtr, testClaims),
1251 XtRImmediate, (XtPointer) True},
1252 { "checkMates", "checkMates", XtRBoolean,
1253 sizeof(Boolean), XtOffset(AppDataPtr, checkMates),
1254 XtRImmediate, (XtPointer) True},
1255 { "materialDraws", "materialDraws", XtRBoolean,
1256 sizeof(Boolean), XtOffset(AppDataPtr, materialDraws),
1257 XtRImmediate, (XtPointer) True},
1258 { "trivialDraws", "trivialDraws", XtRBoolean,
1259 sizeof(Boolean), XtOffset(AppDataPtr, trivialDraws),
1260 XtRImmediate, (XtPointer) False},
1261 { "ruleMoves", "ruleMoves", XtRInt,
1262 sizeof(int), XtOffset(AppDataPtr, ruleMoves),
1263 XtRImmediate, (XtPointer) 51},
1264 { "repeatsToDraw", "repeatsToDraw", XtRInt,
1265 sizeof(int), XtOffset(AppDataPtr, drawRepeats),
1266 XtRImmediate, (XtPointer) 6},
1267 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1268 sizeof(int), XtOffset(AppDataPtr, engineComments),
1269 XtRImmediate, (XtPointer) 1},
1270 { "userName", "userName", XtRString,
1271 sizeof(int), XtOffset(AppDataPtr, userName),
1272 XtRImmediate, (XtPointer) 0},
1273 { "autoKibitz", "autoKibitz", XtRBoolean,
1274 sizeof(Boolean), XtOffset(AppDataPtr, autoKibitz),
1275 XtRImmediate, (XtPointer) False},
1276 { "firstTimeOdds", "firstTimeOdds", XtRInt,
1277 sizeof(int), XtOffset(AppDataPtr, firstTimeOdds),
1278 XtRImmediate, (XtPointer) 1},
1279 { "secondTimeOdds", "secondTimeOdds", XtRInt,
1280 sizeof(int), XtOffset(AppDataPtr, secondTimeOdds),
1281 XtRImmediate, (XtPointer) 1},
1282 { "timeOddsMode", "timeOddsMode", XtRInt,
1283 sizeof(int), XtOffset(AppDataPtr, timeOddsMode),
1284 XtRImmediate, (XtPointer) 0},
1285 { "firstAccumulateTC", "firstAccumulateTC", XtRInt,
1286 sizeof(int), XtOffset(AppDataPtr, firstAccumulateTC),
1287 XtRImmediate, (XtPointer) 1},
1288 { "secondAccumulateTC", "secondAccumulateTC", XtRInt,
1289 sizeof(int), XtOffset(AppDataPtr, secondAccumulateTC),
1290 XtRImmediate, (XtPointer) 1},
1291 { "firstNPS", "firstNPS", XtRInt,
1292 sizeof(int), XtOffset(AppDataPtr, firstNPS),
1293 XtRImmediate, (XtPointer) -1},
1294 { "secondNPS", "secondNPS", XtRInt,
1295 sizeof(int), XtOffset(AppDataPtr, secondNPS),
1296 XtRImmediate, (XtPointer) -1},
1297 { "serverMoves", "serverMoves", XtRString,
1298 sizeof(String), XtOffset(AppDataPtr, serverMovesName),
1299 XtRImmediate, (XtPointer) 0},
1300 { "serverPause", "serverPause", XtRInt,
1301 sizeof(int), XtOffset(AppDataPtr, serverPause),
1302 XtRImmediate, (XtPointer) 0},
1303 { "suppressLoadMoves", "suppressLoadMoves", XtRBoolean,
1304 sizeof(Boolean), XtOffset(AppDataPtr, suppressLoadMoves),
1305 XtRImmediate, (XtPointer) False},
1306 { "userName", "userName", XtRString,
1307 sizeof(String), XtOffset(AppDataPtr, userName),
1308 XtRImmediate, (XtPointer) 0},
1309 { "egtFormats", "egtFormats", XtRString,
1310 sizeof(String), XtOffset(AppDataPtr, egtFormats),
1311 XtRImmediate, (XtPointer) 0},
1312 { "rewindIndex", "rewindIndex", XtRInt,
1313 sizeof(int), XtOffset(AppDataPtr, rewindIndex),
1314 XtRImmediate, (XtPointer) 0},
1315 { "sameColorGames", "sameColorGames", XtRInt,
1316 sizeof(int), XtOffset(AppDataPtr, sameColorGames),
1317 XtRImmediate, (XtPointer) 0},
1318 { "smpCores", "smpCores", XtRInt,
1319 sizeof(int), XtOffset(AppDataPtr, smpCores),
1320 XtRImmediate, (XtPointer) 1},
1321 { "niceEngines", "niceEngines", XtRInt,
1322 sizeof(int), XtOffset(AppDataPtr, niceEngines),
1323 XtRImmediate, (XtPointer) 0},
1324 { "nameOfDebugFile", "nameOfDebugFile", XtRString,
1325 sizeof(String), XtOffset(AppDataPtr, nameOfDebugFile),
1326 XtRImmediate, (XtPointer) "xboard.debug"},
1327 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1328 sizeof(int), XtOffset(AppDataPtr, engineComments),
1329 XtRImmediate, (XtPointer) 0},
1330 { "noGUI", "noGUI", XtRBoolean,
1331 sizeof(Boolean), XtOffset(AppDataPtr, noGUI),
1332 XtRImmediate, (XtPointer) 0},
1333 { "firstOptions", "firstOptions", XtRString,
1334 sizeof(String), XtOffset(AppDataPtr, firstOptions),
1335 XtRImmediate, (XtPointer) "" },
1336 { "secondOptions", "secondOptions", XtRString,
1337 sizeof(String), XtOffset(AppDataPtr, secondOptions),
1338 XtRImmediate, (XtPointer) "" },
1339 { "firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XtRString,
1340 sizeof(String), XtOffset(AppDataPtr, fenOverride1),
1341 XtRImmediate, (XtPointer) 0 },
1342 { "secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XtRString,
1343 sizeof(String), XtOffset(AppDataPtr, fenOverride2),
1344 XtRImmediate, (XtPointer) 0 },
1346 // [HGM] Winboard_x UCI options
1347 { "firstIsUCI", "firstIsUCI", XtRBoolean,
1348 sizeof(Boolean), XtOffset(AppDataPtr, firstIsUCI),
1349 XtRImmediate, (XtPointer) False},
1350 { "secondIsUCI", "secondIsUCI", XtRBoolean,
1351 sizeof(Boolean), XtOffset(AppDataPtr, secondIsUCI),
1352 XtRImmediate, (XtPointer) False},
1353 { "firstHasOwnBookUCI", "firstHasOwnBookUCI", XtRBoolean,
1354 sizeof(Boolean), XtOffset(AppDataPtr, firstHasOwnBookUCI),
1355 XtRImmediate, (XtPointer) True},
1356 { "secondHasOwnBookUCI", "secondHasOwnBookUCI", XtRBoolean,
1357 sizeof(Boolean), XtOffset(AppDataPtr, secondHasOwnBookUCI),
1358 XtRImmediate, (XtPointer) True},
1359 { "usePolyglotBook", "usePolyglotBook", XtRBoolean,
1360 sizeof(Boolean), XtOffset(AppDataPtr, usePolyglotBook),
1361 XtRImmediate, (XtPointer) False},
1362 { "defaultHashSize", "defaultHashSize", XtRInt,
1363 sizeof(int), XtOffset(AppDataPtr, defaultHashSize),
1364 XtRImmediate, (XtPointer) 64},
1365 { "defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XtRInt,
1366 sizeof(int), XtOffset(AppDataPtr, defaultCacheSizeEGTB),
1367 XtRImmediate, (XtPointer) 4},
1368 { "polyglotDir", "polyglotDir", XtRString,
1369 sizeof(String), XtOffset(AppDataPtr, polyglotDir),
1370 XtRImmediate, (XtPointer) "." },
1371 { "polyglotBook", "polyglotBook", XtRString,
1372 sizeof(String), XtOffset(AppDataPtr, polyglotBook),
1373 XtRImmediate, (XtPointer) "" },
1374 { "defaultPathEGTB", "defaultPathEGTB", XtRString,
1375 sizeof(String), XtOffset(AppDataPtr, defaultPathEGTB),
1376 XtRImmediate, (XtPointer) "/usr/local/share/egtb"},
1377 { "delayBeforeQuit", "delayBeforeQuit", XtRInt,
1378 sizeof(int), XtOffset(AppDataPtr, delayBeforeQuit),
1379 XtRImmediate, (XtPointer) 0},
1380 { "delayAfterQuit", "delayAfterQuit", XtRInt,
1381 sizeof(int), XtOffset(AppDataPtr, delayAfterQuit),
1382 XtRImmediate, (XtPointer) 0},
1385 XrmOptionDescRec shellOptions[] = {
1386 { "-whitePieceColor", "whitePieceColor", XrmoptionSepArg, NULL },
1387 { "-blackPieceColor", "blackPieceColor", XrmoptionSepArg, NULL },
1388 { "-lightSquareColor", "lightSquareColor", XrmoptionSepArg, NULL },
1389 { "-darkSquareColor", "darkSquareColor", XrmoptionSepArg, NULL },
1390 { "-highlightSquareColor", "highlightSquareColor", XrmoptionSepArg, NULL },
1391 { "-premoveHighlightColor", "premoveHighlightColor", XrmoptionSepArg,NULL},
1392 { "-movesPerSession", "movesPerSession", XrmoptionSepArg, NULL },
1393 { "-mps", "movesPerSession", XrmoptionSepArg, NULL },
1394 { "-timeIncrement", "timeIncrement", XrmoptionSepArg, NULL },
1395 { "-inc", "timeIncrement", XrmoptionSepArg, NULL },
1396 { "-initString", "initString", XrmoptionSepArg, NULL },
1397 { "-firstInitString", "initString", XrmoptionSepArg, NULL },
1398 { "-secondInitString", "secondInitString", XrmoptionSepArg, NULL },
1399 { "-firstComputerString", "firstComputerString", XrmoptionSepArg, NULL },
1400 { "-secondComputerString", "secondComputerString", XrmoptionSepArg, NULL },
1401 { "-firstChessProgram", "firstChessProgram", XrmoptionSepArg, NULL },
1402 { "-fcp", "firstChessProgram", XrmoptionSepArg, NULL },
1403 { "-secondChessProgram", "secondChessProgram", XrmoptionSepArg, NULL },
1404 { "-scp", "secondChessProgram", XrmoptionSepArg, NULL },
1405 { "-firstPlaysBlack", "firstPlaysBlack", XrmoptionSepArg, NULL },
1406 { "-fb", "firstPlaysBlack", XrmoptionNoArg, "True" },
1407 { "-xfb", "firstPlaysBlack", XrmoptionNoArg, "False" },
1408 { "-noChessProgram", "noChessProgram", XrmoptionSepArg, NULL },
1409 { "-ncp", "noChessProgram", XrmoptionNoArg, "True" },
1410 { "-xncp", "noChessProgram", XrmoptionNoArg, "False" },
1411 { "-firstHost", "firstHost", XrmoptionSepArg, NULL },
1412 { "-fh", "firstHost", XrmoptionSepArg, NULL },
1413 { "-secondHost", "secondHost", XrmoptionSepArg, NULL },
1414 { "-sh", "secondHost", XrmoptionSepArg, NULL },
1415 { "-firstDirectory", "firstDirectory", XrmoptionSepArg, NULL },
1416 { "-fd", "firstDirectory", XrmoptionSepArg, NULL },
1417 { "-secondDirectory", "secondDirectory", XrmoptionSepArg, NULL },
1418 { "-sd", "secondDirectory", XrmoptionSepArg, NULL },
1419 { "-bitmapDirectory", "bitmapDirectory", XrmoptionSepArg, NULL },
1420 { "-bm", "bitmapDirectory", XrmoptionSepArg, NULL },
1421 { "-remoteShell", "remoteShell", XrmoptionSepArg, NULL },
1422 { "-rsh", "remoteShell", XrmoptionSepArg, NULL },
1423 { "-remoteUser", "remoteUser", XrmoptionSepArg, NULL },
1424 { "-ruser", "remoteUser", XrmoptionSepArg, NULL },
1425 { "-timeDelay", "timeDelay", XrmoptionSepArg, NULL },
1426 { "-td", "timeDelay", XrmoptionSepArg, NULL },
1427 { "-timeControl", "timeControl", XrmoptionSepArg, NULL },
1428 { "-tc", "timeControl", XrmoptionSepArg, NULL },
1429 { "-internetChessServerMode", "internetChessServerMode",
1430 XrmoptionSepArg, NULL },
1431 { "-ics", "internetChessServerMode", XrmoptionNoArg, "True" },
1432 { "-xics", "internetChessServerMode", XrmoptionNoArg, "False" },
1433 { "-internetChessServerHost", "internetChessServerHost",
1434 XrmoptionSepArg, NULL },
1435 { "-icshost", "internetChessServerHost", XrmoptionSepArg, NULL },
1436 { "-internetChessServerPort", "internetChessServerPort",
1437 XrmoptionSepArg, NULL },
1438 { "-icsport", "internetChessServerPort", XrmoptionSepArg, NULL },
1439 { "-internetChessServerCommPort", "internetChessServerCommPort",
1440 XrmoptionSepArg, NULL },
1441 { "-icscomm", "internetChessServerCommPort", XrmoptionSepArg, NULL },
1442 { "-internetChessServerLogonScript", "internetChessServerLogonScript",
1443 XrmoptionSepArg, NULL },
1444 { "-icslogon", "internetChessServerLogonScript", XrmoptionSepArg, NULL },
1445 { "-internetChessServerHelper", "internetChessServerHelper",
1446 XrmoptionSepArg, NULL },
1447 { "-icshelper", "internetChessServerHelper", XrmoptionSepArg, NULL },
1448 { "-internetChessServerInputBox", "internetChessServerInputBox",
1449 XrmoptionSepArg, NULL },
1450 { "-icsinput", "internetChessServerInputBox", XrmoptionNoArg, "True" },
1451 { "-xicsinput", "internetChessServerInputBox", XrmoptionNoArg, "False" },
1452 { "-icsAlarm", "icsAlarm", XrmoptionSepArg, NULL },
1453 { "-alarm", "icsAlarm", XrmoptionNoArg, "True" },
1454 { "-xalarm", "icsAlarm", XrmoptionNoArg, "False" },
1455 { "-icsAlarmTime", "icsAlarmTime", XrmoptionSepArg, NULL },
1456 { "-useTelnet", "useTelnet", XrmoptionSepArg, NULL },
1457 { "-telnet", "useTelnet", XrmoptionNoArg, "True" },
1458 { "-xtelnet", "useTelnet", XrmoptionNoArg, "False" },
1459 { "-telnetProgram", "telnetProgram", XrmoptionSepArg, NULL },
1460 { "-gateway", "gateway", XrmoptionSepArg, NULL },
1461 { "-loadGameFile", "loadGameFile", XrmoptionSepArg, NULL },
1462 { "-lgf", "loadGameFile", XrmoptionSepArg, NULL },
1463 { "-loadGameIndex", "loadGameIndex", XrmoptionSepArg, NULL },
1464 { "-lgi", "loadGameIndex", XrmoptionSepArg, NULL },
1465 { "-saveGameFile", "saveGameFile", XrmoptionSepArg, NULL },
1466 { "-sgf", "saveGameFile", XrmoptionSepArg, NULL },
1467 { "-autoSaveGames", "autoSaveGames", XrmoptionSepArg, NULL },
1468 { "-autosave", "autoSaveGames", XrmoptionNoArg, "True" },
1469 { "-xautosave", "autoSaveGames", XrmoptionNoArg, "False" },
1470 { "-autoRaiseBoard", "autoRaiseBoard", XrmoptionSepArg, NULL },
1471 { "-autoraise", "autoRaiseBoard", XrmoptionNoArg, "True" },
1472 { "-xautoraise", "autoRaiseBoard", XrmoptionNoArg, "False" },
1473 { "-blindfold", "blindfold", XrmoptionSepArg, NULL },
1474 { "-blind", "blindfold", XrmoptionNoArg, "True" },
1475 { "-xblind", "blindfold", XrmoptionNoArg, "False" },
1476 { "-loadPositionFile", "loadPositionFile", XrmoptionSepArg, NULL },
1477 { "-lpf", "loadPositionFile", XrmoptionSepArg, NULL },
1478 { "-loadPositionIndex", "loadPositionIndex", XrmoptionSepArg, NULL },
1479 { "-lpi", "loadPositionIndex", XrmoptionSepArg, NULL },
1480 { "-savePositionFile", "savePositionFile", XrmoptionSepArg, NULL },
1481 { "-spf", "savePositionFile", XrmoptionSepArg, NULL },
1482 { "-matchMode", "matchMode", XrmoptionSepArg, NULL },
1483 { "-mm", "matchMode", XrmoptionNoArg, "True" },
1484 { "-xmm", "matchMode", XrmoptionNoArg, "False" },
1485 { "-matchGames", "matchGames", XrmoptionSepArg, NULL },
1486 { "-mg", "matchGames", XrmoptionSepArg, NULL },
1487 { "-monoMode", "monoMode", XrmoptionSepArg, NULL },
1488 { "-mono", "monoMode", XrmoptionNoArg, "True" },
1489 { "-xmono", "monoMode", XrmoptionNoArg, "False" },
1490 { "-debugMode", "debugMode", XrmoptionSepArg, NULL },
1491 { "-debug", "debugMode", XrmoptionNoArg, "True" },
1492 { "-xdebug", "debugMode", XrmoptionNoArg, "False" },
1493 { "-clockMode", "clockMode", XrmoptionSepArg, NULL },
1494 { "-clock", "clockMode", XrmoptionNoArg, "True" },
1495 { "-xclock", "clockMode", XrmoptionNoArg, "False" },
1496 { "-boardSize", "boardSize", XrmoptionSepArg, NULL },
1497 { "-size", "boardSize", XrmoptionSepArg, NULL },
1498 { "-searchTime", "searchTime", XrmoptionSepArg, NULL },
1499 { "-st", "searchTime", XrmoptionSepArg, NULL },
1500 { "-searchDepth", "searchDepth", XrmoptionSepArg, NULL },
1501 { "-depth", "searchDepth", XrmoptionSepArg, NULL },
1502 { "-showCoords", "showCoords", XrmoptionSepArg, NULL },
1503 { "-coords", "showCoords", XrmoptionNoArg, "True" },
1504 { "-xcoords", "showCoords", XrmoptionNoArg, "False" },
1506 { "-showJail", "showJail", XrmoptionSepArg, NULL },
1507 { "-jail", "showJail", XrmoptionNoArg, "1" },
1508 { "-sidejail", "showJail", XrmoptionNoArg, "2" },
1509 { "-xjail", "showJail", XrmoptionNoArg, "0" },
1511 { "-showThinking", "showThinking", XrmoptionSepArg, NULL },
1512 { "-thinking", "showThinking", XrmoptionNoArg, "True" },
1513 { "-xthinking", "showThinking", XrmoptionNoArg, "False" },
1514 { "-ponderNextMove", "ponderNextMove", XrmoptionSepArg, NULL },
1515 { "-ponder", "ponderNextMove", XrmoptionNoArg, "True" },
1516 { "-xponder", "ponderNextMove", XrmoptionNoArg, "False" },
1517 { "-periodicUpdates", "periodicUpdates", XrmoptionSepArg, NULL },
1518 { "-periodic", "periodicUpdates", XrmoptionNoArg, "True" },
1519 { "-xperiodic", "periodicUpdates", XrmoptionNoArg, "False" },
1520 { "-clockFont", "clockFont", XrmoptionSepArg, NULL },
1521 { "-coordFont", "coordFont", XrmoptionSepArg, NULL },
1522 { "-font", "font", XrmoptionSepArg, NULL },
1523 { "-ringBellAfterMoves", "ringBellAfterMoves", XrmoptionSepArg, NULL },
1524 { "-bell", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1525 { "-xbell", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1526 { "-movesound", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1527 { "-xmovesound", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1528 { "-autoCallFlag", "autoCallFlag", XrmoptionSepArg, NULL },
1529 { "-autoflag", "autoCallFlag", XrmoptionNoArg, "True" },
1530 { "-xautoflag", "autoCallFlag", XrmoptionNoArg, "False" },
1531 { "-autoFlipView", "autoFlipView", XrmoptionSepArg, NULL },
1532 { "-autoflip", "autoFlipView", XrmoptionNoArg, "True" },
1533 { "-xautoflip", "autoFlipView", XrmoptionNoArg, "False" },
1534 { "-autoObserve", "autoObserve", XrmoptionSepArg, NULL },
1535 { "-autobs", "autoObserve", XrmoptionNoArg, "True" },
1536 { "-xautobs", "autoObserve", XrmoptionNoArg, "False" },
1537 { "-autoComment", "autoComment", XrmoptionSepArg, NULL },
1538 { "-autocomm", "autoComment", XrmoptionNoArg, "True" },
1539 { "-xautocomm", "autoComment", XrmoptionNoArg, "False" },
1540 { "-getMoveList", "getMoveList", XrmoptionSepArg, NULL },
1541 { "-moves", "getMoveList", XrmoptionNoArg, "True" },
1542 { "-xmoves", "getMoveList", XrmoptionNoArg, "False" },
1544 { "-highlightDragging", "highlightDragging", XrmoptionSepArg, NULL },
1545 { "-highdrag", "highlightDragging", XrmoptionNoArg, "True" },
1546 { "-xhighdrag", "highlightDragging", XrmoptionNoArg, "False" },
1548 { "-highlightLastMove", "highlightLastMove", XrmoptionSepArg, NULL },
1549 { "-highlight", "highlightLastMove", XrmoptionNoArg, "True" },
1550 { "-xhighlight", "highlightLastMove", XrmoptionNoArg, "False" },
1551 { "-premove", "premove", XrmoptionSepArg, NULL },
1552 { "-pre", "premove", XrmoptionNoArg, "True" },
1553 { "-xpre", "premove", XrmoptionNoArg, "False" },
1554 { "-testLegality", "testLegality", XrmoptionSepArg, NULL },
1555 { "-legal", "testLegality", XrmoptionNoArg, "True" },
1556 { "-xlegal", "testLegality", XrmoptionNoArg, "False" },
1557 { "-flipView", "flipView", XrmoptionSepArg, NULL },
1558 { "-flip", "flipView", XrmoptionNoArg, "True" },
1559 { "-xflip", "flipView", XrmoptionNoArg, "False" },
1560 { "-cmail", "cmailGameName", XrmoptionSepArg, NULL },
1561 { "-alwaysPromoteToQueen", "alwaysPromoteToQueen",
1562 XrmoptionSepArg, NULL },
1563 { "-queen", "alwaysPromoteToQueen", XrmoptionNoArg, "True" },
1564 { "-xqueen", "alwaysPromoteToQueen", XrmoptionNoArg, "False" },
1565 { "-oldSaveStyle", "oldSaveStyle", XrmoptionSepArg, NULL },
1566 { "-oldsave", "oldSaveStyle", XrmoptionNoArg, "True" },
1567 { "-xoldsave", "oldSaveStyle", XrmoptionNoArg, "False" },
1568 { "-quietPlay", "quietPlay", XrmoptionSepArg, NULL },
1569 { "-quiet", "quietPlay", XrmoptionNoArg, "True" },
1570 { "-xquiet", "quietPlay", XrmoptionNoArg, "False" },
1571 { "-titleInWindow", "titleInWindow", XrmoptionSepArg, NULL },
1572 { "-title", "titleInWindow", XrmoptionNoArg, "True" },
1573 { "-xtitle", "titleInWindow", XrmoptionNoArg, "False" },
1575 { "-zippyTalk", "zippyTalk", XrmoptionSepArg, NULL },
1576 { "-zt", "zippyTalk", XrmoptionNoArg, "True" },
1577 { "-xzt", "zippyTalk", XrmoptionNoArg, "False" },
1578 { "-zippyPlay", "zippyPlay", XrmoptionSepArg, NULL },
1579 { "-zp", "zippyPlay", XrmoptionNoArg, "True" },
1580 { "-xzp", "zippyPlay", XrmoptionNoArg, "False" },
1581 { "-zippyLines", "zippyLines", XrmoptionSepArg, NULL },
1582 { "-zippyPinhead", "zippyPinhead", XrmoptionSepArg, NULL },
1583 { "-zippyPassword", "zippyPassword", XrmoptionSepArg, NULL },
1584 { "-zippyPassword2", "zippyPassword2", XrmoptionSepArg, NULL },
1585 { "-zippyWrongPassword", "zippyWrongPassword", XrmoptionSepArg, NULL },
1586 { "-zippyAcceptOnly", "zippyAcceptOnly", XrmoptionSepArg, NULL },
1587 { "-zippyUseI", "zippyUseI", XrmoptionSepArg, NULL },
1588 { "-zui", "zippyUseI", XrmoptionNoArg, "True" },
1589 { "-xzui", "zippyUseI", XrmoptionNoArg, "False" },
1590 { "-zippyBughouse", "zippyBughouse", XrmoptionSepArg, NULL },
1591 { "-zippyNoplayCrafty", "zippyNoplayCrafty", XrmoptionSepArg, NULL },
1592 { "-znc", "zippyNoplayCrafty", XrmoptionNoArg, "True" },
1593 { "-xznc", "zippyNoplayCrafty", XrmoptionNoArg, "False" },
1594 { "-zippyGameEnd", "zippyGameEnd", XrmoptionSepArg, NULL },
1595 { "-zippyGameStart", "zippyGameStart", XrmoptionSepArg, NULL },
1596 { "-zippyAdjourn", "zippyAdjourn", XrmoptionSepArg, NULL },
1597 { "-zadj", "zippyAdjourn", XrmoptionNoArg, "True" },
1598 { "-xzadj", "zippyAdjourn", XrmoptionNoArg, "False" },
1599 { "-zippyAbort", "zippyAbort", XrmoptionSepArg, NULL },
1600 { "-zab", "zippyAbort", XrmoptionNoArg, "True" },
1601 { "-xzab", "zippyAbort", XrmoptionNoArg, "False" },
1602 { "-zippyVariants", "zippyVariants", XrmoptionSepArg, NULL },
1603 { "-zippyMaxGames", "zippyMaxGames", XrmoptionSepArg, NULL },
1604 { "-zippyReplayTimeout", "zippyReplayTimeout", XrmoptionSepArg, NULL },
1605 { "-zippyShortGame", "zippyShortGame", XrmoptionSepArg, NULL },
1607 { "-flashCount", "flashCount", XrmoptionSepArg, NULL },
1608 { "-flash", "flashCount", XrmoptionNoArg, "3" },
1609 { "-xflash", "flashCount", XrmoptionNoArg, "0" },
1610 { "-flashRate", "flashRate", XrmoptionSepArg, NULL },
1611 { "-pixmapDirectory", "pixmapDirectory", XrmoptionSepArg, NULL },
1612 { "-msLoginDelay", "msLoginDelay", XrmoptionSepArg, NULL },
1613 { "-pixmap", "pixmapDirectory", XrmoptionSepArg, NULL },
1614 { "-colorizeMessages", "colorizeMessages", XrmoptionSepArg, NULL },
1615 { "-colorize", "colorizeMessages", XrmoptionNoArg, "True" },
1616 { "-xcolorize", "colorizeMessages", XrmoptionNoArg, "False" },
1617 { "-colorShout", "colorShout", XrmoptionSepArg, NULL },
1618 { "-colorSShout", "colorSShout", XrmoptionSepArg, NULL },
1619 { "-colorCShout", "colorSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1620 { "-colorChannel1", "colorChannel1", XrmoptionSepArg, NULL },
1621 { "-colorChannel", "colorChannel", XrmoptionSepArg, NULL },
1622 { "-colorKibitz", "colorKibitz", XrmoptionSepArg, NULL },
1623 { "-colorTell", "colorTell", XrmoptionSepArg, NULL },
1624 { "-colorChallenge", "colorChallenge", XrmoptionSepArg, NULL },
1625 { "-colorRequest", "colorRequest", XrmoptionSepArg, NULL },
1626 { "-colorSeek", "colorSeek", XrmoptionSepArg, NULL },
1627 { "-colorNormal", "colorNormal", XrmoptionSepArg, NULL },
1628 { "-soundProgram", "soundProgram", XrmoptionSepArg, NULL },
1629 { "-soundShout", "soundShout", XrmoptionSepArg, NULL },
1630 { "-soundSShout", "soundSShout", XrmoptionSepArg, NULL },
1631 { "-soundCShout", "soundSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1632 { "-soundChannel1", "soundChannel1", XrmoptionSepArg, NULL },
1633 { "-soundChannel", "soundChannel", XrmoptionSepArg, NULL },
1634 { "-soundKibitz", "soundKibitz", XrmoptionSepArg, NULL },
1635 { "-soundTell", "soundTell", XrmoptionSepArg, NULL },
1636 { "-soundChallenge", "soundChallenge", XrmoptionSepArg, NULL },
1637 { "-soundRequest", "soundRequest", XrmoptionSepArg, NULL },
1638 { "-soundSeek", "soundSeek", XrmoptionSepArg, NULL },
1639 { "-soundMove", "soundMove", XrmoptionSepArg, NULL },
1640 { "-soundIcsWin", "soundIcsWin", XrmoptionSepArg, NULL },
1641 { "-soundIcsLoss", "soundIcsLoss", XrmoptionSepArg, NULL },
1642 { "-soundIcsDraw", "soundIcsDraw", XrmoptionSepArg, NULL },
1643 { "-soundIcsUnfinished", "soundIcsUnfinished", XrmoptionSepArg, NULL },
1644 { "-soundIcsAlarm", "soundIcsAlarm", XrmoptionSepArg, NULL },
1645 { "-reuseFirst", "reuseFirst", XrmoptionSepArg, NULL },
1646 { "-reuseChessPrograms", "reuseFirst", XrmoptionSepArg, NULL }, /*compat*/
1647 { "-reuse", "reuseFirst", XrmoptionNoArg, "True" },
1648 { "-xreuse", "reuseFirst", XrmoptionNoArg, "False" },
1649 { "-reuseSecond", "reuseSecond", XrmoptionSepArg, NULL },
1650 { "-reuse2", "reuseSecond", XrmoptionNoArg, "True" },
1651 { "-xreuse2", "reuseSecond", XrmoptionNoArg, "False" },
1652 { "-animateMoving", "animateMoving", XrmoptionSepArg, NULL },
1653 { "-animate", "animateMoving", XrmoptionNoArg, "True" },
1654 { "-xanimate", "animateMoving", XrmoptionNoArg, "False" },
1655 { "-animateDragging", "animateDragging", XrmoptionSepArg, NULL },
1656 { "-drag", "animateDragging", XrmoptionNoArg, "True" },
1657 { "-xdrag", "animateDragging", XrmoptionNoArg, "False" },
1658 { "-animateSpeed", "animateSpeed", XrmoptionSepArg, NULL },
1659 { "-popupExitMessage", "popupExitMessage", XrmoptionSepArg, NULL },
1660 { "-exit", "popupExitMessage", XrmoptionNoArg, "True" },
1661 { "-xexit", "popupExitMessage", XrmoptionNoArg, "False" },
1662 { "-popupMoveErrors", "popupMoveErrors", XrmoptionSepArg, NULL },
1663 { "-popup", "popupMoveErrors", XrmoptionNoArg, "True" },
1664 { "-xpopup", "popupMoveErrors", XrmoptionNoArg, "False" },
1665 { "-fontSizeTolerance", "fontSizeTolerance", XrmoptionSepArg, NULL },
1666 { "-initialMode", "initialMode", XrmoptionSepArg, NULL },
1667 { "-mode", "initialMode", XrmoptionSepArg, NULL },
1668 { "-variant", "variant", XrmoptionSepArg, NULL },
1669 { "-firstProtocolVersion", "firstProtocolVersion", XrmoptionSepArg, NULL },
1670 { "-secondProtocolVersion","secondProtocolVersion",XrmoptionSepArg, NULL },
1671 { "-showButtonBar", "showButtonBar", XrmoptionSepArg, NULL },
1672 { "-buttons", "showButtonBar", XrmoptionNoArg, "True" },
1673 { "-xbuttons", "showButtonBar", XrmoptionNoArg, "False" },
1674 { "-lowTimeWarningColor", "lowTimeWarningColor", XrmoptionSepArg, NULL },
1675 { "-lowTimeWarning", "lowTimeWarning", XrmoptionSepArg, NULL },
1676 /* [AS,HR] New features */
1677 { "-firstScoreAbs", "firstScoreAbs", XrmoptionSepArg, NULL },
1678 { "-secondScoreAbs", "secondScoreAbs", XrmoptionSepArg, NULL },
1679 { "-pgnExtendedInfo", "pgnExtendedInfo", XrmoptionSepArg, NULL },
1680 { "-hideThinkingFromHuman", "hideThinkingFromHuman", XrmoptionSepArg, NULL },
1681 { "-adjudicateLossThreshold", "adjudicateLossThreshold", XrmoptionSepArg, NULL },
1682 { "-pgnEventHeader", "pgnEventHeader", XrmoptionSepArg, NULL },
1683 { "-firstIsUCI", "firstIsUCI", XrmoptionSepArg, NULL },
1684 { "-secondIsUCI", "secondIsUCI", XrmoptionSepArg, NULL },
1685 { "-fUCI", "firstIsUCI", XrmoptionNoArg, "True" },
1686 { "-sUCI", "secondIsUCI", XrmoptionNoArg, "True" },
1687 { "-firstHasOwnBookUCI", "firstHasOwnBookUCI", XrmoptionSepArg, NULL },
1688 { "-secondHasOwnBookUCI", "secondHasOwnBookUCI", XrmoptionSepArg, NULL },
1689 { "-fNoOwnBookUCI", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1690 { "-sNoOwnBookUCI", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1691 { "-firstXBook", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1692 { "-secondXBook", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1693 { "-polyglotDir", "polyglotDir", XrmoptionSepArg, NULL },
1694 { "-usePolyglotBook", "usePolyglotBook", XrmoptionSepArg, NULL },
1695 { "-polyglotBook", "polyglotBook", XrmoptionSepArg, NULL },
1696 { "-defaultHashSize", "defaultHashSize", XrmoptionSepArg, NULL },
1697 { "-defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XrmoptionSepArg, NULL },
1698 { "-defaultPathEGTB", "defaultPathEGTB", XrmoptionSepArg, NULL },
1699 { "-defaultFrcPosition", "defaultFrcPosition", XrmoptionSepArg, NULL },
1700 { "-gameListTags", "gameListTags", XrmoptionSepArg, NULL },
1701 // [HGM] I am sure AS added many more options, but we have to fish them out, from the list in winboard.c
1703 /* [HGM,HR] User-selectable board size */
1704 { "-boardWidth", "boardWidth", XrmoptionSepArg, NULL },
1705 { "-boardHeight", "boardHeight", XrmoptionSepArg, NULL },
1706 { "-matchPause", "matchPause", XrmoptionSepArg, NULL },
1708 /* [HGM] new arguments of 4.3.xx. All except first three are back-end options, which should work immediately */
1709 { "-holdingsSize", "holdingsSize", XrmoptionSepArg, NULL }, // requires extensive front-end changes to work
1710 { "-flipBlack", "flipBlack", XrmoptionSepArg, NULL }, // requires front-end changes to work
1711 { "-allWhite", "allWhite", XrmoptionSepArg, NULL }, // requires front-end changes to work
1712 { "-pieceToCharTable", "pieceToCharTable", XrmoptionSepArg, NULL },
1713 { "-alphaRank", "alphaRank", XrmoptionSepArg, NULL },
1714 { "-testClaims", "testClaims", XrmoptionSepArg, NULL },
1715 { "-checkMates", "checkMates", XrmoptionSepArg, NULL },
1716 { "-materialDraws", "materialDraws", XrmoptionSepArg, NULL },
1717 { "-trivialDraws", "trivialDraws", XrmoptionSepArg, NULL },
1718 { "-ruleMoves", "ruleMoves", XrmoptionSepArg, NULL },
1719 { "-repeatsToDraw", "repeatsToDraw", XrmoptionSepArg, NULL },
1720 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1721 { "-userName", "userName", XrmoptionSepArg, NULL },
1722 { "-autoKibitz", "autoKibitz", XrmoptionNoArg, "True" },
1723 { "-firstTimeOdds", "firstTimeOdds", XrmoptionSepArg, NULL },
1724 { "-secondTimeOdds", "secondTimeOdds", XrmoptionSepArg, NULL },
1725 { "-timeOddsMode", "timeOddsMode", XrmoptionSepArg, NULL },
1726 { "-firstAccumulateTC", "firstAccumulateTC", XrmoptionSepArg, NULL },
1727 { "-secondAccumulateTC", "secondAccumulateTC", XrmoptionSepArg, NULL },
1728 { "-firstNPS", "firstNPS", XrmoptionSepArg, NULL },
1729 { "-secondNPS", "secondNPS", XrmoptionSepArg, NULL },
1730 { "-serverMoves", "serverMoves", XrmoptionSepArg, NULL },
1731 { "-serverPause", "serverPause", XrmoptionSepArg, NULL },
1732 { "-suppressLoadMoves", "suppressLoadMoves", XrmoptionSepArg, NULL },
1733 { "-egtFormats", "egtFormats", XrmoptionSepArg, NULL },
1734 { "-userName", "userName", XrmoptionSepArg, NULL },
1735 { "-smpCores", "smpCores", XrmoptionSepArg, NULL },
1736 { "-sameColorGames", "sameColorGames", XrmoptionSepArg, NULL },
1737 { "-rewindIndex", "rewindIndex", XrmoptionSepArg, NULL },
1738 { "-niceEngines", "niceEngines", XrmoptionSepArg, NULL },
1739 { "-delayBeforeQuit", "delayBeforeQuit", XrmoptionSepArg, NULL },
1740 { "-delayAfterQuit", "delayAfterQuit", XrmoptionSepArg, NULL },
1741 { "-nameOfDebugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1742 { "-debugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1743 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1744 { "-noGUI", "noGUI", XrmoptionNoArg, "True" },
1745 { "-firstOptions", "firstOptions", XrmoptionSepArg, NULL },
1746 { "-secondOptions", "secondOptions", XrmoptionSepArg, NULL },
1747 { "-firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1748 { "-secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1752 XtActionsRec boardActions[] = {
1753 { "DrawPosition", DrawPositionProc },
1754 { "HandleUserMove", HandleUserMove },
1755 { "AnimateUserMove", AnimateUserMove },
1756 { "FileNameAction", FileNameAction },
1757 { "AskQuestionProc", AskQuestionProc },
1758 { "AskQuestionReplyAction", AskQuestionReplyAction },
1759 { "PieceMenuPopup", PieceMenuPopup },
1760 { "WhiteClock", WhiteClock },
1761 { "BlackClock", BlackClock },
1762 { "Iconify", Iconify },
1763 { "LoadSelectedProc", LoadSelectedProc },
1764 { "LoadPositionProc", LoadPositionProc },
1765 { "LoadNextPositionProc", LoadNextPositionProc },
1766 { "LoadPrevPositionProc", LoadPrevPositionProc },
1767 { "ReloadPositionProc", ReloadPositionProc },
1768 { "CopyPositionProc", CopyPositionProc },
1769 { "PastePositionProc", PastePositionProc },
1770 { "CopyGameProc", CopyGameProc },
1771 { "PasteGameProc", PasteGameProc },
1772 { "SaveGameProc", SaveGameProc },
1773 { "SavePositionProc", SavePositionProc },
1774 { "MailMoveProc", MailMoveProc },
1775 { "ReloadCmailMsgProc", ReloadCmailMsgProc },
1776 { "MachineWhiteProc", MachineWhiteProc },
1777 { "MachineBlackProc", MachineBlackProc },
1778 { "AnalysisModeProc", AnalyzeModeProc },
1779 { "AnalyzeFileProc", AnalyzeFileProc },
1780 { "TwoMachinesProc", TwoMachinesProc },
1781 { "IcsClientProc", IcsClientProc },
1782 { "EditGameProc", EditGameProc },
1783 { "EditPositionProc", EditPositionProc },
1784 { "TrainingProc", EditPositionProc },
1785 { "EngineOutputProc", EngineOutputProc}, // [HGM] Winboard_x engine-output window
1786 { "ShowGameListProc", ShowGameListProc },
1787 { "ShowMoveListProc", HistoryShowProc},
1788 { "EditTagsProc", EditCommentProc },
1789 { "EditCommentProc", EditCommentProc },
1790 { "IcsAlarmProc", IcsAlarmProc },
1791 { "IcsInputBoxProc", IcsInputBoxProc },
1792 { "AcceptProc", AcceptProc },
1793 { "DeclineProc", DeclineProc },
1794 { "RematchProc", RematchProc },
1795 { "CallFlagProc", CallFlagProc },
1796 { "DrawProc", DrawProc },
1797 { "AdjournProc", AdjournProc },
1798 { "AbortProc", AbortProc },
1799 { "ResignProc", ResignProc },
1800 { "AdjuWhiteProc", AdjuWhiteProc },
1801 { "AdjuBlackProc", AdjuBlackProc },
1802 { "AdjuDrawProc", AdjuDrawProc },
1803 { "EnterKeyProc", EnterKeyProc },
1804 { "StopObservingProc", StopObservingProc },
1805 { "StopExaminingProc", StopExaminingProc },
1806 { "BackwardProc", BackwardProc },
1807 { "ForwardProc", ForwardProc },
1808 { "ToStartProc", ToStartProc },
1809 { "ToEndProc", ToEndProc },
1810 { "RevertProc", RevertProc },
1811 { "TruncateGameProc", TruncateGameProc },
1812 { "MoveNowProc", MoveNowProc },
1813 { "RetractMoveProc", RetractMoveProc },
1814 { "AlwaysQueenProc", AlwaysQueenProc },
1815 { "AnimateDraggingProc", AnimateDraggingProc },
1816 { "AnimateMovingProc", AnimateMovingProc },
1817 { "AutoflagProc", AutoflagProc },
1818 { "AutoflipProc", AutoflipProc },
1819 { "AutobsProc", AutobsProc },
1820 { "AutoraiseProc", AutoraiseProc },
1821 { "AutosaveProc", AutosaveProc },
1822 { "BlindfoldProc", BlindfoldProc },
1823 { "FlashMovesProc", FlashMovesProc },
1824 { "FlipViewProc", FlipViewProc },
1825 { "GetMoveListProc", GetMoveListProc },
1827 { "HighlightDraggingProc", HighlightDraggingProc },
1829 { "HighlightLastMoveProc", HighlightLastMoveProc },
1830 { "IcsAlarmProc", IcsAlarmProc },
1831 { "MoveSoundProc", MoveSoundProc },
1832 { "OldSaveStyleProc", OldSaveStyleProc },
1833 { "PeriodicUpdatesProc", PeriodicUpdatesProc },
1834 { "PonderNextMoveProc", PonderNextMoveProc },
1835 { "PopupExitMessageProc", PopupExitMessageProc },
1836 { "PopupMoveErrorsProc", PopupMoveErrorsProc },
1837 { "PremoveProc", PremoveProc },
1838 { "QuietPlayProc", QuietPlayProc },
1839 { "ShowThinkingProc", ShowThinkingProc },
1840 { "HideThinkingProc", HideThinkingProc },
1841 { "TestLegalityProc", TestLegalityProc },
1842 { "InfoProc", InfoProc },
1843 { "ManProc", ManProc },
1844 { "HintProc", HintProc },
1845 { "BookProc", BookProc },
1846 { "AboutGameProc", AboutGameProc },
1847 { "DebugProc", DebugProc },
1848 { "NothingProc", NothingProc },
1849 { "CommentPopDown", (XtActionProc) CommentPopDown },
1850 { "EditCommentPopDown", (XtActionProc) EditCommentPopDown },
1851 { "TagsPopDown", (XtActionProc) TagsPopDown },
1852 { "ErrorPopDown", (XtActionProc) ErrorPopDown },
1853 { "ICSInputBoxPopDown", (XtActionProc) ICSInputBoxPopDown },
1854 { "AnalysisPopDown", (XtActionProc) AnalysisPopDown },
1855 { "FileNamePopDown", (XtActionProc) FileNamePopDown },
1856 { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown },
1857 { "GameListPopDown", (XtActionProc) GameListPopDown },
1858 { "PromotionPopDown", (XtActionProc) PromotionPopDown },
1859 { "HistoryPopDown", (XtActionProc) HistoryPopDown },
1860 { "EngineOutputPopDown", (XtActionProc) EngineOutputPopDown },
1861 { "ShufflePopDown", (XtActionProc) ShufflePopDown },
1862 { "EnginePopDown", (XtActionProc) EnginePopDown },
1863 { "UciPopDown", (XtActionProc) UciPopDown },
1864 { "TimeControlPopDown", (XtActionProc) TimeControlPopDown },
1865 { "NewVariantPopDown", (XtActionProc) NewVariantPopDown },
1866 { "SettingsPopDown", (XtActionProc) SettingsPopDown },
1869 char globalTranslations[] =
1870 ":<Key>R: ResignProc() \n \
1871 :<Key>F: ToEndProc() \n \
1872 :<Key>f: ForwardProc() \n \
1873 :<Key>B: ToStartProc() \n \
1874 :<Key>b: BackwardProc() \n \
1875 :<Key>d: DrawProc() \n \
1876 :<Key>t: CallFlagProc() \n \
1877 :<Key>i: Iconify() \n \
1878 :<Key>c: Iconify() \n \
1879 :<Key>v: FlipViewProc() \n \
1880 <KeyDown>Control_L: BackwardProc() \n \
1881 <KeyUp>Control_L: ForwardProc() \n \
1882 <KeyDown>Control_R: BackwardProc() \n \
1883 <KeyUp>Control_R: ForwardProc() \n \
1884 Shift<Key>1: AskQuestionProc(\"Direct command\",\
1885 \"Send to chess program:\",,1) \n \
1886 Shift<Key>2: AskQuestionProc(\"Direct command\",\
1887 \"Send to second chess program:\",,2) \n";
1889 char boardTranslations[] =
1890 "<Btn1Down>: HandleUserMove() \n \
1891 <Btn1Up>: HandleUserMove() \n \
1892 <Btn1Motion>: AnimateUserMove() \n \
1893 Shift<Btn2Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD)\
1894 PieceMenuPopup(menuB) \n \
1895 Any<Btn2Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD) \
1896 PieceMenuPopup(menuW) \n \
1897 Shift<Btn3Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD)\
1898 PieceMenuPopup(menuW) \n \
1899 Any<Btn3Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD) \
1900 PieceMenuPopup(menuB) \n";
1902 char whiteTranslations[] = "<BtnDown>: WhiteClock()\n";
1903 char blackTranslations[] = "<BtnDown>: BlackClock()\n";
1905 char ICSInputTranslations[] =
1906 "<Key>Return: EnterKeyProc() \n";
1908 String xboardResources[] = {
1909 "*fileName*value.translations: #override\\n <Key>Return: FileNameAction()",
1910 "*question*value.translations: #override\\n <Key>Return: AskQuestionReplyAction()",
1911 "*errorpopup*translations: #override\\n <Key>Return: ErrorPopDown()",
1916 /* Max possible square size */
1917 #define MAXSQSIZE 256
1919 static int xpm_avail[MAXSQSIZE];
1921 #ifdef HAVE_DIR_STRUCT
1923 /* Extract piece size from filename */
1925 xpm_getsize(name, len, ext)
1936 if ((p=strchr(name, '.')) == NULL ||
1937 StrCaseCmp(p+1, ext) != 0)
1943 while (*p && isdigit(*p))
1950 /* Setup xpm_avail */
1952 xpm_getavail(dirname, ext)
1960 for (i=0; i<MAXSQSIZE; ++i)
1963 if (appData.debugMode)
1964 fprintf(stderr, "XPM dir:%s:ext:%s:\n", dirname, ext);
1966 dir = opendir(dirname);
1969 fprintf(stderr, _("%s: Can't access XPM directory %s\n"),
1970 programName, dirname);
1974 while ((ent=readdir(dir)) != NULL) {
1975 i = xpm_getsize(ent->d_name, NAMLEN(ent), ext);
1976 if (i > 0 && i < MAXSQSIZE)
1986 xpm_print_avail(fp, ext)
1992 fprintf(fp, _("Available `%s' sizes:\n"), ext);
1993 for (i=1; i<MAXSQSIZE; ++i) {
1999 /* Return XPM piecesize closest to size */
2001 xpm_closest_to(dirname, size, ext)
2007 int sm_diff = MAXSQSIZE;
2011 xpm_getavail(dirname, ext);
2013 if (appData.debugMode)
2014 xpm_print_avail(stderr, ext);
2016 for (i=1; i<MAXSQSIZE; ++i) {
2019 diff = (diff<0) ? -diff : diff;
2020 if (diff < sm_diff) {
2028 fprintf(stderr, _("Error: No `%s' files!\n"), ext);
2034 #else /* !HAVE_DIR_STRUCT */
2035 /* If we are on a system without a DIR struct, we can't
2036 read the directory, so we can't collect a list of
2037 filenames, etc., so we can't do any size-fitting. */
2039 xpm_closest_to(dirname, size, ext)
2044 fprintf(stderr, _("\
2045 Warning: No DIR structure found on this system --\n\
2046 Unable to autosize for XPM/XIM pieces.\n\
2047 Please report this error to frankm@hiwaay.net.\n\
2048 Include system type & operating system in message.\n"));
2051 #endif /* HAVE_DIR_STRUCT */
2053 static char *cnames[9] = { "black", "red", "green", "yellow", "blue",
2054 "magenta", "cyan", "white" };
2058 TextColors textColors[(int)NColorClasses];
2060 /* String is: "fg, bg, attr". Which is 0, 1, 2 */
2062 parse_color(str, which)
2066 char *p, buf[100], *d;
2069 if (strlen(str) > 99) /* watch bounds on buf */
2074 for (i=0; i<which; ++i) {
2081 /* Could be looking at something like:
2083 .. in which case we want to stop on a comma also */
2084 while (*p && *p != ',' && !isalpha(*p) && !isdigit(*p))
2088 return -1; /* Use default for empty field */
2091 if (which == 2 || isdigit(*p))
2094 while (*p && isalpha(*p))
2099 for (i=0; i<8; ++i) {
2100 if (!StrCaseCmp(buf, cnames[i]))
2101 return which? (i+40) : (i+30);
2103 if (!StrCaseCmp(buf, "default")) return -1;
2105 fprintf(stderr, _("%s: unrecognized color %s\n"), programName, buf);
2110 parse_cpair(cc, str)
2114 if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {
2115 fprintf(stderr, _("%s: can't parse foreground color in `%s'\n"),
2120 /* bg and attr are optional */
2121 textColors[(int)cc].bg = parse_color(str, 1);
2122 if ((textColors[(int)cc].attr = parse_color(str, 2)) < 0) {
2123 textColors[(int)cc].attr = 0;
2129 /* Arrange to catch delete-window events */
2130 Atom wm_delete_window;
2132 CatchDeleteWindow(Widget w, String procname)
2135 XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
2136 snprintf(buf, sizeof(buf), "<Message>WM_PROTOCOLS: %s() \n", procname);
2137 XtAugmentTranslations(w, XtParseTranslationTable(buf));
2143 /* this should raise the board to the top */
2144 gtk_window_present(GTK_WINDOW(GUI_Window));
2149 // eventually, all layout determining code should go into a subroutine, but until then IDSIZE remains undefined
2151 #define BoardSize int
2152 void InitDrawingSizes(BoardSize boardSize, int flags)
2153 { // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
2154 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2156 XtGeometryResult gres;
2159 // if(!formWidget) return;
2162 * Enable shell resizing.
2164 // shellArgs[0].value = (XtArgVal) &w;
2165 // shellArgs[1].value = (XtArgVal) &h;
2166 // XtGetValues(shellWidget, shellArgs, 2);
2168 // shellArgs[4].value = 2*w; shellArgs[2].value = 10;
2169 // shellArgs[5].value = 2*h; shellArgs[3].value = 10;
2170 // XtSetValues(shellWidget, &shellArgs[2], 4);
2172 // XtSetArg(args[0], XtNdefaultDistance, &sep);
2173 // XtGetValues(formWidget, args, 1);
2175 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2176 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2178 // XtSetArg(args[0], XtNwidth, boardWidth);
2179 // XtSetArg(args[1], XtNheight, boardHeight);
2180 // XtSetValues(boardWidget, args, 2);
2182 timerWidth = (boardWidth - sep) / 2;
2183 // XtSetArg(args[0], XtNwidth, timerWidth);
2184 // XtSetValues(whiteTimerWidget, args, 1);
2185 // XtSetValues(blackTimerWidget, args, 1);
2187 // XawFormDoLayout(formWidget, False);
2189 if (appData.titleInWindow) {
2191 // XtSetArg(args[i], XtNborderWidth, &bor); i++;
2192 // XtSetArg(args[i], XtNheight, &h); i++;
2193 // XtGetValues(titleWidget, args, i);
2195 w = boardWidth - 2*bor;
2197 // XtSetArg(args[0], XtNwidth, &w);
2198 // XtGetValues(menuBarWidget, args, 1);
2199 w = boardWidth - w - sep - 2*bor - 2; // WIDTH_FUDGE
2202 // gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2203 // if (gres != XtGeometryYes && appData.debugMode) {
2205 // _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2206 // programName, gres, w, h, wr, hr);
2209 if(!formWidget) return;
2211 // XawFormDoLayout(formWidget, True);
2214 * Inhibit shell resizing.
2216 shellArgs[0].value = w = (XtArgVal) boardWidth + marginW;
2217 shellArgs[1].value = h = (XtArgVal) boardHeight + marginH;
2218 shellArgs[4].value = shellArgs[2].value = w;
2219 shellArgs[5].value = shellArgs[3].value = h;
2220 // XtSetValues(shellWidget, &shellArgs[0], 6);
2222 // [HGM] pieces: tailor piece bitmaps to needs of specific variant
2225 for(i=0; i<4; i++) {
2227 for(p=0; p<=(int)WhiteKing; p++)
2228 xpmPieceBitmap[i][p] = xpmPieceBitmap2[i][p]; // defaults
2229 if(gameInfo.variant == VariantShogi) {
2230 xpmPieceBitmap[i][(int)WhiteCannon] = xpmPieceBitmap2[i][(int)WhiteKing+1];
2231 xpmPieceBitmap[i][(int)WhiteNightrider] = xpmPieceBitmap2[i][(int)WhiteKing+2];
2232 xpmPieceBitmap[i][(int)WhiteSilver] = xpmPieceBitmap2[i][(int)WhiteKing+3];
2233 xpmPieceBitmap[i][(int)WhiteGrasshopper] = xpmPieceBitmap2[i][(int)WhiteKing+4];
2234 xpmPieceBitmap[i][(int)WhiteQueen] = xpmPieceBitmap2[i][(int)WhiteLance];
2237 if(gameInfo.variant == VariantGothic) {
2238 xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteSilver];
2242 // [HGM] why are thee ximMasks used at all? the ximPieceBitmaps seem to be never used!
2243 for(p=0; p<=(int)WhiteKing; p++)
2244 ximMaskPm[p] = ximMaskPm2[p]; // defaults
2245 if(gameInfo.variant == VariantShogi) {
2246 ximMaskPm[(int)WhiteCannon] = ximMaskPm2[(int)WhiteKing+1];
2247 ximMaskPm[(int)WhiteNightrider] = ximMaskPm2[(int)WhiteKing+2];
2248 ximMaskPm[(int)WhiteSilver] = ximMaskPm2[(int)WhiteKing+3];
2249 ximMaskPm[(int)WhiteGrasshopper] = ximMaskPm2[(int)WhiteKing+4];
2250 ximMaskPm[(int)WhiteQueen] = ximMaskPm2[(int)WhiteLance];
2253 if(gameInfo.variant == VariantGothic) {
2254 ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[i][(int)WhiteSilver];
2260 for(i=0; i<2; i++) {
2262 for(p=0; p<=(int)WhiteKing; p++)
2263 pieceBitmap[i][p] = pieceBitmap2[i][p]; // defaults
2264 if(gameInfo.variant == VariantShogi) {
2265 pieceBitmap[i][(int)WhiteCannon] = pieceBitmap2[i][(int)WhiteKing+1];
2266 pieceBitmap[i][(int)WhiteNightrider] = pieceBitmap2[i][(int)WhiteKing+2];
2267 pieceBitmap[i][(int)WhiteSilver] = pieceBitmap2[i][(int)WhiteKing+3];
2268 pieceBitmap[i][(int)WhiteGrasshopper] = pieceBitmap2[i][(int)WhiteKing+4];
2269 pieceBitmap[i][(int)WhiteQueen] = pieceBitmap2[i][(int)WhiteLance];
2272 if(gameInfo.variant == VariantGothic) {
2273 pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteSilver];
2289 int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
2290 XSetWindowAttributes window_attributes;
2292 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2293 XrmValue vFrom, vTo;
2294 XtGeometryResult gres;
2297 int forceMono = False;
2301 // [HGM] before anything else, expand any indirection files amongst options
2302 char *argvCopy[1000]; // 1000 seems enough
2303 char newArgs[10000]; // holds actual characters
2306 srandom(time(0)); // [HGM] book: make random truly random
2309 for(i=0; i<argc; i++) {
2310 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2311 //fprintf(stderr, "arg %s\n", argv[i]);
2312 if(argv[i][0] != '@') argvCopy[j++] = argv[i]; else {
2314 FILE *f = fopen(argv[i]+1, "rb");
2315 if(f == NULL) { fprintf(stderr, _("ignore %s\n"), argv[i]); continue; } // do not expand non-existing
2316 argvCopy[j++] = newArgs + k; // get ready for first argument from file
2317 while((c = fgetc(f)) != EOF) { // each line of file inserts 1 argument in the list
2319 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2320 newArgs[k++] = 0; // terminate current arg
2321 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2322 argvCopy[j++] = newArgs + k; // get ready for next
2324 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2337 if(appData.debugMode,1) { // OK, appData is not initialized here yet...
2338 for(i=0; i<argc; i++) fprintf(stderr, "argv[%2d] = '%s'\n", i, argv[i]);
2344 setbuf(stdout, NULL);
2345 setbuf(stderr, NULL);
2348 programName = strrchr(argv[0], '/');
2349 if (programName == NULL)
2350 programName = argv[0];
2355 XtSetLanguageProc(NULL, NULL, NULL);
2356 bindtextdomain(PACKAGE, LOCALEDIR);
2357 textdomain(PACKAGE);
2361 XtAppInitialize(&appContext, "XBoard", shellOptions,
2362 XtNumber(shellOptions),
2363 &argc, argv, xboardResources, NULL, 0);
2365 gtk_init (&argc, &argv);
2367 /* parse glade file */
2369 builder = gtk_builder_new ();
2370 gtk_builder_add_from_file (builder, "gtk-interface.xml", NULL);
2372 GUI_Window = GTK_WIDGET (gtk_builder_get_object (builder, "MainWindow"));
2373 if(!GUI_Window) printf("Error: gtk_builder didn't work!\n");
2374 GUI_Board = GTK_WIDGET (gtk_builder_get_object (builder, "Board"));
2375 if(!GUI_Board) printf("Error: gtk_builder didn't work!\n");
2376 GUI_Whiteclock = GTK_WIDGET (gtk_builder_get_object (builder, "WhiteClock"));
2377 if(!GUI_Whiteclock) printf("Error: gtk_builder didn't work!\n");
2378 GUI_Blackclock = GTK_WIDGET (gtk_builder_get_object (builder, "BlackClock"));
2379 if(!GUI_Blackclock) printf("Error: gtk_builder didn't work!\n");
2381 gtk_builder_connect_signals (builder, NULL);
2382 // don't unref the builder, since we use it to get references to widgets
2383 // g_object_unref (G_OBJECT (builder));
2385 /* end parse glade file */
2389 fprintf(stderr, _("%s: unrecognized argument %s\n"),
2390 programName, argv[1]);
2391 fprintf(stderr, "Recognized options:\n");
2392 for(i = 0; i < XtNumber(shellOptions); i++)
2394 j = fprintf(stderr, " %s%s", shellOptions[i].option,
2395 (shellOptions[i].argKind == XrmoptionSepArg
2397 if (i++ < XtNumber(shellOptions))
2399 fprintf(stderr, "%*c%s%s\n", 40 - j, ' ',
2400 shellOptions[i].option,
2401 (shellOptions[i].argKind == XrmoptionSepArg
2406 fprintf(stderr, "\n");
2412 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL)
2418 if (chdir(chessDir) != 0)
2420 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
2427 if (p == NULL) p = "/tmp";
2428 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
2429 gameCopyFilename = (char*) malloc(i);
2430 gamePasteFilename = (char*) malloc(i);
2431 snprintf(gameCopyFilename,i, "%s/.xboard%05uc.pgn", p, getpid());
2432 snprintf(gamePasteFilename,i, "%s/.xboard%05up.pgn", p, getpid());
2434 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
2435 clientResources, XtNumber(clientResources),
2438 if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) {
2439 /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */
2440 if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL) {
2441 printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile);
2444 setbuf(debugFP, NULL);
2447 /* [HGM,HR] make sure board size is acceptable */
2448 if(appData.NrFiles > BOARD_SIZE ||
2449 appData.NrRanks > BOARD_SIZE )
2450 DisplayFatalError(_("Recompile with BOARD_SIZE > 12, to support this size"), 0, 2);
2453 /* This feature does not work; animation needs a rewrite */
2454 appData.highlightDragging = FALSE;
2458 xDisplay = XtDisplay(shellWidget);
2459 xScreen = DefaultScreen(xDisplay);
2460 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
2462 gameInfo.variant = StringToVariant(appData.variant);
2463 InitPosition(FALSE);
2466 * Determine boardSize
2468 gameInfo.boardWidth = gameInfo.boardHeight = 8; // [HGM] boardsize: make sure we start as 8x8
2471 // [HGM] as long as we have not created the possibility to change size while running, start with requested size
2472 gameInfo.boardWidth = appData.NrFiles > 0 ? appData.NrFiles : 8;
2473 gameInfo.boardHeight = appData.NrRanks > 0 ? appData.NrRanks : 8;
2474 gameInfo.holdingsWidth = appData.holdingsSize > 0 ? 2 : 0;
2479 InitDrawingSizes(-1, 0); // [HGM] initsize: make this into a subroutine
2481 if (isdigit(appData.boardSize[0])) {
2482 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
2483 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
2484 &fontPxlSize, &smallLayout, &tinyLayout);
2486 fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
2487 programName, appData.boardSize);
2491 /* Find some defaults; use the nearest known size */
2492 SizeDefaults *szd, *nearest;
2493 int distance = 99999;
2494 nearest = szd = sizeDefaults;
2495 while (szd->name != NULL) {
2496 if (abs(szd->squareSize - squareSize) < distance) {
2498 distance = abs(szd->squareSize - squareSize);
2499 if (distance == 0) break;
2503 if (i < 2) lineGap = nearest->lineGap;
2504 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
2505 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
2506 if (i < 5) fontPxlSize = nearest->fontPxlSize;
2507 if (i < 6) smallLayout = nearest->smallLayout;
2508 if (i < 7) tinyLayout = nearest->tinyLayout;
2511 SizeDefaults *szd = sizeDefaults;
2512 if (*appData.boardSize == NULLCHAR) {
2513 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize ||
2514 DisplayHeight(xDisplay, xScreen) < szd->minScreenSize) {
2517 if (szd->name == NULL) szd--;
2519 while (szd->name != NULL &&
2520 StrCaseCmp(szd->name, appData.boardSize) != 0) szd++;
2521 if (szd->name == NULL) {
2522 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
2523 programName, appData.boardSize);
2527 squareSize = szd->squareSize;
2528 lineGap = szd->lineGap;
2529 clockFontPxlSize = szd->clockFontPxlSize;
2530 coordFontPxlSize = szd->coordFontPxlSize;
2531 fontPxlSize = szd->fontPxlSize;
2532 smallLayout = szd->smallLayout;
2533 tinyLayout = szd->tinyLayout;
2536 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2537 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2538 if (appData.showJail == 1) {
2539 /* Jail on top and bottom */
2540 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2541 XtSetArg(boardArgs[2], XtNheight,
2542 boardHeight + 2*(lineGap + squareSize));
2543 } else if (appData.showJail == 2) {
2545 XtSetArg(boardArgs[1], XtNwidth,
2546 boardWidth + 2*(lineGap + squareSize));
2547 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2550 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2551 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2555 * Determine what fonts to use.
2557 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
2558 clockFontID = XLoadFont(xDisplay, appData.clockFont);
2559 clockFontStruct = XQueryFont(xDisplay, clockFontID);
2560 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
2561 coordFontID = XLoadFont(xDisplay, appData.coordFont);
2562 coordFontStruct = XQueryFont(xDisplay, coordFontID);
2563 appData.font = FindFont(appData.font, fontPxlSize);
2564 countFontID = XLoadFont(xDisplay, appData.coordFont); // [HGM] holdings
2565 countFontStruct = XQueryFont(xDisplay, countFontID);
2566 // appData.font = FindFont(appData.font, fontPxlSize);
2568 xdb = XtDatabase(xDisplay);
2569 XrmPutStringResource(&xdb, "*font", appData.font);
2572 * Detect if there are not enough colors available and adapt.
2574 if (DefaultDepth(xDisplay, xScreen) <= 2) {
2575 appData.monoMode = True;
2578 if (!appData.monoMode) {
2579 vFrom.addr = (caddr_t) appData.lightSquareColor;
2580 vFrom.size = strlen(appData.lightSquareColor);
2581 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2582 if (vTo.addr == NULL) {
2583 appData.monoMode = True;
2586 lightSquareColor = *(Pixel *) vTo.addr;
2589 if (!appData.monoMode) {
2590 vFrom.addr = (caddr_t) appData.darkSquareColor;
2591 vFrom.size = strlen(appData.darkSquareColor);
2592 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2593 if (vTo.addr == NULL) {
2594 appData.monoMode = True;
2597 darkSquareColor = *(Pixel *) vTo.addr;
2600 if (!appData.monoMode) {
2601 vFrom.addr = (caddr_t) appData.whitePieceColor;
2602 vFrom.size = strlen(appData.whitePieceColor);
2603 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2604 if (vTo.addr == NULL) {
2605 appData.monoMode = True;
2608 whitePieceColor = *(Pixel *) vTo.addr;
2611 if (!appData.monoMode) {
2612 vFrom.addr = (caddr_t) appData.blackPieceColor;
2613 vFrom.size = strlen(appData.blackPieceColor);
2614 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2615 if (vTo.addr == NULL) {
2616 appData.monoMode = True;
2619 blackPieceColor = *(Pixel *) vTo.addr;
2623 if (!appData.monoMode) {
2624 vFrom.addr = (caddr_t) appData.highlightSquareColor;
2625 vFrom.size = strlen(appData.highlightSquareColor);
2626 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2627 if (vTo.addr == NULL) {
2628 appData.monoMode = True;
2631 highlightSquareColor = *(Pixel *) vTo.addr;
2635 if (!appData.monoMode) {
2636 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
2637 vFrom.size = strlen(appData.premoveHighlightColor);
2638 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2639 if (vTo.addr == NULL) {
2640 appData.monoMode = True;
2643 premoveHighlightColor = *(Pixel *) vTo.addr;
2648 fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2651 if (appData.bitmapDirectory == NULL ||
2652 appData.bitmapDirectory[0] == NULLCHAR)
2653 appData.bitmapDirectory = DEF_BITMAP_DIR;
2656 if (appData.lowTimeWarning && !appData.monoMode) {
2657 vFrom.addr = (caddr_t) appData.lowTimeWarningColor;
2658 vFrom.size = strlen(appData.lowTimeWarningColor);
2659 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2660 if (vTo.addr == NULL)
2661 appData.monoMode = True;
2663 lowTimeWarningColor = *(Pixel *) vTo.addr;
2666 if (appData.monoMode && appData.debugMode) {
2667 fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2668 (unsigned long) XWhitePixel(xDisplay, xScreen),
2669 (unsigned long) XBlackPixel(xDisplay, xScreen));
2672 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
2673 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
2674 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
2675 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
2676 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
2677 parse_cpair(ColorTell, appData.colorTell) < 0 ||
2678 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
2679 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
2680 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
2681 parse_cpair(ColorNormal, appData.colorNormal) < 0)
2683 if (appData.colorize) {
2685 _("%s: can't parse color names; disabling colorization\n"),
2688 appData.colorize = FALSE;
2690 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2691 textColors[ColorNone].attr = 0;
2693 // XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2699 layoutName = "tinyLayout";
2700 } else if (smallLayout) {
2701 layoutName = "smallLayout";
2703 layoutName = "normalLayout";
2705 /* Outer layoutWidget is there only to provide a name for use in
2706 resources that depend on the layout style */
2708 XtCreateManagedWidget(layoutName, formWidgetClass, shellWidget,
2709 layoutArgs, XtNumber(layoutArgs));
2711 XtCreateManagedWidget("form", formWidgetClass, layoutWidget,
2712 formArgs, XtNumber(formArgs));
2713 XtSetArg(args[0], XtNdefaultDistance, &sep);
2714 XtGetValues(formWidget, args, 1);
2717 widgetList[j++] = menuBarWidget = CreateMenuBar(menuBar);
2718 XtSetArg(args[0], XtNtop, XtChainTop);
2719 XtSetArg(args[1], XtNbottom, XtChainTop);
2720 XtSetValues(menuBarWidget, args, 2);
2722 widgetList[j++] = whiteTimerWidget =
2723 XtCreateWidget("whiteTime", labelWidgetClass,
2724 formWidget, timerArgs, XtNumber(timerArgs));
2725 XtSetArg(args[0], XtNfont, clockFontStruct);
2726 XtSetArg(args[1], XtNtop, XtChainTop);
2727 XtSetArg(args[2], XtNbottom, XtChainTop);
2728 XtSetValues(whiteTimerWidget, args, 3);
2730 widgetList[j++] = blackTimerWidget =
2731 XtCreateWidget("blackTime", labelWidgetClass,
2732 formWidget, timerArgs, XtNumber(timerArgs));
2733 XtSetArg(args[0], XtNfont, clockFontStruct);
2734 XtSetArg(args[1], XtNtop, XtChainTop);
2735 XtSetArg(args[2], XtNbottom, XtChainTop);
2736 XtSetValues(blackTimerWidget, args, 3);
2738 if (appData.titleInWindow) {
2739 widgetList[j++] = titleWidget =
2740 XtCreateWidget("title", labelWidgetClass, formWidget,
2741 titleArgs, XtNumber(titleArgs));
2742 XtSetArg(args[0], XtNtop, XtChainTop);
2743 XtSetArg(args[1], XtNbottom, XtChainTop);
2744 XtSetValues(titleWidget, args, 2);
2747 if (appData.showButtonBar) {
2748 widgetList[j++] = buttonBarWidget = CreateButtonBar(buttonBar);
2749 XtSetArg(args[0], XtNleft, XtChainRight); // [HGM] glue to right window edge
2750 XtSetArg(args[1], XtNright, XtChainRight); // for good run-time sizing
2751 XtSetArg(args[2], XtNtop, XtChainTop);
2752 XtSetArg(args[3], XtNbottom, XtChainTop);
2753 XtSetValues(buttonBarWidget, args, 4);
2756 // widgetList[j++] = messageWidget =
2757 // XtCreateWidget("message", labelWidgetClass, formWidget,
2758 // messageArgs, XtNumber(messageArgs));
2759 // XtSetArg(args[0], XtNtop, XtChainTop);
2760 // XtSetArg(args[1], XtNbottom, XtChainTop);
2761 // XtSetValues(messageWidget, args, 2);
2763 // widgetList[j++] = boardWidget =
2764 // XtCreateWidget("board", widgetClass, formWidget, boardArgs,
2765 // XtNumber(boardArgs));
2767 // XtManageChildren(widgetList, j);
2769 // timerWidth = (boardWidth - sep) / 2;
2770 // XtSetArg(args[0], XtNwidth, timerWidth);
2771 // XtSetValues(whiteTimerWidget, args, 1);
2772 // XtSetValues(blackTimerWidget, args, 1);
2774 // XtSetArg(args[0], XtNbackground, &timerBackgroundPixel);
2775 // XtSetArg(args[1], XtNforeground, &timerForegroundPixel);
2776 // XtGetValues(whiteTimerWidget, args, 2);
2778 // if (appData.showButtonBar) {
2779 // XtSetArg(args[0], XtNbackground, &buttonBackgroundPixel);
2780 // XtSetArg(args[1], XtNforeground, &buttonForegroundPixel);
2781 // XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
2786 * gtk set properties of widgets
2789 /* set board size */
2790 gtk_widget_set_size_request(GTK_WIDGET(GUI_Board),
2791 boardWidth,boardHeight);
2793 /* end gtk set properties of widgets */
2796 * formWidget uses these constraints but they are stored
2800 // XtSetArg(args[i], XtNfromHoriz, 0); i++;
2801 // XtSetValues(menuBarWidget, args, i);
2802 // if (appData.titleInWindow) {
2803 // if (smallLayout) {
2805 // XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2806 // XtSetValues(whiteTimerWidget, args, i);
2808 // XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2809 // XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2810 // XtSetValues(blackTimerWidget, args, i);
2812 // XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2813 // XtSetArg(args[i], XtNjustify, XtJustifyLeft); i++;
2814 // XtSetValues(titleWidget, args, i);
2816 // XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2817 // XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2818 // XtSetValues(messageWidget, args, i);
2819 // if (appData.showButtonBar) {
2821 // XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2822 // XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2823 // XtSetValues(buttonBarWidget, args, i);
2827 // XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2828 // XtSetValues(whiteTimerWidget, args, i);
2830 // XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2831 // XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2832 // XtSetValues(blackTimerWidget, args, i);
2834 // XtSetArg(args[i], XtNfromHoriz, menuBarWidget); i++;
2835 // XtSetValues(titleWidget, args, i);
2837 // XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2838 // XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2839 // XtSetValues(messageWidget, args, i);
2840 // if (appData.showButtonBar) {
2842 // XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2843 // XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2844 // XtSetValues(buttonBarWidget, args, i);
2850 // XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2851 // XtSetValues(whiteTimerWidget, args, i);
2853 // XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2854 // XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2855 // XtSetValues(blackTimerWidget, args, i);
2857 // XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2858 // XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2859 // XtSetValues(messageWidget, args, i);
2860 // if (appData.showButtonBar) {
2862 // XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2863 // XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2864 // XtSetValues(buttonBarWidget, args, i);
2868 // XtSetArg(args[0], XtNfromVert, messageWidget);
2869 // XtSetArg(args[1], XtNtop, XtChainTop);
2870 // XtSetArg(args[2], XtNbottom, XtChainBottom);
2871 // XtSetArg(args[3], XtNleft, XtChainLeft);
2872 // XtSetArg(args[4], XtNright, XtChainRight);
2873 // XtSetValues(boardWidget, args, 5);
2875 // XtRealizeWidget(shellWidget);
2879 * Correct the width of the message and title widgets.
2880 * It is not known why some systems need the extra fudge term.
2881 * The value "2" is probably larger than needed.
2883 // XawFormDoLayout(formWidget, False);
2885 #define WIDTH_FUDGE 2
2887 // XtSetArg(args[i], XtNborderWidth, &bor); i++;
2888 // XtSetArg(args[i], XtNheight, &h); i++;
2889 // XtGetValues(messageWidget, args, i);
2890 if (appData.showButtonBar) {
2892 // XtSetArg(args[i], XtNwidth, &w); i++;
2893 // XtGetValues(buttonBarWidget, args, i);
2894 // w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2896 // w = boardWidth - 2*bor + 1; /*!! +1 compensates for kludge below */
2899 // gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2900 if (gres != XtGeometryYes && appData.debugMode) {
2901 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2902 programName, gres, w, h, wr, hr);
2905 /* !! Horrible hack to work around bug in XFree86 4.0.1 (X11R6.4.3) */
2906 /* The size used for the child widget in layout lags one resize behind
2907 its true size, so we resize a second time, 1 pixel smaller. Yeech! */
2909 // gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2910 if (gres != XtGeometryYes && appData.debugMode) {
2911 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2912 programName, gres, w, h, wr, hr);
2915 // XtSetArg(args[0], XtNleft, XtChainLeft); // [HGM] glue ends for good run-time sizing
2916 // XtSetArg(args[1], XtNright, XtChainRight);
2917 // XtSetValues(messageWidget, args, 2);
2919 if (appData.titleInWindow) {
2921 // XtSetArg(args[i], XtNborderWidth, &bor); i++;
2922 // XtSetArg(args[i], XtNheight, &h); i++;
2923 // XtGetValues(titleWidget, args, i);
2925 w = boardWidth - 2*bor;
2927 // XtSetArg(args[0], XtNwidth, &w);
2928 // XtGetValues(menuBarWidget, args, 1);
2929 // w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2932 // gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2933 if (gres != XtGeometryYes && appData.debugMode) {
2935 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2936 programName, gres, w, h, wr, hr);
2939 // XawFormDoLayout(formWidget, True);
2941 // xBoardWindow = XtWindow(boardWidget);
2943 // [HGM] it seems the layout code ends here, but perhaps the color stuff is size independent and would
2944 // not need to go into InitDrawingSizes().
2947 if (appData.alwaysPromoteToQueen) {
2948 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Always Queen")),TRUE);
2950 if (appData.animateDragging) {
2951 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Animate Dragging")),TRUE);
2953 if (appData.animate) {
2954 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Animate Moving")),TRUE);
2956 if (appData.autoComment) {
2957 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Comment")),TRUE);
2959 if (appData.autoCallFlag) {
2960 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Flag")),TRUE);
2962 if (appData.autoFlipView) {
2963 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Flip View")),TRUE);
2965 if (appData.autoObserve) {
2966 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Observe")),TRUE);
2968 if (appData.autoRaiseBoard) {
2969 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Raise Board")),TRUE);
2971 if (appData.autoSaveGames) {
2972 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Save")),TRUE);
2974 if (appData.saveGameFile[0] != NULLCHAR) {
2975 /* Can't turn this off from menu */
2976 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Save")),TRUE);
2977 gtk_action_set_sensitive(GTK_ACTION (gtk_builder_get_object (builder, "menuOptions.Auto Save")),FALSE);
2979 if (appData.blindfold) {
2980 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Blindfold")),TRUE);
2982 if (appData.flashCount > 0) {
2983 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Flash Moves")),TRUE);
2985 if (appData.getMoveList) {
2986 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Get Move List")),TRUE);
2989 if (appData.highlightDragging) {
2990 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Highlight Dragging")),TRUE);
2993 if (appData.highlightLastMove) {
2994 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Highlight Last Move")),TRUE);
2996 if (appData.icsAlarm) {
2997 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.ICS Alarm")),TRUE);
2999 if (appData.ringBellAfterMoves) {
3000 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Move Sound")),TRUE);
3002 if (appData.oldSaveStyle) {
3003 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Old Save Style")),TRUE);
3005 if (appData.periodicUpdates) {
3006 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Periodic Updates")),TRUE);
3008 if (appData.ponderNextMove) {
3009 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Ponder Next Move")),TRUE);
3011 if (appData.popupExitMessage) {
3012 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Popup Exit Message")),TRUE);
3014 if (appData.popupMoveErrors) {
3015 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Popup Move Errors")),TRUE);
3017 if (appData.premove) {
3018 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Premove")),TRUE);
3020 if (appData.quietPlay) {
3021 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Quit Play")),TRUE);
3023 if (appData.showCoords) {
3024 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Show Coords")),TRUE);
3026 if (appData.showThinking) {
3027 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Show Thinking")),TRUE);
3029 if (appData.testLegality) {
3030 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Test Legality")),TRUE);
3036 // ReadBitmap(&wIconPixmap, "icon_white.bm",
3037 // icon_white_bits, icon_white_width, icon_white_height);
3038 // ReadBitmap(&bIconPixmap, "icon_black.bm",
3039 // icon_black_bits, icon_black_width, icon_black_height);
3040 // iconPixmap = wIconPixmap;
3042 // XtSetArg(args[i], XtNiconPixmap, iconPixmap); i++;
3043 // XtSetValues(shellWidget, args, i);
3046 /* load square colors */
3047 SVGLightSquare = load_pixbuf("svg/LightSquare.svg",squareSize);
3048 SVGDarkSquare = load_pixbuf("svg/DarkSquare.svg",squareSize);
3049 SVGNeutralSquare = load_pixbuf("svg/NeutralSquare.svg",squareSize);
3051 /* use two icons to indicate if it is white's or black's turn */
3052 WhiteIcon = load_pixbuf("svg/icon_white.svg",0);
3053 BlackIcon = load_pixbuf("svg/icon_black.svg",0);
3054 WindowIcon = WhiteIcon;
3055 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
3057 /* do resizing to a fixed aspect ratio */
3058 GUI_SetAspectRatio(0.8);
3060 /* realize window */
3061 gtk_widget_show (GUI_Window);
3068 if (appData.animate || appData.animateDragging)
3071 // XtAugmentTranslations(formWidget,
3072 // XtParseTranslationTable(globalTranslations));
3073 // XtAugmentTranslations(boardWidget,
3074 // XtParseTranslationTable(boardTranslations));
3075 // XtAugmentTranslations(whiteTimerWidget,
3076 // XtParseTranslationTable(whiteTranslations));
3077 // XtAugmentTranslations(blackTimerWidget,
3078 // XtParseTranslationTable(blackTranslations));
3082 if (errorExitStatus == -1) {
3083 if (appData.icsActive) {
3084 /* We now wait until we see "login:" from the ICS before
3085 sending the logon script (problems with timestamp otherwise) */
3086 /*ICSInitScript();*/
3087 if (appData.icsInputBox) ICSInputBoxPopUp();
3090 signal(SIGINT, IntSigHandler);
3091 signal(SIGTERM, IntSigHandler);
3092 if (*appData.cmailGameName != NULLCHAR) {
3093 signal(SIGUSR1, CmailSigHandler);
3096 gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes()
3100 * Create a cursor for the board widget.
3101 * (This needs to be called after the window has been created to have access to board-window)
3104 BoardCursor = gdk_cursor_new(GDK_HAND2);
3105 gdk_window_set_cursor(GUI_Board->window, BoardCursor);
3106 gdk_cursor_destroy(BoardCursor);
3111 if (appData.debugMode) fclose(debugFP); // [DM] debug
3118 if (appData.icsActive && oldICSInteractionTitle != NULL) {
3119 DisplayIcsInteractionTitle(oldICSInteractionTitle);
3121 unlink(gameCopyFilename);
3122 unlink(gamePasteFilename);
3133 CmailSigHandler(sig)
3139 signal(SIGUSR1, SIG_IGN); /* suspend handler */
3141 /* Activate call-back function CmailSigHandlerCallBack() */
3142 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
3144 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
3148 CmailSigHandlerCallBack(isr, closure, message, count, error)
3156 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
3158 /**** end signal code ****/
3168 f = fopen(appData.icsLogon, "r");
3174 strcat(buf, appData.icsLogon);
3175 f = fopen(buf, "r");
3179 ProcessICSInitScript(f);
3186 EditCommentPopDown();
3197 SetMenuEnables(enab)
3202 if (!builder) return;
3203 while (enab->name != NULL) {
3204 o = gtk_builder_get_object(builder, enab->name);
3205 if(GTK_IS_WIDGET(o))
3206 gtk_widget_set_sensitive(GTK_WIDGET (o),enab->value);
3209 if(GTK_IS_ACTION(o))
3210 gtk_action_set_sensitive(GTK_ACTION (o),enab->value);
3212 DisplayError(enab->name, 0);
3218 Enables icsEnables[] = {
3219 { "menuFile.Mail Move", False },
3220 { "menuFile.Reload CMail Message", False },
3221 { "menuMode.Machine Black", False },
3222 { "menuMode.Machine White", False },
3223 { "menuMode.Analysis Mode", False },
3224 { "menuMode.Analyze File", False },
3225 { "menuMode.Two Machines", False },
3227 { "menuHelp.Hint", False },
3228 { "menuHelp.Book", False },
3229 { "menuStep.Move Now", False },
3230 { "menuOptions.Periodic Updates", False },
3231 { "menuOptions.Hide Thinking", False },
3232 { "menuOptions.Ponder Next Move", False },
3237 Enables ncpEnables[] = {
3238 { "menuFile.Mail Move", False },
3239 { "menuFile.Reload CMail Message", False },
3240 { "menuMode.Machine White", False },
3241 { "menuMode.Machine Black", False },
3242 { "menuMode.Analysis Mode", False },
3243 { "menuMode.Analyze File", False },
3244 { "menuMode.Two Machines", False },
3245 { "menuMode.ICS Client", False },
3246 { "menuMode.ICS Input Box", False },
3247 { "Action", False },
3248 { "menuStep.Revert", False },
3249 { "menuStep.Move Now", False },
3250 { "menuStep.Retract Move", False },
3251 { "menuOptions.Auto Comment", False },
3252 { "menuOptions.Auto Flag", False },
3253 { "menuOptions.Auto Flip View", False },
3254 { "menuOptions.Auto Observe", False },
3255 { "menuOptions.Auto Raise Board", False },
3256 { "menuOptions.Get Move List", False },
3257 { "menuOptions.ICS Alarm", False },
3258 { "menuOptions.Move Sound", False },
3259 { "menuOptions.Quiet Play", False },
3260 { "menuOptions.Hide Thinking", False },
3261 { "menuOptions.Periodic Updates", False },
3262 { "menuOptions.Ponder Next Move", False },
3263 { "menuHelp.Hint", False },
3264 { "menuHelp.Book", False },
3268 Enables gnuEnables[] = {
3269 { "menuMode.ICS Client", False },
3270 { "menuMode.ICS Input Box", False },
3271 { "menuAction.Accept", False },
3272 { "menuAction.Decline", False },
3273 { "menuAction.Rematch", False },
3274 { "menuAction.Adjourn", False },
3275 { "menuAction.Stop Examining", False },
3276 { "menuAction.Stop Observing", False },
3277 { "menuStep.Revert", False },
3278 { "menuOptions.Auto Comment", False },
3279 { "menuOptions.Auto Observe", False },
3280 { "menuOptions.Auto Raise Board", False },
3281 { "menuOptions.Get Move List", False },
3282 { "menuOptions.Premove", False },
3283 { "menuOptions.Quiet Play", False },
3285 /* The next two options rely on SetCmailMode being called *after* */
3286 /* SetGNUMode so that when GNU is being used to give hints these */
3287 /* menu options are still available */
3289 { "menuFile.Mail Move", False },
3290 { "menuFile.Reload CMail Message", False },
3294 Enables cmailEnables[] = {
3296 { "menuAction.Call Flag", False },
3297 { "menuAction.Draw", True },
3298 { "menuAction.Adjourn", False },
3299 { "menuAction.Abort", False },
3300 { "menuAction.Stop Observing", False },
3301 { "menuAction.Stop Examining", False },
3302 { "menuFile.Mail Move", True },
3303 { "menuFile.Reload CMail Message", True },
3307 Enables trainingOnEnables[] = {
3308 { "menuMode.Edit Comment", False },
3309 { "menuMode.Pause", False },
3310 { "menuStep.Forward", False },
3311 { "menuStep.Backward", False },
3312 { "menuStep.Forward to End", False },
3313 { "menuStep.Back to Start", False },
3314 { "menuStep.Move Now", False },
3315 { "menuStep.Truncate Game", False },
3319 Enables trainingOffEnables[] = {
3320 { "menuMode.Edit Comment", True },
3321 { "menuMode.Pause", True },
3322 { "menuStep.Forward", True },
3323 { "menuStep.Backward", True },
3324 { "menuStep.Forward to End", True },
3325 { "menuStep.Back to Start", True },
3326 { "menuStep.Move Now", True },
3327 { "menuStep.Truncate Game", True },
3331 Enables machineThinkingEnables[] = {
3332 { "menuFile.Load Game", False },
3333 { "menuFile.Load Next Game", False },
3334 { "menuFile.Load Previous Game", False },
3335 { "menuFile.Reload Same Game", False },
3336 { "menuFile.Paste Game", False },
3337 { "menuFile.Load Position", False },
3338 { "menuFile.Load Next Position", False },
3339 { "menuFile.Load Previous Position", False },
3340 { "menuFile.Reload Same Position", False },
3341 { "menuFile.Paste Position", False },
3342 { "menuMode.Machine White", False },
3343 { "menuMode.Machine Black", False },
3344 { "menuMode.Two Machines", False },
3345 { "menuStep.Retract Move", False },
3349 Enables userThinkingEnables[] = {
3350 { "menuFile.Load Game", True },
3351 { "menuFile.Load Next Game", True },
3352 { "menuFile.Load Previous Game", True },
3353 { "menuFile.Reload Same Game", True },
3354 { "menuFile.Paste Game", True },
3355 { "menuFile.Load Position", True },
3356 { "menuFile.Load Next Position", True },
3357 { "menuFile.Load Previous Position", True },
3358 { "menuFile.Reload Same Position", True },
3359 { "menuFile.Paste Position", True },
3360 { "menuMode.Machine White", True },
3361 { "menuMode.Machine Black", True },
3362 { "menuMode.Two Machines", True },
3363 { "menuStep.Retract Move", True },
3369 SetMenuEnables(icsEnables);
3372 if (appData.zippyPlay && !appData.noChessProgram) /* [DM] icsEngineAnalyze */
3373 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
3380 SetMenuEnables(ncpEnables);
3386 SetMenuEnables(gnuEnables);
3392 SetMenuEnables(cmailEnables);
3398 SetMenuEnables(trainingOnEnables);
3399 if (appData.showButtonBar) {
3400 XtSetSensitive(buttonBarWidget, False);
3406 SetTrainingModeOff()
3408 SetMenuEnables(trainingOffEnables);
3409 if (appData.showButtonBar) {
3410 XtSetSensitive(buttonBarWidget, True);
3415 SetUserThinkingEnables()
3417 if (appData.noChessProgram) return;
3418 SetMenuEnables(userThinkingEnables);
3422 SetMachineThinkingEnables()
3424 if (appData.noChessProgram) return;
3425 SetMenuEnables(machineThinkingEnables);
3427 case MachinePlaysBlack:
3428 case MachinePlaysWhite:
3429 case TwoMachinesPlay:
3430 XtSetSensitive(XtNameToWidget(menuBarWidget,
3431 ModeToWidgetName(gameMode)), True);
3438 #define Abs(n) ((n)<0 ? -(n) : (n))
3441 * Find a font that matches "pattern" that is as close as
3442 * possible to the targetPxlSize. Prefer fonts that are k
3443 * pixels smaller to fonts that are k pixels larger. The
3444 * pattern must be in the X Consortium standard format,
3445 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
3446 * The return value should be freed with XtFree when no
3449 char *FindFont(pattern, targetPxlSize)
3453 char **fonts, *p, *best, *scalable, *scalableTail;
3454 int i, j, nfonts, minerr, err, pxlSize;
3457 char **missing_list;
3459 char *def_string, *base_fnt_lst, strInt[3];
3461 XFontStruct **fnt_list;
3463 base_fnt_lst = calloc(1, strlen(pattern) + 3);
3464 sprintf(strInt, "%d", targetPxlSize);
3465 p = strstr(pattern, "--");
3466 strncpy(base_fnt_lst, pattern, p - pattern + 2);
3467 strcat(base_fnt_lst, strInt);
3468 strcat(base_fnt_lst, strchr(p + 2, '-'));
3470 if ((fntSet = XCreateFontSet(xDisplay,
3474 &def_string)) == NULL) {
3476 fprintf(stderr, _("Unable to create font set.\n"));
3480 nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
3482 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
3484 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
3485 programName, pattern);
3493 for (i=0; i<nfonts; i++) {
3496 if (*p != '-') continue;
3498 if (*p == NULLCHAR) break;
3499 if (*p++ == '-') j++;
3501 if (j < 7) continue;
3504 scalable = fonts[i];
3507 err = pxlSize - targetPxlSize;
3508 if (Abs(err) < Abs(minerr) ||
3509 (minerr > 0 && err < 0 && -err == minerr)) {
3515 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
3516 /* If the error is too big and there is a scalable font,
3517 use the scalable font. */
3518 int headlen = scalableTail - scalable;
3519 p = (char *) XtMalloc(strlen(scalable) + 10);
3520 while (isdigit(*scalableTail)) scalableTail++;
3521 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
3523 p = (char *) XtMalloc(strlen(best) + 1);
3526 if (appData.debugMode) {
3527 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
3528 pattern, targetPxlSize, p);
3531 if (missing_count > 0)
3532 XFreeStringList(missing_list);
3533 XFreeFontSet(xDisplay, fntSet);
3535 XFreeFontNames(fonts);
3542 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
3543 | GCBackground | GCFunction | GCPlaneMask;
3544 XGCValues gc_values;
3547 gc_values.plane_mask = AllPlanes;
3548 gc_values.line_width = lineGap;
3549 gc_values.line_style = LineSolid;
3550 gc_values.function = GXcopy;
3552 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3553 gc_values.background = XWhitePixel(xDisplay, xScreen);
3554 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
3555 XSetFont(xDisplay, coordGC, coordFontID);
3557 // [HGM] make font for holdings counts (white on black0
3558 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3559 gc_values.background = XBlackPixel(xDisplay, xScreen);
3560 countGC = XtGetGC(shellWidget, value_mask, &gc_values);
3561 XSetFont(xDisplay, countGC, countFontID);
3563 if (appData.monoMode) {
3564 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3565 gc_values.background = XBlackPixel(xDisplay, xScreen);
3566 lightSquareGC = wbPieceGC
3567 = XtGetGC(shellWidget, value_mask, &gc_values);
3569 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3570 gc_values.background = XWhitePixel(xDisplay, xScreen);
3571 darkSquareGC = bwPieceGC
3572 = XtGetGC(shellWidget, value_mask, &gc_values);
3574 if (DefaultDepth(xDisplay, xScreen) == 1) {
3575 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3576 gc_values.function = GXcopyInverted;
3577 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3578 gc_values.function = GXcopy;
3579 if (XBlackPixel(xDisplay, xScreen) == 1) {
3580 bwPieceGC = darkSquareGC;
3581 wbPieceGC = copyInvertedGC;
3583 bwPieceGC = copyInvertedGC;
3584 wbPieceGC = lightSquareGC;
3588 gc_values.foreground = lightSquareColor;
3589 gc_values.background = darkSquareColor;
3590 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3592 gc_values.foreground = darkSquareColor;
3593 gc_values.background = lightSquareColor;
3594 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3596 gc_values.foreground = jailSquareColor;
3597 gc_values.background = jailSquareColor;
3598 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3600 gc_values.foreground = whitePieceColor;
3601 gc_values.background = darkSquareColor;
3602 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3604 gc_values.foreground = whitePieceColor;
3605 gc_values.background = lightSquareColor;
3606 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3608 gc_values.foreground = whitePieceColor;
3609 gc_values.background = jailSquareColor;
3610 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3612 gc_values.foreground = blackPieceColor;
3613 gc_values.background = darkSquareColor;
3614 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3616 gc_values.foreground = blackPieceColor;
3617 gc_values.background = lightSquareColor;
3618 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3620 gc_values.foreground = blackPieceColor;
3621 gc_values.background = jailSquareColor;
3622 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3629 WhitePawn, WhiteKnight, WhiteBishop, WhiteRook, WhiteQueen, WhiteKing,
3630 BlackPawn, BlackKnight, BlackBishop, BlackRook, BlackQueen, BlackKing,
3633 SVGpieces[WhitePawn] = load_pixbuf("svg/WhitePawn.svg",squareSize);
3634 SVGpieces[WhiteKnight] = load_pixbuf("svg/WhiteKnight.svg",squareSize);
3635 SVGpieces[WhiteBishop] = load_pixbuf("svg/WhiteBishop.svg",squareSize);
3636 SVGpieces[WhiteRook] = load_pixbuf("svg/WhiteRook.svg",squareSize);
3637 SVGpieces[WhiteQueen] = load_pixbuf("svg/WhiteQueen.svg",squareSize);
3638 SVGpieces[WhiteKing] = load_pixbuf("svg/WhiteKing.svg",squareSize);
3640 SVGpieces[BlackPawn] = load_pixbuf("svg/BlackPawn.svg",squareSize);
3641 SVGpieces[BlackKnight] = load_pixbuf("svg/BlackKnight.svg",squareSize);
3642 SVGpieces[BlackBishop] = load_pixbuf("svg/BlackBishop.svg",squareSize);
3643 SVGpieces[BlackRook] = load_pixbuf("svg/BlackRook.svg",squareSize);
3644 SVGpieces[BlackQueen] = load_pixbuf("svg/BlackQueen.svg",squareSize);
3645 SVGpieces[BlackKing] = load_pixbuf("svg/BlackKing.svg",squareSize);
3651 static void MenuBarSelect(w, addr, index)
3656 XtActionProc proc = (XtActionProc) addr;
3658 (proc)(NULL, NULL, NULL, NULL);
3661 void CreateMenuBarPopup(parent, name, mb)
3671 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3674 XtSetArg(args[j], XtNleftMargin, 20); j++;
3675 XtSetArg(args[j], XtNrightMargin, 20); j++;
3677 while (mi->string != NULL) {
3678 if (strcmp(mi->string, "----") == 0) {
3679 entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
3682 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string)));
3683 entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass,
3685 XtAddCallback(entry, XtNcallback,
3686 (XtCallbackProc) MenuBarSelect,
3687 (caddr_t) mi->proc);
3693 Widget CreateMenuBar(mb)
3697 Widget anchor, menuBar;
3699 char menuName[MSG_SIZ];
3702 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3703 XtSetArg(args[j], XtNvSpace, 0); j++;
3704 XtSetArg(args[j], XtNborderWidth, 0); j++;
3705 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
3706 formWidget, args, j);
3708 while (mb->name != NULL) {
3709 strcpy(menuName, "menu");
3710 strcat(menuName, mb->name);
3712 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
3715 shortName[0] = _(mb->name)[0];
3716 shortName[1] = NULLCHAR;
3717 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
3720 XtSetArg(args[j], XtNlabel, XtNewString(_(mb->name))); j++;
3723 XtSetArg(args[j], XtNborderWidth, 0); j++;
3724 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
3726 CreateMenuBarPopup(menuBar, menuName, mb);
3732 Widget CreateButtonBar(mi)
3736 Widget button, buttonBar;
3740 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3742 XtSetArg(args[j], XtNhSpace, 0); j++;
3744 XtSetArg(args[j], XtNborderWidth, 0); j++;
3745 XtSetArg(args[j], XtNvSpace, 0); j++;
3746 buttonBar = XtCreateWidget("buttonBar", boxWidgetClass,
3747 formWidget, args, j);
3749 while (mi->string != NULL) {
3752 XtSetArg(args[j], XtNinternalWidth, 2); j++;
3753 XtSetArg(args[j], XtNborderWidth, 0); j++;
3755 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string))); j++;
3756 button = XtCreateManagedWidget(mi->string, commandWidgetClass,
3757 buttonBar, args, j);
3758 XtAddCallback(button, XtNcallback,
3759 (XtCallbackProc) MenuBarSelect,
3760 (caddr_t) mi->proc);
3767 CreatePieceMenu(name, color)
3774 ChessSquare selection;
3776 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3777 boardWidget, args, 0);
3779 for (i = 0; i < PIECE_MENU_SIZE; i++) {
3780 String item = pieceMenuStrings[color][i];
3782 if (strcmp(item, "----") == 0) {
3783 entry = XtCreateManagedWidget(item, smeLineObjectClass,
3786 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3787 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3789 selection = pieceMenuTranslation[color][i];
3790 XtAddCallback(entry, XtNcallback,
3791 (XtCallbackProc) PieceMenuSelect,
3792 (caddr_t) selection);
3793 if (selection == WhitePawn || selection == BlackPawn) {
3794 XtSetArg(args[0], XtNpopupOnEntry, entry);
3795 XtSetValues(menu, args, 1);
3808 ChessSquare selection;
3810 // whitePieceMenu = CreatePieceMenu("menuW", 0);
3811 // blackPieceMenu = CreatePieceMenu("menuB", 1);
3813 // XtRegisterGrabAction(PieceMenuPopup, True,
3814 // (unsigned)(ButtonPressMask|ButtonReleaseMask),
3815 // GrabModeAsync, GrabModeAsync);
3817 // XtSetArg(args[0], XtNlabel, _("Drop"));
3818 // dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
3819 // boardWidget, args, 1);
3820 // for (i = 0; i < DROP_MENU_SIZE; i++) {
3821 // String item = dropMenuStrings[i];
3823 // if (strcmp(item, "----") == 0) {
3824 // entry = XtCreateManagedWidget(item, smeLineObjectClass,
3825 // dropMenu, NULL, 0);
3827 // XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3828 // entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3829 // dropMenu, args, 1);
3830 // selection = dropMenuTranslation[i];
3831 // XtAddCallback(entry, XtNcallback,
3832 // (XtCallbackProc) DropMenuSelect,
3833 // (caddr_t) selection);
3838 void SetupDropMenu()
3846 for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
3847 entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
3848 p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
3849 dmEnables[i].piece);
3850 XtSetSensitive(entry, p != NULL || !appData.testLegality
3851 /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
3852 && !appData.icsActive));
3854 while (p && *p++ == dmEnables[i].piece) count++;
3855 snprintf(label, sizeof(label), "%s %d", dmEnables[i].widget, count);
3857 XtSetArg(args[j], XtNlabel, label); j++;
3858 XtSetValues(entry, args, j);
3862 void PieceMenuPopup(w, event, params, num_params)
3866 Cardinal *num_params;
3869 if (event->type != ButtonPress) return;
3870 if (errorUp) ErrorPopDown();
3874 whichMenu = params[0];
3876 case IcsPlayingWhite:
3877 case IcsPlayingBlack:
3879 case MachinePlaysWhite:
3880 case MachinePlaysBlack:
3881 if (appData.testLegality &&
3882 gameInfo.variant != VariantBughouse &&
3883 gameInfo.variant != VariantCrazyhouse) return;
3885 whichMenu = "menuD";
3891 if (((pmFromX = EventToSquare(event->xbutton.x, BOARD_WIDTH)) < 0) ||
3892 ((pmFromY = EventToSquare(event->xbutton.y, BOARD_HEIGHT)) < 0)) {
3893 pmFromX = pmFromY = -1;
3897 pmFromX = BOARD_WIDTH - 1 - pmFromX;
3899 pmFromY = BOARD_HEIGHT - 1 - pmFromY;
3901 XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
3904 static void PieceMenuSelect(w, piece, junk)
3909 if (pmFromX < 0 || pmFromY < 0) return;
3910 EditPositionMenuEvent(piece, pmFromX, pmFromY);
3913 static void DropMenuSelect(w, piece, junk)
3918 if (pmFromX < 0 || pmFromY < 0) return;
3919 DropMenuEvent(piece, pmFromX, pmFromY);
3922 void WhiteClock(w, event, prms, nprms)
3928 if (gameMode == EditPosition || gameMode == IcsExamining) {
3929 SetWhiteToPlayEvent();
3930 } else if (gameMode == IcsPlayingBlack || gameMode == MachinePlaysWhite) {
3935 void BlackClock(w, event, prms, nprms)
3941 if (gameMode == EditPosition || gameMode == IcsExamining) {
3942 SetBlackToPlayEvent();
3943 } else if (gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) {
3950 * If the user selects on a border boundary, return -1; if off the board,
3951 * return -2. Otherwise map the event coordinate to the square.
3953 int EventToSquare(x, limit)
3961 if ((x % (squareSize + lineGap)) >= squareSize)
3963 x /= (squareSize + lineGap);
3969 static void do_flash_delay(msec)
3975 static void drawHighlight(file, rank, line_type)
3976 int file, rank, line_type;
3981 if (lineGap == 0 || appData.blindfold) return;
3985 x = lineGap/2 + ((BOARD_WIDTH-1)-file) *
3986 (squareSize + lineGap);
3987 y = lineGap/2 + rank * (squareSize + lineGap);
3991 x = lineGap/2 + file * (squareSize + lineGap);
3992 y = lineGap/2 + ((BOARD_HEIGHT-1)-rank) *
3993 (squareSize + lineGap);
3997 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3999 /* draw the highlight */
4000 cairo_move_to (cr, x, y);
4001 cairo_rel_line_to (cr, 0,squareSize+lineGap);
4002 cairo_rel_line_to (cr, squareSize+lineGap,0);
4003 cairo_rel_line_to (cr, 0,-squareSize-lineGap);
4004 cairo_close_path (cr);
4006 cairo_set_line_width (cr, lineGap);
4009 /* TODO: use appdata colors */
4010 case LINE_TYPE_HIGHLIGHT:
4011 cairo_set_source_rgba (cr, 1, 1, 0, 1.0);
4014 cairo_set_source_rgba (cr, 1, 0, 0, 1.0);
4016 case LINE_TYPE_NORMAL:
4018 cairo_set_source_rgba (cr, 0, 1, 0, 1.0);
4029 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
4030 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
4033 SetHighlights(fromX, fromY, toX, toY)
4034 int fromX, fromY, toX, toY;
4036 if (hi1X != fromX || hi1Y != fromY)
4038 if (hi1X >= 0 && hi1Y >= 0)
4040 drawHighlight(hi1X, hi1Y, LINE_TYPE_NORMAL);
4042 if (fromX >= 0 && fromY >= 0)
4044 drawHighlight(fromX, fromY, LINE_TYPE_HIGHLIGHT);
4047 if (hi2X != toX || hi2Y != toY)
4049 if (hi2X >= 0 && hi2Y >= 0)
4051 drawHighlight(hi2X, hi2Y, LINE_TYPE_NORMAL);
4053 if (toX >= 0 && toY >= 0)
4055 drawHighlight(toX, toY, LINE_TYPE_HIGHLIGHT);
4069 SetHighlights(-1, -1, -1, -1);
4074 SetPremoveHighlights(fromX, fromY, toX, toY)
4075 int fromX, fromY, toX, toY;
4077 if (pm1X != fromX || pm1Y != fromY)
4079 if (pm1X >= 0 && pm1Y >= 0)
4081 drawHighlight(pm1X, pm1Y, LINE_TYPE_NORMAL);
4083 if (fromX >= 0 && fromY >= 0)
4085 drawHighlight(fromX, fromY, LINE_TYPE_PRE);
4088 if (pm2X != toX || pm2Y != toY)
4090 if (pm2X >= 0 && pm2Y >= 0)
4092 drawHighlight(pm2X, pm2Y, LINE_TYPE_NORMAL);
4094 if (toX >= 0 && toY >= 0)
4096 drawHighlight(toX, toY, LINE_TYPE_PRE);
4109 ClearPremoveHighlights()
4111 SetPremoveHighlights(-1, -1, -1, -1);
4114 static void BlankSquare(x, y, color, piece, dest)
4122 pb = SVGLightSquare;
4127 case 2: /* neutral */
4129 pb = SVGNeutralSquare;
4132 gdk_draw_pixbuf(GDK_WINDOW(GUI_Board->window),NULL,pb,0,0,x,y,-1,-1, GDK_RGB_DITHER_NORMAL, 0, 0);
4135 static void DrawPiece(piece, square_color, x, y, dest)
4137 int square_color, x, y;
4140 gdk_draw_pixbuf(GDK_WINDOW(GUI_Board->window),NULL,
4141 GDK_PIXBUF(SVGpieces[piece]),0,0,x,y,-1,-1,
4142 GDK_RGB_DITHER_NORMAL, 0, 0);
4146 /* [HR] determine square color depending on chess variant. */
4147 static int SquareColor(row, column)
4152 if (gameInfo.variant == VariantXiangqi) {
4153 if (column >= 3 && column <= 5 && row >= 0 && row <= 2) {
4155 } else if (column >= 3 && column <= 5 && row >= 7 && row <= 9) {
4157 } else if (row <= 4) {
4163 square_color = ((column + row) % 2) == 1;
4166 /* [hgm] holdings: next line makes all holdings squares light */
4167 if(column < BOARD_LEFT || column >= BOARD_RGHT) square_color = 1;
4169 return square_color;
4172 void DrawSquare(row, column, piece, do_flash)
4173 int row, column, do_flash;
4176 int square_color, x, y, direction, font_ascent, font_descent;
4179 XCharStruct overall;
4182 /* Calculate delay in milliseconds (2-delays per complete flash) */
4183 flash_delay = 500 / appData.flashRate;
4185 /* calculate x and y coordinates from row and column */
4188 x = lineGap + ((BOARD_WIDTH-1)-column) *
4189 (squareSize + lineGap);
4190 y = lineGap + row * (squareSize + lineGap);
4194 x = lineGap + column * (squareSize + lineGap);
4195 y = lineGap + ((BOARD_HEIGHT-1)-row) *
4196 (squareSize + lineGap);
4199 square_color = SquareColor(row, column);
4201 // [HGM] holdings: blank out area between board and holdings
4202 if ( column == BOARD_LEFT-1 || column == BOARD_RGHT
4203 || (column == BOARD_LEFT-2 && row < BOARD_HEIGHT-gameInfo.holdingsSize)
4204 || (column == BOARD_RGHT+1 && row >= gameInfo.holdingsSize) )
4206 BlankSquare(x, y, 2, EmptySquare, xBoardWindow);
4208 // [HGM] print piece counts next to holdings
4209 string[1] = NULLCHAR;
4210 if (column == (flipView ? BOARD_LEFT-1 : BOARD_RGHT) && piece > 1 )
4212 string[0] = '0' + piece;
4213 XTextExtents(countFontStruct, string, 1, &direction,
4214 &font_ascent, &font_descent, &overall);
4215 if (appData.monoMode)
4217 XDrawImageString(xDisplay, xBoardWindow, countGC,
4218 x + squareSize - overall.width - 2,
4219 y + font_ascent + 1, string, 1);
4223 XDrawString(xDisplay, xBoardWindow, countGC,
4224 x + squareSize - overall.width - 2,
4225 y + font_ascent + 1, string, 1);
4228 if (column == (flipView ? BOARD_RGHT : BOARD_LEFT-1) && piece > 1)
4230 string[0] = '0' + piece;
4231 XTextExtents(countFontStruct, string, 1, &direction,
4232 &font_ascent, &font_descent, &overall);
4233 if (appData.monoMode)
4235 XDrawImageString(xDisplay, xBoardWindow, countGC,
4236 x + 2, y + font_ascent + 1, string, 1);
4240 XDrawString(xDisplay, xBoardWindow, countGC,
4241 x + 2, y + font_ascent + 1, string, 1);
4247 /* square on the board */
4248 if (piece == EmptySquare || appData.blindfold)
4250 BlankSquare(x, y, square_color, piece, xBoardWindow);
4254 if (do_flash && appData.flashCount > 0)
4256 for (i=0; i<appData.flashCount; ++i)
4259 DrawPiece(piece, square_color, x, y, xBoardWindow);
4260 do_flash_delay(flash_delay);
4262 BlankSquare(x, y, square_color, piece, xBoardWindow);
4263 do_flash_delay(flash_delay);
4266 DrawPiece(piece, square_color, x, y, xBoardWindow);
4270 /* show coordinates if necessary */
4271 string[1] = NULLCHAR;
4272 if (appData.showCoords && row == (flipView ? BOARD_HEIGHT-1 : 0)
4273 && column >= BOARD_LEFT && column < BOARD_RGHT)
4275 string[0] = 'a' + column - BOARD_LEFT;
4276 XTextExtents(coordFontStruct, string, 1, &direction,
4277 &font_ascent, &font_descent, &overall);
4278 if (appData.monoMode)
4280 XDrawImageString(xDisplay, xBoardWindow, coordGC,
4281 x + squareSize - overall.width - 2,
4282 y + squareSize - font_descent - 1, string, 1);
4286 XDrawString(xDisplay, xBoardWindow, coordGC,
4287 x + squareSize - overall.width - 2,
4288 y + squareSize - font_descent - 1, string, 1);
4291 if (appData.showCoords && column == (flipView ? BOARD_RGHT-1 : BOARD_LEFT))
4293 string[0] = ONE + row;
4294 XTextExtents(coordFontStruct, string, 1, &direction,
4295 &font_ascent, &font_descent, &overall);
4296 if (appData.monoMode)
4298 XDrawImageString(xDisplay, xBoardWindow, coordGC,
4299 x + 2, y + font_ascent + 1, string, 1);
4303 XDrawString(xDisplay, xBoardWindow, coordGC,
4304 x + 2, y + font_ascent + 1, string, 1);
4312 /* Returns 1 if there are "too many" differences between b1 and b2
4313 (i.e. more than 1 move was made) */
4314 static int too_many_diffs(b1, b2)
4320 for (i=0; i<BOARD_HEIGHT; ++i) {
4321 for (j=0; j<BOARD_WIDTH; ++j) {
4322 if (b1[i][j] != b2[i][j]) {
4323 if (++c > 4) /* Castling causes 4 diffs */
4332 /* Matrix describing castling maneuvers */
4333 /* Row, ColRookFrom, ColKingFrom, ColRookTo, ColKingTo */
4334 static int castling_matrix[4][5] = {
4335 { 0, 0, 4, 3, 2 }, /* 0-0-0, white */
4336 { 0, 7, 4, 5, 6 }, /* 0-0, white */
4337 { 7, 0, 4, 3, 2 }, /* 0-0-0, black */
4338 { 7, 7, 4, 5, 6 } /* 0-0, black */
4341 /* Checks whether castling occurred. If it did, *rrow and *rcol
4342 are set to the destination (row,col) of the rook that moved.
4344 Returns 1 if castling occurred, 0 if not.
4346 Note: Only handles a max of 1 castling move, so be sure
4347 to call too_many_diffs() first.
4349 static int check_castle_draw(newb, oldb, rrow, rcol)
4356 /* For each type of castling... */
4357 for (i=0; i<4; ++i) {
4358 r = castling_matrix[i];
4360 /* Check the 4 squares involved in the castling move */
4362 for (j=1; j<=4; ++j) {
4363 if (newb[r[0]][r[j]] == oldb[r[0]][r[j]]) {
4370 /* All 4 changed, so it must be a castling move */
4379 static int damage[BOARD_SIZE][BOARD_SIZE];
4382 * event handler for redrawing the board
4384 void DrawPosition( repaint, board)
4385 /*Boolean*/int repaint;
4389 static int lastFlipView = 0;
4390 static int lastBoardValid = 0;
4391 static Board lastBoard;
4395 if (board == NULL) {
4396 if (!lastBoardValid) return;
4399 if (!lastBoardValid || lastFlipView != flipView) {
4400 XtSetArg(args[0], XtNleftBitmap, (flipView ? xMarkPixmap : None));
4401 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flip View"),
4406 * It would be simpler to clear the window with XClearWindow()
4407 * but this causes a very distracting flicker.
4410 if (!repaint && lastBoardValid && lastFlipView == flipView)
4412 /* If too much changes (begin observing new game, etc.), don't
4414 do_flash = too_many_diffs(board, lastBoard) ? 0 : 1;
4416 /* Special check for castling so we don't flash both the king
4417 and the rook (just flash the king). */
4420 if (check_castle_draw(board, lastBoard, &rrow, &rcol))
4422 /* Draw rook with NO flashing. King will be drawn flashing later */
4423 DrawSquare(rrow, rcol, board[rrow][rcol], 0);
4424 lastBoard[rrow][rcol] = board[rrow][rcol];
4428 /* First pass -- Draw (newly) empty squares and repair damage.
4429 This prevents you from having a piece show up twice while it
4430 is flashing on its new square */
4431 for (i = 0; i < BOARD_HEIGHT; i++)
4432 for (j = 0; j < BOARD_WIDTH; j++)
4433 if ((board[i][j] != lastBoard[i][j] && board[i][j] == EmptySquare)
4436 DrawSquare(i, j, board[i][j], 0);
4437 damage[i][j] = False;
4440 /* Second pass -- Draw piece(s) in new position and flash them */
4441 for (i = 0; i < BOARD_HEIGHT; i++)
4442 for (j = 0; j < BOARD_WIDTH; j++)
4443 if (board[i][j] != lastBoard[i][j])
4445 DrawSquare(i, j, board[i][j], do_flash);
4457 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
4459 cairo_set_line_width (cr, lineGap);
4461 /* TODO: use appdata colors */
4462 cairo_set_source_rgba (cr, 0, 1, 0, 1.0);
4466 for (i = 0; i < BOARD_HEIGHT + 1; i++)
4469 x2 = lineGap + BOARD_WIDTH * (squareSize + lineGap);
4470 y1 = y2 = lineGap / 2 + (i * (squareSize + lineGap));
4472 cairo_move_to (cr, x1, y1);
4473 cairo_rel_line_to (cr, x2,0);
4477 for (j = 0; j < BOARD_WIDTH + 1; j++)
4480 y2 = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
4481 x1 = x2 = lineGap / 2 + (j * (squareSize + lineGap));
4483 cairo_move_to (cr, x1, y1);
4484 cairo_rel_line_to (cr, 0, y2);
4493 for (i = 0; i < BOARD_HEIGHT; i++)
4494 for (j = 0; j < BOARD_WIDTH; j++)
4496 DrawSquare(i, j, board[i][j], 0);
4497 damage[i][j] = False;
4501 CopyBoard(lastBoard, board);
4503 lastFlipView = flipView;
4505 /* Draw highlights */
4506 if (pm1X >= 0 && pm1Y >= 0)
4508 drawHighlight(pm1X, pm1Y, LINE_TYPE_PRE);
4510 if (pm2X >= 0 && pm2Y >= 0)
4512 drawHighlight(pm2X, pm2Y, LINE_TYPE_PRE);
4514 if (hi1X >= 0 && hi1Y >= 0)
4516 drawHighlight(hi1X, hi1Y, LINE_TYPE_HIGHLIGHT);
4518 if (hi2X >= 0 && hi2Y >= 0)
4520 drawHighlight(hi2X, hi2Y, LINE_TYPE_HIGHLIGHT);
4523 /* If piece being dragged around board, must redraw that too */
4529 * event handler for redrawing the board
4531 void DrawPositionProc(w, event, prms, nprms)
4537 DrawPosition(True, NULL);
4542 * event handler for parsing user moves
4544 // [HGM] This routine will need quite some reworking. Although the backend still supports the old
4545 // way of doing things, by calling UserMoveEvent() to test the legality of the move and then perform
4546 // it at the end, and doing all kind of preliminary tests here (e.g. to weed out self-captures), it
4547 // should be made to use the new way, of calling UserMoveTest early to determine the legality of the
4548 // move, (which will weed out the illegal selfcaptures and moves into the holdings, and flag promotions),
4549 // and at the end FinishMove() to perform the move after optional promotion popups.
4550 // For now I patched it to allow self-capture with King, and suppress clicks between board and holdings.
4551 void HandleUserMove(w, event, prms, nprms)
4558 Boolean saveAnimate;
4559 static int second = 0;
4561 if (w != boardWidget || errorExitStatus != -1) return;
4563 if (event->type == ButtonPress) ErrorPopDown();
4566 if (event->type == ButtonPress) {
4567 XtPopdown(promotionShell);
4568 XtDestroyWidget(promotionShell);
4569 promotionUp = False;
4577 x = EventToSquare(event->xbutton.x, BOARD_WIDTH);
4578 y = EventToSquare(event->xbutton.y, BOARD_HEIGHT);
4579 if (!flipView && y >= 0) {
4580 y = BOARD_HEIGHT - 1 - y;
4582 if (flipView && x >= 0) {
4583 x = BOARD_WIDTH - 1 - x;
4586 /* [HGM] holdings: next 5 lines: ignore all clicks between board and holdings */
4587 if(event->type == ButtonPress
4588 && ( x == BOARD_LEFT-1 || x == BOARD_RGHT
4589 || x == BOARD_LEFT-2 && y < BOARD_HEIGHT-gameInfo.holdingsSize
4590 || x == BOARD_RGHT+1 && y >= gameInfo.holdingsSize) )
4594 if (event->type == ButtonPress) {
4596 if (OKToStartUserMove(x, y)) {
4600 DragPieceBegin(event->xbutton.x, event->xbutton.y);
4601 if (appData.highlightDragging) {
4602 SetHighlights(x, y, -1, -1);
4610 if (event->type == ButtonPress && gameMode != EditPosition &&
4615 /* Check if clicking again on the same color piece */
4616 fromP = boards[currentMove][fromY][fromX];
4617 toP = boards[currentMove][y][x];
4618 if ((WhitePawn <= fromP && fromP < WhiteKing && // [HGM] this test should go, as UserMoveTest now does it.
4619 WhitePawn <= toP && toP <= WhiteKing) || // For now I made it less critical by exempting King
4620 (BlackPawn <= fromP && fromP < BlackKing && // moves, to not interfere with FRC castlings.
4621 BlackPawn <= toP && toP <= BlackKing)) {
4622 /* Clicked again on same color piece -- changed his mind */
4623 second = (x == fromX && y == fromY);
4624 if (appData.highlightDragging) {
4625 SetHighlights(x, y, -1, -1);
4629 if (OKToStartUserMove(x, y)) {
4632 DragPieceBegin(event->xbutton.x, event->xbutton.y);
4638 if (event->type == ButtonRelease && x == fromX && y == fromY) {
4639 DragPieceEnd(event->xbutton.x, event->xbutton.y);
4640 if (appData.animateDragging) {
4641 /* Undo animation damage if any */
4642 DrawPosition(FALSE, NULL);
4645 /* Second up/down in same square; just abort move */
4650 ClearPremoveHighlights();
4652 /* First upclick in same square; start click-click mode */
4653 SetHighlights(x, y, -1, -1);
4658 /* Completed move */
4661 saveAnimate = appData.animate;
4662 if (event->type == ButtonPress) {
4663 /* Finish clickclick move */
4664 if (appData.animate || appData.highlightLastMove) {
4665 SetHighlights(fromX, fromY, toX, toY);
4670 /* Finish drag move */
4671 if (appData.highlightLastMove) {
4672 SetHighlights(fromX, fromY, toX, toY);
4676 DragPieceEnd(event->xbutton.x, event->xbutton.y);
4677 /* Don't animate move and drag both */
4678 appData.animate = FALSE;
4680 if (IsPromotion(fromX, fromY, toX, toY)) {
4681 if (appData.alwaysPromoteToQueen) {
4682 UserMoveEvent(fromX, fromY, toX, toY, 'q');
4683 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
4684 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
4687 SetHighlights(fromX, fromY, toX, toY);
4691 UserMoveEvent(fromX, fromY, toX, toY, NULLCHAR);
4692 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
4693 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
4696 appData.animate = saveAnimate;
4697 if (appData.animate || appData.animateDragging) {
4698 /* Undo animation damage if needed */
4699 DrawPosition(FALSE, NULL);
4703 void AnimateUserMove (Widget w, XEvent * event,
4704 String * params, Cardinal * nParams)
4706 DragPieceMove(event->xmotion.x, event->xmotion.y);
4709 Widget CommentCreate(name, text, mutable, callback, lines)
4711 int /*Boolean*/ mutable;
4712 XtCallbackProc callback;
4716 Widget shell, layout, form, edit, b_ok, b_cancel, b_clear, b_close, b_edit;
4721 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4722 XtGetValues(boardWidget, args, j);
4725 XtSetArg(args[j], XtNresizable, True); j++;
4728 XtCreatePopupShell(name, topLevelShellWidgetClass,
4729 shellWidget, args, j);
4732 XtCreatePopupShell(name, transientShellWidgetClass,
4733 shellWidget, args, j);
4736 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
4737 layoutArgs, XtNumber(layoutArgs));
4739 XtCreateManagedWidget("form", formWidgetClass, layout,
4740 formArgs, XtNumber(formArgs));
4744 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
4745 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
4747 XtSetArg(args[j], XtNstring, text); j++;
4748 XtSetArg(args[j], XtNtop, XtChainTop); j++;
4749 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4750 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4751 XtSetArg(args[j], XtNright, XtChainRight); j++;
4752 XtSetArg(args[j], XtNresizable, True); j++;
4753 XtSetArg(args[j], XtNwidth, bw_width); j++; /*force wider than buttons*/
4755 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
4757 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
4758 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
4760 XtSetArg(args[j], XtNautoFill, True); j++;
4761 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
4763 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
4767 XtSetArg(args[j], XtNfromVert, edit); j++;
4768 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4769 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4770 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4771 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4773 XtCreateManagedWidget(_("ok"), commandWidgetClass, form, args, j);
4774 XtAddCallback(b_ok, XtNcallback, callback, (XtPointer) 0);
4777 XtSetArg(args[j], XtNfromVert, edit); j++;
4778 XtSetArg(args[j], XtNfromHoriz, b_ok); j++;
4779 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4780 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4781 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4782 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4784 XtCreateManagedWidget(_("cancel"), commandWidgetClass, form, args, j);
4785 XtAddCallback(b_cancel, XtNcallback, callback, (XtPointer) 0);
4788 XtSetArg(args[j], XtNfromVert, edit); j++;
4789 XtSetArg(args[j], XtNfromHoriz, b_cancel); j++;
4790 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4791 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4792 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4793 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4795 XtCreateManagedWidget(_("clear"), commandWidgetClass, form, args, j);
4796 XtAddCallback(b_clear, XtNcallback, callback, (XtPointer) 0);
4799 XtSetArg(args[j], XtNfromVert, edit); j++;
4800 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4801 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4802 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4803 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4805 XtCreateManagedWidget(_("close"), commandWidgetClass, form, args, j);
4806 XtAddCallback(b_close, XtNcallback, callback, (XtPointer) 0);
4809 XtSetArg(args[j], XtNfromVert, edit); j++;
4810 XtSetArg(args[j], XtNfromHoriz, b_close); j++;
4811 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4812 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4813 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4814 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4816 XtCreateManagedWidget(_("edit"), commandWidgetClass, form, args, j);
4817 XtAddCallback(b_edit, XtNcallback, callback, (XtPointer) 0);
4820 XtRealizeWidget(shell);
4822 if (commentX == -1) {
4825 Dimension pw_height;
4826 Dimension ew_height;
4829 XtSetArg(args[j], XtNheight, &ew_height); j++;
4830 XtGetValues(edit, args, j);
4833 XtSetArg(args[j], XtNheight, &pw_height); j++;
4834 XtGetValues(shell, args, j);
4835 commentH = pw_height + (lines - 1) * ew_height;
4836 commentW = bw_width - 16;
4838 XSync(xDisplay, False);
4840 /* This code seems to tickle an X bug if it is executed too soon
4841 after xboard starts up. The coordinates get transformed as if
4842 the main window was positioned at (0, 0).
4844 XtTranslateCoords(shellWidget,
4845 (bw_width - commentW) / 2, 0 - commentH / 2,
4846 &commentX, &commentY);
4848 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
4849 RootWindowOfScreen(XtScreen(shellWidget)),
4850 (bw_width - commentW) / 2, 0 - commentH / 2,
4855 if (commentY < 0) commentY = 0; /*avoid positioning top offscreen*/
4858 XtSetArg(args[j], XtNheight, commentH); j++;
4859 XtSetArg(args[j], XtNwidth, commentW); j++;
4860 XtSetArg(args[j], XtNx, commentX); j++;
4861 XtSetArg(args[j], XtNy, commentY); j++;
4862 XtSetValues(shell, args, j);
4863 XtSetKeyboardFocus(shell, edit);
4868 /* Used for analysis window and ICS input window */
4869 Widget MiscCreate(name, text, mutable, callback, lines)
4871 int /*Boolean*/ mutable;
4872 XtCallbackProc callback;
4876 Widget shell, layout, form, edit;
4878 Dimension bw_width, pw_height, ew_height, w, h;
4884 XtSetArg(args[j], XtNresizable, True); j++;
4887 XtCreatePopupShell(name, topLevelShellWidgetClass,
4888 shellWidget, args, j);
4891 XtCreatePopupShell(name, transientShellWidgetClass,
4892 shellWidget, args, j);
4895 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
4896 layoutArgs, XtNumber(layoutArgs));
4898 XtCreateManagedWidget("form", formWidgetClass, layout,
4899 formArgs, XtNumber(formArgs));
4903 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
4904 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
4906 XtSetArg(args[j], XtNstring, text); j++;
4907 XtSetArg(args[j], XtNtop, XtChainTop); j++;
4908 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4909 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4910 XtSetArg(args[j], XtNright, XtChainRight); j++;
4911 XtSetArg(args[j], XtNresizable, True); j++;
4913 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
4915 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
4916 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
4918 XtSetArg(args[j], XtNautoFill, True); j++;
4919 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
4921 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
4923 XtRealizeWidget(shell);
4926 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4927 XtGetValues(boardWidget, args, j);
4930 XtSetArg(args[j], XtNheight, &ew_height); j++;
4931 XtGetValues(edit, args, j);
4934 XtSetArg(args[j], XtNheight, &pw_height); j++;
4935 XtGetValues(shell, args, j);
4936 h = pw_height + (lines - 1) * ew_height;
4939 XSync(xDisplay, False);
4941 /* This code seems to tickle an X bug if it is executed too soon
4942 after xboard starts up. The coordinates get transformed as if
4943 the main window was positioned at (0, 0).
4945 XtTranslateCoords(shellWidget, (bw_width - w) / 2, 0 - h / 2, &x, &y);
4947 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
4948 RootWindowOfScreen(XtScreen(shellWidget)),
4949 (bw_width - w) / 2, 0 - h / 2, &xx, &yy, &junk);
4953 if (y < 0) y = 0; /*avoid positioning top offscreen*/
4956 XtSetArg(args[j], XtNheight, h); j++;
4957 XtSetArg(args[j], XtNwidth, w); j++;
4958 XtSetArg(args[j], XtNx, x); j++;
4959 XtSetArg(args[j], XtNy, y); j++;
4960 XtSetValues(shell, args, j);
4966 static int savedIndex; /* gross that this is global */
4968 void EditCommentPopUp(index, title, text)
4977 if (text == NULL) text = "";
4979 if (editShell == NULL) {
4981 CommentCreate(title, text, True, EditCommentCallback, 4);
4982 XtRealizeWidget(editShell);
4983 CatchDeleteWindow(editShell, "EditCommentPopDown");
4985 edit = XtNameToWidget(editShell, "*form.text");
4987 XtSetArg(args[j], XtNstring, text); j++;
4988 XtSetValues(edit, args, j);
4990 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4991 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4992 XtSetValues(editShell, args, j);
4995 XtPopup(editShell, XtGrabNone);
4999 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
5000 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
5004 void EditCommentCallback(w, client_data, call_data)
5006 XtPointer client_data, call_data;
5014 XtSetArg(args[j], XtNlabel, &name); j++;
5015 XtGetValues(w, args, j);
5017 if (strcmp(name, _("ok")) == 0) {
5018 edit = XtNameToWidget(editShell, "*form.text");
5020 XtSetArg(args[j], XtNstring, &val); j++;
5021 XtGetValues(edit, args, j);
5022 ReplaceComment(savedIndex, val);
5023 EditCommentPopDown();
5024 } else if (strcmp(name, _("cancel")) == 0) {
5025 EditCommentPopDown();
5026 } else if (strcmp(name, _("clear")) == 0) {
5027 edit = XtNameToWidget(editShell, "*form.text");
5028 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
5029 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
5033 void EditCommentPopDown()
5038 if (!editUp) return;
5040 XtSetArg(args[j], XtNx, &commentX); j++;
5041 XtSetArg(args[j], XtNy, &commentY); j++;
5042 XtSetArg(args[j], XtNheight, &commentH); j++;
5043 XtSetArg(args[j], XtNwidth, &commentW); j++;
5044 XtGetValues(editShell, args, j);
5045 XtPopdown(editShell);
5048 XtSetArg(args[j], XtNleftBitmap, None); j++;
5049 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
5053 void ICSInputBoxPopUp()
5058 char *title = _("ICS Input");
5061 if (ICSInputShell == NULL) {
5062 ICSInputShell = MiscCreate(title, "", True, NULL, 1);
5063 tr = XtParseTranslationTable(ICSInputTranslations);
5064 edit = XtNameToWidget(ICSInputShell, "*form.text");
5065 XtOverrideTranslations(edit, tr);
5066 XtRealizeWidget(ICSInputShell);
5067 CatchDeleteWindow(ICSInputShell, "ICSInputBoxPopDown");
5070 edit = XtNameToWidget(ICSInputShell, "*form.text");
5072 XtSetArg(args[j], XtNstring, ""); j++;
5073 XtSetValues(edit, args, j);
5075 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5076 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5077 XtSetValues(ICSInputShell, args, j);
5080 XtPopup(ICSInputShell, XtGrabNone);
5081 XtSetKeyboardFocus(ICSInputShell, edit);
5083 ICSInputBoxUp = True;
5085 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
5086 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
5090 void ICSInputSendText()
5097 edit = XtNameToWidget(ICSInputShell, "*form.text");
5099 XtSetArg(args[j], XtNstring, &val); j++;
5100 XtGetValues(edit, args, j);
5101 SendMultiLineToICS(val);
5102 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
5103 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
5106 void ICSInputBoxPopDown()
5111 if (!ICSInputBoxUp) return;
5113 XtPopdown(ICSInputShell);
5114 ICSInputBoxUp = False;
5116 XtSetArg(args[j], XtNleftBitmap, None); j++;
5117 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
5121 void CommentPopUp(title, text)
5128 if (commentShell == NULL) {
5130 CommentCreate(title, text, False, CommentCallback, 4);
5131 XtRealizeWidget(commentShell);
5132 CatchDeleteWindow(commentShell, "CommentPopDown");
5134 edit = XtNameToWidget(commentShell, "*form.text");
5136 XtSetArg(args[j], XtNstring, text); j++;
5137 XtSetValues(edit, args, j);
5139 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5140 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5141 XtSetValues(commentShell, args, j);
5144 XtPopup(commentShell, XtGrabNone);
5145 XSync(xDisplay, False);
5150 void AnalysisPopUp(title, text)
5157 if (analysisShell == NULL) {
5158 analysisShell = MiscCreate(title, text, False, NULL, 4);
5159 XtRealizeWidget(analysisShell);
5160 CatchDeleteWindow(analysisShell, "AnalysisPopDown");
5163 edit = XtNameToWidget(analysisShell, "*form.text");
5165 XtSetArg(args[j], XtNstring, text); j++;
5166 XtSetValues(edit, args, j);
5168 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5169 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5170 XtSetValues(analysisShell, args, j);
5174 XtPopup(analysisShell, XtGrabNone);
5176 XSync(xDisplay, False);
5181 void CommentCallback(w, client_data, call_data)
5183 XtPointer client_data, call_data;
5190 XtSetArg(args[j], XtNlabel, &name); j++;
5191 XtGetValues(w, args, j);
5193 if (strcmp(name, _("close")) == 0) {
5195 } else if (strcmp(name, _("edit")) == 0) {
5202 void CommentPopDown()
5207 if (!commentUp) return;
5209 XtSetArg(args[j], XtNx, &commentX); j++;
5210 XtSetArg(args[j], XtNy, &commentY); j++;
5211 XtSetArg(args[j], XtNwidth, &commentW); j++;
5212 XtSetArg(args[j], XtNheight, &commentH); j++;
5213 XtGetValues(commentShell, args, j);
5214 XtPopdown(commentShell);
5215 XSync(xDisplay, False);
5219 void AnalysisPopDown()
5221 if (!analysisUp) return;
5222 XtPopdown(analysisShell);
5223 XSync(xDisplay, False);
5225 if (appData.icsEngineAnalyze) ExitAnalyzeMode(); /* [DM] icsEngineAnalyze */
5229 void FileNamePopUp(label, def, proc, openMode)
5236 Widget popup, layout, dialog, edit;
5242 fileProc = proc; /* I can't see a way not */
5243 fileOpenMode = openMode; /* to use globals here */
5246 XtSetArg(args[i], XtNresizable, True); i++;
5247 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
5248 XtSetArg(args[i], XtNtitle, XtNewString(_("File name prompt"))); i++;
5249 fileNameShell = popup =
5250 XtCreatePopupShell("File name prompt", transientShellWidgetClass,
5251 shellWidget, args, i);
5254 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
5255 layoutArgs, XtNumber(layoutArgs));
5258 XtSetArg(args[i], XtNlabel, label); i++;
5259 XtSetArg(args[i], XtNvalue, def); i++;
5260 XtSetArg(args[i], XtNborderWidth, 0); i++;
5261 dialog = XtCreateManagedWidget("fileName", dialogWidgetClass,
5264 XawDialogAddButton(dialog, _("ok"), FileNameCallback, (XtPointer) dialog);
5265 XawDialogAddButton(dialog, _("cancel"), FileNameCallback,
5266 (XtPointer) dialog);
5268 XtRealizeWidget(popup);
5269 CatchDeleteWindow(popup, "FileNamePopDown");
5271 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
5272 &x, &y, &win_x, &win_y, &mask);
5274 XtSetArg(args[0], XtNx, x - 10);
5275 XtSetArg(args[1], XtNy, y - 30);
5276 XtSetValues(popup, args, 2);
5278 XtPopup(popup, XtGrabExclusive);
5281 edit = XtNameToWidget(dialog, "*value");
5282 XtSetKeyboardFocus(popup, edit);
5285 void FileNamePopDown()
5287 if (!filenameUp) return;
5288 XtPopdown(fileNameShell);
5289 XtDestroyWidget(fileNameShell);
5294 void FileNameCallback(w, client_data, call_data)
5296 XtPointer client_data, call_data;
5301 XtSetArg(args[0], XtNlabel, &name);
5302 XtGetValues(w, args, 1);
5304 if (strcmp(name, _("cancel")) == 0) {
5309 FileNameAction(w, NULL, NULL, NULL);
5312 void FileNameAction(w, event, prms, nprms)
5324 name = XawDialogGetValueString(w = XtParent(w));
5326 if ((name != NULL) && (*name != NULLCHAR)) {
5328 XtPopdown(w = XtParent(XtParent(w)));
5332 p = strrchr(buf, ' ');
5339 fullname = ExpandPathName(buf);
5341 ErrorPopUp(_("Error"), _("Can't open file"), FALSE);
5344 f = fopen(fullname, fileOpenMode);
5346 DisplayError(_("Failed to open file"), errno);
5348 (void) (*fileProc)(f, index, buf);
5355 XtPopdown(w = XtParent(XtParent(w)));
5361 void PromotionPopUp()
5364 Widget dialog, layout;
5366 Dimension bw_width, pw_width;
5370 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5371 XtGetValues(boardWidget, args, j);
5374 XtSetArg(args[j], XtNresizable, True); j++;
5375 XtSetArg(args[j], XtNtitle, XtNewString(_("Promotion"))); j++;
5377 XtCreatePopupShell("Promotion", transientShellWidgetClass,
5378 shellWidget, args, j);
5380 XtCreateManagedWidget(layoutName, formWidgetClass, promotionShell,
5381 layoutArgs, XtNumber(layoutArgs));
5384 XtSetArg(args[j], XtNlabel, _("Promote to what?")); j++;
5385 XtSetArg(args[j], XtNborderWidth, 0); j++;
5386 dialog = XtCreateManagedWidget("promotion", dialogWidgetClass,
5389 if(gameInfo.variant != VariantShogi) {
5390 XawDialogAddButton(dialog, _("Queen"), PromotionCallback,
5391 (XtPointer) dialog);
5392 XawDialogAddButton(dialog, _("Rook"), PromotionCallback,
5393 (XtPointer) dialog);
5394 XawDialogAddButton(dialog, _("Bishop"), PromotionCallback,
5395 (XtPointer) dialog);
5396 XawDialogAddButton(dialog, _("Knight"), PromotionCallback,
5397 (XtPointer) dialog);
5398 if (!appData.testLegality || gameInfo.variant == VariantSuicide ||
5399 gameInfo.variant == VariantGiveaway) {
5400 XawDialogAddButton(dialog, _("King"), PromotionCallback,
5401 (XtPointer) dialog);
5403 if(gameInfo.variant == VariantCapablanca ||
5404 gameInfo.variant == VariantGothic ||
5405 gameInfo.variant == VariantCapaRandom) {
5406 XawDialogAddButton(dialog, _("Archbishop"), PromotionCallback,
5407 (XtPointer) dialog);
5408 XawDialogAddButton(dialog, _("Chancellor"), PromotionCallback,
5409 (XtPointer) dialog);
5411 } else // [HGM] shogi
5413 XawDialogAddButton(dialog, _("Promote"), PromotionCallback,
5414 (XtPointer) dialog);
5415 XawDialogAddButton(dialog, _("Defer"), PromotionCallback,
5416 (XtPointer) dialog);
5418 XawDialogAddButton(dialog, _("cancel"), PromotionCallback,
5419 (XtPointer) dialog);
5421 XtRealizeWidget(promotionShell);
5422 CatchDeleteWindow(promotionShell, "PromotionPopDown");
5425 XtSetArg(args[j], XtNwidth, &pw_width); j++;
5426 XtGetValues(promotionShell, args, j);
5428 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
5429 lineGap + squareSize/3 +
5430 ((toY == BOARD_HEIGHT-1) ^ (flipView) ?
5431 0 : 6*(squareSize + lineGap)), &x, &y);
5434 XtSetArg(args[j], XtNx, x); j++;
5435 XtSetArg(args[j], XtNy, y); j++;
5436 XtSetValues(promotionShell, args, j);
5438 XtPopup(promotionShell, XtGrabNone);
5443 void PromotionPopDown()
5445 if (!promotionUp) return;
5446 XtPopdown(promotionShell);
5447 XtDestroyWidget(promotionShell);
5448 promotionUp = False;
5451 void PromotionCallback(w, client_data, call_data)
5453 XtPointer client_data, call_data;
5459 XtSetArg(args[0], XtNlabel, &name);
5460 XtGetValues(w, args, 1);
5464 if (fromX == -1) return;
5466 if (strcmp(name, _("cancel")) == 0) {
5470 } else if (strcmp(name, _("Knight")) == 0) {
5472 } else if (strcmp(name, _("Promote")) == 0) {
5474 } else if (strcmp(name, _("Defer")) == 0) {
5477 promoChar = ToLower(name[0]);
5480 UserMoveEvent(fromX, fromY, toX, toY, promoChar);
5482 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
5483 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
5488 void ErrorCallback(w, client_data, call_data)
5490 XtPointer client_data, call_data;
5493 XtPopdown(w = XtParent(XtParent(XtParent(w))));
5495 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5501 if (!errorUp) return;
5503 XtPopdown(errorShell);
5504 XtDestroyWidget(errorShell);
5505 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5508 void ErrorPopUp(title, label, modal)
5509 char *title, *label;
5514 dialog = gtk_message_dialog_new(GTK_WINDOW(GUI_Window),
5515 GTK_DIALOG_DESTROY_WITH_PARENT,
5520 gtk_window_set_title(GTK_WINDOW(dialog),(gchar *) title);
5523 gtk_dialog_run(GTK_DIALOG(dialog));
5524 gtk_widget_destroy(GTK_WIDGET(dialog));
5528 g_signal_connect_swapped (dialog, "response",
5529 G_CALLBACK (ErrorPopDownProc),
5532 gtk_widget_show(GTK_WIDGET(dialog));
5536 /* Disable all user input other than deleting the window */
5537 static int frozen = 0;
5541 /* Grab by a widget that doesn't accept input */
5542 // XtAddGrab(messageWidget, TRUE, FALSE);
5546 /* Undo a FreezeUI */
5549 if (!frozen) return;
5550 XtRemoveGrab(messageWidget);
5554 char *ModeToWidgetName(mode)
5558 case BeginningOfGame:
5559 if (appData.icsActive)
5560 return "menuMode.ICS Client";
5561 else if (appData.noChessProgram ||
5562 *appData.cmailGameName != NULLCHAR)
5563 return "menuMode.Edit Game";
5565 return "menuMode.Machine Black";
5566 case MachinePlaysBlack:
5567 return "menuMode.Machine Black";
5568 case MachinePlaysWhite:
5569 return "menuMode.Machine White";
5571 return "menuMode.Analysis Mode";
5573 return "menuMode.Analyze File";
5574 case TwoMachinesPlay:
5575 return "menuMode.Two Machines";
5577 return "menuMode.Edit Game";
5578 case PlayFromGameFile:
5579 return "menuFile.Load Game";
5581 return "menuMode.Edit Position";
5583 return "menuMode.Training";
5584 case IcsPlayingWhite:
5585 case IcsPlayingBlack:
5589 return "menuMode.ICS Client";
5596 void ModeHighlight()
5598 static int oldPausing = FALSE;
5599 static GameMode oldmode = (GameMode) -1;
5602 // todo this toggling of the pause button doesn't seem to work?
5603 // e.g. select pause from buttonbar doesn't activate menumode.pause
5605 // if (!boardWidget || !XtIsRealized(boardWidget)) return;
5607 if (pausing != oldPausing) {
5608 oldPausing = pausing;
5609 gtk_button_set_relief(GTK_BUTTON (gtk_builder_get_object (builder, "menuMode.Pause")),pausing?GTK_RELIEF_NORMAL:GTK_RELIEF_NONE);
5610 /* toggle background color in showbuttonbar */
5611 if (appData.showButtonBar) {
5613 gtk_button_pressed(GTK_BUTTON (gtk_builder_get_object (builder, "buttonbar.Pause")));
5615 gtk_button_released(GTK_BUTTON (gtk_builder_get_object (builder, "buttonbar.Pause")));
5620 wname = ModeToWidgetName(oldmode);
5622 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, wname)),True);
5626 /* Maybe all the enables should be handled here, not just this one */
5627 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuMode.Training")),
5628 gameMode == Training || gameMode == PlayFromGameFile);
5633 * Button/menu procedures
5636 int LoadGamePopUp(f, gameNumber, title)
5641 cmailMsgLoaded = FALSE;
5642 if (gameNumber == 0) {
5643 int error = GameListBuild(f);
5645 DisplayError(_("Cannot build game list"), error);
5646 } else if (!ListEmpty(&gameList) &&
5647 ((ListGame *) gameList.tailPred)->number > 1) {
5648 GameListPopUp(f, title);
5654 return LoadGame(f, gameNumber, title, FALSE);
5658 void LoadNextPositionProc(w, event, prms, nprms)
5667 void LoadPrevPositionProc(w, event, prms, nprms)
5676 void ReloadPositionProc(w, event, prms, nprms)
5685 void LoadPositionProc(w, event, prms, nprms)
5691 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
5694 FileNamePopUp(_("Load position file name?"), "", LoadPosition, "rb");
5697 void SaveGameProc(w, event, prms, nprms)
5703 FileNamePopUp(_("Save game file name?"),
5704 DefaultFileName(appData.oldSaveStyle ? "game" : "pgn"),
5708 void SavePositionProc(w, event, prms, nprms)
5714 FileNamePopUp(_("Save position file name?"),
5715 DefaultFileName(appData.oldSaveStyle ? "pos" : "fen"),
5719 void ReloadCmailMsgProc(w, event, prms, nprms)
5725 ReloadCmailMsgEvent(FALSE);
5728 void MailMoveProc(w, event, prms, nprms)
5737 /* this variable is shared between CopyPositionProc and SendPositionSelection */
5738 static char *selected_fen_position=NULL;
5741 SendPositionSelection(Widget w, Atom *selection, Atom *target,
5742 Atom *type_return, XtPointer *value_return,
5743 unsigned long *length_return, int *format_return)
5745 char *selection_tmp;
5747 if (!selected_fen_position) return False; /* should never happen */
5748 if (*target == XA_STRING){
5749 /* note: since no XtSelectionDoneProc was registered, Xt will
5750 * automatically call XtFree on the value returned. So have to
5751 * make a copy of it allocated with XtMalloc */
5752 selection_tmp= XtMalloc(strlen(selected_fen_position)+16);
5753 strcpy(selection_tmp, selected_fen_position);
5755 *value_return=selection_tmp;
5756 *length_return=strlen(selection_tmp);
5757 *type_return=XA_STRING;
5758 *format_return = 8; /* bits per byte */
5765 /* note: when called from menu all parameters are NULL, so no clue what the
5766 * Widget which was clicked on was, or what the click event was
5768 void CopyPositionProc(w, event, prms, nprms)
5776 if (selected_fen_position) free(selected_fen_position);
5777 selected_fen_position = (char *)PositionToFEN(currentMove, NULL);
5778 if (!selected_fen_position) return;
5779 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
5781 SendPositionSelection,
5782 NULL/* lose_ownership_proc */ ,
5783 NULL/* transfer_done_proc */);
5785 free(selected_fen_position);
5786 selected_fen_position=NULL;
5790 /* function called when the data to Paste is ready */
5792 PastePositionCB(Widget w, XtPointer client_data, Atom *selection,
5793 Atom *type, XtPointer value, unsigned long *len, int *format)
5796 if (value==NULL || *len==0) return; /* nothing had been selected to copy */
5797 fenstr[*len]='\0'; /* normally this string is terminated, but be safe */
5798 EditPositionPasteFEN(fenstr);
5802 /* called when Paste Position button is pressed,
5803 * all parameters will be NULL */
5804 void PastePositionProc(w, event, prms, nprms)
5810 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
5811 /* (XtSelectionCallbackProc) */ PastePositionCB,
5812 NULL, /* client_data passed to PastePositionCB */
5814 /* better to use the time field from the event that triggered the
5815 * call to this function, but that isn't trivial to get
5823 SendGameSelection(Widget w, Atom *selection, Atom *target,
5824 Atom *type_return, XtPointer *value_return,
5825 unsigned long *length_return, int *format_return)
5827 char *selection_tmp;
5829 if (*target == XA_STRING){
5830 FILE* f = fopen(gameCopyFilename, "r");
5833 if (f == NULL) return False;
5837 selection_tmp = XtMalloc(len + 1);
5838 count = fread(selection_tmp, 1, len, f);
5840 XtFree(selection_tmp);
5843 selection_tmp[len] = NULLCHAR;
5844 *value_return = selection_tmp;
5845 *length_return = len;
5846 *type_return = XA_STRING;
5847 *format_return = 8; /* bits per byte */
5854 /* note: when called from menu all parameters are NULL, so no clue what the
5855 * Widget which was clicked on was, or what the click event was
5857 void CopyGameProc(w, event, prms, nprms)
5865 ret = SaveGameToFile(gameCopyFilename, FALSE);
5868 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
5871 NULL/* lose_ownership_proc */ ,
5872 NULL/* transfer_done_proc */);
5875 /* function called when the data to Paste is ready */
5877 PasteGameCB(Widget w, XtPointer client_data, Atom *selection,
5878 Atom *type, XtPointer value, unsigned long *len, int *format)
5881 if (value == NULL || *len == 0) {
5882 return; /* nothing had been selected to copy */
5884 f = fopen(gamePasteFilename, "w");
5886 DisplayError(_("Can't open temp file"), errno);
5889 fwrite(value, 1, *len, f);
5892 LoadGameFromFile(gamePasteFilename, 0, gamePasteFilename, TRUE);
5895 /* called when Paste Game button is pressed,
5896 * all parameters will be NULL */
5897 void PasteGameProc(w, event, prms, nprms)
5903 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
5904 /* (XtSelectionCallbackProc) */ PasteGameCB,
5905 NULL, /* client_data passed to PasteGameCB */
5907 /* better to use the time field from the event that triggered the
5908 * call to this function, but that isn't trivial to get
5918 SaveGameProc(NULL, NULL, NULL, NULL);
5921 void MachineBlackProc(w, event, prms, nprms)
5927 MachineBlackEvent();
5930 void MachineWhiteProc(w, event, prms, nprms)
5936 MachineWhiteEvent();
5939 void AnalyzeModeProc(w, event, prms, nprms)
5947 if (!first.analysisSupport) {
5948 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
5949 DisplayError(buf, 0);
5952 /* [DM] icsEngineAnalyze [HGM] This is horrible code; reverse the gameMode and isEngineAnalyze tests! */
5953 if (appData.icsActive) {
5954 if (gameMode != IcsObserving) {
5955 sprintf(buf,_("You are not observing a game"));
5956 DisplayError(buf, 0);
5958 if (appData.icsEngineAnalyze) {
5959 if (appData.debugMode)
5960 fprintf(debugFP, _("Found unexpected active ICS engine analyze \n"));
5966 /* if enable, use want disable icsEngineAnalyze */
5967 if (appData.icsEngineAnalyze) {
5972 appData.icsEngineAnalyze = TRUE;
5973 if (appData.debugMode)
5974 fprintf(debugFP, _("ICS engine analyze starting... \n"));
5976 if (!appData.showThinking)
5977 ShowThinkingProc(w,event,prms,nprms);
5982 void AnalyzeFileProc(w, event, prms, nprms)
5988 if (!first.analysisSupport) {
5990 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
5991 DisplayError(buf, 0);
5996 if (!appData.showThinking)
5997 ShowThinkingProc(w,event,prms,nprms);
6000 FileNamePopUp(_("File to analyze"), "", LoadGamePopUp, "rb");
6001 AnalysisPeriodicEvent(1);
6004 void TwoMachinesProc(w, event, prms, nprms)
6013 void IcsClientProc(w, event, prms, nprms)
6022 void EditGameProc(w, event, prms, nprms)
6031 void EditPositionProc(w, event, prms, nprms)
6037 EditPositionEvent();
6040 void TrainingProc(w, event, prms, nprms)
6049 void EditCommentProc(w, event, prms, nprms)
6056 EditCommentPopDown();
6062 void IcsInputBoxProc(w, event, prms, nprms)
6068 if (ICSInputBoxUp) {
6069 ICSInputBoxPopDown();
6075 void AcceptProc(w, event, prms, nprms)
6084 void DeclineProc(w, event, prms, nprms)
6093 void RematchProc(w, event, prms, nprms)
6102 void CallFlagProc(w, event, prms, nprms)
6111 void DrawProc(w, event, prms, nprms)
6120 void AbortProc(w, event, prms, nprms)
6129 void AdjournProc(w, event, prms, nprms)
6138 void ResignProc(w, event, prms, nprms)
6147 void AdjuWhiteProc(w, event, prms, nprms)
6153 UserAdjudicationEvent(+1);
6156 void AdjuBlackProc(w, event, prms, nprms)
6162 UserAdjudicationEvent(-1);
6165 void AdjuDrawProc(w, event, prms, nprms)
6171 UserAdjudicationEvent(0);
6174 void EnterKeyProc(w, event, prms, nprms)
6180 if (ICSInputBoxUp == True)
6184 void StopObservingProc(w, event, prms, nprms)
6190 StopObservingEvent();
6193 void StopExaminingProc(w, event, prms, nprms)
6199 StopExaminingEvent();
6203 void ForwardProc(w, event, prms, nprms)
6213 void BackwardProc(w, event, prms, nprms)
6222 void ToStartProc(w, event, prms, nprms)
6231 void ToEndProc(w, event, prms, nprms)
6240 void RevertProc(w, event, prms, nprms)
6249 void TruncateGameProc(w, event, prms, nprms)
6255 TruncateGameEvent();
6257 void RetractMoveProc(w, event, prms, nprms)
6266 void MoveNowProc(w, event, prms, nprms)
6276 void AlwaysQueenProc(w, event, prms, nprms)
6284 appData.alwaysPromoteToQueen = !appData.alwaysPromoteToQueen;
6286 if (appData.alwaysPromoteToQueen) {
6287 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6289 XtSetArg(args[0], XtNleftBitmap, None);
6291 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
6295 void AnimateDraggingProc(w, event, prms, nprms)
6303 appData.animateDragging = !appData.animateDragging;
6305 if (appData.animateDragging) {
6306 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6309 XtSetArg(args[0], XtNleftBitmap, None);
6311 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Dragging"),
6315 void AnimateMovingProc(w, event, prms, nprms)
6323 appData.animate = !appData.animate;
6325 if (appData.animate) {
6326 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6329 XtSetArg(args[0], XtNleftBitmap, None);
6331 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
6335 void AutocommProc(w, event, prms, nprms)
6343 appData.autoComment = !appData.autoComment;
6345 if (appData.autoComment) {
6346 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6348 XtSetArg(args[0], XtNleftBitmap, None);
6350 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
6355 void AutoflagProc(w, event, prms, nprms)
6363 appData.autoCallFlag = !appData.autoCallFlag;
6365 if (appData.autoCallFlag) {
6366 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6368 XtSetArg(args[0], XtNleftBitmap, None);
6370 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
6374 void AutoflipProc(w, event, prms, nprms)
6382 appData.autoFlipView = !appData.autoFlipView;
6384 if (appData.autoFlipView) {
6385 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6387 XtSetArg(args[0], XtNleftBitmap, None);
6389 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flip View"),
6393 void AutobsProc(w, event, prms, nprms)
6401 appData.autoObserve = !appData.autoObserve;
6403 if (appData.autoObserve) {
6404 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6406 XtSetArg(args[0], XtNleftBitmap, None);
6408 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
6412 void AutoraiseProc(w, event, prms, nprms)
6420 appData.autoRaiseBoard = !appData.autoRaiseBoard;
6422 if (appData.autoRaiseBoard) {
6423 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6425 XtSetArg(args[0], XtNleftBitmap, None);
6427 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Raise Board"),
6431 void AutosaveProc(w, event, prms, nprms)
6439 appData.autoSaveGames = !appData.autoSaveGames;
6441 if (appData.autoSaveGames) {
6442 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6444 XtSetArg(args[0], XtNleftBitmap, None);
6446 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
6450 void BlindfoldProc(w, event, prms, nprms)
6458 appData.blindfold = !appData.blindfold;
6460 if (appData.blindfold) {
6461 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6463 XtSetArg(args[0], XtNleftBitmap, None);
6465 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Blindfold"),
6468 DrawPosition(True, NULL);
6471 void TestLegalityProc(w, event, prms, nprms)
6479 appData.testLegality = !appData.testLegality;
6481 if (appData.testLegality) {
6482 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6484 XtSetArg(args[0], XtNleftBitmap, None);
6486 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Test Legality"),
6491 void FlashMovesProc(w, event, prms, nprms)
6499 if (appData.flashCount == 0) {
6500 appData.flashCount = 3;
6502 appData.flashCount = -appData.flashCount;
6505 if (appData.flashCount > 0) {
6506 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6508 XtSetArg(args[0], XtNleftBitmap, None);
6510 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flash Moves"),
6514 void FlipViewProc(w, event, prms, nprms)
6520 flipView = !flipView;
6521 DrawPosition(True, NULL);
6524 void GetMoveListProc(w, event, prms, nprms)
6532 appData.getMoveList = !appData.getMoveList;
6534 if (appData.getMoveList) {
6535 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6538 XtSetArg(args[0], XtNleftBitmap, None);
6540 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
6545 void HighlightDraggingProc(w, event, prms, nprms)
6553 appData.highlightDragging = !appData.highlightDragging;
6555 if (appData.highlightDragging) {
6556 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6558 XtSetArg(args[0], XtNleftBitmap, None);
6560 XtSetValues(XtNameToWidget(menuBarWidget,
6561 "menuOptions.Highlight Dragging"), args, 1);
6565 void HighlightLastMoveProc(w, event, prms, nprms)
6573 appData.highlightLastMove = !appData.highlightLastMove;
6575 if (appData.highlightLastMove) {
6576 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6578 XtSetArg(args[0], XtNleftBitmap, None);
6580 XtSetValues(XtNameToWidget(menuBarWidget,
6581 "menuOptions.Highlight Last Move"), args, 1);
6584 void IcsAlarmProc(w, event, prms, nprms)
6592 appData.icsAlarm = !appData.icsAlarm;
6594 if (appData.icsAlarm) {
6595 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6597 XtSetArg(args[0], XtNleftBitmap, None);
6599 XtSetValues(XtNameToWidget(menuBarWidget,
6600 "menuOptions.ICS Alarm"), args, 1);
6603 void MoveSoundProc(w, event, prms, nprms)
6611 appData.ringBellAfterMoves = !appData.ringBellAfterMoves;
6613 if (appData.ringBellAfterMoves) {
6614 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6616 XtSetArg(args[0], XtNleftBitmap, None);
6618 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
6623 void OldSaveStyleProc(w, event, prms, nprms)
6631 appData.oldSaveStyle = !appData.oldSaveStyle;
6633 if (appData.oldSaveStyle) {
6634 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6636 XtSetArg(args[0], XtNleftBitmap, None);
6638 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Old Save Style"),
6642 void PeriodicUpdatesProc(w, event, prms, nprms)
6650 PeriodicUpdatesEvent(!appData.periodicUpdates);
6652 if (appData.periodicUpdates) {
6653 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6655 XtSetArg(args[0], XtNleftBitmap, None);
6657 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Periodic Updates"),
6661 void PonderNextMoveProc(w, event, prms, nprms)
6669 PonderNextMoveEvent(!appData.ponderNextMove);
6671 if (appData.ponderNextMove) {
6672 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6674 XtSetArg(args[0], XtNleftBitmap, None);
6676 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Ponder Next Move"),
6680 void PopupExitMessageProc(w, event, prms, nprms)
6688 appData.popupExitMessage = !appData.popupExitMessage;
6690 if (appData.popupExitMessage) {
6691 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6693 XtSetArg(args[0], XtNleftBitmap, None);
6695 XtSetValues(XtNameToWidget(menuBarWidget,
6696 "menuOptions.Popup Exit Message"), args, 1);
6699 void PopupMoveErrorsProc(w, event, prms, nprms)
6707 appData.popupMoveErrors = !appData.popupMoveErrors;
6709 if (appData.popupMoveErrors) {
6710 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6712 XtSetArg(args[0], XtNleftBitmap, None);
6714 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Popup Move Errors"),
6718 void PremoveProc(w, event, prms, nprms)
6726 appData.premove = !appData.premove;
6728 if (appData.premove) {
6729 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6731 XtSetArg(args[0], XtNleftBitmap, None);
6733 XtSetValues(XtNameToWidget(menuBarWidget,
6734 "menuOptions.Premove"), args, 1);
6737 void QuietPlayProc(w, event, prms, nprms)
6745 appData.quietPlay = !appData.quietPlay;
6747 if (appData.quietPlay) {
6748 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6750 XtSetArg(args[0], XtNleftBitmap, None);
6752 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Quiet Play"),
6756 void ShowThinkingProc(w, event, prms, nprms)
6764 appData.showThinking = !appData.showThinking; // [HGM] thinking: tken out of ShowThinkingEvent
6765 ShowThinkingEvent();
6767 // [HGM] thinking: currently no suc menu item; replaced by Hide Thinking (From Human)
6768 if (appData.showThinking) {
6769 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6771 XtSetArg(args[0], XtNleftBitmap, None);
6773 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Thinking"),
6778 void HideThinkingProc(w, event, prms, nprms)
6786 appData.hideThinkingFromHuman = !appData.hideThinkingFromHuman; // [HGM] thinking: tken out of ShowThinkingEvent
6787 ShowThinkingEvent();
6789 if (appData.hideThinkingFromHuman) {
6790 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6792 XtSetArg(args[0], XtNleftBitmap, None);
6794 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
6798 void InfoProc(w, event, prms, nprms)
6805 snprintf(buf, sizeof(buf), "xterm -e info --directory %s --directory . -f %s &",
6810 void ManProc(w, event, prms, nprms)
6818 if (nprms && *nprms > 0)
6822 snprintf(buf, sizeof(buf), "xterm -e man %s &", name);
6826 void HintProc(w, event, prms, nprms)
6835 void BookProc(w, event, prms, nprms)
6844 void DebugProc(w, event, prms, nprms)
6850 appData.debugMode = !appData.debugMode;
6853 void AboutGameProc(w, event, prms, nprms)
6862 void NothingProc(w, event, prms, nprms)
6871 void Iconify(w, event, prms, nprms)
6880 XtSetArg(args[0], XtNiconic, True);
6881 XtSetValues(shellWidget, args, 1);
6884 void DisplayMessage(message, extMessage)
6885 gchar *message, *extMessage;
6892 snprintf(buf, sizeof(buf), "%s %s", message, extMessage);
6895 message = extMessage;
6898 gtk_label_set_text( GTK_LABEL(gtk_builder_get_object (builder, "Messages")),message);
6901 void DisplayTitle(text)
6906 char title[MSG_SIZ];
6909 if (text == NULL) text = "";
6911 if (appData.titleInWindow) {
6913 XtSetArg(args[i], XtNlabel, text); i++;
6914 XtSetValues(titleWidget, args, i);
6917 if (*text != NULLCHAR) {
6919 strcpy(title, text);
6920 } else if (appData.icsActive) {
6921 snprintf(icon, sizeof(icon), "%s", appData.icsHost);
6922 snprintf(title, sizeof(title), "%s: %s", programName, appData.icsHost);
6923 } else if (appData.cmailGameName[0] != NULLCHAR) {
6924 snprintf(icon, sizeof(icon), "%s", "CMail");
6925 snprintf(title,sizeof(title), "%s: %s", programName, "CMail");
6927 // [HGM] license: This stuff should really be done in back-end, but WinBoard already had a pop-up for it
6928 } else if (gameInfo.variant == VariantGothic) {
6929 strcpy(icon, programName);
6930 strcpy(title, GOTHIC);
6933 } else if (gameInfo.variant == VariantFalcon) {
6934 strcpy(icon, programName);
6935 strcpy(title, FALCON);
6937 } else if (appData.noChessProgram) {
6938 strcpy(icon, programName);
6939 strcpy(title, programName);
6941 strcpy(icon, first.tidy);
6942 snprintf(title,sizeof(title), "%s: %s", programName, first.tidy);
6945 XtSetArg(args[i], XtNiconName, (XtArgVal) icon); i++;
6946 XtSetArg(args[i], XtNtitle, (XtArgVal) title); i++;
6947 XtSetValues(shellWidget, args, i);
6951 void DisplayError(message, error)
6958 if (appData.debugMode || appData.matchMode) {
6959 fprintf(stderr, "%s: %s\n", programName, message);
6962 if (appData.debugMode || appData.matchMode) {
6963 fprintf(stderr, "%s: %s: %s\n",
6964 programName, message, strerror(error));
6966 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
6969 ErrorPopUp(_("Error"), message, FALSE);
6973 void DisplayMoveError(message)
6978 DrawPosition(FALSE, NULL);
6979 if (appData.debugMode || appData.matchMode) {
6980 fprintf(stderr, "%s: %s\n", programName, message);
6982 if (appData.popupMoveErrors) {
6983 ErrorPopUp(_("Error"), message, FALSE);
6985 DisplayMessage(message, "");
6990 void DisplayFatalError(message, error, status)
6996 errorExitStatus = status;
6998 fprintf(stderr, "%s: %s\n", programName, message);
7000 fprintf(stderr, "%s: %s: %s\n",
7001 programName, message, strerror(error));
7002 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
7005 if (appData.popupExitMessage && boardWidget && XtIsRealized(boardWidget)) {
7006 ErrorPopUp(status ? _("Fatal Error") : _("Exiting"), message, TRUE);
7012 void DisplayInformation(message)
7016 ErrorPopUp(_("Information"), message, TRUE);
7019 void DisplayNote(message)
7023 ErrorPopUp(_("Note"), message, FALSE);
7027 NullXErrorCheck(dpy, error_event)
7029 XErrorEvent *error_event;
7034 void DisplayIcsInteractionTitle(message)
7037 if (oldICSInteractionTitle == NULL) {
7038 /* Magic to find the old window title, adapted from vim */
7039 char *wina = getenv("WINDOWID");
7041 Window win = (Window) atoi(wina);
7042 Window root, parent, *children;
7043 unsigned int nchildren;
7044 int (*oldHandler)() = XSetErrorHandler(NullXErrorCheck);
7046 if (XFetchName(xDisplay, win, &oldICSInteractionTitle)) break;
7047 if (!XQueryTree(xDisplay, win, &root, &parent,
7048 &children, &nchildren)) break;
7049 if (children) XFree((void *)children);
7050 if (parent == root || parent == 0) break;
7053 XSetErrorHandler(oldHandler);
7055 if (oldICSInteractionTitle == NULL) {
7056 oldICSInteractionTitle = "xterm";
7059 printf("\033]0;%s\007", message);
7063 char pendingReplyPrefix[MSG_SIZ];
7064 ProcRef pendingReplyPR;
7066 void AskQuestionProc(w, event, prms, nprms)
7073 fprintf(stderr, _("AskQuestionProc needed 4 parameters, got %d\n"),
7077 AskQuestionEvent(prms[0], prms[1], prms[2], prms[3]);
7080 void AskQuestionPopDown()
7082 if (!askQuestionUp) return;
7083 XtPopdown(askQuestionShell);
7084 XtDestroyWidget(askQuestionShell);
7085 askQuestionUp = False;
7088 void AskQuestionReplyAction(w, event, prms, nprms)
7098 reply = XawDialogGetValueString(w = XtParent(w));
7099 strcpy(buf, pendingReplyPrefix);
7100 if (*buf) strcat(buf, " ");
7103 OutputToProcess(pendingReplyPR, buf, strlen(buf), &err);
7104 AskQuestionPopDown();
7106 if (err) DisplayFatalError(_("Error writing to chess program"), err, 0);
7109 void AskQuestionCallback(w, client_data, call_data)
7111 XtPointer client_data, call_data;
7116 XtSetArg(args[0], XtNlabel, &name);
7117 XtGetValues(w, args, 1);
7119 if (strcmp(name, _("cancel")) == 0) {
7120 AskQuestionPopDown();
7122 AskQuestionReplyAction(w, NULL, NULL, NULL);
7126 void AskQuestion(title, question, replyPrefix, pr)
7127 char *title, *question, *replyPrefix;
7131 Widget popup, layout, dialog, edit;
7137 strcpy(pendingReplyPrefix, replyPrefix);
7138 pendingReplyPR = pr;
7141 XtSetArg(args[i], XtNresizable, True); i++;
7142 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
7143 askQuestionShell = popup =
7144 XtCreatePopupShell(title, transientShellWidgetClass,
7145 shellWidget, args, i);
7148 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
7149 layoutArgs, XtNumber(layoutArgs));
7152 XtSetArg(args[i], XtNlabel, question); i++;
7153 XtSetArg(args[i], XtNvalue, ""); i++;
7154 XtSetArg(args[i], XtNborderWidth, 0); i++;
7155 dialog = XtCreateManagedWidget("question", dialogWidgetClass,
7158 XawDialogAddButton(dialog, _("enter"), AskQuestionCallback,
7159 (XtPointer) dialog);
7160 XawDialogAddButton(dialog, _("cancel"), AskQuestionCallback,
7161 (XtPointer) dialog);
7163 XtRealizeWidget(popup);
7164 CatchDeleteWindow(popup, "AskQuestionPopDown");
7166 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
7167 &x, &y, &win_x, &win_y, &mask);
7169 XtSetArg(args[0], XtNx, x - 10);
7170 XtSetArg(args[1], XtNy, y - 30);
7171 XtSetValues(popup, args, 2);
7173 XtPopup(popup, XtGrabExclusive);
7174 askQuestionUp = True;
7176 edit = XtNameToWidget(dialog, "*value");
7177 XtSetKeyboardFocus(popup, edit);
7185 if (*name == NULLCHAR) {
7187 } else if (strcmp(name, "$") == 0) {
7188 putc(BELLCHAR, stderr);
7191 snprintf(buf, sizeof(buf), "%s '%s' &", appData.soundProgram, name);
7199 PlaySound(appData.soundMove);
7205 PlaySound(appData.soundIcsWin);
7211 PlaySound(appData.soundIcsLoss);
7217 PlaySound(appData.soundIcsDraw);
7221 PlayIcsUnfinishedSound()
7223 PlaySound(appData.soundIcsUnfinished);
7229 PlaySound(appData.soundIcsAlarm);
7235 system("stty echo");
7241 system("stty -echo");
7245 Colorize(cc, continuation)
7250 int count, outCount, error;
7252 if (textColors[(int)cc].bg > 0) {
7253 if (textColors[(int)cc].fg > 0) {
7254 sprintf(buf, "\033[0;%d;%d;%dm", textColors[(int)cc].attr,
7255 textColors[(int)cc].fg, textColors[(int)cc].bg);
7257 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
7258 textColors[(int)cc].bg);
7261 if (textColors[(int)cc].fg > 0) {
7262 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
7263 textColors[(int)cc].fg);
7265 sprintf(buf, "\033[0;%dm", textColors[(int)cc].attr);
7268 count = strlen(buf);
7269 outCount = OutputToProcess(NoProc, buf, count, &error);
7270 if (outCount < count) {
7271 DisplayFatalError(_("Error writing to display"), error, 1);
7274 if (continuation) return;
7277 PlaySound(appData.soundShout);
7280 PlaySound(appData.soundSShout);
7283 PlaySound(appData.soundChannel1);
7286 PlaySound(appData.soundChannel);
7289 PlaySound(appData.soundKibitz);
7292 PlaySound(appData.soundTell);
7294 case ColorChallenge:
7295 PlaySound(appData.soundChallenge);
7298 PlaySound(appData.soundRequest);
7301 PlaySound(appData.soundSeek);
7312 return getpwuid(getuid())->pw_name;
7315 static char *ExpandPathName(path)
7318 static char static_buf[2000];
7319 char *d, *s, buf[2000];
7325 while (*s && isspace(*s))
7334 if (*(s+1) == '/') {
7335 strcpy(d, getpwuid(getuid())->pw_dir);
7340 *strchr(buf, '/') = 0;
7341 pwd = getpwnam(buf);
7344 fprintf(stderr, _("ERROR: Unknown user %s (in path %s)\n"),
7348 strcpy(d, pwd->pw_dir);
7349 strcat(d, strchr(s+1, '/'));
7360 static char host_name[MSG_SIZ];
7362 #if HAVE_GETHOSTNAME
7363 gethostname(host_name, MSG_SIZ);
7365 #else /* not HAVE_GETHOSTNAME */
7366 # if HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H
7367 sysinfo(SI_HOSTNAME, host_name, MSG_SIZ);
7369 # else /* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
7371 # endif/* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
7372 #endif /* not HAVE_GETHOSTNAME */
7375 XtIntervalId delayedEventTimerXID = 0;
7376 DelayedEventCallback delayedEventCallback = 0;
7381 delayedEventTimerXID = 0;
7382 delayedEventCallback();
7386 ScheduleDelayedEvent(cb, millisec)
7387 DelayedEventCallback cb; long millisec;
7389 delayedEventCallback = cb;
7390 delayedEventTimerXID =
7391 XtAppAddTimeOut(appContext, millisec,
7392 (XtTimerCallbackProc) FireDelayedEvent, (XtPointer) 0);
7395 DelayedEventCallback
7398 if (delayedEventTimerXID) {
7399 return delayedEventCallback;
7406 CancelDelayedEvent()
7408 if (delayedEventTimerXID) {
7409 XtRemoveTimeOut(delayedEventTimerXID);
7410 delayedEventTimerXID = 0;
7414 XtIntervalId loadGameTimerXID = 0;
7416 int LoadGameTimerRunning()
7418 return loadGameTimerXID != 0;
7421 int StopLoadGameTimer()
7423 if (loadGameTimerXID != 0) {
7424 XtRemoveTimeOut(loadGameTimerXID);
7425 loadGameTimerXID = 0;
7433 LoadGameTimerCallback(arg, id)
7437 loadGameTimerXID = 0;
7442 StartLoadGameTimer(millisec)
7446 XtAppAddTimeOut(appContext, millisec,
7447 (XtTimerCallbackProc) LoadGameTimerCallback,
7451 XtIntervalId analysisClockXID = 0;
7454 AnalysisClockCallback(arg, id)
7458 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile
7459 || appData.icsEngineAnalyze) { // [DM]
7460 AnalysisPeriodicEvent(0);
7461 StartAnalysisClock();
7466 StartAnalysisClock()
7469 XtAppAddTimeOut(appContext, 2000,
7470 (XtTimerCallbackProc) AnalysisClockCallback,
7474 gint clockTimerTag = 0;
7476 int ClockTimerRunning()
7478 return clockTimerTag != 0;
7481 int StopClockTimer()
7483 if (clockTimerTag != 0) {
7484 gtk_timeout_remove(clockTimerTag);
7493 ClockTimerCallback(data)
7502 StartClockTimer(millisec)
7505 clockTimerTag = gtk_timeout_add(millisec,(GtkFunction) ClockTimerCallback,NULL);
7510 DisplayTimerLabel(w, color, timer, highlight)
7519 if (appData.clockMode) {
7520 sprintf(buf, "%s: %s", color, TimeString(timer));
7522 sprintf(buf, "%s ", color);
7524 gtk_label_set_text(GTK_LABEL(w),buf);
7526 /* check for low time warning */
7527 // Pixel foregroundOrWarningColor = timerForegroundPixel;
7530 // appData.lowTimeWarning &&
7531 // (timer / 1000) < appData.icsAlarmTime)
7532 // foregroundOrWarningColor = lowTimeWarningColor;
7534 // if (appData.clockMode) {
7535 // sprintf(buf, "%s: %s", color, TimeString(timer));
7536 // XtSetArg(args[0], XtNlabel, buf);
7538 // sprintf(buf, "%s ", color);
7539 // XtSetArg(args[0], XtNlabel, buf);
7544 // XtSetArg(args[1], XtNbackground, foregroundOrWarningColor);
7545 // XtSetArg(args[2], XtNforeground, timerBackgroundPixel);
7547 // XtSetArg(args[1], XtNbackground, timerBackgroundPixel);
7548 // XtSetArg(args[2], XtNforeground, foregroundOrWarningColor);
7551 // XtSetValues(w, args, 3);
7556 DisplayWhiteClock(timeRemaining, highlight)
7560 if(appData.noGUI) return;
7562 DisplayTimerLabel(GUI_Whiteclock, _("White"), timeRemaining, highlight);
7563 if (highlight && WindowIcon == BlackIcon) {
7564 WindowIcon = WhiteIcon;
7565 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
7570 DisplayBlackClock(timeRemaining, highlight)
7574 if(appData.noGUI) return;
7575 DisplayTimerLabel(GUI_Blackclock, _("Black"), timeRemaining, highlight);
7576 if (highlight && WindowIcon == WhiteIcon) {
7577 WindowIcon = BlackIcon;
7578 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
7596 int StartChildProcess(cmdLine, dir, pr)
7603 int to_prog[2], from_prog[2];
7607 if (appData.debugMode) {
7608 fprintf(stderr, "StartChildProcess (dir=\"%s\") %s\n",dir, cmdLine);
7611 /* We do NOT feed the cmdLine to the shell; we just
7612 parse it into blank-separated arguments in the
7613 most simple-minded way possible.
7616 strcpy(buf, cmdLine);
7621 if (p == NULL) break;
7626 SetUpChildIO(to_prog, from_prog);
7628 if ((pid = fork()) == 0) {
7630 // [HGM] PSWBTM: made order resistant against case where fd of created pipe was 0 or 1
7631 close(to_prog[1]); // first close the unused pipe ends
7632 close(from_prog[0]);
7633 dup2(to_prog[0], 0); // to_prog was created first, nd is the only one to use 0 or 1
7634 dup2(from_prog[1], 1);
7635 if(to_prog[0] >= 2) close(to_prog[0]); // if 0 or 1, the dup2 already cosed the original
7636 close(from_prog[1]); // and closing again loses one of the pipes!
7637 if(fileno(stderr) >= 2) // better safe than sorry...
7638 dup2(1, fileno(stderr)); /* force stderr to the pipe */
7640 if (dir[0] != NULLCHAR && chdir(dir) != 0) {
7645 nice(appData.niceEngines); // [HGM] nice: adjust priority of engine proc
7647 execvp(argv[0], argv);
7649 /* If we get here, exec failed */
7654 /* Parent process */
7656 close(from_prog[1]);
7658 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7661 cp->fdFrom = from_prog[0];
7662 cp->fdTo = to_prog[1];
7667 // [HGM] kill: implement the 'hard killing' of AS's Winboard_x
7668 static RETSIGTYPE AlarmCallBack(int n)
7674 DestroyChildProcess(pr, signalType)
7678 ChildProc *cp = (ChildProc *) pr;
7680 if (cp->kind != CPReal) return;
7682 if (signalType == 10) { // [HGM] kill: if it does not terminate in 3 sec, kill
7683 signal(SIGALRM, AlarmCallBack);
7685 if(wait((int *) 0) == -1) { // process does not terminate on its own accord
7686 kill(cp->pid, SIGKILL); // kill it forcefully
7687 wait((int *) 0); // and wait again
7691 kill(cp->pid, signalType == 9 ? SIGKILL : SIGTERM); // [HGM] kill: use hard kill if so requested
7693 /* Process is exiting either because of the kill or because of
7694 a quit command sent by the backend; either way, wait for it to die.
7703 InterruptChildProcess(pr)
7706 ChildProc *cp = (ChildProc *) pr;
7708 if (cp->kind != CPReal) return;
7709 (void) kill(cp->pid, SIGINT); /* stop it thinking */
7712 int OpenTelnet(host, port, pr)
7717 char cmdLine[MSG_SIZ];
7719 if (port[0] == NULLCHAR) {
7720 snprintf(cmdLine, sizeof(cmdLine), "%s %s", appData.telnetProgram, host);
7722 snprintf(cmdLine, sizeof(cmdLine), "%s %s %s", appData.telnetProgram, host, port);
7724 return StartChildProcess(cmdLine, "", pr);
7727 int OpenTCP(host, port, pr)
7733 DisplayFatalError(_("Socket support is not configured in"), 0, 2);
7734 #else /* !OMIT_SOCKETS */
7736 struct sockaddr_in sa;
7738 unsigned short uport;
7741 if ((s = socket(AF_INET, SOCK_STREAM, 6)) < 0) {
7745 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
7746 sa.sin_family = AF_INET;
7747 sa.sin_addr.s_addr = INADDR_ANY;
7748 uport = (unsigned short) 0;
7749 sa.sin_port = htons(uport);
7750 if (bind(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)) < 0) {
7754 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
7755 if (!(hp = gethostbyname(host))) {
7757 if (sscanf(host, "%d.%d.%d.%d", &b0, &b1, &b2, &b3) == 4) {
7758 hp = (struct hostent *) calloc(1, sizeof(struct hostent));
7759 hp->h_addrtype = AF_INET;
7761 hp->h_addr_list = (char **) calloc(2, sizeof(char *));
7762 hp->h_addr_list[0] = (char *) malloc(4);
7763 hp->h_addr_list[0][0] = b0;
7764 hp->h_addr_list[0][1] = b1;
7765 hp->h_addr_list[0][2] = b2;
7766 hp->h_addr_list[0][3] = b3;
7771 sa.sin_family = hp->h_addrtype;
7772 uport = (unsigned short) atoi(port);
7773 sa.sin_port = htons(uport);
7774 memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);
7776 if (connect(s, (struct sockaddr *) &sa,
7777 sizeof(struct sockaddr_in)) < 0) {
7781 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7788 #endif /* !OMIT_SOCKETS */
7793 int OpenCommPort(name, pr)
7800 fd = open(name, 2, 0);
7801 if (fd < 0) return errno;
7803 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7813 int OpenLoopback(pr)
7819 SetUpChildIO(to, from);
7821 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7824 cp->fdFrom = to[0]; /* note not from[0]; we are doing a loopback */
7831 int OpenRcmd(host, user, cmd, pr)
7832 char *host, *user, *cmd;
7835 DisplayFatalError(_("internal rcmd not implemented for Unix"), 0, 1);
7839 #define INPUT_SOURCE_BUF_SIZE 8192
7848 char buf[INPUT_SOURCE_BUF_SIZE];
7853 DoInputCallback(closure, source, xid)
7858 InputSource *is = (InputSource *) closure;
7863 if (is->lineByLine) {
7864 count = read(is->fd, is->unused,
7865 INPUT_SOURCE_BUF_SIZE - (is->unused - is->buf));
7867 (is->func)(is, is->closure, is->buf, count, count ? errno : 0);
7870 is->unused += count;
7872 while (p < is->unused) {
7873 q = memchr(p, '\n', is->unused - p);
7874 if (q == NULL) break;
7876 (is->func)(is, is->closure, p, q - p, 0);
7880 while (p < is->unused) {
7885 count = read(is->fd, is->buf, INPUT_SOURCE_BUF_SIZE);
7890 (is->func)(is, is->closure, is->buf, count, error);
7894 InputSourceRef AddInputSource(pr, lineByLine, func, closure)
7901 ChildProc *cp = (ChildProc *) pr;
7903 is = (InputSource *) calloc(1, sizeof(InputSource));
7904 is->lineByLine = lineByLine;
7908 is->fd = fileno(stdin);
7910 is->kind = cp->kind;
7911 is->fd = cp->fdFrom;
7914 is->unused = is->buf;
7917 is->xid = XtAppAddInput(appContext, is->fd,
7918 (XtPointer) (XtInputReadMask),
7919 (XtInputCallbackProc) DoInputCallback,
7921 is->closure = closure;
7922 return (InputSourceRef) is;
7926 RemoveInputSource(isr)
7929 InputSource *is = (InputSource *) isr;
7931 if (is->xid == 0) return;
7932 XtRemoveInput(is->xid);
7936 int OutputToProcess(pr, message, count, outError)
7942 ChildProc *cp = (ChildProc *) pr;
7946 outCount = fwrite(message, 1, count, stdout);
7948 outCount = write(cp->fdTo, message, count);
7958 /* Output message to process, with "ms" milliseconds of delay
7959 between each character. This is needed when sending the logon
7960 script to ICC, which for some reason doesn't like the
7961 instantaneous send. */
7962 int OutputToProcessDelayed(pr, message, count, outError, msdelay)
7969 ChildProc *cp = (ChildProc *) pr;
7974 r = write(cp->fdTo, message++, 1);
7987 /**** Animation code by Hugh Fisher, DCS, ANU.
7989 Known problem: if a window overlapping the board is
7990 moved away while a piece is being animated underneath,
7991 the newly exposed area won't be updated properly.
7992 I can live with this.
7994 Known problem: if you look carefully at the animation
7995 of pieces in mono mode, they are being drawn as solid
7996 shapes without interior detail while moving. Fixing
7997 this would be a major complication for minimal return.
8000 /* Masks for XPM pieces. Black and white pieces can have
8001 different shapes, but in the interest of retaining my
8002 sanity pieces must have the same outline on both light
8003 and dark squares, and all pieces must use the same
8004 background square colors/images. */
8006 static int xpmDone = 0;
8009 CreateAnimMasks (pieceDepth)
8016 unsigned long plane;
8019 /* Need a bitmap just to get a GC with right depth */
8020 buf = XCreatePixmap(xDisplay, xBoardWindow,
8022 values.foreground = 1;
8023 values.background = 0;
8024 /* Don't use XtGetGC, not read only */
8025 maskGC = XCreateGC(xDisplay, buf,
8026 GCForeground | GCBackground, &values);
8027 XFreePixmap(xDisplay, buf);
8029 buf = XCreatePixmap(xDisplay, xBoardWindow,
8030 squareSize, squareSize, pieceDepth);
8031 values.foreground = XBlackPixel(xDisplay, xScreen);
8032 values.background = XWhitePixel(xDisplay, xScreen);
8033 bufGC = XCreateGC(xDisplay, buf,
8034 GCForeground | GCBackground, &values);
8036 for (piece = WhitePawn; piece <= BlackKing; piece++) {
8037 /* Begin with empty mask */
8038 if(!xpmDone) // [HGM] pieces: keep using existing
8039 xpmMask[piece] = XCreatePixmap(xDisplay, xBoardWindow,
8040 squareSize, squareSize, 1);
8041 XSetFunction(xDisplay, maskGC, GXclear);
8042 XFillRectangle(xDisplay, xpmMask[piece], maskGC,
8043 0, 0, squareSize, squareSize);
8045 /* Take a copy of the piece */
8050 XSetFunction(xDisplay, bufGC, GXcopy);
8051 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn],
8053 0, 0, squareSize, squareSize, 0, 0);
8055 /* XOR the background (light) over the piece */
8056 XSetFunction(xDisplay, bufGC, GXxor);
8058 XCopyArea(xDisplay, xpmLightSquare, buf, bufGC,
8059 0, 0, squareSize, squareSize, 0, 0);
8061 XSetForeground(xDisplay, bufGC, lightSquareColor);
8062 XFillRectangle(xDisplay, buf, bufGC, 0, 0, squareSize, squareSize);
8065 /* We now have an inverted piece image with the background
8066 erased. Construct mask by just selecting all the non-zero
8067 pixels - no need to reconstruct the original image. */
8068 XSetFunction(xDisplay, maskGC, GXor);
8070 /* Might be quicker to download an XImage and create bitmap
8071 data from it rather than this N copies per piece, but it
8072 only takes a fraction of a second and there is a much
8073 longer delay for loading the pieces. */
8074 for (n = 0; n < pieceDepth; n ++) {
8075 XCopyPlane(xDisplay, buf, xpmMask[piece], maskGC,
8076 0, 0, squareSize, squareSize,
8082 XFreePixmap(xDisplay, buf);
8083 XFreeGC(xDisplay, bufGC);
8084 XFreeGC(xDisplay, maskGC);
8088 InitAnimState (anim, info)
8090 XWindowAttributes * info;
8095 /* Each buffer is square size, same depth as window */
8096 anim->saveBuf = XCreatePixmap(xDisplay, xBoardWindow,
8097 squareSize, squareSize, info->depth);
8098 anim->newBuf = XCreatePixmap(xDisplay, xBoardWindow,
8099 squareSize, squareSize, info->depth);
8101 /* Create a plain GC for blitting */
8102 mask = GCForeground | GCBackground | GCFunction |
8103 GCPlaneMask | GCGraphicsExposures;
8104 values.foreground = XBlackPixel(xDisplay, xScreen);
8105 values.background = XWhitePixel(xDisplay, xScreen);
8106 values.function = GXcopy;
8107 values.plane_mask = AllPlanes;
8108 values.graphics_exposures = False;
8109 anim->blitGC = XCreateGC(xDisplay, xBoardWindow, mask, &values);
8111 /* Piece will be copied from an existing context at
8112 the start of each new animation/drag. */
8113 anim->pieceGC = XCreateGC(xDisplay, xBoardWindow, 0, &values);
8115 /* Outline will be a read-only copy of an existing */
8116 anim->outlineGC = None;
8122 static VariantClass old = (VariantClass) -1; // [HGM] pieces: redo every time variant changes
8123 XWindowAttributes info;
8125 if (xpmDone && gameInfo.variant == old) return;
8126 if(xpmDone) old = gameInfo.variant; // first time pieces might not be created yet
8127 // XGetWindowAttributes(xDisplay, xBoardWindow, &info);
8129 InitAnimState(&game, &info);
8130 InitAnimState(&player, &info);
8132 /* For XPM pieces, we need bitmaps to use as masks. */
8134 CreateAnimMasks(info.depth);
8140 static Boolean frameWaiting;
8142 static RETSIGTYPE FrameAlarm (sig)
8145 frameWaiting = False;
8146 /* In case System-V style signals. Needed?? */
8147 signal(SIGALRM, FrameAlarm);
8154 struct itimerval delay;
8156 XSync(xDisplay, False);
8159 frameWaiting = True;
8160 signal(SIGALRM, FrameAlarm);
8161 delay.it_interval.tv_sec =
8162 delay.it_value.tv_sec = time / 1000;
8163 delay.it_interval.tv_usec =
8164 delay.it_value.tv_usec = (time % 1000) * 1000;
8165 setitimer(ITIMER_REAL, &delay, NULL);
8167 /* Ugh -- busy-wait! --tpm */
8168 while (frameWaiting);
8170 while (frameWaiting) pause();
8172 delay.it_interval.tv_sec = delay.it_value.tv_sec = 0;
8173 delay.it_interval.tv_usec = delay.it_value.tv_usec = 0;
8174 setitimer(ITIMER_REAL, &delay, NULL);
8184 XSync(xDisplay, False);
8186 usleep(time * 1000);
8191 /* Convert board position to corner of screen rect and color */
8194 ScreenSquare(column, row, pt, color)
8195 int column; int row; XPoint * pt; int * color;
8198 pt->x = lineGap + ((BOARD_WIDTH-1)-column) * (squareSize + lineGap);
8199 pt->y = lineGap + row * (squareSize + lineGap);
8201 pt->x = lineGap + column * (squareSize + lineGap);
8202 pt->y = lineGap + ((BOARD_HEIGHT-1)-row) * (squareSize + lineGap);
8204 *color = SquareColor(row, column);
8207 /* Convert window coords to square */
8210 BoardSquare(x, y, column, row)
8211 int x; int y; int * column; int * row;
8213 *column = EventToSquare(x, BOARD_WIDTH);
8214 if (flipView && *column >= 0)
8215 *column = BOARD_WIDTH - 1 - *column;
8216 *row = EventToSquare(y, BOARD_HEIGHT);
8217 if (!flipView && *row >= 0)
8218 *row = BOARD_HEIGHT - 1 - *row;
8223 #undef Max /* just in case */
8225 #define Max(a, b) ((a) > (b) ? (a) : (b))
8226 #define Min(a, b) ((a) < (b) ? (a) : (b))
8229 SetRect(rect, x, y, width, height)
8230 XRectangle * rect; int x; int y; int width; int height;
8234 rect->width = width;
8235 rect->height = height;
8238 /* Test if two frames overlap. If they do, return
8239 intersection rect within old and location of
8240 that rect within new. */
8243 Intersect(old, new, size, area, pt)
8244 XPoint * old; XPoint * new;
8245 int size; XRectangle * area; XPoint * pt;
8247 if (old->x > new->x + size || new->x > old->x + size ||
8248 old->y > new->y + size || new->y > old->y + size) {
8251 SetRect(area, Max(new->x - old->x, 0), Max(new->y - old->y, 0),
8252 size - abs(old->x - new->x), size - abs(old->y - new->y));
8253 pt->x = Max(old->x - new->x, 0);
8254 pt->y = Max(old->y - new->y, 0);
8259 /* For two overlapping frames, return the rect(s)
8260 in the old that do not intersect with the new. */
8263 CalcUpdateRects(old, new, size, update, nUpdates)
8264 XPoint * old; XPoint * new; int size;
8265 XRectangle update[]; int * nUpdates;
8269 /* If old = new (shouldn't happen) then nothing to draw */
8270 if (old->x == new->x && old->y == new->y) {
8274 /* Work out what bits overlap. Since we know the rects
8275 are the same size we don't need a full intersect calc. */
8277 /* Top or bottom edge? */
8278 if (new->y > old->y) {
8279 SetRect(&(update[count]), old->x, old->y, size, new->y - old->y);
8281 } else if (old->y > new->y) {
8282 SetRect(&(update[count]), old->x, old->y + size - (old->y - new->y),
8283 size, old->y - new->y);
8286 /* Left or right edge - don't overlap any update calculated above. */
8287 if (new->x > old->x) {
8288 SetRect(&(update[count]), old->x, Max(new->y, old->y),
8289 new->x - old->x, size - abs(new->y - old->y));
8291 } else if (old->x > new->x) {
8292 SetRect(&(update[count]), new->x + size, Max(new->y, old->y),
8293 old->x - new->x, size - abs(new->y - old->y));
8300 /* Generate a series of frame coords from start->mid->finish.
8301 The movement rate doubles until the half way point is
8302 reached, then halves back down to the final destination,
8303 which gives a nice slow in/out effect. The algorithmn
8304 may seem to generate too many intermediates for short
8305 moves, but remember that the purpose is to attract the
8306 viewers attention to the piece about to be moved and
8307 then to where it ends up. Too few frames would be less
8311 Tween(start, mid, finish, factor, frames, nFrames)
8312 XPoint * start; XPoint * mid;
8313 XPoint * finish; int factor;
8314 XPoint frames[]; int * nFrames;
8316 int fraction, n, count;
8320 /* Slow in, stepping 1/16th, then 1/8th, ... */
8322 for (n = 0; n < factor; n++)
8324 for (n = 0; n < factor; n++) {
8325 frames[count].x = start->x + (mid->x - start->x) / fraction;
8326 frames[count].y = start->y + (mid->y - start->y) / fraction;
8328 fraction = fraction / 2;
8332 frames[count] = *mid;
8335 /* Slow out, stepping 1/2, then 1/4, ... */
8337 for (n = 0; n < factor; n++) {
8338 frames[count].x = finish->x - (finish->x - mid->x) / fraction;
8339 frames[count].y = finish->y - (finish->y - mid->y) / fraction;
8341 fraction = fraction * 2;
8346 /* Draw a piece on the screen without disturbing what's there */
8349 SelectGCMask(piece, clip, outline, mask)
8350 ChessSquare piece; GC * clip; GC * outline; Pixmap * mask;
8354 /* Bitmap for piece being moved. */
8355 if (appData.monoMode) {
8356 *mask = *pieceToSolid(piece);
8357 } else if (useImages) {
8359 *mask = xpmMask[piece];
8361 *mask = ximMaskPm[piece];
8364 *mask = *pieceToSolid(piece);
8367 /* GC for piece being moved. Square color doesn't matter, but
8368 since it gets modified we make a copy of the original. */
8370 if (appData.monoMode)
8375 if (appData.monoMode)
8380 XCopyGC(xDisplay, source, 0xFFFFFFFF, *clip);
8382 /* Outline only used in mono mode and is not modified */
8384 *outline = bwPieceGC;
8386 *outline = wbPieceGC;
8390 OverlayPiece(piece, clip, outline, dest)
8391 ChessSquare piece; GC clip; GC outline; Drawable dest;
8396 /* Draw solid rectangle which will be clipped to shape of piece */
8397 XFillRectangle(xDisplay, dest, clip,
8398 0, 0, squareSize, squareSize);
8399 if (appData.monoMode)
8400 /* Also draw outline in contrasting color for black
8401 on black / white on white cases */
8402 XCopyPlane(xDisplay, *pieceToOutline(piece), dest, outline,
8403 0, 0, squareSize, squareSize, 0, 0, 1);
8405 /* Copy the piece */
8410 XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
8412 0, 0, squareSize, squareSize,
8417 /* Animate the movement of a single piece */
8420 BeginAnimation(anim, piece, startColor, start)
8428 /* The old buffer is initialised with the start square (empty) */
8429 BlankSquare(0, 0, startColor, EmptySquare, anim->saveBuf);
8430 anim->prevFrame = *start;
8432 /* The piece will be drawn using its own bitmap as a matte */
8433 SelectGCMask(piece, &anim->pieceGC, &anim->outlineGC, &mask);
8434 XSetClipMask(xDisplay, anim->pieceGC, mask);
8438 AnimationFrame(anim, frame, piece)
8443 XRectangle updates[4];
8448 /* Save what we are about to draw into the new buffer */
8449 XCopyArea(xDisplay, xBoardWindow, anim->newBuf, anim->blitGC,
8450 frame->x, frame->y, squareSize, squareSize,
8453 /* Erase bits of the previous frame */
8454 if (Intersect(&anim->prevFrame, frame, squareSize, &overlap, &pt)) {
8455 /* Where the new frame overlapped the previous,
8456 the contents in newBuf are wrong. */
8457 XCopyArea(xDisplay, anim->saveBuf, anim->newBuf, anim->blitGC,
8458 overlap.x, overlap.y,
8459 overlap.width, overlap.height,
8461 /* Repaint the areas in the old that don't overlap new */
8462 CalcUpdateRects(&anim->prevFrame, frame, squareSize, updates, &count);
8463 for (i = 0; i < count; i++)
8464 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
8465 updates[i].x - anim->prevFrame.x,
8466 updates[i].y - anim->prevFrame.y,
8467 updates[i].width, updates[i].height,
8468 updates[i].x, updates[i].y);
8470 /* Easy when no overlap */
8471 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
8472 0, 0, squareSize, squareSize,
8473 anim->prevFrame.x, anim->prevFrame.y);
8476 /* Save this frame for next time round */
8477 XCopyArea(xDisplay, anim->newBuf, anim->saveBuf, anim->blitGC,
8478 0, 0, squareSize, squareSize,
8480 anim->prevFrame = *frame;
8482 /* Draw piece over original screen contents, not current,
8483 and copy entire rect. Wipes out overlapping piece images. */
8484 OverlayPiece(piece, anim->pieceGC, anim->outlineGC, anim->newBuf);
8485 XCopyArea(xDisplay, anim->newBuf, xBoardWindow, anim->blitGC,
8486 0, 0, squareSize, squareSize,
8487 frame->x, frame->y);
8491 EndAnimation (anim, finish)
8495 XRectangle updates[4];
8500 /* The main code will redraw the final square, so we
8501 only need to erase the bits that don't overlap. */
8502 if (Intersect(&anim->prevFrame, finish, squareSize, &overlap, &pt)) {
8503 CalcUpdateRects(&anim->prevFrame, finish, squareSize, updates, &count);
8504 for (i = 0; i < count; i++)
8505 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
8506 updates[i].x - anim->prevFrame.x,
8507 updates[i].y - anim->prevFrame.y,
8508 updates[i].width, updates[i].height,
8509 updates[i].x, updates[i].y);
8511 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
8512 0, 0, squareSize, squareSize,
8513 anim->prevFrame.x, anim->prevFrame.y);
8518 FrameSequence(anim, piece, startColor, start, finish, frames, nFrames)
8520 ChessSquare piece; int startColor;
8521 XPoint * start; XPoint * finish;
8522 XPoint frames[]; int nFrames;
8526 BeginAnimation(anim, piece, startColor, start);
8527 for (n = 0; n < nFrames; n++) {
8528 AnimationFrame(anim, &(frames[n]), piece);
8529 FrameDelay(appData.animSpeed);
8531 EndAnimation(anim, finish);
8534 /* Main control logic for deciding what to animate and how */
8537 AnimateMove(board, fromX, fromY, toX, toY)
8546 XPoint start, finish, mid;
8547 XPoint frames[kFactor * 2 + 1];
8548 int nFrames, startColor, endColor;
8550 /* Are we animating? */
8551 if (!appData.animate || appData.blindfold)
8554 if(board[toY][toX] == WhiteRook && board[fromY][fromX] == WhiteKing ||
8555 board[toY][toX] == BlackRook && board[fromY][fromX] == BlackKing)
8556 return; // [HGM] FRC: no animtion of FRC castlings, as to-square is not true to-square
8558 if (fromY < 0 || fromX < 0 || toX < 0 || toY < 0) return;
8559 piece = board[fromY][fromX];
8560 if (piece >= EmptySquare) return;
8565 hop = (piece == WhiteKnight || piece == BlackKnight);
8568 if (appData.debugMode) {
8569 fprintf(debugFP, hop ? _("AnimateMove: piece %d hops from %d,%d to %d,%d \n") :
8570 _("AnimateMove: piece %d slides from %d,%d to %d,%d \n"),
8571 piece, fromX, fromY, toX, toY); }
8573 ScreenSquare(fromX, fromY, &start, &startColor);
8574 ScreenSquare(toX, toY, &finish, &endColor);
8577 /* Knight: make diagonal movement then straight */
8578 if (abs(toY - fromY) < abs(toX - fromX)) {
8579 mid.x = start.x + (finish.x - start.x) / 2;
8583 mid.y = start.y + (finish.y - start.y) / 2;
8586 mid.x = start.x + (finish.x - start.x) / 2;
8587 mid.y = start.y + (finish.y - start.y) / 2;
8590 /* Don't use as many frames for very short moves */
8591 if (abs(toY - fromY) + abs(toX - fromX) <= 2)
8592 Tween(&start, &mid, &finish, kFactor - 1, frames, &nFrames);
8594 Tween(&start, &mid, &finish, kFactor, frames, &nFrames);
8595 FrameSequence(&game, piece, startColor, &start, &finish, frames, nFrames);
8597 /* Be sure end square is redrawn */
8598 damage[toY][toX] = True;
8602 DragPieceBegin(x, y)
8605 int boardX, boardY, color;
8608 /* Are we animating? */
8609 if (!appData.animateDragging || appData.blindfold)
8612 /* Figure out which square we start in and the
8613 mouse position relative to top left corner. */
8614 BoardSquare(x, y, &boardX, &boardY);
8615 player.startBoardX = boardX;
8616 player.startBoardY = boardY;
8617 ScreenSquare(boardX, boardY, &corner, &color);
8618 player.startSquare = corner;
8619 player.startColor = color;
8621 /* Start from exactly where the piece is. This can be confusing
8622 if you start dragging far from the center of the square; most
8623 or all of the piece can be over a different square from the one
8624 the mouse pointer is in. */
8625 player.mouseDelta.x = x - corner.x;
8626 player.mouseDelta.y = y - corner.y;
8628 /* As soon as we start dragging, the piece will jump slightly to
8629 be centered over the mouse pointer. */
8630 player.mouseDelta.x = squareSize/2;
8631 player.mouseDelta.y = squareSize/2;
8633 /* Initialise animation */
8634 player.dragPiece = PieceForSquare(boardX, boardY);
8636 if (player.dragPiece >= 0 && player.dragPiece < EmptySquare) {
8637 player.dragActive = True;
8638 BeginAnimation(&player, player.dragPiece, color, &corner);
8639 /* Mark this square as needing to be redrawn. Note that
8640 we don't remove the piece though, since logically (ie
8641 as seen by opponent) the move hasn't been made yet. */
8642 if(boardX == BOARD_RGHT+1 && PieceForSquare(boardX-1, boardY) > 1 ||
8643 boardX == BOARD_LEFT-2 && PieceForSquare(boardX+1, boardY) > 1)
8644 XCopyArea(xDisplay, xBoardWindow, player.saveBuf, player.blitGC,
8645 corner.x, corner.y, squareSize, squareSize,
8646 0, 0); // [HGM] zh: unstack in stead of grab
8647 damage[boardY][boardX] = True;
8649 player.dragActive = False;
8659 /* Are we animating? */
8660 if (!appData.animateDragging || appData.blindfold)
8664 if (! player.dragActive)
8666 /* Move piece, maintaining same relative position
8667 of mouse within square */
8668 corner.x = x - player.mouseDelta.x;
8669 corner.y = y - player.mouseDelta.y;
8670 AnimationFrame(&player, &corner, player.dragPiece);
8672 if (appData.highlightDragging) {
8674 BoardSquare(x, y, &boardX, &boardY);
8675 SetHighlights(fromX, fromY, boardX, boardY);
8684 int boardX, boardY, color;
8687 /* Are we animating? */
8688 if (!appData.animateDragging || appData.blindfold)
8692 if (! player.dragActive)
8694 /* Last frame in sequence is square piece is
8695 placed on, which may not match mouse exactly. */
8696 BoardSquare(x, y, &boardX, &boardY);
8697 ScreenSquare(boardX, boardY, &corner, &color);
8698 EndAnimation(&player, &corner);
8700 /* Be sure end square is redrawn */
8701 damage[boardY][boardX] = True;
8703 /* This prevents weird things happening with fast successive
8704 clicks which on my Sun at least can cause motion events
8705 without corresponding press/release. */
8706 player.dragActive = False;
8709 /* Handle expose event while piece being dragged */
8714 if (!player.dragActive || appData.blindfold)
8717 /* What we're doing: logically, the move hasn't been made yet,
8718 so the piece is still in it's original square. But visually
8719 it's being dragged around the board. So we erase the square
8720 that the piece is on and draw it at the last known drag point. */
8721 BlankSquare(player.startSquare.x, player.startSquare.y,
8722 player.startColor, EmptySquare, xBoardWindow);
8723 AnimationFrame(&player, &player.prevFrame, player.dragPiece);
8724 damage[player.startBoardY][player.startBoardX] = TRUE;
8728 SetProgramStats( FrontEndProgramStats * stats )
8731 // [HGM] done, but perhaps backend should call this directly?
8732 EngineOutputUpdate( stats );