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 },
1870 char ICSInputTranslations[] =
1871 "<Key>Return: EnterKeyProc() \n";
1873 String xboardResources[] = {
1874 "*fileName*value.translations: #override\\n <Key>Return: FileNameAction()",
1875 "*question*value.translations: #override\\n <Key>Return: AskQuestionReplyAction()",
1876 "*errorpopup*translations: #override\\n <Key>Return: ErrorPopDown()",
1880 static char *cnames[9] = { "black", "red", "green", "yellow", "blue",
1881 "magenta", "cyan", "white" };
1885 TextColors textColors[(int)NColorClasses];
1887 /* String is: "fg, bg, attr". Which is 0, 1, 2 */
1889 parse_color(str, which)
1893 char *p, buf[100], *d;
1896 if (strlen(str) > 99) /* watch bounds on buf */
1901 for (i=0; i<which; ++i) {
1908 /* Could be looking at something like:
1910 .. in which case we want to stop on a comma also */
1911 while (*p && *p != ',' && !isalpha(*p) && !isdigit(*p))
1915 return -1; /* Use default for empty field */
1918 if (which == 2 || isdigit(*p))
1921 while (*p && isalpha(*p))
1926 for (i=0; i<8; ++i) {
1927 if (!StrCaseCmp(buf, cnames[i]))
1928 return which? (i+40) : (i+30);
1930 if (!StrCaseCmp(buf, "default")) return -1;
1932 fprintf(stderr, _("%s: unrecognized color %s\n"), programName, buf);
1937 parse_cpair(cc, str)
1941 if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {
1942 fprintf(stderr, _("%s: can't parse foreground color in `%s'\n"),
1947 /* bg and attr are optional */
1948 textColors[(int)cc].bg = parse_color(str, 1);
1949 if ((textColors[(int)cc].attr = parse_color(str, 2)) < 0) {
1950 textColors[(int)cc].attr = 0;
1956 /* Arrange to catch delete-window events */
1957 Atom wm_delete_window;
1959 CatchDeleteWindow(Widget w, String procname)
1962 XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
1963 snprintf(buf, sizeof(buf), "<Message>WM_PROTOCOLS: %s() \n", procname);
1964 XtAugmentTranslations(w, XtParseTranslationTable(buf));
1970 /* this should raise the board to the top */
1971 gtk_window_present(GTK_WINDOW(GUI_Window));
1976 // eventually, all layout determining code should go into a subroutine, but until then IDSIZE remains undefined
1978 #define BoardSize int
1979 void InitDrawingSizes(BoardSize boardSize, int flags)
1980 { // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
1981 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
1983 XtGeometryResult gres;
1986 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
1987 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
1989 timerWidth = (boardWidth - sep) / 2;
1991 if (appData.titleInWindow)
1996 w = boardWidth - 2*bor;
2000 w = boardWidth - w - sep - 2*bor - 2; // WIDTH_FUDGE
2004 if(!formWidget) return;
2007 * Inhibit shell resizing.
2010 // [HGM] pieces: tailor piece bitmaps to needs of specific variant
2013 for(i=0; i<4; i++) {
2015 for(p=0; p<=(int)WhiteKing; p++)
2016 xpmPieceBitmap[i][p] = xpmPieceBitmap2[i][p]; // defaults
2017 if(gameInfo.variant == VariantShogi) {
2018 xpmPieceBitmap[i][(int)WhiteCannon] = xpmPieceBitmap2[i][(int)WhiteKing+1];
2019 xpmPieceBitmap[i][(int)WhiteNightrider] = xpmPieceBitmap2[i][(int)WhiteKing+2];
2020 xpmPieceBitmap[i][(int)WhiteSilver] = xpmPieceBitmap2[i][(int)WhiteKing+3];
2021 xpmPieceBitmap[i][(int)WhiteGrasshopper] = xpmPieceBitmap2[i][(int)WhiteKing+4];
2022 xpmPieceBitmap[i][(int)WhiteQueen] = xpmPieceBitmap2[i][(int)WhiteLance];
2025 if(gameInfo.variant == VariantGothic) {
2026 xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteSilver];
2030 // [HGM] why are thee ximMasks used at all? the ximPieceBitmaps seem to be never used!
2031 for(p=0; p<=(int)WhiteKing; p++)
2032 ximMaskPm[p] = ximMaskPm2[p]; // defaults
2033 if(gameInfo.variant == VariantShogi) {
2034 ximMaskPm[(int)WhiteCannon] = ximMaskPm2[(int)WhiteKing+1];
2035 ximMaskPm[(int)WhiteNightrider] = ximMaskPm2[(int)WhiteKing+2];
2036 ximMaskPm[(int)WhiteSilver] = ximMaskPm2[(int)WhiteKing+3];
2037 ximMaskPm[(int)WhiteGrasshopper] = ximMaskPm2[(int)WhiteKing+4];
2038 ximMaskPm[(int)WhiteQueen] = ximMaskPm2[(int)WhiteLance];
2041 if(gameInfo.variant == VariantGothic) {
2042 ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[i][(int)WhiteSilver];
2048 for(i=0; i<2; i++) {
2050 for(p=0; p<=(int)WhiteKing; p++)
2051 pieceBitmap[i][p] = pieceBitmap2[i][p]; // defaults
2052 if(gameInfo.variant == VariantShogi) {
2053 pieceBitmap[i][(int)WhiteCannon] = pieceBitmap2[i][(int)WhiteKing+1];
2054 pieceBitmap[i][(int)WhiteNightrider] = pieceBitmap2[i][(int)WhiteKing+2];
2055 pieceBitmap[i][(int)WhiteSilver] = pieceBitmap2[i][(int)WhiteKing+3];
2056 pieceBitmap[i][(int)WhiteGrasshopper] = pieceBitmap2[i][(int)WhiteKing+4];
2057 pieceBitmap[i][(int)WhiteQueen] = pieceBitmap2[i][(int)WhiteLance];
2060 if(gameInfo.variant == VariantGothic) {
2061 pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteSilver];
2077 int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
2078 XSetWindowAttributes window_attributes;
2080 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2081 XrmValue vFrom, vTo;
2082 XtGeometryResult gres;
2085 int forceMono = False;
2089 // [HGM] before anything else, expand any indirection files amongst options
2090 char *argvCopy[1000]; // 1000 seems enough
2091 char newArgs[10000]; // holds actual characters
2094 srandom(time(0)); // [HGM] book: make random truly random
2097 for(i=0; i<argc; i++) {
2098 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2099 //fprintf(stderr, "arg %s\n", argv[i]);
2100 if(argv[i][0] != '@') argvCopy[j++] = argv[i]; else {
2102 FILE *f = fopen(argv[i]+1, "rb");
2103 if(f == NULL) { fprintf(stderr, _("ignore %s\n"), argv[i]); continue; } // do not expand non-existing
2104 argvCopy[j++] = newArgs + k; // get ready for first argument from file
2105 while((c = fgetc(f)) != EOF) { // each line of file inserts 1 argument in the list
2107 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2108 newArgs[k++] = 0; // terminate current arg
2109 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2110 argvCopy[j++] = newArgs + k; // get ready for next
2112 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2125 if(appData.debugMode,1) { // OK, appData is not initialized here yet...
2126 for(i=0; i<argc; i++) fprintf(stderr, "argv[%2d] = '%s'\n", i, argv[i]);
2132 setbuf(stdout, NULL);
2133 setbuf(stderr, NULL);
2136 programName = strrchr(argv[0], '/');
2137 if (programName == NULL)
2138 programName = argv[0];
2143 XtSetLanguageProc(NULL, NULL, NULL);
2144 bindtextdomain(PACKAGE, LOCALEDIR);
2145 textdomain(PACKAGE);
2149 XtAppInitialize(&appContext, "XBoard", shellOptions,
2150 XtNumber(shellOptions),
2151 &argc, argv, xboardResources, NULL, 0);
2155 gtk_init (&argc, &argv);
2157 /* parse glade file to build widgets */
2159 builder = gtk_builder_new ();
2160 gtk_builder_add_from_file (builder, "gtk-interface.xml", NULL);
2162 /* test if everything worked ok */
2164 GUI_Window = GTK_WIDGET (gtk_builder_get_object (builder, "MainWindow"));
2165 if(!GUI_Window) printf("Error: gtk_builder didn't work!\n");
2166 GUI_Board = GTK_WIDGET (gtk_builder_get_object (builder, "Board"));
2167 if(!GUI_Board) printf("Error: gtk_builder didn't work!\n");
2168 GUI_Whiteclock = GTK_WIDGET (gtk_builder_get_object (builder, "WhiteClock"));
2169 if(!GUI_Whiteclock) printf("Error: gtk_builder didn't work!\n");
2170 GUI_Blackclock = GTK_WIDGET (gtk_builder_get_object (builder, "BlackClock"));
2171 if(!GUI_Blackclock) printf("Error: gtk_builder didn't work!\n");
2173 gtk_builder_connect_signals (builder, NULL);
2175 // don't unref the builder, since we use it to get references to widgets
2176 // g_object_unref (G_OBJECT (builder));
2178 /* end parse glade file */
2182 fprintf(stderr, _("%s: unrecognized argument %s\n"),
2183 programName, argv[1]);
2184 fprintf(stderr, "Recognized options:\n");
2185 for(i = 0; i < XtNumber(shellOptions); i++)
2187 j = fprintf(stderr, " %s%s", shellOptions[i].option,
2188 (shellOptions[i].argKind == XrmoptionSepArg
2190 if (i++ < XtNumber(shellOptions))
2192 fprintf(stderr, "%*c%s%s\n", 40 - j, ' ',
2193 shellOptions[i].option,
2194 (shellOptions[i].argKind == XrmoptionSepArg
2199 fprintf(stderr, "\n");
2205 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL)
2211 if (chdir(chessDir) != 0)
2213 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
2220 if (p == NULL) p = "/tmp";
2221 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
2222 gameCopyFilename = (char*) malloc(i);
2223 gamePasteFilename = (char*) malloc(i);
2224 snprintf(gameCopyFilename,i, "%s/.xboard%05uc.pgn", p, getpid());
2225 snprintf(gamePasteFilename,i, "%s/.xboard%05up.pgn", p, getpid());
2227 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
2228 clientResources, XtNumber(clientResources),
2231 if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) {
2232 /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */
2233 if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL) {
2234 printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile);
2237 setbuf(debugFP, NULL);
2240 /* [HGM,HR] make sure board size is acceptable */
2241 if(appData.NrFiles > BOARD_SIZE ||
2242 appData.NrRanks > BOARD_SIZE )
2243 DisplayFatalError(_("Recompile with BOARD_SIZE > 12, to support this size"), 0, 2);
2246 /* This feature does not work; animation needs a rewrite */
2247 appData.highlightDragging = FALSE;
2251 xDisplay = XtDisplay(shellWidget);
2252 xScreen = DefaultScreen(xDisplay);
2253 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
2255 gameInfo.variant = StringToVariant(appData.variant);
2256 InitPosition(FALSE);
2260 * Determine boardSize
2262 gameInfo.boardWidth = gameInfo.boardHeight = 8; // [HGM] boardsize: make sure we start as 8x8
2265 // [HGM] as long as we have not created the possibility to change size while running, start with requested size
2266 gameInfo.boardWidth = appData.NrFiles > 0 ? appData.NrFiles : 8;
2267 gameInfo.boardHeight = appData.NrRanks > 0 ? appData.NrRanks : 8;
2268 gameInfo.holdingsWidth = appData.holdingsSize > 0 ? 2 : 0;
2273 InitDrawingSizes(-1, 0); // [HGM] initsize: make this into a subroutine
2275 if (isdigit(appData.boardSize[0])) {
2276 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
2277 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
2278 &fontPxlSize, &smallLayout, &tinyLayout);
2280 fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
2281 programName, appData.boardSize);
2285 /* Find some defaults; use the nearest known size */
2286 SizeDefaults *szd, *nearest;
2287 int distance = 99999;
2288 nearest = szd = sizeDefaults;
2289 while (szd->name != NULL) {
2290 if (abs(szd->squareSize - squareSize) < distance) {
2292 distance = abs(szd->squareSize - squareSize);
2293 if (distance == 0) break;
2297 if (i < 2) lineGap = nearest->lineGap;
2298 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
2299 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
2300 if (i < 5) fontPxlSize = nearest->fontPxlSize;
2301 if (i < 6) smallLayout = nearest->smallLayout;
2302 if (i < 7) tinyLayout = nearest->tinyLayout;
2305 SizeDefaults *szd = sizeDefaults;
2306 if (*appData.boardSize == NULLCHAR) {
2307 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize ||
2308 DisplayHeight(xDisplay, xScreen) < szd->minScreenSize) {
2311 if (szd->name == NULL) szd--;
2313 while (szd->name != NULL &&
2314 StrCaseCmp(szd->name, appData.boardSize) != 0) szd++;
2315 if (szd->name == NULL) {
2316 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
2317 programName, appData.boardSize);
2321 squareSize = szd->squareSize;
2322 lineGap = szd->lineGap;
2323 clockFontPxlSize = szd->clockFontPxlSize;
2324 coordFontPxlSize = szd->coordFontPxlSize;
2325 fontPxlSize = szd->fontPxlSize;
2326 smallLayout = szd->smallLayout;
2327 tinyLayout = szd->tinyLayout;
2330 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2331 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2332 if (appData.showJail == 1) {
2333 /* Jail on top and bottom */
2334 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2335 XtSetArg(boardArgs[2], XtNheight,
2336 boardHeight + 2*(lineGap + squareSize));
2337 } else if (appData.showJail == 2) {
2339 XtSetArg(boardArgs[1], XtNwidth,
2340 boardWidth + 2*(lineGap + squareSize));
2341 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2344 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2345 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2349 * Determine what fonts to use.
2351 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
2352 clockFontID = XLoadFont(xDisplay, appData.clockFont);
2353 clockFontStruct = XQueryFont(xDisplay, clockFontID);
2354 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
2355 coordFontID = XLoadFont(xDisplay, appData.coordFont);
2356 coordFontStruct = XQueryFont(xDisplay, coordFontID);
2357 appData.font = FindFont(appData.font, fontPxlSize);
2358 countFontID = XLoadFont(xDisplay, appData.coordFont); // [HGM] holdings
2359 countFontStruct = XQueryFont(xDisplay, countFontID);
2360 // appData.font = FindFont(appData.font, fontPxlSize);
2362 xdb = XtDatabase(xDisplay);
2363 XrmPutStringResource(&xdb, "*font", appData.font);
2366 * Detect if there are not enough colors available and adapt.
2368 if (DefaultDepth(xDisplay, xScreen) <= 2) {
2369 appData.monoMode = True;
2372 if (!appData.monoMode) {
2373 vFrom.addr = (caddr_t) appData.lightSquareColor;
2374 vFrom.size = strlen(appData.lightSquareColor);
2375 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2376 if (vTo.addr == NULL) {
2377 appData.monoMode = True;
2380 lightSquareColor = *(Pixel *) vTo.addr;
2383 if (!appData.monoMode) {
2384 vFrom.addr = (caddr_t) appData.darkSquareColor;
2385 vFrom.size = strlen(appData.darkSquareColor);
2386 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2387 if (vTo.addr == NULL) {
2388 appData.monoMode = True;
2391 darkSquareColor = *(Pixel *) vTo.addr;
2394 if (!appData.monoMode) {
2395 vFrom.addr = (caddr_t) appData.whitePieceColor;
2396 vFrom.size = strlen(appData.whitePieceColor);
2397 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2398 if (vTo.addr == NULL) {
2399 appData.monoMode = True;
2402 whitePieceColor = *(Pixel *) vTo.addr;
2405 if (!appData.monoMode) {
2406 vFrom.addr = (caddr_t) appData.blackPieceColor;
2407 vFrom.size = strlen(appData.blackPieceColor);
2408 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2409 if (vTo.addr == NULL) {
2410 appData.monoMode = True;
2413 blackPieceColor = *(Pixel *) vTo.addr;
2417 if (!appData.monoMode) {
2418 vFrom.addr = (caddr_t) appData.highlightSquareColor;
2419 vFrom.size = strlen(appData.highlightSquareColor);
2420 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2421 if (vTo.addr == NULL) {
2422 appData.monoMode = True;
2425 highlightSquareColor = *(Pixel *) vTo.addr;
2429 if (!appData.monoMode) {
2430 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
2431 vFrom.size = strlen(appData.premoveHighlightColor);
2432 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2433 if (vTo.addr == NULL) {
2434 appData.monoMode = True;
2437 premoveHighlightColor = *(Pixel *) vTo.addr;
2442 fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2445 if (appData.bitmapDirectory == NULL ||
2446 appData.bitmapDirectory[0] == NULLCHAR)
2447 appData.bitmapDirectory = DEF_BITMAP_DIR;
2450 if (appData.lowTimeWarning && !appData.monoMode) {
2451 vFrom.addr = (caddr_t) appData.lowTimeWarningColor;
2452 vFrom.size = strlen(appData.lowTimeWarningColor);
2453 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2454 if (vTo.addr == NULL)
2455 appData.monoMode = True;
2457 lowTimeWarningColor = *(Pixel *) vTo.addr;
2460 if (appData.monoMode && appData.debugMode) {
2461 fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2462 (unsigned long) XWhitePixel(xDisplay, xScreen),
2463 (unsigned long) XBlackPixel(xDisplay, xScreen));
2466 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
2467 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
2468 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
2469 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
2470 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
2471 parse_cpair(ColorTell, appData.colorTell) < 0 ||
2472 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
2473 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
2474 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
2475 parse_cpair(ColorNormal, appData.colorNormal) < 0)
2477 if (appData.colorize) {
2479 _("%s: can't parse color names; disabling colorization\n"),
2482 appData.colorize = FALSE;
2484 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2485 textColors[ColorNone].attr = 0;
2487 // XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2493 layoutName = "tinyLayout";
2494 } else if (smallLayout) {
2495 layoutName = "smallLayout";
2497 layoutName = "normalLayout";
2500 if (appData.titleInWindow) {
2501 /* todo check what this appdata does */
2504 if (appData.showButtonBar) {
2505 /* TODO hide button bar if requested */
2509 * gtk set properties of widgets
2512 /* set board size */
2513 gtk_widget_set_size_request(GTK_WIDGET(GUI_Board),
2514 boardWidth,boardHeight);
2516 /* end gtk set properties of widgets */
2518 if (appData.titleInWindow)
2523 if (appData.showButtonBar)
2530 if (appData.showButtonBar)
2539 // [HGM] it seems the layout code ends here, but perhaps the color stuff is size independent and would
2540 // not need to go into InitDrawingSizes().
2543 /* set some checkboxes in the menu according to appData */
2545 if (appData.alwaysPromoteToQueen)
2546 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Always Queen")),TRUE);
2548 if (appData.animateDragging)
2549 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Animate Dragging")),TRUE);
2551 if (appData.animate)
2552 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Animate Moving")),TRUE);
2554 if (appData.autoComment)
2555 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Comment")),TRUE);
2557 if (appData.autoCallFlag)
2558 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Flag")),TRUE);
2560 if (appData.autoFlipView)
2561 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Flip View")),TRUE);
2563 if (appData.autoObserve)
2564 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Observe")),TRUE);
2566 if (appData.autoRaiseBoard)
2567 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Raise Board")),TRUE);
2569 if (appData.autoSaveGames)
2570 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Save")),TRUE);
2572 if (appData.saveGameFile[0] != NULLCHAR)
2574 /* Can't turn this off from menu */
2575 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Save")),TRUE);
2576 gtk_action_set_sensitive(GTK_ACTION (gtk_builder_get_object (builder, "menuOptions.Auto Save")),FALSE);
2579 if (appData.blindfold)
2580 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Blindfold")),TRUE);
2582 if (appData.flashCount > 0)
2583 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Flash Moves")),TRUE);
2585 if (appData.getMoveList)
2586 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Get Move List")),TRUE);
2589 if (appData.highlightDragging)
2590 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Highlight Dragging")),TRUE);
2593 if (appData.highlightLastMove)
2594 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Highlight Last Move")),TRUE);
2596 if (appData.icsAlarm)
2597 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.ICS Alarm")),TRUE);
2599 if (appData.ringBellAfterMoves)
2600 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Move Sound")),TRUE);
2602 if (appData.oldSaveStyle)
2603 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Old Save Style")),TRUE);
2605 if (appData.periodicUpdates)
2606 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Periodic Updates")),TRUE);
2608 if (appData.ponderNextMove)
2609 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Ponder Next Move")),TRUE);
2611 if (appData.popupExitMessage)
2612 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Popup Exit Message")),TRUE);
2614 if (appData.popupMoveErrors)
2615 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Popup Move Errors")),TRUE);
2617 if (appData.premove)
2618 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Premove")),TRUE);
2620 if (appData.quietPlay)
2621 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Quit Play")),TRUE);
2623 if (appData.showCoords)
2624 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Show Coords")),TRUE);
2626 if (appData.showThinking)
2627 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Show Thinking")),TRUE);
2629 if (appData.testLegality)
2630 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Test Legality")),TRUE);
2632 /* end setting check boxes */
2635 /* load square colors */
2636 SVGLightSquare = load_pixbuf("svg/LightSquare.svg",squareSize);
2637 SVGDarkSquare = load_pixbuf("svg/DarkSquare.svg",squareSize);
2638 SVGNeutralSquare = load_pixbuf("svg/NeutralSquare.svg",squareSize);
2640 /* use two icons to indicate if it is white's or black's turn */
2641 WhiteIcon = load_pixbuf("svg/icon_white.svg",0);
2642 BlackIcon = load_pixbuf("svg/icon_black.svg",0);
2643 WindowIcon = WhiteIcon;
2644 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
2646 /* do resizing to a fixed aspect ratio */
2648 printf("DEBUG: %d %d\n",boardWidth, boardHeight);
2652 GUI_SetAspectRatio(0.7);
2654 /* realize window */
2655 gtk_widget_show (GUI_Window);
2661 if (appData.animate || appData.animateDragging)
2666 if (errorExitStatus == -1) {
2667 if (appData.icsActive) {
2668 /* We now wait until we see "login:" from the ICS before
2669 sending the logon script (problems with timestamp otherwise) */
2670 /*ICSInitScript();*/
2671 if (appData.icsInputBox) ICSInputBoxPopUp();
2674 signal(SIGINT, IntSigHandler);
2675 signal(SIGTERM, IntSigHandler);
2676 if (*appData.cmailGameName != NULLCHAR) {
2677 signal(SIGUSR1, CmailSigHandler);
2680 gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes()
2684 * Create a cursor for the board widget.
2685 * (This needs to be called after the window has been created to have access to board-window)
2688 BoardCursor = gdk_cursor_new(GDK_HAND2);
2689 gdk_window_set_cursor(GUI_Board->window, BoardCursor);
2690 gdk_cursor_destroy(BoardCursor);
2695 if (appData.debugMode) fclose(debugFP); // [DM] debug
2702 if (appData.icsActive && oldICSInteractionTitle != NULL) {
2703 DisplayIcsInteractionTitle(oldICSInteractionTitle);
2705 unlink(gameCopyFilename);
2706 unlink(gamePasteFilename);
2717 CmailSigHandler(sig)
2723 signal(SIGUSR1, SIG_IGN); /* suspend handler */
2725 /* Activate call-back function CmailSigHandlerCallBack() */
2726 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
2728 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
2732 CmailSigHandlerCallBack(isr, closure, message, count, error)
2740 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
2742 /**** end signal code ****/
2752 f = fopen(appData.icsLogon, "r");
2758 strcat(buf, appData.icsLogon);
2759 f = fopen(buf, "r");
2763 ProcessICSInitScript(f);
2770 EditCommentPopDown();
2781 SetMenuEnables(enab)
2786 if (!builder) return;
2787 while (enab->name != NULL) {
2788 o = gtk_builder_get_object(builder, enab->name);
2789 if(GTK_IS_WIDGET(o))
2790 gtk_widget_set_sensitive(GTK_WIDGET (o),enab->value);
2793 if(GTK_IS_ACTION(o))
2794 gtk_action_set_sensitive(GTK_ACTION (o),enab->value);
2796 DisplayError(enab->name, 0);
2802 Enables icsEnables[] = {
2803 { "menuFile.Mail Move", False },
2804 { "menuFile.Reload CMail Message", False },
2805 { "menuMode.Machine Black", False },
2806 { "menuMode.Machine White", False },
2807 { "menuMode.Analysis Mode", False },
2808 { "menuMode.Analyze File", False },
2809 { "menuMode.Two Machines", False },
2811 { "menuHelp.Hint", False },
2812 { "menuHelp.Book", False },
2813 { "menuStep.Move Now", False },
2814 { "menuOptions.Periodic Updates", False },
2815 { "menuOptions.Hide Thinking", False },
2816 { "menuOptions.Ponder Next Move", False },
2821 Enables ncpEnables[] = {
2822 { "menuFile.Mail Move", False },
2823 { "menuFile.Reload CMail Message", False },
2824 { "menuMode.Machine White", False },
2825 { "menuMode.Machine Black", False },
2826 { "menuMode.Analysis Mode", False },
2827 { "menuMode.Analyze File", False },
2828 { "menuMode.Two Machines", False },
2829 { "menuMode.ICS Client", False },
2830 { "menuMode.ICS Input Box", False },
2831 { "Action", False },
2832 { "menuStep.Revert", False },
2833 { "menuStep.Move Now", False },
2834 { "menuStep.Retract Move", False },
2835 { "menuOptions.Auto Comment", False },
2836 { "menuOptions.Auto Flag", False },
2837 { "menuOptions.Auto Flip View", False },
2838 { "menuOptions.Auto Observe", False },
2839 { "menuOptions.Auto Raise Board", False },
2840 { "menuOptions.Get Move List", False },
2841 { "menuOptions.ICS Alarm", False },
2842 { "menuOptions.Move Sound", False },
2843 { "menuOptions.Quiet Play", False },
2844 { "menuOptions.Hide Thinking", False },
2845 { "menuOptions.Periodic Updates", False },
2846 { "menuOptions.Ponder Next Move", False },
2847 { "menuHelp.Hint", False },
2848 { "menuHelp.Book", False },
2852 Enables gnuEnables[] = {
2853 { "menuMode.ICS Client", False },
2854 { "menuMode.ICS Input Box", False },
2855 { "menuAction.Accept", False },
2856 { "menuAction.Decline", False },
2857 { "menuAction.Rematch", False },
2858 { "menuAction.Adjourn", False },
2859 { "menuAction.Stop Examining", False },
2860 { "menuAction.Stop Observing", False },
2861 { "menuStep.Revert", False },
2862 { "menuOptions.Auto Comment", False },
2863 { "menuOptions.Auto Observe", False },
2864 { "menuOptions.Auto Raise Board", False },
2865 { "menuOptions.Get Move List", False },
2866 { "menuOptions.Premove", False },
2867 { "menuOptions.Quiet Play", False },
2869 /* The next two options rely on SetCmailMode being called *after* */
2870 /* SetGNUMode so that when GNU is being used to give hints these */
2871 /* menu options are still available */
2873 { "menuFile.Mail Move", False },
2874 { "menuFile.Reload CMail Message", False },
2878 Enables cmailEnables[] = {
2880 { "menuAction.Call Flag", False },
2881 { "menuAction.Draw", True },
2882 { "menuAction.Adjourn", False },
2883 { "menuAction.Abort", False },
2884 { "menuAction.Stop Observing", False },
2885 { "menuAction.Stop Examining", False },
2886 { "menuFile.Mail Move", True },
2887 { "menuFile.Reload CMail Message", True },
2891 Enables trainingOnEnables[] = {
2892 { "menuMode.Edit Comment", False },
2893 { "menuMode.Pause", False },
2894 { "menuStep.Forward", False },
2895 { "menuStep.Backward", False },
2896 { "menuStep.Forward to End", False },
2897 { "menuStep.Back to Start", False },
2898 { "menuStep.Move Now", False },
2899 { "menuStep.Truncate Game", False },
2903 Enables trainingOffEnables[] = {
2904 { "menuMode.Edit Comment", True },
2905 { "menuMode.Pause", True },
2906 { "menuStep.Forward", True },
2907 { "menuStep.Backward", True },
2908 { "menuStep.Forward to End", True },
2909 { "menuStep.Back to Start", True },
2910 { "menuStep.Move Now", True },
2911 { "menuStep.Truncate Game", True },
2915 Enables machineThinkingEnables[] = {
2916 { "menuFile.Load Game", False },
2917 { "menuFile.Load Next Game", False },
2918 { "menuFile.Load Previous Game", False },
2919 { "menuFile.Reload Same Game", False },
2920 { "menuFile.Paste Game", False },
2921 { "menuFile.Load Position", False },
2922 { "menuFile.Load Next Position", False },
2923 { "menuFile.Load Previous Position", False },
2924 { "menuFile.Reload Same Position", False },
2925 { "menuFile.Paste Position", False },
2926 { "menuMode.Machine White", False },
2927 { "menuMode.Machine Black", False },
2928 { "menuMode.Two Machines", False },
2929 { "menuStep.Retract Move", False },
2933 Enables userThinkingEnables[] = {
2934 { "menuFile.Load Game", True },
2935 { "menuFile.Load Next Game", True },
2936 { "menuFile.Load Previous Game", True },
2937 { "menuFile.Reload Same Game", True },
2938 { "menuFile.Paste Game", True },
2939 { "menuFile.Load Position", True },
2940 { "menuFile.Load Next Position", True },
2941 { "menuFile.Load Previous Position", True },
2942 { "menuFile.Reload Same Position", True },
2943 { "menuFile.Paste Position", True },
2944 { "menuMode.Machine White", True },
2945 { "menuMode.Machine Black", True },
2946 { "menuMode.Two Machines", True },
2947 { "menuStep.Retract Move", True },
2953 SetMenuEnables(icsEnables);
2956 if (appData.zippyPlay && !appData.noChessProgram) /* [DM] icsEngineAnalyze */
2957 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
2964 SetMenuEnables(ncpEnables);
2970 SetMenuEnables(gnuEnables);
2976 SetMenuEnables(cmailEnables);
2982 SetMenuEnables(trainingOnEnables);
2983 if (appData.showButtonBar) {
2984 XtSetSensitive(buttonBarWidget, False);
2990 SetTrainingModeOff()
2992 SetMenuEnables(trainingOffEnables);
2993 if (appData.showButtonBar) {
2994 XtSetSensitive(buttonBarWidget, True);
2999 SetUserThinkingEnables()
3001 if (appData.noChessProgram) return;
3002 SetMenuEnables(userThinkingEnables);
3006 SetMachineThinkingEnables()
3008 if (appData.noChessProgram) return;
3009 SetMenuEnables(machineThinkingEnables);
3011 case MachinePlaysBlack:
3012 case MachinePlaysWhite:
3013 case TwoMachinesPlay:
3014 XtSetSensitive(XtNameToWidget(menuBarWidget,
3015 ModeToWidgetName(gameMode)), True);
3022 #define Abs(n) ((n)<0 ? -(n) : (n))
3025 * Find a font that matches "pattern" that is as close as
3026 * possible to the targetPxlSize. Prefer fonts that are k
3027 * pixels smaller to fonts that are k pixels larger. The
3028 * pattern must be in the X Consortium standard format,
3029 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
3030 * The return value should be freed with XtFree when no
3033 char *FindFont(pattern, targetPxlSize)
3037 char **fonts, *p, *best, *scalable, *scalableTail;
3038 int i, j, nfonts, minerr, err, pxlSize;
3041 char **missing_list;
3043 char *def_string, *base_fnt_lst, strInt[3];
3045 XFontStruct **fnt_list;
3047 base_fnt_lst = calloc(1, strlen(pattern) + 3);
3048 sprintf(strInt, "%d", targetPxlSize);
3049 p = strstr(pattern, "--");
3050 strncpy(base_fnt_lst, pattern, p - pattern + 2);
3051 strcat(base_fnt_lst, strInt);
3052 strcat(base_fnt_lst, strchr(p + 2, '-'));
3054 if ((fntSet = XCreateFontSet(xDisplay,
3058 &def_string)) == NULL) {
3060 fprintf(stderr, _("Unable to create font set.\n"));
3064 nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
3066 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
3068 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
3069 programName, pattern);
3077 for (i=0; i<nfonts; i++) {
3080 if (*p != '-') continue;
3082 if (*p == NULLCHAR) break;
3083 if (*p++ == '-') j++;
3085 if (j < 7) continue;
3088 scalable = fonts[i];
3091 err = pxlSize - targetPxlSize;
3092 if (Abs(err) < Abs(minerr) ||
3093 (minerr > 0 && err < 0 && -err == minerr)) {
3099 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
3100 /* If the error is too big and there is a scalable font,
3101 use the scalable font. */
3102 int headlen = scalableTail - scalable;
3103 p = (char *) XtMalloc(strlen(scalable) + 10);
3104 while (isdigit(*scalableTail)) scalableTail++;
3105 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
3107 p = (char *) XtMalloc(strlen(best) + 1);
3110 if (appData.debugMode) {
3111 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
3112 pattern, targetPxlSize, p);
3115 if (missing_count > 0)
3116 XFreeStringList(missing_list);
3117 XFreeFontSet(xDisplay, fntSet);
3119 XFreeFontNames(fonts);
3126 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
3127 | GCBackground | GCFunction | GCPlaneMask;
3128 XGCValues gc_values;
3131 gc_values.plane_mask = AllPlanes;
3132 gc_values.line_width = lineGap;
3133 gc_values.line_style = LineSolid;
3134 gc_values.function = GXcopy;
3136 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3137 gc_values.background = XWhitePixel(xDisplay, xScreen);
3138 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
3139 XSetFont(xDisplay, coordGC, coordFontID);
3141 // [HGM] make font for holdings counts (white on black0
3142 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3143 gc_values.background = XBlackPixel(xDisplay, xScreen);
3144 countGC = XtGetGC(shellWidget, value_mask, &gc_values);
3145 XSetFont(xDisplay, countGC, countFontID);
3147 if (appData.monoMode) {
3148 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3149 gc_values.background = XBlackPixel(xDisplay, xScreen);
3150 lightSquareGC = wbPieceGC
3151 = XtGetGC(shellWidget, value_mask, &gc_values);
3153 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3154 gc_values.background = XWhitePixel(xDisplay, xScreen);
3155 darkSquareGC = bwPieceGC
3156 = XtGetGC(shellWidget, value_mask, &gc_values);
3158 if (DefaultDepth(xDisplay, xScreen) == 1) {
3159 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3160 gc_values.function = GXcopyInverted;
3161 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3162 gc_values.function = GXcopy;
3163 if (XBlackPixel(xDisplay, xScreen) == 1) {
3164 bwPieceGC = darkSquareGC;
3165 wbPieceGC = copyInvertedGC;
3167 bwPieceGC = copyInvertedGC;
3168 wbPieceGC = lightSquareGC;
3172 gc_values.foreground = lightSquareColor;
3173 gc_values.background = darkSquareColor;
3174 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3176 gc_values.foreground = darkSquareColor;
3177 gc_values.background = lightSquareColor;
3178 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3180 gc_values.foreground = jailSquareColor;
3181 gc_values.background = jailSquareColor;
3182 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3184 gc_values.foreground = whitePieceColor;
3185 gc_values.background = darkSquareColor;
3186 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3188 gc_values.foreground = whitePieceColor;
3189 gc_values.background = lightSquareColor;
3190 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3192 gc_values.foreground = whitePieceColor;
3193 gc_values.background = jailSquareColor;
3194 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3196 gc_values.foreground = blackPieceColor;
3197 gc_values.background = darkSquareColor;
3198 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3200 gc_values.foreground = blackPieceColor;
3201 gc_values.background = lightSquareColor;
3202 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3204 gc_values.foreground = blackPieceColor;
3205 gc_values.background = jailSquareColor;
3206 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3213 WhitePawn, WhiteKnight, WhiteBishop, WhiteRook, WhiteQueen, WhiteKing,
3214 BlackPawn, BlackKnight, BlackBishop, BlackRook, BlackQueen, BlackKing,
3217 SVGpieces[WhitePawn] = load_pixbuf("svg/WhitePawn.svg",squareSize);
3218 SVGpieces[WhiteKnight] = load_pixbuf("svg/WhiteKnight.svg",squareSize);
3219 SVGpieces[WhiteBishop] = load_pixbuf("svg/WhiteBishop.svg",squareSize);
3220 SVGpieces[WhiteRook] = load_pixbuf("svg/WhiteRook.svg",squareSize);
3221 SVGpieces[WhiteQueen] = load_pixbuf("svg/WhiteQueen.svg",squareSize);
3222 SVGpieces[WhiteKing] = load_pixbuf("svg/WhiteKing.svg",squareSize);
3224 SVGpieces[BlackPawn] = load_pixbuf("svg/BlackPawn.svg",squareSize);
3225 SVGpieces[BlackKnight] = load_pixbuf("svg/BlackKnight.svg",squareSize);
3226 SVGpieces[BlackBishop] = load_pixbuf("svg/BlackBishop.svg",squareSize);
3227 SVGpieces[BlackRook] = load_pixbuf("svg/BlackRook.svg",squareSize);
3228 SVGpieces[BlackQueen] = load_pixbuf("svg/BlackQueen.svg",squareSize);
3229 SVGpieces[BlackKing] = load_pixbuf("svg/BlackKing.svg",squareSize);
3235 static void MenuBarSelect(w, addr, index)
3240 XtActionProc proc = (XtActionProc) addr;
3242 (proc)(NULL, NULL, NULL, NULL);
3245 void CreateMenuBarPopup(parent, name, mb)
3255 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3258 XtSetArg(args[j], XtNleftMargin, 20); j++;
3259 XtSetArg(args[j], XtNrightMargin, 20); j++;
3261 while (mi->string != NULL) {
3262 if (strcmp(mi->string, "----") == 0) {
3263 entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
3266 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string)));
3267 entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass,
3269 XtAddCallback(entry, XtNcallback,
3270 (XtCallbackProc) MenuBarSelect,
3271 (caddr_t) mi->proc);
3277 Widget CreateMenuBar(mb)
3281 Widget anchor, menuBar;
3283 char menuName[MSG_SIZ];
3286 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3287 XtSetArg(args[j], XtNvSpace, 0); j++;
3288 XtSetArg(args[j], XtNborderWidth, 0); j++;
3289 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
3290 formWidget, args, j);
3292 while (mb->name != NULL) {
3293 strcpy(menuName, "menu");
3294 strcat(menuName, mb->name);
3296 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
3299 shortName[0] = _(mb->name)[0];
3300 shortName[1] = NULLCHAR;
3301 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
3304 XtSetArg(args[j], XtNlabel, XtNewString(_(mb->name))); j++;
3307 XtSetArg(args[j], XtNborderWidth, 0); j++;
3308 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
3310 CreateMenuBarPopup(menuBar, menuName, mb);
3316 Widget CreateButtonBar(mi)
3320 Widget button, buttonBar;
3324 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3326 XtSetArg(args[j], XtNhSpace, 0); j++;
3328 XtSetArg(args[j], XtNborderWidth, 0); j++;
3329 XtSetArg(args[j], XtNvSpace, 0); j++;
3330 buttonBar = XtCreateWidget("buttonBar", boxWidgetClass,
3331 formWidget, args, j);
3333 while (mi->string != NULL) {
3336 XtSetArg(args[j], XtNinternalWidth, 2); j++;
3337 XtSetArg(args[j], XtNborderWidth, 0); j++;
3339 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string))); j++;
3340 button = XtCreateManagedWidget(mi->string, commandWidgetClass,
3341 buttonBar, args, j);
3342 XtAddCallback(button, XtNcallback,
3343 (XtCallbackProc) MenuBarSelect,
3344 (caddr_t) mi->proc);
3351 CreatePieceMenu(name, color)
3358 ChessSquare selection;
3360 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3361 boardWidget, args, 0);
3363 for (i = 0; i < PIECE_MENU_SIZE; i++) {
3364 String item = pieceMenuStrings[color][i];
3366 if (strcmp(item, "----") == 0) {
3367 entry = XtCreateManagedWidget(item, smeLineObjectClass,
3370 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3371 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3373 selection = pieceMenuTranslation[color][i];
3374 XtAddCallback(entry, XtNcallback,
3375 (XtCallbackProc) PieceMenuSelect,
3376 (caddr_t) selection);
3377 if (selection == WhitePawn || selection == BlackPawn) {
3378 XtSetArg(args[0], XtNpopupOnEntry, entry);
3379 XtSetValues(menu, args, 1);
3392 ChessSquare selection;
3394 // whitePieceMenu = CreatePieceMenu("menuW", 0);
3395 // blackPieceMenu = CreatePieceMenu("menuB", 1);
3397 // XtRegisterGrabAction(PieceMenuPopup, True,
3398 // (unsigned)(ButtonPressMask|ButtonReleaseMask),
3399 // GrabModeAsync, GrabModeAsync);
3401 // XtSetArg(args[0], XtNlabel, _("Drop"));
3402 // dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
3403 // boardWidget, args, 1);
3404 // for (i = 0; i < DROP_MENU_SIZE; i++) {
3405 // String item = dropMenuStrings[i];
3407 // if (strcmp(item, "----") == 0) {
3408 // entry = XtCreateManagedWidget(item, smeLineObjectClass,
3409 // dropMenu, NULL, 0);
3411 // XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3412 // entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3413 // dropMenu, args, 1);
3414 // selection = dropMenuTranslation[i];
3415 // XtAddCallback(entry, XtNcallback,
3416 // (XtCallbackProc) DropMenuSelect,
3417 // (caddr_t) selection);
3422 void SetupDropMenu()
3430 for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
3431 entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
3432 p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
3433 dmEnables[i].piece);
3434 XtSetSensitive(entry, p != NULL || !appData.testLegality
3435 /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
3436 && !appData.icsActive));
3438 while (p && *p++ == dmEnables[i].piece) count++;
3439 snprintf(label, sizeof(label), "%s %d", dmEnables[i].widget, count);
3441 XtSetArg(args[j], XtNlabel, label); j++;
3442 XtSetValues(entry, args, j);
3446 void PieceMenuPopup(w, event, params, num_params)
3450 Cardinal *num_params;
3453 if (event->type != ButtonPress) return;
3454 if (errorUp) ErrorPopDown();
3458 whichMenu = params[0];
3460 case IcsPlayingWhite:
3461 case IcsPlayingBlack:
3463 case MachinePlaysWhite:
3464 case MachinePlaysBlack:
3465 if (appData.testLegality &&
3466 gameInfo.variant != VariantBughouse &&
3467 gameInfo.variant != VariantCrazyhouse) return;
3469 whichMenu = "menuD";
3475 if (((pmFromX = EventToSquare(event->xbutton.x, BOARD_WIDTH)) < 0) ||
3476 ((pmFromY = EventToSquare(event->xbutton.y, BOARD_HEIGHT)) < 0)) {
3477 pmFromX = pmFromY = -1;
3481 pmFromX = BOARD_WIDTH - 1 - pmFromX;
3483 pmFromY = BOARD_HEIGHT - 1 - pmFromY;
3485 XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
3488 static void PieceMenuSelect(w, piece, junk)
3493 if (pmFromX < 0 || pmFromY < 0) return;
3494 EditPositionMenuEvent(piece, pmFromX, pmFromY);
3497 static void DropMenuSelect(w, piece, junk)
3502 if (pmFromX < 0 || pmFromY < 0) return;
3503 DropMenuEvent(piece, pmFromX, pmFromY);
3506 void WhiteClock(w, event, prms, nprms)
3512 if (gameMode == EditPosition || gameMode == IcsExamining) {
3513 SetWhiteToPlayEvent();
3514 } else if (gameMode == IcsPlayingBlack || gameMode == MachinePlaysWhite) {
3519 void BlackClock(w, event, prms, nprms)
3525 if (gameMode == EditPosition || gameMode == IcsExamining) {
3526 SetBlackToPlayEvent();
3527 } else if (gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) {
3534 * If the user selects on a border boundary, return -1; if off the board,
3535 * return -2. Otherwise map the event coordinate to the square.
3537 int EventToSquare(x, limit)
3545 if ((x % (squareSize + lineGap)) >= squareSize)
3547 x /= (squareSize + lineGap);
3553 static void do_flash_delay(msec)
3559 static void drawHighlight(file, rank, line_type)
3560 int file, rank, line_type;
3565 if (lineGap == 0 || appData.blindfold) return;
3569 x = lineGap/2 + ((BOARD_WIDTH-1)-file) *
3570 (squareSize + lineGap);
3571 y = lineGap/2 + rank * (squareSize + lineGap);
3575 x = lineGap/2 + file * (squareSize + lineGap);
3576 y = lineGap/2 + ((BOARD_HEIGHT-1)-rank) *
3577 (squareSize + lineGap);
3581 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3583 /* draw the highlight */
3584 cairo_move_to (cr, x, y);
3585 cairo_rel_line_to (cr, 0,squareSize+lineGap);
3586 cairo_rel_line_to (cr, squareSize+lineGap,0);
3587 cairo_rel_line_to (cr, 0,-squareSize-lineGap);
3588 cairo_close_path (cr);
3590 cairo_set_line_width (cr, lineGap);
3593 /* TODO: use appdata colors */
3594 case LINE_TYPE_HIGHLIGHT:
3595 cairo_set_source_rgba (cr, 1, 1, 0, 1.0);
3598 cairo_set_source_rgba (cr, 1, 0, 0, 1.0);
3600 case LINE_TYPE_NORMAL:
3602 cairo_set_source_rgba (cr, 0, 1, 0, 1.0);
3613 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
3614 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
3617 SetHighlights(fromX, fromY, toX, toY)
3618 int fromX, fromY, toX, toY;
3620 if (hi1X != fromX || hi1Y != fromY)
3622 if (hi1X >= 0 && hi1Y >= 0)
3624 drawHighlight(hi1X, hi1Y, LINE_TYPE_NORMAL);
3626 if (fromX >= 0 && fromY >= 0)
3628 drawHighlight(fromX, fromY, LINE_TYPE_HIGHLIGHT);
3631 if (hi2X != toX || hi2Y != toY)
3633 if (hi2X >= 0 && hi2Y >= 0)
3635 drawHighlight(hi2X, hi2Y, LINE_TYPE_NORMAL);
3637 if (toX >= 0 && toY >= 0)
3639 drawHighlight(toX, toY, LINE_TYPE_HIGHLIGHT);
3653 SetHighlights(-1, -1, -1, -1);
3658 SetPremoveHighlights(fromX, fromY, toX, toY)
3659 int fromX, fromY, toX, toY;
3661 if (pm1X != fromX || pm1Y != fromY)
3663 if (pm1X >= 0 && pm1Y >= 0)
3665 drawHighlight(pm1X, pm1Y, LINE_TYPE_NORMAL);
3667 if (fromX >= 0 && fromY >= 0)
3669 drawHighlight(fromX, fromY, LINE_TYPE_PRE);
3672 if (pm2X != toX || pm2Y != toY)
3674 if (pm2X >= 0 && pm2Y >= 0)
3676 drawHighlight(pm2X, pm2Y, LINE_TYPE_NORMAL);
3678 if (toX >= 0 && toY >= 0)
3680 drawHighlight(toX, toY, LINE_TYPE_PRE);
3693 ClearPremoveHighlights()
3695 SetPremoveHighlights(-1, -1, -1, -1);
3698 static void BlankSquare(x, y, color, piece, dest)
3706 pb = SVGLightSquare;
3711 case 2: /* neutral */
3713 pb = SVGNeutralSquare;
3716 gdk_draw_pixbuf(GDK_WINDOW(GUI_Board->window),NULL,pb,0,0,x,y,-1,-1, GDK_RGB_DITHER_NORMAL, 0, 0);
3719 static void DrawPiece(piece, square_color, x, y, dest)
3721 int square_color, x, y;
3724 gdk_draw_pixbuf(GDK_WINDOW(GUI_Board->window),NULL,
3725 GDK_PIXBUF(SVGpieces[piece]),0,0,x,y,-1,-1,
3726 GDK_RGB_DITHER_NORMAL, 0, 0);
3730 /* [HR] determine square color depending on chess variant. */
3731 static int SquareColor(row, column)
3736 if (gameInfo.variant == VariantXiangqi) {
3737 if (column >= 3 && column <= 5 && row >= 0 && row <= 2) {
3739 } else if (column >= 3 && column <= 5 && row >= 7 && row <= 9) {
3741 } else if (row <= 4) {
3747 square_color = ((column + row) % 2) == 1;
3750 /* [hgm] holdings: next line makes all holdings squares light */
3751 if(column < BOARD_LEFT || column >= BOARD_RGHT) square_color = 1;
3753 return square_color;
3756 void DrawSquare(row, column, piece, do_flash)
3757 int row, column, do_flash;
3760 int square_color, x, y, direction, font_ascent, font_descent;
3763 XCharStruct overall;
3766 /* Calculate delay in milliseconds (2-delays per complete flash) */
3767 flash_delay = 500 / appData.flashRate;
3769 /* calculate x and y coordinates from row and column */
3772 x = lineGap + ((BOARD_WIDTH-1)-column) *
3773 (squareSize + lineGap);
3774 y = lineGap + row * (squareSize + lineGap);
3778 x = lineGap + column * (squareSize + lineGap);
3779 y = lineGap + ((BOARD_HEIGHT-1)-row) *
3780 (squareSize + lineGap);
3783 square_color = SquareColor(row, column);
3785 // [HGM] holdings: blank out area between board and holdings
3786 if ( column == BOARD_LEFT-1 || column == BOARD_RGHT
3787 || (column == BOARD_LEFT-2 && row < BOARD_HEIGHT-gameInfo.holdingsSize)
3788 || (column == BOARD_RGHT+1 && row >= gameInfo.holdingsSize) )
3790 BlankSquare(x, y, 2, EmptySquare, xBoardWindow);
3792 // [HGM] print piece counts next to holdings
3793 string[1] = NULLCHAR;
3794 if (column == (flipView ? BOARD_LEFT-1 : BOARD_RGHT) && piece > 1 )
3796 string[0] = '0' + piece;
3797 XTextExtents(countFontStruct, string, 1, &direction,
3798 &font_ascent, &font_descent, &overall);
3799 if (appData.monoMode)
3801 XDrawImageString(xDisplay, xBoardWindow, countGC,
3802 x + squareSize - overall.width - 2,
3803 y + font_ascent + 1, string, 1);
3807 XDrawString(xDisplay, xBoardWindow, countGC,
3808 x + squareSize - overall.width - 2,
3809 y + font_ascent + 1, string, 1);
3812 if (column == (flipView ? BOARD_RGHT : BOARD_LEFT-1) && piece > 1)
3814 string[0] = '0' + piece;
3815 XTextExtents(countFontStruct, string, 1, &direction,
3816 &font_ascent, &font_descent, &overall);
3817 if (appData.monoMode)
3819 XDrawImageString(xDisplay, xBoardWindow, countGC,
3820 x + 2, y + font_ascent + 1, string, 1);
3824 XDrawString(xDisplay, xBoardWindow, countGC,
3825 x + 2, y + font_ascent + 1, string, 1);
3831 /* square on the board */
3832 if (piece == EmptySquare || appData.blindfold)
3834 BlankSquare(x, y, square_color, piece, xBoardWindow);
3838 if (do_flash && appData.flashCount > 0)
3840 for (i=0; i<appData.flashCount; ++i)
3843 DrawPiece(piece, square_color, x, y, xBoardWindow);
3844 do_flash_delay(flash_delay);
3846 BlankSquare(x, y, square_color, piece, xBoardWindow);
3847 do_flash_delay(flash_delay);
3850 DrawPiece(piece, square_color, x, y, xBoardWindow);
3854 /* show coordinates if necessary */
3855 string[1] = NULLCHAR;
3856 if (appData.showCoords && row == (flipView ? BOARD_HEIGHT-1 : 0)
3857 && column >= BOARD_LEFT && column < BOARD_RGHT)
3859 string[0] = 'a' + column - BOARD_LEFT;
3860 XTextExtents(coordFontStruct, string, 1, &direction,
3861 &font_ascent, &font_descent, &overall);
3862 if (appData.monoMode)
3864 XDrawImageString(xDisplay, xBoardWindow, coordGC,
3865 x + squareSize - overall.width - 2,
3866 y + squareSize - font_descent - 1, string, 1);
3870 XDrawString(xDisplay, xBoardWindow, coordGC,
3871 x + squareSize - overall.width - 2,
3872 y + squareSize - font_descent - 1, string, 1);
3875 if (appData.showCoords && column == (flipView ? BOARD_RGHT-1 : BOARD_LEFT))
3877 string[0] = ONE + row;
3878 XTextExtents(coordFontStruct, string, 1, &direction,
3879 &font_ascent, &font_descent, &overall);
3880 if (appData.monoMode)
3882 XDrawImageString(xDisplay, xBoardWindow, coordGC,
3883 x + 2, y + font_ascent + 1, string, 1);
3887 XDrawString(xDisplay, xBoardWindow, coordGC,
3888 x + 2, y + font_ascent + 1, string, 1);
3896 /* Returns 1 if there are "too many" differences between b1 and b2
3897 (i.e. more than 1 move was made) */
3898 static int too_many_diffs(b1, b2)
3904 for (i=0; i<BOARD_HEIGHT; ++i) {
3905 for (j=0; j<BOARD_WIDTH; ++j) {
3906 if (b1[i][j] != b2[i][j]) {
3907 if (++c > 4) /* Castling causes 4 diffs */
3916 /* Matrix describing castling maneuvers */
3917 /* Row, ColRookFrom, ColKingFrom, ColRookTo, ColKingTo */
3918 static int castling_matrix[4][5] = {
3919 { 0, 0, 4, 3, 2 }, /* 0-0-0, white */
3920 { 0, 7, 4, 5, 6 }, /* 0-0, white */
3921 { 7, 0, 4, 3, 2 }, /* 0-0-0, black */
3922 { 7, 7, 4, 5, 6 } /* 0-0, black */
3925 /* Checks whether castling occurred. If it did, *rrow and *rcol
3926 are set to the destination (row,col) of the rook that moved.
3928 Returns 1 if castling occurred, 0 if not.
3930 Note: Only handles a max of 1 castling move, so be sure
3931 to call too_many_diffs() first.
3933 static int check_castle_draw(newb, oldb, rrow, rcol)
3940 /* For each type of castling... */
3941 for (i=0; i<4; ++i) {
3942 r = castling_matrix[i];
3944 /* Check the 4 squares involved in the castling move */
3946 for (j=1; j<=4; ++j) {
3947 if (newb[r[0]][r[j]] == oldb[r[0]][r[j]]) {
3954 /* All 4 changed, so it must be a castling move */
3963 static int damage[BOARD_SIZE][BOARD_SIZE];
3966 * event handler for redrawing the board
3968 void DrawPosition( repaint, board)
3969 /*Boolean*/int repaint;
3973 static int lastFlipView = 0;
3974 static int lastBoardValid = 0;
3975 static Board lastBoard;
3979 if (board == NULL) {
3980 if (!lastBoardValid) return;
3983 if (!lastBoardValid || lastFlipView != flipView) {
3984 XtSetArg(args[0], XtNleftBitmap, (flipView ? xMarkPixmap : None));
3985 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flip View"),
3990 * It would be simpler to clear the window with XClearWindow()
3991 * but this causes a very distracting flicker.
3994 if (!repaint && lastBoardValid && lastFlipView == flipView)
3996 /* If too much changes (begin observing new game, etc.), don't
3998 do_flash = too_many_diffs(board, lastBoard) ? 0 : 1;
4000 /* Special check for castling so we don't flash both the king
4001 and the rook (just flash the king). */
4004 if (check_castle_draw(board, lastBoard, &rrow, &rcol))
4006 /* Draw rook with NO flashing. King will be drawn flashing later */
4007 DrawSquare(rrow, rcol, board[rrow][rcol], 0);
4008 lastBoard[rrow][rcol] = board[rrow][rcol];
4012 /* First pass -- Draw (newly) empty squares and repair damage.
4013 This prevents you from having a piece show up twice while it
4014 is flashing on its new square */
4015 for (i = 0; i < BOARD_HEIGHT; i++)
4016 for (j = 0; j < BOARD_WIDTH; j++)
4017 if ((board[i][j] != lastBoard[i][j] && board[i][j] == EmptySquare)
4020 DrawSquare(i, j, board[i][j], 0);
4021 damage[i][j] = False;
4024 /* Second pass -- Draw piece(s) in new position and flash them */
4025 for (i = 0; i < BOARD_HEIGHT; i++)
4026 for (j = 0; j < BOARD_WIDTH; j++)
4027 if (board[i][j] != lastBoard[i][j])
4029 DrawSquare(i, j, board[i][j], do_flash);
4041 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
4043 cairo_set_line_width (cr, lineGap);
4045 /* TODO: use appdata colors */
4046 cairo_set_source_rgba (cr, 0, 1, 0, 1.0);
4050 for (i = 0; i < BOARD_HEIGHT + 1; i++)
4053 x2 = lineGap + BOARD_WIDTH * (squareSize + lineGap);
4054 y1 = y2 = lineGap / 2 + (i * (squareSize + lineGap));
4056 cairo_move_to (cr, x1, y1);
4057 cairo_rel_line_to (cr, x2,0);
4061 for (j = 0; j < BOARD_WIDTH + 1; j++)
4064 y2 = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
4065 x1 = x2 = lineGap / 2 + (j * (squareSize + lineGap));
4067 cairo_move_to (cr, x1, y1);
4068 cairo_rel_line_to (cr, 0, y2);
4077 for (i = 0; i < BOARD_HEIGHT; i++)
4078 for (j = 0; j < BOARD_WIDTH; j++)
4080 DrawSquare(i, j, board[i][j], 0);
4081 damage[i][j] = False;
4085 CopyBoard(lastBoard, board);
4087 lastFlipView = flipView;
4089 /* Draw highlights */
4090 if (pm1X >= 0 && pm1Y >= 0)
4092 drawHighlight(pm1X, pm1Y, LINE_TYPE_PRE);
4094 if (pm2X >= 0 && pm2Y >= 0)
4096 drawHighlight(pm2X, pm2Y, LINE_TYPE_PRE);
4098 if (hi1X >= 0 && hi1Y >= 0)
4100 drawHighlight(hi1X, hi1Y, LINE_TYPE_HIGHLIGHT);
4102 if (hi2X >= 0 && hi2Y >= 0)
4104 drawHighlight(hi2X, hi2Y, LINE_TYPE_HIGHLIGHT);
4107 /* If piece being dragged around board, must redraw that too */
4113 * event handler for redrawing the board
4115 void DrawPositionProc(w, event, prms, nprms)
4121 DrawPosition(True, NULL);
4126 * event handler for parsing user moves
4128 // [HGM] This routine will need quite some reworking. Although the backend still supports the old
4129 // way of doing things, by calling UserMoveEvent() to test the legality of the move and then perform
4130 // it at the end, and doing all kind of preliminary tests here (e.g. to weed out self-captures), it
4131 // should be made to use the new way, of calling UserMoveTest early to determine the legality of the
4132 // move, (which will weed out the illegal selfcaptures and moves into the holdings, and flag promotions),
4133 // and at the end FinishMove() to perform the move after optional promotion popups.
4134 // For now I patched it to allow self-capture with King, and suppress clicks between board and holdings.
4135 void HandleUserMove(w, event, prms, nprms)
4142 Boolean saveAnimate;
4143 static int second = 0;
4145 if (w != boardWidget || errorExitStatus != -1) return;
4147 if (event->type == ButtonPress) ErrorPopDown();
4150 if (event->type == ButtonPress) {
4151 XtPopdown(promotionShell);
4152 XtDestroyWidget(promotionShell);
4153 promotionUp = False;
4161 x = EventToSquare(event->xbutton.x, BOARD_WIDTH);
4162 y = EventToSquare(event->xbutton.y, BOARD_HEIGHT);
4163 if (!flipView && y >= 0) {
4164 y = BOARD_HEIGHT - 1 - y;
4166 if (flipView && x >= 0) {
4167 x = BOARD_WIDTH - 1 - x;
4170 /* [HGM] holdings: next 5 lines: ignore all clicks between board and holdings */
4171 if(event->type == ButtonPress
4172 && ( x == BOARD_LEFT-1 || x == BOARD_RGHT
4173 || x == BOARD_LEFT-2 && y < BOARD_HEIGHT-gameInfo.holdingsSize
4174 || x == BOARD_RGHT+1 && y >= gameInfo.holdingsSize) )
4178 if (event->type == ButtonPress) {
4180 if (OKToStartUserMove(x, y)) {
4184 DragPieceBegin(event->xbutton.x, event->xbutton.y);
4185 if (appData.highlightDragging) {
4186 SetHighlights(x, y, -1, -1);
4194 if (event->type == ButtonPress && gameMode != EditPosition &&
4199 /* Check if clicking again on the same color piece */
4200 fromP = boards[currentMove][fromY][fromX];
4201 toP = boards[currentMove][y][x];
4202 if ((WhitePawn <= fromP && fromP < WhiteKing && // [HGM] this test should go, as UserMoveTest now does it.
4203 WhitePawn <= toP && toP <= WhiteKing) || // For now I made it less critical by exempting King
4204 (BlackPawn <= fromP && fromP < BlackKing && // moves, to not interfere with FRC castlings.
4205 BlackPawn <= toP && toP <= BlackKing)) {
4206 /* Clicked again on same color piece -- changed his mind */
4207 second = (x == fromX && y == fromY);
4208 if (appData.highlightDragging) {
4209 SetHighlights(x, y, -1, -1);
4213 if (OKToStartUserMove(x, y)) {
4216 DragPieceBegin(event->xbutton.x, event->xbutton.y);
4222 if (event->type == ButtonRelease && x == fromX && y == fromY) {
4223 DragPieceEnd(event->xbutton.x, event->xbutton.y);
4224 if (appData.animateDragging) {
4225 /* Undo animation damage if any */
4226 DrawPosition(FALSE, NULL);
4229 /* Second up/down in same square; just abort move */
4234 ClearPremoveHighlights();
4236 /* First upclick in same square; start click-click mode */
4237 SetHighlights(x, y, -1, -1);
4242 /* Completed move */
4245 saveAnimate = appData.animate;
4246 if (event->type == ButtonPress) {
4247 /* Finish clickclick move */
4248 if (appData.animate || appData.highlightLastMove) {
4249 SetHighlights(fromX, fromY, toX, toY);
4254 /* Finish drag move */
4255 if (appData.highlightLastMove) {
4256 SetHighlights(fromX, fromY, toX, toY);
4260 DragPieceEnd(event->xbutton.x, event->xbutton.y);
4261 /* Don't animate move and drag both */
4262 appData.animate = FALSE;
4264 if (IsPromotion(fromX, fromY, toX, toY)) {
4265 if (appData.alwaysPromoteToQueen) {
4266 UserMoveEvent(fromX, fromY, toX, toY, 'q');
4267 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
4268 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
4271 SetHighlights(fromX, fromY, toX, toY);
4275 UserMoveEvent(fromX, fromY, toX, toY, NULLCHAR);
4276 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
4277 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
4280 appData.animate = saveAnimate;
4281 if (appData.animate || appData.animateDragging) {
4282 /* Undo animation damage if needed */
4283 DrawPosition(FALSE, NULL);
4287 void AnimateUserMove (Widget w, XEvent * event,
4288 String * params, Cardinal * nParams)
4290 DragPieceMove(event->xmotion.x, event->xmotion.y);
4293 Widget CommentCreate(name, text, mutable, callback, lines)
4295 int /*Boolean*/ mutable;
4296 XtCallbackProc callback;
4300 Widget shell, layout, form, edit, b_ok, b_cancel, b_clear, b_close, b_edit;
4305 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4306 XtGetValues(boardWidget, args, j);
4309 XtSetArg(args[j], XtNresizable, True); j++;
4312 XtCreatePopupShell(name, topLevelShellWidgetClass,
4313 shellWidget, args, j);
4316 XtCreatePopupShell(name, transientShellWidgetClass,
4317 shellWidget, args, j);
4320 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
4321 layoutArgs, XtNumber(layoutArgs));
4323 XtCreateManagedWidget("form", formWidgetClass, layout,
4324 formArgs, XtNumber(formArgs));
4328 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
4329 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
4331 XtSetArg(args[j], XtNstring, text); j++;
4332 XtSetArg(args[j], XtNtop, XtChainTop); j++;
4333 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4334 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4335 XtSetArg(args[j], XtNright, XtChainRight); j++;
4336 XtSetArg(args[j], XtNresizable, True); j++;
4337 XtSetArg(args[j], XtNwidth, bw_width); j++; /*force wider than buttons*/
4339 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
4341 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
4342 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
4344 XtSetArg(args[j], XtNautoFill, True); j++;
4345 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
4347 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
4351 XtSetArg(args[j], XtNfromVert, edit); j++;
4352 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4353 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4354 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4355 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4357 XtCreateManagedWidget(_("ok"), commandWidgetClass, form, args, j);
4358 XtAddCallback(b_ok, XtNcallback, callback, (XtPointer) 0);
4361 XtSetArg(args[j], XtNfromVert, edit); j++;
4362 XtSetArg(args[j], XtNfromHoriz, b_ok); j++;
4363 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4364 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4365 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4366 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4368 XtCreateManagedWidget(_("cancel"), commandWidgetClass, form, args, j);
4369 XtAddCallback(b_cancel, XtNcallback, callback, (XtPointer) 0);
4372 XtSetArg(args[j], XtNfromVert, edit); j++;
4373 XtSetArg(args[j], XtNfromHoriz, b_cancel); j++;
4374 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4375 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4376 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4377 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4379 XtCreateManagedWidget(_("clear"), commandWidgetClass, form, args, j);
4380 XtAddCallback(b_clear, XtNcallback, callback, (XtPointer) 0);
4383 XtSetArg(args[j], XtNfromVert, edit); j++;
4384 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4385 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4386 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4387 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4389 XtCreateManagedWidget(_("close"), commandWidgetClass, form, args, j);
4390 XtAddCallback(b_close, XtNcallback, callback, (XtPointer) 0);
4393 XtSetArg(args[j], XtNfromVert, edit); j++;
4394 XtSetArg(args[j], XtNfromHoriz, b_close); j++;
4395 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4396 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4397 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4398 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4400 XtCreateManagedWidget(_("edit"), commandWidgetClass, form, args, j);
4401 XtAddCallback(b_edit, XtNcallback, callback, (XtPointer) 0);
4404 XtRealizeWidget(shell);
4406 if (commentX == -1) {
4409 Dimension pw_height;
4410 Dimension ew_height;
4413 XtSetArg(args[j], XtNheight, &ew_height); j++;
4414 XtGetValues(edit, args, j);
4417 XtSetArg(args[j], XtNheight, &pw_height); j++;
4418 XtGetValues(shell, args, j);
4419 commentH = pw_height + (lines - 1) * ew_height;
4420 commentW = bw_width - 16;
4422 XSync(xDisplay, False);
4424 /* This code seems to tickle an X bug if it is executed too soon
4425 after xboard starts up. The coordinates get transformed as if
4426 the main window was positioned at (0, 0).
4428 XtTranslateCoords(shellWidget,
4429 (bw_width - commentW) / 2, 0 - commentH / 2,
4430 &commentX, &commentY);
4432 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
4433 RootWindowOfScreen(XtScreen(shellWidget)),
4434 (bw_width - commentW) / 2, 0 - commentH / 2,
4439 if (commentY < 0) commentY = 0; /*avoid positioning top offscreen*/
4442 XtSetArg(args[j], XtNheight, commentH); j++;
4443 XtSetArg(args[j], XtNwidth, commentW); j++;
4444 XtSetArg(args[j], XtNx, commentX); j++;
4445 XtSetArg(args[j], XtNy, commentY); j++;
4446 XtSetValues(shell, args, j);
4447 XtSetKeyboardFocus(shell, edit);
4452 /* Used for analysis window and ICS input window */
4453 Widget MiscCreate(name, text, mutable, callback, lines)
4455 int /*Boolean*/ mutable;
4456 XtCallbackProc callback;
4460 Widget shell, layout, form, edit;
4462 Dimension bw_width, pw_height, ew_height, w, h;
4468 XtSetArg(args[j], XtNresizable, True); j++;
4471 XtCreatePopupShell(name, topLevelShellWidgetClass,
4472 shellWidget, args, j);
4475 XtCreatePopupShell(name, transientShellWidgetClass,
4476 shellWidget, args, j);
4479 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
4480 layoutArgs, XtNumber(layoutArgs));
4482 XtCreateManagedWidget("form", formWidgetClass, layout,
4483 formArgs, XtNumber(formArgs));
4487 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
4488 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
4490 XtSetArg(args[j], XtNstring, text); j++;
4491 XtSetArg(args[j], XtNtop, XtChainTop); j++;
4492 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4493 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4494 XtSetArg(args[j], XtNright, XtChainRight); j++;
4495 XtSetArg(args[j], XtNresizable, True); j++;
4497 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
4499 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
4500 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
4502 XtSetArg(args[j], XtNautoFill, True); j++;
4503 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
4505 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
4507 XtRealizeWidget(shell);
4510 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4511 XtGetValues(boardWidget, args, j);
4514 XtSetArg(args[j], XtNheight, &ew_height); j++;
4515 XtGetValues(edit, args, j);
4518 XtSetArg(args[j], XtNheight, &pw_height); j++;
4519 XtGetValues(shell, args, j);
4520 h = pw_height + (lines - 1) * ew_height;
4523 XSync(xDisplay, False);
4525 /* This code seems to tickle an X bug if it is executed too soon
4526 after xboard starts up. The coordinates get transformed as if
4527 the main window was positioned at (0, 0).
4529 XtTranslateCoords(shellWidget, (bw_width - w) / 2, 0 - h / 2, &x, &y);
4531 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
4532 RootWindowOfScreen(XtScreen(shellWidget)),
4533 (bw_width - w) / 2, 0 - h / 2, &xx, &yy, &junk);
4537 if (y < 0) y = 0; /*avoid positioning top offscreen*/
4540 XtSetArg(args[j], XtNheight, h); j++;
4541 XtSetArg(args[j], XtNwidth, w); j++;
4542 XtSetArg(args[j], XtNx, x); j++;
4543 XtSetArg(args[j], XtNy, y); j++;
4544 XtSetValues(shell, args, j);
4550 static int savedIndex; /* gross that this is global */
4552 void EditCommentPopUp(index, title, text)
4561 if (text == NULL) text = "";
4563 if (editShell == NULL) {
4565 CommentCreate(title, text, True, EditCommentCallback, 4);
4566 XtRealizeWidget(editShell);
4567 CatchDeleteWindow(editShell, "EditCommentPopDown");
4569 edit = XtNameToWidget(editShell, "*form.text");
4571 XtSetArg(args[j], XtNstring, text); j++;
4572 XtSetValues(edit, args, j);
4574 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4575 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4576 XtSetValues(editShell, args, j);
4579 XtPopup(editShell, XtGrabNone);
4583 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
4584 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
4588 void EditCommentCallback(w, client_data, call_data)
4590 XtPointer client_data, call_data;
4598 XtSetArg(args[j], XtNlabel, &name); j++;
4599 XtGetValues(w, args, j);
4601 if (strcmp(name, _("ok")) == 0) {
4602 edit = XtNameToWidget(editShell, "*form.text");
4604 XtSetArg(args[j], XtNstring, &val); j++;
4605 XtGetValues(edit, args, j);
4606 ReplaceComment(savedIndex, val);
4607 EditCommentPopDown();
4608 } else if (strcmp(name, _("cancel")) == 0) {
4609 EditCommentPopDown();
4610 } else if (strcmp(name, _("clear")) == 0) {
4611 edit = XtNameToWidget(editShell, "*form.text");
4612 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
4613 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
4617 void EditCommentPopDown()
4622 if (!editUp) return;
4624 XtSetArg(args[j], XtNx, &commentX); j++;
4625 XtSetArg(args[j], XtNy, &commentY); j++;
4626 XtSetArg(args[j], XtNheight, &commentH); j++;
4627 XtSetArg(args[j], XtNwidth, &commentW); j++;
4628 XtGetValues(editShell, args, j);
4629 XtPopdown(editShell);
4632 XtSetArg(args[j], XtNleftBitmap, None); j++;
4633 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
4637 void ICSInputBoxPopUp()
4642 char *title = _("ICS Input");
4645 if (ICSInputShell == NULL) {
4646 ICSInputShell = MiscCreate(title, "", True, NULL, 1);
4647 tr = XtParseTranslationTable(ICSInputTranslations);
4648 edit = XtNameToWidget(ICSInputShell, "*form.text");
4649 XtOverrideTranslations(edit, tr);
4650 XtRealizeWidget(ICSInputShell);
4651 CatchDeleteWindow(ICSInputShell, "ICSInputBoxPopDown");
4654 edit = XtNameToWidget(ICSInputShell, "*form.text");
4656 XtSetArg(args[j], XtNstring, ""); j++;
4657 XtSetValues(edit, args, j);
4659 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4660 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4661 XtSetValues(ICSInputShell, args, j);
4664 XtPopup(ICSInputShell, XtGrabNone);
4665 XtSetKeyboardFocus(ICSInputShell, edit);
4667 ICSInputBoxUp = True;
4669 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
4670 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
4674 void ICSInputSendText()
4681 edit = XtNameToWidget(ICSInputShell, "*form.text");
4683 XtSetArg(args[j], XtNstring, &val); j++;
4684 XtGetValues(edit, args, j);
4685 SendMultiLineToICS(val);
4686 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
4687 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
4690 void ICSInputBoxPopDown()
4695 if (!ICSInputBoxUp) return;
4697 XtPopdown(ICSInputShell);
4698 ICSInputBoxUp = False;
4700 XtSetArg(args[j], XtNleftBitmap, None); j++;
4701 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
4705 void CommentPopUp(title, text)
4712 if (commentShell == NULL) {
4714 CommentCreate(title, text, False, CommentCallback, 4);
4715 XtRealizeWidget(commentShell);
4716 CatchDeleteWindow(commentShell, "CommentPopDown");
4718 edit = XtNameToWidget(commentShell, "*form.text");
4720 XtSetArg(args[j], XtNstring, text); j++;
4721 XtSetValues(edit, args, j);
4723 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4724 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4725 XtSetValues(commentShell, args, j);
4728 XtPopup(commentShell, XtGrabNone);
4729 XSync(xDisplay, False);
4734 void AnalysisPopUp(title, text)
4741 if (analysisShell == NULL) {
4742 analysisShell = MiscCreate(title, text, False, NULL, 4);
4743 XtRealizeWidget(analysisShell);
4744 CatchDeleteWindow(analysisShell, "AnalysisPopDown");
4747 edit = XtNameToWidget(analysisShell, "*form.text");
4749 XtSetArg(args[j], XtNstring, text); j++;
4750 XtSetValues(edit, args, j);
4752 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4753 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4754 XtSetValues(analysisShell, args, j);
4758 XtPopup(analysisShell, XtGrabNone);
4760 XSync(xDisplay, False);
4765 void CommentCallback(w, client_data, call_data)
4767 XtPointer client_data, call_data;
4774 XtSetArg(args[j], XtNlabel, &name); j++;
4775 XtGetValues(w, args, j);
4777 if (strcmp(name, _("close")) == 0) {
4779 } else if (strcmp(name, _("edit")) == 0) {
4786 void CommentPopDown()
4791 if (!commentUp) return;
4793 XtSetArg(args[j], XtNx, &commentX); j++;
4794 XtSetArg(args[j], XtNy, &commentY); j++;
4795 XtSetArg(args[j], XtNwidth, &commentW); j++;
4796 XtSetArg(args[j], XtNheight, &commentH); j++;
4797 XtGetValues(commentShell, args, j);
4798 XtPopdown(commentShell);
4799 XSync(xDisplay, False);
4803 void AnalysisPopDown()
4805 if (!analysisUp) return;
4806 XtPopdown(analysisShell);
4807 XSync(xDisplay, False);
4809 if (appData.icsEngineAnalyze) ExitAnalyzeMode(); /* [DM] icsEngineAnalyze */
4813 void FileNamePopUp(label, def, proc, openMode)
4820 Widget popup, layout, dialog, edit;
4826 fileProc = proc; /* I can't see a way not */
4827 fileOpenMode = openMode; /* to use globals here */
4830 XtSetArg(args[i], XtNresizable, True); i++;
4831 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
4832 XtSetArg(args[i], XtNtitle, XtNewString(_("File name prompt"))); i++;
4833 fileNameShell = popup =
4834 XtCreatePopupShell("File name prompt", transientShellWidgetClass,
4835 shellWidget, args, i);
4838 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
4839 layoutArgs, XtNumber(layoutArgs));
4842 XtSetArg(args[i], XtNlabel, label); i++;
4843 XtSetArg(args[i], XtNvalue, def); i++;
4844 XtSetArg(args[i], XtNborderWidth, 0); i++;
4845 dialog = XtCreateManagedWidget("fileName", dialogWidgetClass,
4848 XawDialogAddButton(dialog, _("ok"), FileNameCallback, (XtPointer) dialog);
4849 XawDialogAddButton(dialog, _("cancel"), FileNameCallback,
4850 (XtPointer) dialog);
4852 XtRealizeWidget(popup);
4853 CatchDeleteWindow(popup, "FileNamePopDown");
4855 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
4856 &x, &y, &win_x, &win_y, &mask);
4858 XtSetArg(args[0], XtNx, x - 10);
4859 XtSetArg(args[1], XtNy, y - 30);
4860 XtSetValues(popup, args, 2);
4862 XtPopup(popup, XtGrabExclusive);
4865 edit = XtNameToWidget(dialog, "*value");
4866 XtSetKeyboardFocus(popup, edit);
4869 void FileNamePopDown()
4871 if (!filenameUp) return;
4872 XtPopdown(fileNameShell);
4873 XtDestroyWidget(fileNameShell);
4878 void FileNameCallback(w, client_data, call_data)
4880 XtPointer client_data, call_data;
4885 XtSetArg(args[0], XtNlabel, &name);
4886 XtGetValues(w, args, 1);
4888 if (strcmp(name, _("cancel")) == 0) {
4893 FileNameAction(w, NULL, NULL, NULL);
4896 void FileNameAction(w, event, prms, nprms)
4908 name = XawDialogGetValueString(w = XtParent(w));
4910 if ((name != NULL) && (*name != NULLCHAR)) {
4912 XtPopdown(w = XtParent(XtParent(w)));
4916 p = strrchr(buf, ' ');
4923 fullname = ExpandPathName(buf);
4925 ErrorPopUp(_("Error"), _("Can't open file"), FALSE);
4928 f = fopen(fullname, fileOpenMode);
4930 DisplayError(_("Failed to open file"), errno);
4932 (void) (*fileProc)(f, index, buf);
4939 XtPopdown(w = XtParent(XtParent(w)));
4945 void PromotionPopUp()
4948 Widget dialog, layout;
4950 Dimension bw_width, pw_width;
4954 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4955 XtGetValues(boardWidget, args, j);
4958 XtSetArg(args[j], XtNresizable, True); j++;
4959 XtSetArg(args[j], XtNtitle, XtNewString(_("Promotion"))); j++;
4961 XtCreatePopupShell("Promotion", transientShellWidgetClass,
4962 shellWidget, args, j);
4964 XtCreateManagedWidget(layoutName, formWidgetClass, promotionShell,
4965 layoutArgs, XtNumber(layoutArgs));
4968 XtSetArg(args[j], XtNlabel, _("Promote to what?")); j++;
4969 XtSetArg(args[j], XtNborderWidth, 0); j++;
4970 dialog = XtCreateManagedWidget("promotion", dialogWidgetClass,
4973 if(gameInfo.variant != VariantShogi) {
4974 XawDialogAddButton(dialog, _("Queen"), PromotionCallback,
4975 (XtPointer) dialog);
4976 XawDialogAddButton(dialog, _("Rook"), PromotionCallback,
4977 (XtPointer) dialog);
4978 XawDialogAddButton(dialog, _("Bishop"), PromotionCallback,
4979 (XtPointer) dialog);
4980 XawDialogAddButton(dialog, _("Knight"), PromotionCallback,
4981 (XtPointer) dialog);
4982 if (!appData.testLegality || gameInfo.variant == VariantSuicide ||
4983 gameInfo.variant == VariantGiveaway) {
4984 XawDialogAddButton(dialog, _("King"), PromotionCallback,
4985 (XtPointer) dialog);
4987 if(gameInfo.variant == VariantCapablanca ||
4988 gameInfo.variant == VariantGothic ||
4989 gameInfo.variant == VariantCapaRandom) {
4990 XawDialogAddButton(dialog, _("Archbishop"), PromotionCallback,
4991 (XtPointer) dialog);
4992 XawDialogAddButton(dialog, _("Chancellor"), PromotionCallback,
4993 (XtPointer) dialog);
4995 } else // [HGM] shogi
4997 XawDialogAddButton(dialog, _("Promote"), PromotionCallback,
4998 (XtPointer) dialog);
4999 XawDialogAddButton(dialog, _("Defer"), PromotionCallback,
5000 (XtPointer) dialog);
5002 XawDialogAddButton(dialog, _("cancel"), PromotionCallback,
5003 (XtPointer) dialog);
5005 XtRealizeWidget(promotionShell);
5006 CatchDeleteWindow(promotionShell, "PromotionPopDown");
5009 XtSetArg(args[j], XtNwidth, &pw_width); j++;
5010 XtGetValues(promotionShell, args, j);
5012 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
5013 lineGap + squareSize/3 +
5014 ((toY == BOARD_HEIGHT-1) ^ (flipView) ?
5015 0 : 6*(squareSize + lineGap)), &x, &y);
5018 XtSetArg(args[j], XtNx, x); j++;
5019 XtSetArg(args[j], XtNy, y); j++;
5020 XtSetValues(promotionShell, args, j);
5022 XtPopup(promotionShell, XtGrabNone);
5027 void PromotionPopDown()
5029 if (!promotionUp) return;
5030 XtPopdown(promotionShell);
5031 XtDestroyWidget(promotionShell);
5032 promotionUp = False;
5035 void PromotionCallback(w, client_data, call_data)
5037 XtPointer client_data, call_data;
5043 XtSetArg(args[0], XtNlabel, &name);
5044 XtGetValues(w, args, 1);
5048 if (fromX == -1) return;
5050 if (strcmp(name, _("cancel")) == 0) {
5054 } else if (strcmp(name, _("Knight")) == 0) {
5056 } else if (strcmp(name, _("Promote")) == 0) {
5058 } else if (strcmp(name, _("Defer")) == 0) {
5061 promoChar = ToLower(name[0]);
5064 UserMoveEvent(fromX, fromY, toX, toY, promoChar);
5066 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
5067 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
5072 void ErrorCallback(w, client_data, call_data)
5074 XtPointer client_data, call_data;
5077 XtPopdown(w = XtParent(XtParent(XtParent(w))));
5079 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5085 if (!errorUp) return;
5087 XtPopdown(errorShell);
5088 XtDestroyWidget(errorShell);
5089 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5092 void ErrorPopUp(title, label, modal)
5093 char *title, *label;
5098 dialog = gtk_message_dialog_new(GTK_WINDOW(GUI_Window),
5099 GTK_DIALOG_DESTROY_WITH_PARENT,
5104 gtk_window_set_title(GTK_WINDOW(dialog),(gchar *) title);
5107 gtk_dialog_run(GTK_DIALOG(dialog));
5108 gtk_widget_destroy(GTK_WIDGET(dialog));
5112 g_signal_connect_swapped (dialog, "response",
5113 G_CALLBACK (ErrorPopDownProc),
5116 gtk_widget_show(GTK_WIDGET(dialog));
5120 /* Disable all user input other than deleting the window */
5121 static int frozen = 0;
5125 /* Grab by a widget that doesn't accept input */
5126 // XtAddGrab(messageWidget, TRUE, FALSE);
5130 /* Undo a FreezeUI */
5133 if (!frozen) return;
5134 XtRemoveGrab(messageWidget);
5138 char *ModeToWidgetName(mode)
5142 case BeginningOfGame:
5143 if (appData.icsActive)
5144 return "menuMode.ICS Client";
5145 else if (appData.noChessProgram ||
5146 *appData.cmailGameName != NULLCHAR)
5147 return "menuMode.Edit Game";
5149 return "menuMode.Machine Black";
5150 case MachinePlaysBlack:
5151 return "menuMode.Machine Black";
5152 case MachinePlaysWhite:
5153 return "menuMode.Machine White";
5155 return "menuMode.Analysis Mode";
5157 return "menuMode.Analyze File";
5158 case TwoMachinesPlay:
5159 return "menuMode.Two Machines";
5161 return "menuMode.Edit Game";
5162 case PlayFromGameFile:
5163 return "menuFile.Load Game";
5165 return "menuMode.Edit Position";
5167 return "menuMode.Training";
5168 case IcsPlayingWhite:
5169 case IcsPlayingBlack:
5173 return "menuMode.ICS Client";
5180 void ModeHighlight()
5182 static int oldPausing = FALSE;
5183 static GameMode oldmode = (GameMode) -1;
5186 // todo this toggling of the pause button doesn't seem to work?
5187 // e.g. select pause from buttonbar doesn't activate menumode.pause
5189 // if (!boardWidget || !XtIsRealized(boardWidget)) return;
5191 if (pausing != oldPausing) {
5192 oldPausing = pausing;
5193 gtk_button_set_relief(GTK_BUTTON (gtk_builder_get_object (builder, "menuMode.Pause")),pausing?GTK_RELIEF_NORMAL:GTK_RELIEF_NONE);
5194 /* toggle background color in showbuttonbar */
5195 if (appData.showButtonBar) {
5197 gtk_button_pressed(GTK_BUTTON (gtk_builder_get_object (builder, "buttonbar.Pause")));
5199 gtk_button_released(GTK_BUTTON (gtk_builder_get_object (builder, "buttonbar.Pause")));
5204 wname = ModeToWidgetName(oldmode);
5206 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, wname)),True);
5210 /* Maybe all the enables should be handled here, not just this one */
5211 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuMode.Training")),
5212 gameMode == Training || gameMode == PlayFromGameFile);
5217 * Button/menu procedures
5220 int LoadGamePopUp(f, gameNumber, title)
5225 cmailMsgLoaded = FALSE;
5226 if (gameNumber == 0) {
5227 int error = GameListBuild(f);
5229 DisplayError(_("Cannot build game list"), error);
5230 } else if (!ListEmpty(&gameList) &&
5231 ((ListGame *) gameList.tailPred)->number > 1) {
5232 GameListPopUp(f, title);
5238 return LoadGame(f, gameNumber, title, FALSE);
5242 void LoadNextPositionProc(w, event, prms, nprms)
5251 void LoadPrevPositionProc(w, event, prms, nprms)
5260 void ReloadPositionProc(w, event, prms, nprms)
5269 void LoadPositionProc(w, event, prms, nprms)
5275 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
5278 FileNamePopUp(_("Load position file name?"), "", LoadPosition, "rb");
5281 void SaveGameProc(w, event, prms, nprms)
5287 FileNamePopUp(_("Save game file name?"),
5288 DefaultFileName(appData.oldSaveStyle ? "game" : "pgn"),
5292 void SavePositionProc(w, event, prms, nprms)
5298 FileNamePopUp(_("Save position file name?"),
5299 DefaultFileName(appData.oldSaveStyle ? "pos" : "fen"),
5303 void ReloadCmailMsgProc(w, event, prms, nprms)
5309 ReloadCmailMsgEvent(FALSE);
5312 void MailMoveProc(w, event, prms, nprms)
5321 /* this variable is shared between CopyPositionProc and SendPositionSelection */
5322 static char *selected_fen_position=NULL;
5325 SendPositionSelection(Widget w, Atom *selection, Atom *target,
5326 Atom *type_return, XtPointer *value_return,
5327 unsigned long *length_return, int *format_return)
5329 char *selection_tmp;
5331 if (!selected_fen_position) return False; /* should never happen */
5332 if (*target == XA_STRING){
5333 /* note: since no XtSelectionDoneProc was registered, Xt will
5334 * automatically call XtFree on the value returned. So have to
5335 * make a copy of it allocated with XtMalloc */
5336 selection_tmp= XtMalloc(strlen(selected_fen_position)+16);
5337 strcpy(selection_tmp, selected_fen_position);
5339 *value_return=selection_tmp;
5340 *length_return=strlen(selection_tmp);
5341 *type_return=XA_STRING;
5342 *format_return = 8; /* bits per byte */
5349 /* note: when called from menu all parameters are NULL, so no clue what the
5350 * Widget which was clicked on was, or what the click event was
5352 void CopyPositionProc(w, event, prms, nprms)
5360 if (selected_fen_position) free(selected_fen_position);
5361 selected_fen_position = (char *)PositionToFEN(currentMove, NULL);
5362 if (!selected_fen_position) return;
5363 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
5365 SendPositionSelection,
5366 NULL/* lose_ownership_proc */ ,
5367 NULL/* transfer_done_proc */);
5369 free(selected_fen_position);
5370 selected_fen_position=NULL;
5374 /* function called when the data to Paste is ready */
5376 PastePositionCB(Widget w, XtPointer client_data, Atom *selection,
5377 Atom *type, XtPointer value, unsigned long *len, int *format)
5380 if (value==NULL || *len==0) return; /* nothing had been selected to copy */
5381 fenstr[*len]='\0'; /* normally this string is terminated, but be safe */
5382 EditPositionPasteFEN(fenstr);
5386 /* called when Paste Position button is pressed,
5387 * all parameters will be NULL */
5388 void PastePositionProc(w, event, prms, nprms)
5394 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
5395 /* (XtSelectionCallbackProc) */ PastePositionCB,
5396 NULL, /* client_data passed to PastePositionCB */
5398 /* better to use the time field from the event that triggered the
5399 * call to this function, but that isn't trivial to get
5407 SendGameSelection(Widget w, Atom *selection, Atom *target,
5408 Atom *type_return, XtPointer *value_return,
5409 unsigned long *length_return, int *format_return)
5411 char *selection_tmp;
5413 if (*target == XA_STRING){
5414 FILE* f = fopen(gameCopyFilename, "r");
5417 if (f == NULL) return False;
5421 selection_tmp = XtMalloc(len + 1);
5422 count = fread(selection_tmp, 1, len, f);
5424 XtFree(selection_tmp);
5427 selection_tmp[len] = NULLCHAR;
5428 *value_return = selection_tmp;
5429 *length_return = len;
5430 *type_return = XA_STRING;
5431 *format_return = 8; /* bits per byte */
5438 /* note: when called from menu all parameters are NULL, so no clue what the
5439 * Widget which was clicked on was, or what the click event was
5441 void CopyGameProc(w, event, prms, nprms)
5449 ret = SaveGameToFile(gameCopyFilename, FALSE);
5452 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
5455 NULL/* lose_ownership_proc */ ,
5456 NULL/* transfer_done_proc */);
5459 /* function called when the data to Paste is ready */
5461 PasteGameCB(Widget w, XtPointer client_data, Atom *selection,
5462 Atom *type, XtPointer value, unsigned long *len, int *format)
5465 if (value == NULL || *len == 0) {
5466 return; /* nothing had been selected to copy */
5468 f = fopen(gamePasteFilename, "w");
5470 DisplayError(_("Can't open temp file"), errno);
5473 fwrite(value, 1, *len, f);
5476 LoadGameFromFile(gamePasteFilename, 0, gamePasteFilename, TRUE);
5479 /* called when Paste Game button is pressed,
5480 * all parameters will be NULL */
5481 void PasteGameProc(w, event, prms, nprms)
5487 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
5488 /* (XtSelectionCallbackProc) */ PasteGameCB,
5489 NULL, /* client_data passed to PasteGameCB */
5491 /* better to use the time field from the event that triggered the
5492 * call to this function, but that isn't trivial to get
5502 SaveGameProc(NULL, NULL, NULL, NULL);
5505 void MachineBlackProc(w, event, prms, nprms)
5511 MachineBlackEvent();
5514 void MachineWhiteProc(w, event, prms, nprms)
5520 MachineWhiteEvent();
5523 void AnalyzeModeProc(w, event, prms, nprms)
5531 if (!first.analysisSupport) {
5532 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
5533 DisplayError(buf, 0);
5536 /* [DM] icsEngineAnalyze [HGM] This is horrible code; reverse the gameMode and isEngineAnalyze tests! */
5537 if (appData.icsActive) {
5538 if (gameMode != IcsObserving) {
5539 sprintf(buf,_("You are not observing a game"));
5540 DisplayError(buf, 0);
5542 if (appData.icsEngineAnalyze) {
5543 if (appData.debugMode)
5544 fprintf(debugFP, _("Found unexpected active ICS engine analyze \n"));
5550 /* if enable, use want disable icsEngineAnalyze */
5551 if (appData.icsEngineAnalyze) {
5556 appData.icsEngineAnalyze = TRUE;
5557 if (appData.debugMode)
5558 fprintf(debugFP, _("ICS engine analyze starting... \n"));
5560 if (!appData.showThinking)
5561 ShowThinkingProc(w,event,prms,nprms);
5566 void AnalyzeFileProc(w, event, prms, nprms)
5572 if (!first.analysisSupport) {
5574 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
5575 DisplayError(buf, 0);
5580 if (!appData.showThinking)
5581 ShowThinkingProc(w,event,prms,nprms);
5584 FileNamePopUp(_("File to analyze"), "", LoadGamePopUp, "rb");
5585 AnalysisPeriodicEvent(1);
5588 void TwoMachinesProc(w, event, prms, nprms)
5597 void IcsClientProc(w, event, prms, nprms)
5606 void EditGameProc(w, event, prms, nprms)
5615 void EditPositionProc(w, event, prms, nprms)
5621 EditPositionEvent();
5624 void TrainingProc(w, event, prms, nprms)
5633 void EditCommentProc(w, event, prms, nprms)
5640 EditCommentPopDown();
5646 void IcsInputBoxProc(w, event, prms, nprms)
5652 if (ICSInputBoxUp) {
5653 ICSInputBoxPopDown();
5659 void AcceptProc(w, event, prms, nprms)
5668 void DeclineProc(w, event, prms, nprms)
5677 void RematchProc(w, event, prms, nprms)
5686 void CallFlagProc(w, event, prms, nprms)
5695 void DrawProc(w, event, prms, nprms)
5704 void AbortProc(w, event, prms, nprms)
5713 void AdjournProc(w, event, prms, nprms)
5722 void ResignProc(w, event, prms, nprms)
5731 void AdjuWhiteProc(w, event, prms, nprms)
5737 UserAdjudicationEvent(+1);
5740 void AdjuBlackProc(w, event, prms, nprms)
5746 UserAdjudicationEvent(-1);
5749 void AdjuDrawProc(w, event, prms, nprms)
5755 UserAdjudicationEvent(0);
5758 void EnterKeyProc(w, event, prms, nprms)
5764 if (ICSInputBoxUp == True)
5768 void StopObservingProc(w, event, prms, nprms)
5774 StopObservingEvent();
5777 void StopExaminingProc(w, event, prms, nprms)
5783 StopExaminingEvent();
5787 void ForwardProc(w, event, prms, nprms)
5797 void BackwardProc(w, event, prms, nprms)
5806 void ToStartProc(w, event, prms, nprms)
5815 void ToEndProc(w, event, prms, nprms)
5824 void RevertProc(w, event, prms, nprms)
5833 void TruncateGameProc(w, event, prms, nprms)
5839 TruncateGameEvent();
5841 void RetractMoveProc(w, event, prms, nprms)
5850 void MoveNowProc(w, event, prms, nprms)
5860 void AlwaysQueenProc(w, event, prms, nprms)
5868 appData.alwaysPromoteToQueen = !appData.alwaysPromoteToQueen;
5870 if (appData.alwaysPromoteToQueen) {
5871 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5873 XtSetArg(args[0], XtNleftBitmap, None);
5875 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
5879 void AnimateDraggingProc(w, event, prms, nprms)
5887 appData.animateDragging = !appData.animateDragging;
5889 if (appData.animateDragging) {
5890 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5893 XtSetArg(args[0], XtNleftBitmap, None);
5895 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Dragging"),
5899 void AnimateMovingProc(w, event, prms, nprms)
5907 appData.animate = !appData.animate;
5909 if (appData.animate) {
5910 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5913 XtSetArg(args[0], XtNleftBitmap, None);
5915 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
5919 void AutocommProc(w, event, prms, nprms)
5927 appData.autoComment = !appData.autoComment;
5929 if (appData.autoComment) {
5930 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5932 XtSetArg(args[0], XtNleftBitmap, None);
5934 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
5939 void AutoflagProc(w, event, prms, nprms)
5947 appData.autoCallFlag = !appData.autoCallFlag;
5949 if (appData.autoCallFlag) {
5950 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5952 XtSetArg(args[0], XtNleftBitmap, None);
5954 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
5958 void AutoflipProc(w, event, prms, nprms)
5966 appData.autoFlipView = !appData.autoFlipView;
5968 if (appData.autoFlipView) {
5969 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5971 XtSetArg(args[0], XtNleftBitmap, None);
5973 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flip View"),
5977 void AutobsProc(w, event, prms, nprms)
5985 appData.autoObserve = !appData.autoObserve;
5987 if (appData.autoObserve) {
5988 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5990 XtSetArg(args[0], XtNleftBitmap, None);
5992 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
5996 void AutoraiseProc(w, event, prms, nprms)
6004 appData.autoRaiseBoard = !appData.autoRaiseBoard;
6006 if (appData.autoRaiseBoard) {
6007 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6009 XtSetArg(args[0], XtNleftBitmap, None);
6011 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Raise Board"),
6015 void AutosaveProc(w, event, prms, nprms)
6023 appData.autoSaveGames = !appData.autoSaveGames;
6025 if (appData.autoSaveGames) {
6026 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6028 XtSetArg(args[0], XtNleftBitmap, None);
6030 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
6034 void BlindfoldProc(w, event, prms, nprms)
6042 appData.blindfold = !appData.blindfold;
6044 if (appData.blindfold) {
6045 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6047 XtSetArg(args[0], XtNleftBitmap, None);
6049 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Blindfold"),
6052 DrawPosition(True, NULL);
6055 void TestLegalityProc(w, event, prms, nprms)
6063 appData.testLegality = !appData.testLegality;
6065 if (appData.testLegality) {
6066 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6068 XtSetArg(args[0], XtNleftBitmap, None);
6070 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Test Legality"),
6075 void FlashMovesProc(w, event, prms, nprms)
6083 if (appData.flashCount == 0) {
6084 appData.flashCount = 3;
6086 appData.flashCount = -appData.flashCount;
6089 if (appData.flashCount > 0) {
6090 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6092 XtSetArg(args[0], XtNleftBitmap, None);
6094 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flash Moves"),
6098 void FlipViewProc(w, event, prms, nprms)
6104 flipView = !flipView;
6105 DrawPosition(True, NULL);
6108 void GetMoveListProc(w, event, prms, nprms)
6116 appData.getMoveList = !appData.getMoveList;
6118 if (appData.getMoveList) {
6119 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6122 XtSetArg(args[0], XtNleftBitmap, None);
6124 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
6129 void HighlightDraggingProc(w, event, prms, nprms)
6137 appData.highlightDragging = !appData.highlightDragging;
6139 if (appData.highlightDragging) {
6140 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6142 XtSetArg(args[0], XtNleftBitmap, None);
6144 XtSetValues(XtNameToWidget(menuBarWidget,
6145 "menuOptions.Highlight Dragging"), args, 1);
6149 void HighlightLastMoveProc(w, event, prms, nprms)
6157 appData.highlightLastMove = !appData.highlightLastMove;
6159 if (appData.highlightLastMove) {
6160 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6162 XtSetArg(args[0], XtNleftBitmap, None);
6164 XtSetValues(XtNameToWidget(menuBarWidget,
6165 "menuOptions.Highlight Last Move"), args, 1);
6168 void IcsAlarmProc(w, event, prms, nprms)
6176 appData.icsAlarm = !appData.icsAlarm;
6178 if (appData.icsAlarm) {
6179 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6181 XtSetArg(args[0], XtNleftBitmap, None);
6183 XtSetValues(XtNameToWidget(menuBarWidget,
6184 "menuOptions.ICS Alarm"), args, 1);
6187 void MoveSoundProc(w, event, prms, nprms)
6195 appData.ringBellAfterMoves = !appData.ringBellAfterMoves;
6197 if (appData.ringBellAfterMoves) {
6198 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6200 XtSetArg(args[0], XtNleftBitmap, None);
6202 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
6207 void OldSaveStyleProc(w, event, prms, nprms)
6215 appData.oldSaveStyle = !appData.oldSaveStyle;
6217 if (appData.oldSaveStyle) {
6218 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6220 XtSetArg(args[0], XtNleftBitmap, None);
6222 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Old Save Style"),
6226 void PeriodicUpdatesProc(w, event, prms, nprms)
6234 PeriodicUpdatesEvent(!appData.periodicUpdates);
6236 if (appData.periodicUpdates) {
6237 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6239 XtSetArg(args[0], XtNleftBitmap, None);
6241 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Periodic Updates"),
6245 void PonderNextMoveProc(w, event, prms, nprms)
6253 PonderNextMoveEvent(!appData.ponderNextMove);
6255 if (appData.ponderNextMove) {
6256 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6258 XtSetArg(args[0], XtNleftBitmap, None);
6260 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Ponder Next Move"),
6264 void PopupExitMessageProc(w, event, prms, nprms)
6272 appData.popupExitMessage = !appData.popupExitMessage;
6274 if (appData.popupExitMessage) {
6275 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6277 XtSetArg(args[0], XtNleftBitmap, None);
6279 XtSetValues(XtNameToWidget(menuBarWidget,
6280 "menuOptions.Popup Exit Message"), args, 1);
6283 void PopupMoveErrorsProc(w, event, prms, nprms)
6291 appData.popupMoveErrors = !appData.popupMoveErrors;
6293 if (appData.popupMoveErrors) {
6294 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6296 XtSetArg(args[0], XtNleftBitmap, None);
6298 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Popup Move Errors"),
6302 void PremoveProc(w, event, prms, nprms)
6310 appData.premove = !appData.premove;
6312 if (appData.premove) {
6313 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6315 XtSetArg(args[0], XtNleftBitmap, None);
6317 XtSetValues(XtNameToWidget(menuBarWidget,
6318 "menuOptions.Premove"), args, 1);
6321 void QuietPlayProc(w, event, prms, nprms)
6329 appData.quietPlay = !appData.quietPlay;
6331 if (appData.quietPlay) {
6332 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6334 XtSetArg(args[0], XtNleftBitmap, None);
6336 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Quiet Play"),
6340 void ShowThinkingProc(w, event, prms, nprms)
6348 appData.showThinking = !appData.showThinking; // [HGM] thinking: tken out of ShowThinkingEvent
6349 ShowThinkingEvent();
6351 // [HGM] thinking: currently no suc menu item; replaced by Hide Thinking (From Human)
6352 if (appData.showThinking) {
6353 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6355 XtSetArg(args[0], XtNleftBitmap, None);
6357 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Thinking"),
6362 void HideThinkingProc(w, event, prms, nprms)
6370 appData.hideThinkingFromHuman = !appData.hideThinkingFromHuman; // [HGM] thinking: tken out of ShowThinkingEvent
6371 ShowThinkingEvent();
6373 if (appData.hideThinkingFromHuman) {
6374 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6376 XtSetArg(args[0], XtNleftBitmap, None);
6378 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
6382 void InfoProc(w, event, prms, nprms)
6389 snprintf(buf, sizeof(buf), "xterm -e info --directory %s --directory . -f %s &",
6394 void ManProc(w, event, prms, nprms)
6402 if (nprms && *nprms > 0)
6406 snprintf(buf, sizeof(buf), "xterm -e man %s &", name);
6410 void HintProc(w, event, prms, nprms)
6419 void BookProc(w, event, prms, nprms)
6428 void DebugProc(w, event, prms, nprms)
6434 appData.debugMode = !appData.debugMode;
6437 void AboutGameProc(w, event, prms, nprms)
6446 void NothingProc(w, event, prms, nprms)
6455 void Iconify(w, event, prms, nprms)
6464 XtSetArg(args[0], XtNiconic, True);
6465 XtSetValues(shellWidget, args, 1);
6468 void DisplayMessage(message, extMessage)
6469 gchar *message, *extMessage;
6476 snprintf(buf, sizeof(buf), "%s %s", message, extMessage);
6479 message = extMessage;
6482 gtk_label_set_text( GTK_LABEL(gtk_builder_get_object (builder, "Messages")),message);
6485 void DisplayTitle(text)
6490 char title[MSG_SIZ];
6493 if (text == NULL) text = "";
6495 if (appData.titleInWindow) {
6497 XtSetArg(args[i], XtNlabel, text); i++;
6498 XtSetValues(titleWidget, args, i);
6501 if (*text != NULLCHAR) {
6503 strcpy(title, text);
6504 } else if (appData.icsActive) {
6505 snprintf(icon, sizeof(icon), "%s", appData.icsHost);
6506 snprintf(title, sizeof(title), "%s: %s", programName, appData.icsHost);
6507 } else if (appData.cmailGameName[0] != NULLCHAR) {
6508 snprintf(icon, sizeof(icon), "%s", "CMail");
6509 snprintf(title,sizeof(title), "%s: %s", programName, "CMail");
6511 // [HGM] license: This stuff should really be done in back-end, but WinBoard already had a pop-up for it
6512 } else if (gameInfo.variant == VariantGothic) {
6513 strcpy(icon, programName);
6514 strcpy(title, GOTHIC);
6517 } else if (gameInfo.variant == VariantFalcon) {
6518 strcpy(icon, programName);
6519 strcpy(title, FALCON);
6521 } else if (appData.noChessProgram) {
6522 strcpy(icon, programName);
6523 strcpy(title, programName);
6525 strcpy(icon, first.tidy);
6526 snprintf(title,sizeof(title), "%s: %s", programName, first.tidy);
6529 XtSetArg(args[i], XtNiconName, (XtArgVal) icon); i++;
6530 XtSetArg(args[i], XtNtitle, (XtArgVal) title); i++;
6531 XtSetValues(shellWidget, args, i);
6535 void DisplayError(message, error)
6542 if (appData.debugMode || appData.matchMode) {
6543 fprintf(stderr, "%s: %s\n", programName, message);
6546 if (appData.debugMode || appData.matchMode) {
6547 fprintf(stderr, "%s: %s: %s\n",
6548 programName, message, strerror(error));
6550 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
6553 ErrorPopUp(_("Error"), message, FALSE);
6557 void DisplayMoveError(message)
6562 DrawPosition(FALSE, NULL);
6563 if (appData.debugMode || appData.matchMode) {
6564 fprintf(stderr, "%s: %s\n", programName, message);
6566 if (appData.popupMoveErrors) {
6567 ErrorPopUp(_("Error"), message, FALSE);
6569 DisplayMessage(message, "");
6574 void DisplayFatalError(message, error, status)
6580 errorExitStatus = status;
6582 fprintf(stderr, "%s: %s\n", programName, message);
6584 fprintf(stderr, "%s: %s: %s\n",
6585 programName, message, strerror(error));
6586 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
6589 if (appData.popupExitMessage && boardWidget && XtIsRealized(boardWidget)) {
6590 ErrorPopUp(status ? _("Fatal Error") : _("Exiting"), message, TRUE);
6596 void DisplayInformation(message)
6600 ErrorPopUp(_("Information"), message, TRUE);
6603 void DisplayNote(message)
6607 ErrorPopUp(_("Note"), message, FALSE);
6611 NullXErrorCheck(dpy, error_event)
6613 XErrorEvent *error_event;
6618 void DisplayIcsInteractionTitle(message)
6621 if (oldICSInteractionTitle == NULL) {
6622 /* Magic to find the old window title, adapted from vim */
6623 char *wina = getenv("WINDOWID");
6625 Window win = (Window) atoi(wina);
6626 Window root, parent, *children;
6627 unsigned int nchildren;
6628 int (*oldHandler)() = XSetErrorHandler(NullXErrorCheck);
6630 if (XFetchName(xDisplay, win, &oldICSInteractionTitle)) break;
6631 if (!XQueryTree(xDisplay, win, &root, &parent,
6632 &children, &nchildren)) break;
6633 if (children) XFree((void *)children);
6634 if (parent == root || parent == 0) break;
6637 XSetErrorHandler(oldHandler);
6639 if (oldICSInteractionTitle == NULL) {
6640 oldICSInteractionTitle = "xterm";
6643 printf("\033]0;%s\007", message);
6647 char pendingReplyPrefix[MSG_SIZ];
6648 ProcRef pendingReplyPR;
6650 void AskQuestionProc(w, event, prms, nprms)
6657 fprintf(stderr, _("AskQuestionProc needed 4 parameters, got %d\n"),
6661 AskQuestionEvent(prms[0], prms[1], prms[2], prms[3]);
6664 void AskQuestionPopDown()
6666 if (!askQuestionUp) return;
6667 XtPopdown(askQuestionShell);
6668 XtDestroyWidget(askQuestionShell);
6669 askQuestionUp = False;
6672 void AskQuestionReplyAction(w, event, prms, nprms)
6682 reply = XawDialogGetValueString(w = XtParent(w));
6683 strcpy(buf, pendingReplyPrefix);
6684 if (*buf) strcat(buf, " ");
6687 OutputToProcess(pendingReplyPR, buf, strlen(buf), &err);
6688 AskQuestionPopDown();
6690 if (err) DisplayFatalError(_("Error writing to chess program"), err, 0);
6693 void AskQuestionCallback(w, client_data, call_data)
6695 XtPointer client_data, call_data;
6700 XtSetArg(args[0], XtNlabel, &name);
6701 XtGetValues(w, args, 1);
6703 if (strcmp(name, _("cancel")) == 0) {
6704 AskQuestionPopDown();
6706 AskQuestionReplyAction(w, NULL, NULL, NULL);
6710 void AskQuestion(title, question, replyPrefix, pr)
6711 char *title, *question, *replyPrefix;
6715 Widget popup, layout, dialog, edit;
6721 strcpy(pendingReplyPrefix, replyPrefix);
6722 pendingReplyPR = pr;
6725 XtSetArg(args[i], XtNresizable, True); i++;
6726 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
6727 askQuestionShell = popup =
6728 XtCreatePopupShell(title, transientShellWidgetClass,
6729 shellWidget, args, i);
6732 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
6733 layoutArgs, XtNumber(layoutArgs));
6736 XtSetArg(args[i], XtNlabel, question); i++;
6737 XtSetArg(args[i], XtNvalue, ""); i++;
6738 XtSetArg(args[i], XtNborderWidth, 0); i++;
6739 dialog = XtCreateManagedWidget("question", dialogWidgetClass,
6742 XawDialogAddButton(dialog, _("enter"), AskQuestionCallback,
6743 (XtPointer) dialog);
6744 XawDialogAddButton(dialog, _("cancel"), AskQuestionCallback,
6745 (XtPointer) dialog);
6747 XtRealizeWidget(popup);
6748 CatchDeleteWindow(popup, "AskQuestionPopDown");
6750 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
6751 &x, &y, &win_x, &win_y, &mask);
6753 XtSetArg(args[0], XtNx, x - 10);
6754 XtSetArg(args[1], XtNy, y - 30);
6755 XtSetValues(popup, args, 2);
6757 XtPopup(popup, XtGrabExclusive);
6758 askQuestionUp = True;
6760 edit = XtNameToWidget(dialog, "*value");
6761 XtSetKeyboardFocus(popup, edit);
6769 if (*name == NULLCHAR) {
6771 } else if (strcmp(name, "$") == 0) {
6772 putc(BELLCHAR, stderr);
6775 snprintf(buf, sizeof(buf), "%s '%s' &", appData.soundProgram, name);
6783 PlaySound(appData.soundMove);
6789 PlaySound(appData.soundIcsWin);
6795 PlaySound(appData.soundIcsLoss);
6801 PlaySound(appData.soundIcsDraw);
6805 PlayIcsUnfinishedSound()
6807 PlaySound(appData.soundIcsUnfinished);
6813 PlaySound(appData.soundIcsAlarm);
6819 system("stty echo");
6825 system("stty -echo");
6829 Colorize(cc, continuation)
6834 int count, outCount, error;
6836 if (textColors[(int)cc].bg > 0) {
6837 if (textColors[(int)cc].fg > 0) {
6838 sprintf(buf, "\033[0;%d;%d;%dm", textColors[(int)cc].attr,
6839 textColors[(int)cc].fg, textColors[(int)cc].bg);
6841 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
6842 textColors[(int)cc].bg);
6845 if (textColors[(int)cc].fg > 0) {
6846 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
6847 textColors[(int)cc].fg);
6849 sprintf(buf, "\033[0;%dm", textColors[(int)cc].attr);
6852 count = strlen(buf);
6853 outCount = OutputToProcess(NoProc, buf, count, &error);
6854 if (outCount < count) {
6855 DisplayFatalError(_("Error writing to display"), error, 1);
6858 if (continuation) return;
6861 PlaySound(appData.soundShout);
6864 PlaySound(appData.soundSShout);
6867 PlaySound(appData.soundChannel1);
6870 PlaySound(appData.soundChannel);
6873 PlaySound(appData.soundKibitz);
6876 PlaySound(appData.soundTell);
6878 case ColorChallenge:
6879 PlaySound(appData.soundChallenge);
6882 PlaySound(appData.soundRequest);
6885 PlaySound(appData.soundSeek);
6896 return getpwuid(getuid())->pw_name;
6899 static char *ExpandPathName(path)
6902 static char static_buf[2000];
6903 char *d, *s, buf[2000];
6909 while (*s && isspace(*s))
6918 if (*(s+1) == '/') {
6919 strcpy(d, getpwuid(getuid())->pw_dir);
6924 *strchr(buf, '/') = 0;
6925 pwd = getpwnam(buf);
6928 fprintf(stderr, _("ERROR: Unknown user %s (in path %s)\n"),
6932 strcpy(d, pwd->pw_dir);
6933 strcat(d, strchr(s+1, '/'));
6944 static char host_name[MSG_SIZ];
6946 #if HAVE_GETHOSTNAME
6947 gethostname(host_name, MSG_SIZ);
6949 #else /* not HAVE_GETHOSTNAME */
6950 # if HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H
6951 sysinfo(SI_HOSTNAME, host_name, MSG_SIZ);
6953 # else /* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
6955 # endif/* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
6956 #endif /* not HAVE_GETHOSTNAME */
6959 gint delayedEventTimerTag = 0;
6960 DelayedEventCallback delayedEventCallback = 0;
6963 FireDelayedEvent(data)
6966 delayedEventTimerTag = 0;
6967 delayedEventCallback();
6971 ScheduleDelayedEvent(cb, millisec)
6972 DelayedEventCallback cb; long millisec;
6974 delayedEventCallback = cb;
6975 delayedEventTimerTag =
6976 gtk_timeout_add(millisec,(GtkFunction) FireDelayedEvent, NULL);
6979 DelayedEventCallback
6982 if (delayedEventTimerTag)
6984 return delayedEventCallback;
6993 CancelDelayedEvent()
6995 if (delayedEventTimerTag)
6997 gtk_timeout_remove(delayedEventTimerTag);
6998 delayedEventTimerTag = 0;
7003 gint loadGameTimerTag = 0;
7005 int LoadGameTimerRunning()
7007 return loadGameTimerTag != 0;
7010 int StopLoadGameTimer()
7012 if (loadGameTimerTag != 0) {
7013 gtk_timeout_remove(loadGameTimerTag);
7014 loadGameTimerTag = 0;
7022 LoadGameTimerCallback(data)
7025 loadGameTimerTag = 0;
7030 StartLoadGameTimer(millisec)
7034 gtk_timeout_add( millisec, (GtkFunction) LoadGameTimerCallback, NULL);
7037 gint analysisClockTag = 0;
7040 AnalysisClockCallback(data)
7043 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile
7044 || appData.icsEngineAnalyze)
7046 AnalysisPeriodicEvent(0);
7047 StartAnalysisClock();
7052 StartAnalysisClock()
7055 gtk_timeout_add( 2000,(GtkFunction) AnalysisClockCallback, NULL);
7058 gint clockTimerTag = 0;
7060 int ClockTimerRunning()
7062 return clockTimerTag != 0;
7065 int StopClockTimer()
7067 if (clockTimerTag != 0)
7069 gtk_timeout_remove(clockTimerTag);
7080 ClockTimerCallback(data)
7089 StartClockTimer(millisec)
7092 clockTimerTag = gtk_timeout_add(millisec,(GtkFunction) ClockTimerCallback,NULL);
7097 DisplayTimerLabel(w, color, timer, highlight)
7106 if (appData.clockMode) {
7107 sprintf(buf, "%s: %s", color, TimeString(timer));
7109 sprintf(buf, "%s ", color);
7111 gtk_label_set_text(GTK_LABEL(w),buf);
7113 /* check for low time warning */
7114 // Pixel foregroundOrWarningColor = timerForegroundPixel;
7117 // appData.lowTimeWarning &&
7118 // (timer / 1000) < appData.icsAlarmTime)
7119 // foregroundOrWarningColor = lowTimeWarningColor;
7121 // if (appData.clockMode) {
7122 // sprintf(buf, "%s: %s", color, TimeString(timer));
7123 // XtSetArg(args[0], XtNlabel, buf);
7125 // sprintf(buf, "%s ", color);
7126 // XtSetArg(args[0], XtNlabel, buf);
7131 // XtSetArg(args[1], XtNbackground, foregroundOrWarningColor);
7132 // XtSetArg(args[2], XtNforeground, timerBackgroundPixel);
7134 // XtSetArg(args[1], XtNbackground, timerBackgroundPixel);
7135 // XtSetArg(args[2], XtNforeground, foregroundOrWarningColor);
7138 // XtSetValues(w, args, 3);
7143 DisplayWhiteClock(timeRemaining, highlight)
7147 if(appData.noGUI) return;
7149 DisplayTimerLabel(GUI_Whiteclock, _("White"), timeRemaining, highlight);
7150 if (highlight && WindowIcon == BlackIcon)
7152 WindowIcon = WhiteIcon;
7153 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
7158 DisplayBlackClock(timeRemaining, highlight)
7162 if(appData.noGUI) return;
7164 DisplayTimerLabel(GUI_Blackclock, _("Black"), timeRemaining, highlight);
7165 if (highlight && WindowIcon == WhiteIcon)
7167 WindowIcon = BlackIcon;
7168 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
7186 int StartChildProcess(cmdLine, dir, pr)
7193 int to_prog[2], from_prog[2];
7197 if (appData.debugMode) {
7198 fprintf(stderr, "StartChildProcess (dir=\"%s\") %s\n",dir, cmdLine);
7201 /* We do NOT feed the cmdLine to the shell; we just
7202 parse it into blank-separated arguments in the
7203 most simple-minded way possible.
7206 strcpy(buf, cmdLine);
7211 if (p == NULL) break;
7216 SetUpChildIO(to_prog, from_prog);
7218 if ((pid = fork()) == 0) {
7220 // [HGM] PSWBTM: made order resistant against case where fd of created pipe was 0 or 1
7221 close(to_prog[1]); // first close the unused pipe ends
7222 close(from_prog[0]);
7223 dup2(to_prog[0], 0); // to_prog was created first, nd is the only one to use 0 or 1
7224 dup2(from_prog[1], 1);
7225 if(to_prog[0] >= 2) close(to_prog[0]); // if 0 or 1, the dup2 already cosed the original
7226 close(from_prog[1]); // and closing again loses one of the pipes!
7227 if(fileno(stderr) >= 2) // better safe than sorry...
7228 dup2(1, fileno(stderr)); /* force stderr to the pipe */
7230 if (dir[0] != NULLCHAR && chdir(dir) != 0) {
7235 nice(appData.niceEngines); // [HGM] nice: adjust priority of engine proc
7237 execvp(argv[0], argv);
7239 /* If we get here, exec failed */
7244 /* Parent process */
7246 close(from_prog[1]);
7248 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7251 cp->fdFrom = from_prog[0];
7252 cp->fdTo = to_prog[1];
7257 // [HGM] kill: implement the 'hard killing' of AS's Winboard_x
7258 static RETSIGTYPE AlarmCallBack(int n)
7264 DestroyChildProcess(pr, signalType)
7268 ChildProc *cp = (ChildProc *) pr;
7270 if (cp->kind != CPReal) return;
7272 if (signalType == 10) { // [HGM] kill: if it does not terminate in 3 sec, kill
7273 signal(SIGALRM, AlarmCallBack);
7275 if(wait((int *) 0) == -1) { // process does not terminate on its own accord
7276 kill(cp->pid, SIGKILL); // kill it forcefully
7277 wait((int *) 0); // and wait again
7281 kill(cp->pid, signalType == 9 ? SIGKILL : SIGTERM); // [HGM] kill: use hard kill if so requested
7283 /* Process is exiting either because of the kill or because of
7284 a quit command sent by the backend; either way, wait for it to die.
7293 InterruptChildProcess(pr)
7296 ChildProc *cp = (ChildProc *) pr;
7298 if (cp->kind != CPReal) return;
7299 (void) kill(cp->pid, SIGINT); /* stop it thinking */
7302 int OpenTelnet(host, port, pr)
7307 char cmdLine[MSG_SIZ];
7309 if (port[0] == NULLCHAR) {
7310 snprintf(cmdLine, sizeof(cmdLine), "%s %s", appData.telnetProgram, host);
7312 snprintf(cmdLine, sizeof(cmdLine), "%s %s %s", appData.telnetProgram, host, port);
7314 return StartChildProcess(cmdLine, "", pr);
7317 int OpenTCP(host, port, pr)
7323 DisplayFatalError(_("Socket support is not configured in"), 0, 2);
7324 #else /* !OMIT_SOCKETS */
7326 struct sockaddr_in sa;
7328 unsigned short uport;
7331 if ((s = socket(AF_INET, SOCK_STREAM, 6)) < 0) {
7335 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
7336 sa.sin_family = AF_INET;
7337 sa.sin_addr.s_addr = INADDR_ANY;
7338 uport = (unsigned short) 0;
7339 sa.sin_port = htons(uport);
7340 if (bind(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)) < 0) {
7344 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
7345 if (!(hp = gethostbyname(host))) {
7347 if (sscanf(host, "%d.%d.%d.%d", &b0, &b1, &b2, &b3) == 4) {
7348 hp = (struct hostent *) calloc(1, sizeof(struct hostent));
7349 hp->h_addrtype = AF_INET;
7351 hp->h_addr_list = (char **) calloc(2, sizeof(char *));
7352 hp->h_addr_list[0] = (char *) malloc(4);
7353 hp->h_addr_list[0][0] = b0;
7354 hp->h_addr_list[0][1] = b1;
7355 hp->h_addr_list[0][2] = b2;
7356 hp->h_addr_list[0][3] = b3;
7361 sa.sin_family = hp->h_addrtype;
7362 uport = (unsigned short) atoi(port);
7363 sa.sin_port = htons(uport);
7364 memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);
7366 if (connect(s, (struct sockaddr *) &sa,
7367 sizeof(struct sockaddr_in)) < 0) {
7371 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7378 #endif /* !OMIT_SOCKETS */
7383 int OpenCommPort(name, pr)
7390 fd = open(name, 2, 0);
7391 if (fd < 0) return errno;
7393 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7403 int OpenLoopback(pr)
7409 SetUpChildIO(to, from);
7411 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7414 cp->fdFrom = to[0]; /* note not from[0]; we are doing a loopback */
7421 int OpenRcmd(host, user, cmd, pr)
7422 char *host, *user, *cmd;
7425 DisplayFatalError(_("internal rcmd not implemented for Unix"), 0, 1);
7429 #define INPUT_SOURCE_BUF_SIZE 8192
7438 char buf[INPUT_SOURCE_BUF_SIZE];
7443 DoInputCallback(closure, source, xid)
7448 InputSource *is = (InputSource *) closure;
7453 if (is->lineByLine) {
7454 count = read(is->fd, is->unused,
7455 INPUT_SOURCE_BUF_SIZE - (is->unused - is->buf));
7457 (is->func)(is, is->closure, is->buf, count, count ? errno : 0);
7460 is->unused += count;
7462 while (p < is->unused) {
7463 q = memchr(p, '\n', is->unused - p);
7464 if (q == NULL) break;
7466 (is->func)(is, is->closure, p, q - p, 0);
7470 while (p < is->unused) {
7475 count = read(is->fd, is->buf, INPUT_SOURCE_BUF_SIZE);
7480 (is->func)(is, is->closure, is->buf, count, error);
7484 InputSourceRef AddInputSource(pr, lineByLine, func, closure)
7491 ChildProc *cp = (ChildProc *) pr;
7493 is = (InputSource *) calloc(1, sizeof(InputSource));
7494 is->lineByLine = lineByLine;
7498 is->fd = fileno(stdin);
7500 is->kind = cp->kind;
7501 is->fd = cp->fdFrom;
7504 is->unused = is->buf;
7507 is->xid = XtAppAddInput(appContext, is->fd,
7508 (XtPointer) (XtInputReadMask),
7509 (XtInputCallbackProc) DoInputCallback,
7511 is->closure = closure;
7512 return (InputSourceRef) is;
7516 RemoveInputSource(isr)
7519 InputSource *is = (InputSource *) isr;
7521 if (is->xid == 0) return;
7522 XtRemoveInput(is->xid);
7526 int OutputToProcess(pr, message, count, outError)
7532 ChildProc *cp = (ChildProc *) pr;
7536 outCount = fwrite(message, 1, count, stdout);
7538 outCount = write(cp->fdTo, message, count);
7548 /* Output message to process, with "ms" milliseconds of delay
7549 between each character. This is needed when sending the logon
7550 script to ICC, which for some reason doesn't like the
7551 instantaneous send. */
7552 int OutputToProcessDelayed(pr, message, count, outError, msdelay)
7559 ChildProc *cp = (ChildProc *) pr;
7564 r = write(cp->fdTo, message++, 1);
7577 /**** Animation code by Hugh Fisher, DCS, ANU.
7579 Known problem: if a window overlapping the board is
7580 moved away while a piece is being animated underneath,
7581 the newly exposed area won't be updated properly.
7582 I can live with this.
7584 Known problem: if you look carefully at the animation
7585 of pieces in mono mode, they are being drawn as solid
7586 shapes without interior detail while moving. Fixing
7587 this would be a major complication for minimal return.
7590 /* Masks for XPM pieces. Black and white pieces can have
7591 different shapes, but in the interest of retaining my
7592 sanity pieces must have the same outline on both light
7593 and dark squares, and all pieces must use the same
7594 background square colors/images. */
7596 static int xpmDone = 0;
7599 CreateAnimMasks (pieceDepth)
7606 unsigned long plane;
7609 /* Need a bitmap just to get a GC with right depth */
7610 buf = XCreatePixmap(xDisplay, xBoardWindow,
7612 values.foreground = 1;
7613 values.background = 0;
7614 /* Don't use XtGetGC, not read only */
7615 maskGC = XCreateGC(xDisplay, buf,
7616 GCForeground | GCBackground, &values);
7617 XFreePixmap(xDisplay, buf);
7619 buf = XCreatePixmap(xDisplay, xBoardWindow,
7620 squareSize, squareSize, pieceDepth);
7621 values.foreground = XBlackPixel(xDisplay, xScreen);
7622 values.background = XWhitePixel(xDisplay, xScreen);
7623 bufGC = XCreateGC(xDisplay, buf,
7624 GCForeground | GCBackground, &values);
7626 for (piece = WhitePawn; piece <= BlackKing; piece++) {
7627 /* Begin with empty mask */
7628 if(!xpmDone) // [HGM] pieces: keep using existing
7629 xpmMask[piece] = XCreatePixmap(xDisplay, xBoardWindow,
7630 squareSize, squareSize, 1);
7631 XSetFunction(xDisplay, maskGC, GXclear);
7632 XFillRectangle(xDisplay, xpmMask[piece], maskGC,
7633 0, 0, squareSize, squareSize);
7635 /* Take a copy of the piece */
7640 XSetFunction(xDisplay, bufGC, GXcopy);
7641 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn],
7643 0, 0, squareSize, squareSize, 0, 0);
7645 /* XOR the background (light) over the piece */
7646 XSetFunction(xDisplay, bufGC, GXxor);
7648 XCopyArea(xDisplay, xpmLightSquare, buf, bufGC,
7649 0, 0, squareSize, squareSize, 0, 0);
7651 XSetForeground(xDisplay, bufGC, lightSquareColor);
7652 XFillRectangle(xDisplay, buf, bufGC, 0, 0, squareSize, squareSize);
7655 /* We now have an inverted piece image with the background
7656 erased. Construct mask by just selecting all the non-zero
7657 pixels - no need to reconstruct the original image. */
7658 XSetFunction(xDisplay, maskGC, GXor);
7660 /* Might be quicker to download an XImage and create bitmap
7661 data from it rather than this N copies per piece, but it
7662 only takes a fraction of a second and there is a much
7663 longer delay for loading the pieces. */
7664 for (n = 0; n < pieceDepth; n ++) {
7665 XCopyPlane(xDisplay, buf, xpmMask[piece], maskGC,
7666 0, 0, squareSize, squareSize,
7672 XFreePixmap(xDisplay, buf);
7673 XFreeGC(xDisplay, bufGC);
7674 XFreeGC(xDisplay, maskGC);
7678 InitAnimState (anim, info)
7680 XWindowAttributes * info;
7685 /* Each buffer is square size, same depth as window */
7686 anim->saveBuf = XCreatePixmap(xDisplay, xBoardWindow,
7687 squareSize, squareSize, info->depth);
7688 anim->newBuf = XCreatePixmap(xDisplay, xBoardWindow,
7689 squareSize, squareSize, info->depth);
7691 /* Create a plain GC for blitting */
7692 mask = GCForeground | GCBackground | GCFunction |
7693 GCPlaneMask | GCGraphicsExposures;
7694 values.foreground = XBlackPixel(xDisplay, xScreen);
7695 values.background = XWhitePixel(xDisplay, xScreen);
7696 values.function = GXcopy;
7697 values.plane_mask = AllPlanes;
7698 values.graphics_exposures = False;
7699 anim->blitGC = XCreateGC(xDisplay, xBoardWindow, mask, &values);
7701 /* Piece will be copied from an existing context at
7702 the start of each new animation/drag. */
7703 anim->pieceGC = XCreateGC(xDisplay, xBoardWindow, 0, &values);
7705 /* Outline will be a read-only copy of an existing */
7706 anim->outlineGC = None;
7712 static VariantClass old = (VariantClass) -1; // [HGM] pieces: redo every time variant changes
7713 XWindowAttributes info;
7715 if (xpmDone && gameInfo.variant == old) return;
7716 if(xpmDone) old = gameInfo.variant; // first time pieces might not be created yet
7717 // XGetWindowAttributes(xDisplay, xBoardWindow, &info);
7719 InitAnimState(&game, &info);
7720 InitAnimState(&player, &info);
7722 /* For XPM pieces, we need bitmaps to use as masks. */
7724 CreateAnimMasks(info.depth);
7730 static Boolean frameWaiting;
7732 static RETSIGTYPE FrameAlarm (sig)
7735 frameWaiting = False;
7736 /* In case System-V style signals. Needed?? */
7737 signal(SIGALRM, FrameAlarm);
7744 struct itimerval delay;
7746 XSync(xDisplay, False);
7749 frameWaiting = True;
7750 signal(SIGALRM, FrameAlarm);
7751 delay.it_interval.tv_sec =
7752 delay.it_value.tv_sec = time / 1000;
7753 delay.it_interval.tv_usec =
7754 delay.it_value.tv_usec = (time % 1000) * 1000;
7755 setitimer(ITIMER_REAL, &delay, NULL);
7757 /* Ugh -- busy-wait! --tpm */
7758 while (frameWaiting);
7760 while (frameWaiting) pause();
7762 delay.it_interval.tv_sec = delay.it_value.tv_sec = 0;
7763 delay.it_interval.tv_usec = delay.it_value.tv_usec = 0;
7764 setitimer(ITIMER_REAL, &delay, NULL);
7774 XSync(xDisplay, False);
7776 usleep(time * 1000);
7781 /* Convert board position to corner of screen rect and color */
7784 ScreenSquare(column, row, pt, color)
7785 int column; int row; XPoint * pt; int * color;
7788 pt->x = lineGap + ((BOARD_WIDTH-1)-column) * (squareSize + lineGap);
7789 pt->y = lineGap + row * (squareSize + lineGap);
7791 pt->x = lineGap + column * (squareSize + lineGap);
7792 pt->y = lineGap + ((BOARD_HEIGHT-1)-row) * (squareSize + lineGap);
7794 *color = SquareColor(row, column);
7797 /* Convert window coords to square */
7800 BoardSquare(x, y, column, row)
7801 int x; int y; int * column; int * row;
7803 *column = EventToSquare(x, BOARD_WIDTH);
7804 if (flipView && *column >= 0)
7805 *column = BOARD_WIDTH - 1 - *column;
7806 *row = EventToSquare(y, BOARD_HEIGHT);
7807 if (!flipView && *row >= 0)
7808 *row = BOARD_HEIGHT - 1 - *row;
7813 #undef Max /* just in case */
7815 #define Max(a, b) ((a) > (b) ? (a) : (b))
7816 #define Min(a, b) ((a) < (b) ? (a) : (b))
7819 SetRect(rect, x, y, width, height)
7820 XRectangle * rect; int x; int y; int width; int height;
7824 rect->width = width;
7825 rect->height = height;
7828 /* Test if two frames overlap. If they do, return
7829 intersection rect within old and location of
7830 that rect within new. */
7833 Intersect(old, new, size, area, pt)
7834 XPoint * old; XPoint * new;
7835 int size; XRectangle * area; XPoint * pt;
7837 if (old->x > new->x + size || new->x > old->x + size ||
7838 old->y > new->y + size || new->y > old->y + size) {
7841 SetRect(area, Max(new->x - old->x, 0), Max(new->y - old->y, 0),
7842 size - abs(old->x - new->x), size - abs(old->y - new->y));
7843 pt->x = Max(old->x - new->x, 0);
7844 pt->y = Max(old->y - new->y, 0);
7849 /* For two overlapping frames, return the rect(s)
7850 in the old that do not intersect with the new. */
7853 CalcUpdateRects(old, new, size, update, nUpdates)
7854 XPoint * old; XPoint * new; int size;
7855 XRectangle update[]; int * nUpdates;
7859 /* If old = new (shouldn't happen) then nothing to draw */
7860 if (old->x == new->x && old->y == new->y) {
7864 /* Work out what bits overlap. Since we know the rects
7865 are the same size we don't need a full intersect calc. */
7867 /* Top or bottom edge? */
7868 if (new->y > old->y) {
7869 SetRect(&(update[count]), old->x, old->y, size, new->y - old->y);
7871 } else if (old->y > new->y) {
7872 SetRect(&(update[count]), old->x, old->y + size - (old->y - new->y),
7873 size, old->y - new->y);
7876 /* Left or right edge - don't overlap any update calculated above. */
7877 if (new->x > old->x) {
7878 SetRect(&(update[count]), old->x, Max(new->y, old->y),
7879 new->x - old->x, size - abs(new->y - old->y));
7881 } else if (old->x > new->x) {
7882 SetRect(&(update[count]), new->x + size, Max(new->y, old->y),
7883 old->x - new->x, size - abs(new->y - old->y));
7890 /* Generate a series of frame coords from start->mid->finish.
7891 The movement rate doubles until the half way point is
7892 reached, then halves back down to the final destination,
7893 which gives a nice slow in/out effect. The algorithmn
7894 may seem to generate too many intermediates for short
7895 moves, but remember that the purpose is to attract the
7896 viewers attention to the piece about to be moved and
7897 then to where it ends up. Too few frames would be less
7901 Tween(start, mid, finish, factor, frames, nFrames)
7902 XPoint * start; XPoint * mid;
7903 XPoint * finish; int factor;
7904 XPoint frames[]; int * nFrames;
7906 int fraction, n, count;
7910 /* Slow in, stepping 1/16th, then 1/8th, ... */
7912 for (n = 0; n < factor; n++)
7914 for (n = 0; n < factor; n++) {
7915 frames[count].x = start->x + (mid->x - start->x) / fraction;
7916 frames[count].y = start->y + (mid->y - start->y) / fraction;
7918 fraction = fraction / 2;
7922 frames[count] = *mid;
7925 /* Slow out, stepping 1/2, then 1/4, ... */
7927 for (n = 0; n < factor; n++) {
7928 frames[count].x = finish->x - (finish->x - mid->x) / fraction;
7929 frames[count].y = finish->y - (finish->y - mid->y) / fraction;
7931 fraction = fraction * 2;
7936 /* Draw a piece on the screen without disturbing what's there */
7939 SelectGCMask(piece, clip, outline, mask)
7940 ChessSquare piece; GC * clip; GC * outline; Pixmap * mask;
7944 /* Bitmap for piece being moved. */
7945 if (appData.monoMode) {
7946 *mask = *pieceToSolid(piece);
7947 } else if (useImages) {
7949 *mask = xpmMask[piece];
7951 *mask = ximMaskPm[piece];
7954 *mask = *pieceToSolid(piece);
7957 /* GC for piece being moved. Square color doesn't matter, but
7958 since it gets modified we make a copy of the original. */
7960 if (appData.monoMode)
7965 if (appData.monoMode)
7970 XCopyGC(xDisplay, source, 0xFFFFFFFF, *clip);
7972 /* Outline only used in mono mode and is not modified */
7974 *outline = bwPieceGC;
7976 *outline = wbPieceGC;
7980 OverlayPiece(piece, clip, outline, dest)
7981 ChessSquare piece; GC clip; GC outline; Drawable dest;
7986 /* Draw solid rectangle which will be clipped to shape of piece */
7987 XFillRectangle(xDisplay, dest, clip,
7988 0, 0, squareSize, squareSize);
7989 if (appData.monoMode)
7990 /* Also draw outline in contrasting color for black
7991 on black / white on white cases */
7992 XCopyPlane(xDisplay, *pieceToOutline(piece), dest, outline,
7993 0, 0, squareSize, squareSize, 0, 0, 1);
7995 /* Copy the piece */
8000 XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
8002 0, 0, squareSize, squareSize,
8007 /* Animate the movement of a single piece */
8010 BeginAnimation(anim, piece, startColor, start)
8018 /* The old buffer is initialised with the start square (empty) */
8019 BlankSquare(0, 0, startColor, EmptySquare, anim->saveBuf);
8020 anim->prevFrame = *start;
8022 /* The piece will be drawn using its own bitmap as a matte */
8023 SelectGCMask(piece, &anim->pieceGC, &anim->outlineGC, &mask);
8024 XSetClipMask(xDisplay, anim->pieceGC, mask);
8028 AnimationFrame(anim, frame, piece)
8033 XRectangle updates[4];
8038 /* Save what we are about to draw into the new buffer */
8039 XCopyArea(xDisplay, xBoardWindow, anim->newBuf, anim->blitGC,
8040 frame->x, frame->y, squareSize, squareSize,
8043 /* Erase bits of the previous frame */
8044 if (Intersect(&anim->prevFrame, frame, squareSize, &overlap, &pt)) {
8045 /* Where the new frame overlapped the previous,
8046 the contents in newBuf are wrong. */
8047 XCopyArea(xDisplay, anim->saveBuf, anim->newBuf, anim->blitGC,
8048 overlap.x, overlap.y,
8049 overlap.width, overlap.height,
8051 /* Repaint the areas in the old that don't overlap new */
8052 CalcUpdateRects(&anim->prevFrame, frame, squareSize, updates, &count);
8053 for (i = 0; i < count; i++)
8054 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
8055 updates[i].x - anim->prevFrame.x,
8056 updates[i].y - anim->prevFrame.y,
8057 updates[i].width, updates[i].height,
8058 updates[i].x, updates[i].y);
8060 /* Easy when no overlap */
8061 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
8062 0, 0, squareSize, squareSize,
8063 anim->prevFrame.x, anim->prevFrame.y);
8066 /* Save this frame for next time round */
8067 XCopyArea(xDisplay, anim->newBuf, anim->saveBuf, anim->blitGC,
8068 0, 0, squareSize, squareSize,
8070 anim->prevFrame = *frame;
8072 /* Draw piece over original screen contents, not current,
8073 and copy entire rect. Wipes out overlapping piece images. */
8074 OverlayPiece(piece, anim->pieceGC, anim->outlineGC, anim->newBuf);
8075 XCopyArea(xDisplay, anim->newBuf, xBoardWindow, anim->blitGC,
8076 0, 0, squareSize, squareSize,
8077 frame->x, frame->y);
8081 EndAnimation (anim, finish)
8085 XRectangle updates[4];
8090 /* The main code will redraw the final square, so we
8091 only need to erase the bits that don't overlap. */
8092 if (Intersect(&anim->prevFrame, finish, squareSize, &overlap, &pt)) {
8093 CalcUpdateRects(&anim->prevFrame, finish, squareSize, updates, &count);
8094 for (i = 0; i < count; i++)
8095 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
8096 updates[i].x - anim->prevFrame.x,
8097 updates[i].y - anim->prevFrame.y,
8098 updates[i].width, updates[i].height,
8099 updates[i].x, updates[i].y);
8101 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
8102 0, 0, squareSize, squareSize,
8103 anim->prevFrame.x, anim->prevFrame.y);
8108 FrameSequence(anim, piece, startColor, start, finish, frames, nFrames)
8110 ChessSquare piece; int startColor;
8111 XPoint * start; XPoint * finish;
8112 XPoint frames[]; int nFrames;
8116 BeginAnimation(anim, piece, startColor, start);
8117 for (n = 0; n < nFrames; n++) {
8118 AnimationFrame(anim, &(frames[n]), piece);
8119 FrameDelay(appData.animSpeed);
8121 EndAnimation(anim, finish);
8124 /* Main control logic for deciding what to animate and how */
8127 AnimateMove(board, fromX, fromY, toX, toY)
8136 XPoint start, finish, mid;
8137 XPoint frames[kFactor * 2 + 1];
8138 int nFrames, startColor, endColor;
8140 /* Are we animating? */
8141 if (!appData.animate || appData.blindfold)
8144 if(board[toY][toX] == WhiteRook && board[fromY][fromX] == WhiteKing ||
8145 board[toY][toX] == BlackRook && board[fromY][fromX] == BlackKing)
8146 return; // [HGM] FRC: no animtion of FRC castlings, as to-square is not true to-square
8148 if (fromY < 0 || fromX < 0 || toX < 0 || toY < 0) return;
8149 piece = board[fromY][fromX];
8150 if (piece >= EmptySquare) return;
8155 hop = (piece == WhiteKnight || piece == BlackKnight);
8158 if (appData.debugMode) {
8159 fprintf(debugFP, hop ? _("AnimateMove: piece %d hops from %d,%d to %d,%d \n") :
8160 _("AnimateMove: piece %d slides from %d,%d to %d,%d \n"),
8161 piece, fromX, fromY, toX, toY); }
8163 ScreenSquare(fromX, fromY, &start, &startColor);
8164 ScreenSquare(toX, toY, &finish, &endColor);
8167 /* Knight: make diagonal movement then straight */
8168 if (abs(toY - fromY) < abs(toX - fromX)) {
8169 mid.x = start.x + (finish.x - start.x) / 2;
8173 mid.y = start.y + (finish.y - start.y) / 2;
8176 mid.x = start.x + (finish.x - start.x) / 2;
8177 mid.y = start.y + (finish.y - start.y) / 2;
8180 /* Don't use as many frames for very short moves */
8181 if (abs(toY - fromY) + abs(toX - fromX) <= 2)
8182 Tween(&start, &mid, &finish, kFactor - 1, frames, &nFrames);
8184 Tween(&start, &mid, &finish, kFactor, frames, &nFrames);
8185 FrameSequence(&game, piece, startColor, &start, &finish, frames, nFrames);
8187 /* Be sure end square is redrawn */
8188 damage[toY][toX] = True;
8192 DragPieceBegin(x, y)
8195 int boardX, boardY, color;
8198 /* Are we animating? */
8199 if (!appData.animateDragging || appData.blindfold)
8202 /* Figure out which square we start in and the
8203 mouse position relative to top left corner. */
8204 BoardSquare(x, y, &boardX, &boardY);
8205 player.startBoardX = boardX;
8206 player.startBoardY = boardY;
8207 ScreenSquare(boardX, boardY, &corner, &color);
8208 player.startSquare = corner;
8209 player.startColor = color;
8211 /* Start from exactly where the piece is. This can be confusing
8212 if you start dragging far from the center of the square; most
8213 or all of the piece can be over a different square from the one
8214 the mouse pointer is in. */
8215 player.mouseDelta.x = x - corner.x;
8216 player.mouseDelta.y = y - corner.y;
8218 /* As soon as we start dragging, the piece will jump slightly to
8219 be centered over the mouse pointer. */
8220 player.mouseDelta.x = squareSize/2;
8221 player.mouseDelta.y = squareSize/2;
8223 /* Initialise animation */
8224 player.dragPiece = PieceForSquare(boardX, boardY);
8226 if (player.dragPiece >= 0 && player.dragPiece < EmptySquare) {
8227 player.dragActive = True;
8228 BeginAnimation(&player, player.dragPiece, color, &corner);
8229 /* Mark this square as needing to be redrawn. Note that
8230 we don't remove the piece though, since logically (ie
8231 as seen by opponent) the move hasn't been made yet. */
8232 if(boardX == BOARD_RGHT+1 && PieceForSquare(boardX-1, boardY) > 1 ||
8233 boardX == BOARD_LEFT-2 && PieceForSquare(boardX+1, boardY) > 1)
8234 XCopyArea(xDisplay, xBoardWindow, player.saveBuf, player.blitGC,
8235 corner.x, corner.y, squareSize, squareSize,
8236 0, 0); // [HGM] zh: unstack in stead of grab
8237 damage[boardY][boardX] = True;
8239 player.dragActive = False;
8249 /* Are we animating? */
8250 if (!appData.animateDragging || appData.blindfold)
8254 if (! player.dragActive)
8256 /* Move piece, maintaining same relative position
8257 of mouse within square */
8258 corner.x = x - player.mouseDelta.x;
8259 corner.y = y - player.mouseDelta.y;
8260 AnimationFrame(&player, &corner, player.dragPiece);
8262 if (appData.highlightDragging) {
8264 BoardSquare(x, y, &boardX, &boardY);
8265 SetHighlights(fromX, fromY, boardX, boardY);
8274 int boardX, boardY, color;
8277 /* Are we animating? */
8278 if (!appData.animateDragging || appData.blindfold)
8282 if (! player.dragActive)
8284 /* Last frame in sequence is square piece is
8285 placed on, which may not match mouse exactly. */
8286 BoardSquare(x, y, &boardX, &boardY);
8287 ScreenSquare(boardX, boardY, &corner, &color);
8288 EndAnimation(&player, &corner);
8290 /* Be sure end square is redrawn */
8291 damage[boardY][boardX] = True;
8293 /* This prevents weird things happening with fast successive
8294 clicks which on my Sun at least can cause motion events
8295 without corresponding press/release. */
8296 player.dragActive = False;
8299 /* Handle expose event while piece being dragged */
8304 if (!player.dragActive || appData.blindfold)
8307 /* What we're doing: logically, the move hasn't been made yet,
8308 so the piece is still in it's original square. But visually
8309 it's being dragged around the board. So we erase the square
8310 that the piece is on and draw it at the last known drag point. */
8311 BlankSquare(player.startSquare.x, player.startSquare.y,
8312 player.startColor, EmptySquare, xBoardWindow);
8313 AnimationFrame(&player, &player.prevFrame, player.dragPiece);
8314 damage[player.startBoardY][player.startBoardX] = TRUE;
8318 SetProgramStats( FrontEndProgramStats * stats )
8321 // [HGM] done, but perhaps backend should call this directly?
8322 EngineOutputUpdate( stats );