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 CommentPopUp P((char *title, char *label));
264 void CommentPopDown P((void));
265 void CommentCallback P((Widget w, XtPointer client_data,
266 XtPointer call_data));
267 void ICSInputBoxPopUp P((void));
268 void ICSInputBoxPopDown P((void));
269 void FileNamePopUp P((char *label, char *def,
270 FileProc proc, char *openMode));
271 void FileNamePopDown P((void));
272 void FileNameCallback P((Widget w, XtPointer client_data,
273 XtPointer call_data));
274 void FileNameAction P((Widget w, XEvent *event,
275 String *prms, Cardinal *nprms));
276 void AskQuestionReplyAction P((Widget w, XEvent *event,
277 String *prms, Cardinal *nprms));
278 void AskQuestionProc P((Widget w, XEvent *event,
279 String *prms, Cardinal *nprms));
280 void AskQuestionPopDown P((void));
281 void PromotionPopUp P((void));
282 void PromotionPopDown P((void));
283 void PromotionCallback P((Widget w, XtPointer client_data,
284 XtPointer call_data));
285 void EditCommentPopDown P((void));
286 void EditCommentCallback P((Widget w, XtPointer client_data,
287 XtPointer call_data));
288 void SelectCommand P((Widget w, XtPointer client_data, XtPointer call_data));
289 void LoadPositionProc P((Widget w, XEvent *event,
290 String *prms, Cardinal *nprms));
291 void LoadNextPositionProc P((Widget w, XEvent *event, String *prms,
293 void LoadPrevPositionProc P((Widget w, XEvent *event, String *prms,
295 void ReloadPositionProc P((Widget w, XEvent *event, String *prms,
297 void CopyPositionProc P((Widget w, XEvent *event, String *prms,
299 void PastePositionProc P((Widget w, XEvent *event, String *prms,
301 void CopyGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
302 void PasteGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
303 void SaveGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
304 void SavePositionProc P((Widget w, XEvent *event,
305 String *prms, Cardinal *nprms));
306 void MailMoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
307 void ReloadCmailMsgProc P((Widget w, XEvent *event, String *prms,
309 void MachineBlackProc P((Widget w, XEvent *event, String *prms,
311 void MachineWhiteProc P((Widget w, XEvent *event,
312 String *prms, Cardinal *nprms));
313 void AnalyzeModeProc P((Widget w, XEvent *event,
314 String *prms, Cardinal *nprms));
315 void AnalyzeFileProc P((Widget w, XEvent *event,
316 String *prms, Cardinal *nprms));
317 void TwoMachinesProc P((Widget w, XEvent *event, String *prms,
319 void IcsClientProc P((Widget w, XEvent *event, String *prms,
321 void EditGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
322 void EditPositionProc P((Widget w, XEvent *event,
323 String *prms, Cardinal *nprms));
324 void TrainingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
325 void EditCommentProc P((Widget w, XEvent *event,
326 String *prms, Cardinal *nprms));
327 void IcsInputBoxProc P((Widget w, XEvent *event,
328 String *prms, Cardinal *nprms));
329 void AcceptProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
330 void DeclineProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
331 void RematchProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
332 void CallFlagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
333 void DrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
334 void AbortProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
335 void AdjournProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
336 void ResignProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
337 void AdjuWhiteProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
338 void AdjuBlackProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
339 void AdjuDrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
340 void EnterKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
341 void StopObservingProc P((Widget w, XEvent *event, String *prms,
343 void StopExaminingProc P((Widget w, XEvent *event, String *prms,
345 void BackwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
346 void ForwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
347 void ToStartProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
348 void ToEndProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
349 void RevertProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
350 void TruncateGameProc P((Widget w, XEvent *event, String *prms,
352 void RetractMoveProc P((Widget w, XEvent *event, String *prms,
354 void MoveNowProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
355 void AlwaysQueenProc P((Widget w, XEvent *event, String *prms,
357 void AnimateDraggingProc P((Widget w, XEvent *event, String *prms,
359 void AnimateMovingProc P((Widget w, XEvent *event, String *prms,
361 void AutocommProc P((Widget w, XEvent *event, String *prms,
363 void AutoflagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
364 void AutoflipProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
365 void AutobsProc P((Widget w, XEvent *event, String *prms,
367 void AutoraiseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
368 void AutosaveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
369 void BlindfoldProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
370 void FlashMovesProc P((Widget w, XEvent *event, String *prms,
372 void FlipViewProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
373 void GetMoveListProc P((Widget w, XEvent *event, String *prms,
375 void HighlightDraggingProc P((Widget w, XEvent *event, String *prms,
377 void HighlightLastMoveProc P((Widget w, XEvent *event, String *prms,
379 void MoveSoundProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
380 void IcsAlarmProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
381 void OldSaveStyleProc P((Widget w, XEvent *event, String *prms,
383 void PeriodicUpdatesProc P((Widget w, XEvent *event, String *prms,
385 void PonderNextMoveProc P((Widget w, XEvent *event, String *prms,
387 void PopupMoveErrorsProc P((Widget w, XEvent *event, String *prms,
389 void PopupExitMessageProc P((Widget w, XEvent *event, String *prms,
391 void PremoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
392 void QuietPlayProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
393 void ShowThinkingProc P((Widget w, XEvent *event, String *prms,
395 void HideThinkingProc P((Widget w, XEvent *event, String *prms,
397 void TestLegalityProc P((Widget w, XEvent *event, String *prms,
399 void InfoProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
400 void ManProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
401 void HintProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
402 void BookProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
403 void AboutGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
404 void DebugProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
405 void NothingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
406 void Iconify P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
407 void DisplayMove P((int moveNumber));
408 void DisplayTitle P((char *title));
409 void ICSInitScript P((void));
410 int LoadGamePopUp P((FILE *f, int gameNumber, char *title));
411 void ErrorPopUp P((char *title, char *text, int modal));
412 void ErrorPopDown P((void));
413 static char *ExpandPathName P((char *path));
414 static void CreateAnimVars P((void));
415 void DragPieceBegin P((int x, int y));
416 static void DragPieceMove P((int x, int y));
417 void DragPieceEnd P((int x, int y));
418 static void DrawDragPiece P((void));
419 char *ModeToWidgetName P((GameMode mode));
420 void EngineOutputUpdate( FrontEndProgramStats * stats );
421 void ShuffleMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
422 void EngineMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
423 void UciMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
424 void TimeControlProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
425 void NewVariantProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
426 void FirstSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
427 void SecondSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
428 void ShufflePopDown P(());
429 void EnginePopDown P(());
430 void UciPopDown P(());
431 void TimeControlPopDown P(());
432 void NewVariantPopDown P(());
433 void SettingsPopDown P(());
435 * XBoard depends on Xt R4 or higher
437 int xtVersion = XtSpecificationRelease;
442 Pixel lightSquareColor, darkSquareColor, whitePieceColor, blackPieceColor,
443 jailSquareColor, highlightSquareColor, premoveHighlightColor;
444 Pixel lowTimeWarningColor;
446 #define LINE_TYPE_NORMAL 0
447 #define LINE_TYPE_HIGHLIGHT 1
448 #define LINE_TYPE_PRE 2
451 GC lightSquareGC, darkSquareGC, jailSquareGC, wdPieceGC, wlPieceGC,
452 bdPieceGC, blPieceGC, wbPieceGC, bwPieceGC, coordGC,
453 wjPieceGC, bjPieceGC;
454 Pixmap iconPixmap, wIconPixmap, bIconPixmap, xMarkPixmap;
455 Widget shellWidget, layoutWidget, formWidget, boardWidget, messageWidget,
456 whiteTimerWidget, blackTimerWidget, titleWidget, widgetList[16],
457 commentShell, promotionShell, whitePieceMenu, blackPieceMenu, dropMenu,
458 menuBarWidget, buttonBarWidget, editShell, errorShell, analysisShell,
459 ICSInputShell, fileNameShell, askQuestionShell;
460 Font clockFontID, coordFontID, countFontID;
461 XFontStruct *clockFontStruct, *coordFontStruct, *countFontStruct;
462 XtAppContext appContext;
464 char *oldICSInteractionTitle;
468 char installDir[] = "."; // [HGM] UCI: needed for UCI; probably needs run-time initializtion
470 Position commentX = -1, commentY = -1;
471 Dimension commentW, commentH;
473 int squareSize, smallLayout = 0, tinyLayout = 0,
474 marginW, marginH, // [HGM] for run-time resizing
475 fromX = -1, fromY = -1, toX, toY, commentUp = False, analysisUp = False,
476 ICSInputBoxUp = False, askQuestionUp = False,
477 filenameUp = False, promotionUp = False, pmFromX = -1, pmFromY = -1,
478 editUp = False, errorUp = False, errorExitStatus = -1, lineGap;
479 Pixel timerForegroundPixel, timerBackgroundPixel;
480 Pixel buttonForegroundPixel, buttonBackgroundPixel;
481 char *chessDir, *programName, *programVersion,
482 *gameCopyFilename, *gamePasteFilename;
486 Pixmap pieceBitmap[2][(int)BlackPawn];
487 Pixmap pieceBitmap2[2][(int)BlackPawn+4]; /* [HGM] pieces */
488 Pixmap xpmPieceBitmap[4][(int)BlackPawn]; /* LL, LD, DL, DD actually used*/
489 Pixmap xpmPieceBitmap2[4][(int)BlackPawn+4]; /* LL, LD, DL, DD set to select from */
490 Pixmap xpmLightSquare, xpmDarkSquare, xpmJailSquare;
491 int useImages=0, useImageSqs;
492 XImage *ximPieceBitmap[4][(int)BlackPawn+4]; /* LL, LD, DL, DD */
493 Pixmap ximMaskPm[(int)BlackPawn]; /* clipmasks, used for XIM pieces */
494 Pixmap ximMaskPm2[(int)BlackPawn+4]; /* clipmasks, used for XIM pieces */
495 XImage *ximLightSquare, *ximDarkSquare;
498 #define pieceToSolid(piece) &pieceBitmap[SOLID][(piece) % (int)BlackPawn]
499 #define pieceToOutline(piece) &pieceBitmap[OUTLINE][(piece) % (int)BlackPawn]
501 #define White(piece) ((int)(piece) < (int)BlackPawn)
503 /* Variables for doing smooth animation. This whole thing
504 would be much easier if the board was double-buffered,
505 but that would require a fairly major rewrite. */
510 GC blitGC, pieceGC, outlineGC;
511 XPoint startSquare, prevFrame, mouseDelta;
515 int startBoardX, startBoardY;
518 /* There can be two pieces being animated at once: a player
519 can begin dragging a piece before the remote opponent has moved. */
521 static AnimState game, player;
523 /* Bitmaps for use as masks when drawing XPM pieces.
524 Need one for each black and white piece. */
525 static Pixmap xpmMask[BlackKing + 1];
527 /* This magic number is the number of intermediate frames used
528 in each half of the animation. For short moves it's reduced
529 by 1. The total number of frames will be factor * 2 + 1. */
532 SizeDefaults sizeDefaults[] = SIZE_DEFAULTS;
534 MenuItem fileMenu[] = {
535 {N_("New Shuffle Game ..."), ShuffleMenuProc},
536 {N_("New Variant ..."), NewVariantProc}, // [HGM] variant: not functional yet
537 {"----", NothingProc},
538 {N_("Save Game"), SaveGameProc},
539 {"----", NothingProc},
540 {N_("Copy Game"), CopyGameProc},
541 {N_("Paste Game"), PasteGameProc},
542 {"----", NothingProc},
543 {N_("Load Position"), LoadPositionProc},
544 {N_("Load Next Position"), LoadNextPositionProc},
545 {N_("Load Previous Position"), LoadPrevPositionProc},
546 {N_("Reload Same Position"), ReloadPositionProc},
547 {N_("Save Position"), SavePositionProc},
548 {"----", NothingProc},
549 {N_("Copy Position"), CopyPositionProc},
550 {N_("Paste Position"), PastePositionProc},
551 {"----", NothingProc},
552 {N_("Mail Move"), MailMoveProc},
553 {N_("Reload CMail Message"), ReloadCmailMsgProc},
554 {"----", NothingProc},
558 MenuItem modeMenu[] = {
559 {N_("Machine White"), MachineWhiteProc},
560 {N_("Machine Black"), MachineBlackProc},
561 {N_("Two Machines"), TwoMachinesProc},
562 {N_("Analysis Mode"), AnalyzeModeProc},
563 {N_("Analyze File"), AnalyzeFileProc },
564 {N_("ICS Client"), IcsClientProc},
565 {N_("Edit Game"), EditGameProc},
566 {N_("Edit Position"), EditPositionProc},
567 {N_("Training"), TrainingProc},
568 {"----", NothingProc},
569 {N_("Show Engine Output"), EngineOutputProc},
570 {N_("Show Evaluation Graph"), NothingProc}, // [HGM] evalgr: not functional yet
571 {N_("Show Game List"), ShowGameListProc},
572 {"Show Move History", HistoryShowProc}, // [HGM] hist: activate 4.2.7 code
573 {"----", NothingProc},
574 {N_("Edit Tags"), EditTagsProc},
575 {N_("Edit Comment"), EditCommentProc},
576 {N_("ICS Input Box"), IcsInputBoxProc},
580 MenuItem actionMenu[] = {
581 {N_("Accept"), AcceptProc},
582 {N_("Decline"), DeclineProc},
583 {N_("Rematch"), RematchProc},
584 {"----", NothingProc},
585 {N_("Call Flag"), CallFlagProc},
586 {N_("Draw"), DrawProc},
587 {N_("Adjourn"), AdjournProc},
588 {N_("Abort"), AbortProc},
589 {N_("Resign"), ResignProc},
590 {"----", NothingProc},
591 {N_("Stop Observing"), StopObservingProc},
592 {N_("Stop Examining"), StopExaminingProc},
593 {"----", NothingProc},
594 {N_("Adjudicate to White"), AdjuWhiteProc},
595 {N_("Adjudicate to Black"), AdjuBlackProc},
596 {N_("Adjudicate Draw"), AdjuDrawProc},
600 MenuItem stepMenu[] = {
601 {N_("Backward"), BackwardProc},
602 {N_("Forward"), ForwardProc},
603 {N_("Back to Start"), ToStartProc},
604 {N_("Forward to End"), ToEndProc},
605 {N_("Revert"), RevertProc},
606 {N_("Truncate Game"), TruncateGameProc},
607 {"----", NothingProc},
608 {N_("Move Now"), MoveNowProc},
609 {N_("Retract Move"), RetractMoveProc},
613 MenuItem optionsMenu[] = {
614 {N_("Flip View"), FlipViewProc},
615 {"----", NothingProc},
616 {N_("Adjudications ..."), EngineMenuProc},
617 {N_("General Settings ..."), UciMenuProc},
618 {N_("Engine #1 Settings ..."), FirstSettingsProc},
619 {N_("Engine #2 Settings ..."), SecondSettingsProc},
620 {N_("Time Control ..."), TimeControlProc},
621 {"----", NothingProc},
622 {N_("Always Queen"), AlwaysQueenProc},
623 {N_("Animate Dragging"), AnimateDraggingProc},
624 {N_("Animate Moving"), AnimateMovingProc},
625 {N_("Auto Comment"), AutocommProc},
626 {N_("Auto Flag"), AutoflagProc},
627 {N_("Auto Flip View"), AutoflipProc},
628 {N_("Auto Observe"), AutobsProc},
629 {N_("Auto Raise Board"), AutoraiseProc},
630 {N_("Auto Save"), AutosaveProc},
631 {N_("Blindfold"), BlindfoldProc},
632 {N_("Flash Moves"), FlashMovesProc},
633 {N_("Get Move List"), GetMoveListProc},
635 {N_("Highlight Dragging"), HighlightDraggingProc},
637 {N_("Highlight Last Move"), HighlightLastMoveProc},
638 {N_("Move Sound"), MoveSoundProc},
639 {N_("ICS Alarm"), IcsAlarmProc},
640 {N_("Old Save Style"), OldSaveStyleProc},
641 {N_("Periodic Updates"), PeriodicUpdatesProc},
642 {N_("Ponder Next Move"), PonderNextMoveProc},
643 {N_("Popup Exit Message"), PopupExitMessageProc},
644 {N_("Popup Move Errors"), PopupMoveErrorsProc},
645 {N_("Premove"), PremoveProc},
646 {N_("Quiet Play"), QuietPlayProc},
647 {N_("Hide Thinking"), HideThinkingProc},
648 {N_("Test Legality"), TestLegalityProc},
652 MenuItem helpMenu[] = {
653 {N_("Info XBoard"), InfoProc},
654 {N_("Man XBoard"), ManProc},
655 {"----", NothingProc},
656 {N_("Hint"), HintProc},
657 {N_("Book"), BookProc},
658 {"----", NothingProc},
663 {N_("File"), fileMenu},
664 {N_("Mode"), modeMenu},
665 {N_("Action"), actionMenu},
666 {N_("Step"), stepMenu},
667 {N_("Options"), optionsMenu},
668 {N_("Help"), helpMenu},
672 #define PAUSE_BUTTON N_("P")
673 MenuItem buttonBar[] = {
676 // {PAUSE_BUTTON, PauseProc},
682 #define PIECE_MENU_SIZE 18
683 String pieceMenuStrings[2][PIECE_MENU_SIZE] = {
684 { N_("White"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
685 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
686 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
687 N_("Empty square"), N_("Clear board") },
688 { N_("Black"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
689 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
690 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
691 N_("Empty square"), N_("Clear board") }
693 /* must be in same order as PieceMenuStrings! */
694 ChessSquare pieceMenuTranslation[2][PIECE_MENU_SIZE] = {
695 { WhitePlay, (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
696 WhiteRook, WhiteQueen, WhiteKing, (ChessSquare) 0, WhiteAlfil,
697 WhiteCannon, WhiteAngel, WhiteMarshall, (ChessSquare) 0,
698 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
699 { BlackPlay, (ChessSquare) 0, BlackPawn, BlackKnight, BlackBishop,
700 BlackRook, BlackQueen, BlackKing, (ChessSquare) 0, BlackAlfil,
701 BlackCannon, BlackAngel, BlackMarshall, (ChessSquare) 0,
702 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
705 #define DROP_MENU_SIZE 6
706 String dropMenuStrings[DROP_MENU_SIZE] = {
707 "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"), N_("Queen")
709 /* must be in same order as PieceMenuStrings! */
710 ChessSquare dropMenuTranslation[DROP_MENU_SIZE] = {
711 (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
712 WhiteRook, WhiteQueen
720 DropMenuEnables dmEnables[] = {
738 { XtNborderWidth, 0 },
739 { XtNdefaultDistance, 0 },
743 { XtNborderWidth, 0 },
744 { XtNresizable, (XtArgVal) True },
748 { XtNborderWidth, 0 },
754 { XtNjustify, (XtArgVal) XtJustifyRight },
755 { XtNlabel, (XtArgVal) "..." },
756 { XtNresizable, (XtArgVal) True },
757 { XtNresize, (XtArgVal) False }
760 Arg messageArgs[] = {
761 { XtNjustify, (XtArgVal) XtJustifyLeft },
762 { XtNlabel, (XtArgVal) "..." },
763 { XtNresizable, (XtArgVal) True },
764 { XtNresize, (XtArgVal) False }
768 { XtNborderWidth, 0 },
769 { XtNjustify, (XtArgVal) XtJustifyLeft }
772 XtResource clientResources[] = {
773 { "whitePieceColor", "whitePieceColor", XtRString, sizeof(String),
774 XtOffset(AppDataPtr, whitePieceColor), XtRString,
776 { "blackPieceColor", "blackPieceColor", XtRString, sizeof(String),
777 XtOffset(AppDataPtr, blackPieceColor), XtRString,
779 { "lightSquareColor", "lightSquareColor", XtRString,
780 sizeof(String), XtOffset(AppDataPtr, lightSquareColor),
781 XtRString, LIGHT_SQUARE_COLOR },
782 { "darkSquareColor", "darkSquareColor", XtRString, sizeof(String),
783 XtOffset(AppDataPtr, darkSquareColor), XtRString,
785 { "highlightSquareColor", "highlightSquareColor", XtRString,
786 sizeof(String), XtOffset(AppDataPtr, highlightSquareColor),
787 XtRString, HIGHLIGHT_SQUARE_COLOR },
788 { "premoveHighlightColor", "premoveHighlightColor", XtRString,
789 sizeof(String), XtOffset(AppDataPtr, premoveHighlightColor),
790 XtRString, PREMOVE_HIGHLIGHT_COLOR },
791 { "movesPerSession", "movesPerSession", XtRInt, sizeof(int),
792 XtOffset(AppDataPtr, movesPerSession), XtRImmediate,
793 (XtPointer) MOVES_PER_SESSION },
794 { "timeIncrement", "timeIncrement", XtRInt, sizeof(int),
795 XtOffset(AppDataPtr, timeIncrement), XtRImmediate,
796 (XtPointer) TIME_INCREMENT },
797 { "initString", "initString", XtRString, sizeof(String),
798 XtOffset(AppDataPtr, initString), XtRString, INIT_STRING },
799 { "secondInitString", "secondInitString", XtRString, sizeof(String),
800 XtOffset(AppDataPtr, secondInitString), XtRString, INIT_STRING },
801 { "firstComputerString", "firstComputerString", XtRString,
802 sizeof(String), XtOffset(AppDataPtr, firstComputerString), XtRString,
804 { "secondComputerString", "secondComputerString", XtRString,
805 sizeof(String), XtOffset(AppDataPtr, secondComputerString), XtRString,
807 { "firstChessProgram", "firstChessProgram", XtRString,
808 sizeof(String), XtOffset(AppDataPtr, firstChessProgram),
809 XtRString, FIRST_CHESS_PROGRAM },
810 { "secondChessProgram", "secondChessProgram", XtRString,
811 sizeof(String), XtOffset(AppDataPtr, secondChessProgram),
812 XtRString, SECOND_CHESS_PROGRAM },
813 { "firstPlaysBlack", "firstPlaysBlack", XtRBoolean,
814 sizeof(Boolean), XtOffset(AppDataPtr, firstPlaysBlack),
815 XtRImmediate, (XtPointer) False },
816 { "noChessProgram", "noChessProgram", XtRBoolean,
817 sizeof(Boolean), XtOffset(AppDataPtr, noChessProgram),
818 XtRImmediate, (XtPointer) False },
819 { "firstHost", "firstHost", XtRString, sizeof(String),
820 XtOffset(AppDataPtr, firstHost), XtRString, FIRST_HOST },
821 { "secondHost", "secondHost", XtRString, sizeof(String),
822 XtOffset(AppDataPtr, secondHost), XtRString, SECOND_HOST },
823 { "firstDirectory", "firstDirectory", XtRString, sizeof(String),
824 XtOffset(AppDataPtr, firstDirectory), XtRString, "." },
825 { "secondDirectory", "secondDirectory", XtRString, sizeof(String),
826 XtOffset(AppDataPtr, secondDirectory), XtRString, "." },
827 { "bitmapDirectory", "bitmapDirectory", XtRString,
828 sizeof(String), XtOffset(AppDataPtr, bitmapDirectory),
830 { "remoteShell", "remoteShell", XtRString, sizeof(String),
831 XtOffset(AppDataPtr, remoteShell), XtRString, REMOTE_SHELL },
832 { "remoteUser", "remoteUser", XtRString, sizeof(String),
833 XtOffset(AppDataPtr, remoteUser), XtRString, "" },
834 { "timeDelay", "timeDelay", XtRFloat, sizeof(float),
835 XtOffset(AppDataPtr, timeDelay), XtRString,
836 (XtPointer) TIME_DELAY_QUOTE },
837 { "timeControl", "timeControl", XtRString, sizeof(String),
838 XtOffset(AppDataPtr, timeControl), XtRString,
839 (XtPointer) TIME_CONTROL },
840 { "internetChessServerMode", "internetChessServerMode",
841 XtRBoolean, sizeof(Boolean),
842 XtOffset(AppDataPtr, icsActive), XtRImmediate,
844 { "internetChessServerHost", "internetChessServerHost",
845 XtRString, sizeof(String),
846 XtOffset(AppDataPtr, icsHost),
847 XtRString, (XtPointer) ICS_HOST },
848 { "internetChessServerPort", "internetChessServerPort",
849 XtRString, sizeof(String),
850 XtOffset(AppDataPtr, icsPort), XtRString,
851 (XtPointer) ICS_PORT },
852 { "internetChessServerCommPort", "internetChessServerCommPort",
853 XtRString, sizeof(String),
854 XtOffset(AppDataPtr, icsCommPort), XtRString,
856 { "internetChessServerLogonScript", "internetChessServerLogonScript",
857 XtRString, sizeof(String),
858 XtOffset(AppDataPtr, icsLogon), XtRString,
860 { "internetChessServerHelper", "internetChessServerHelper",
861 XtRString, sizeof(String),
862 XtOffset(AppDataPtr, icsHelper), XtRString, "" },
863 { "internetChessServerInputBox", "internetChessServerInputBox",
864 XtRBoolean, sizeof(Boolean),
865 XtOffset(AppDataPtr, icsInputBox), XtRImmediate,
867 { "icsAlarm", "icsAlarm",
868 XtRBoolean, sizeof(Boolean),
869 XtOffset(AppDataPtr, icsAlarm), XtRImmediate,
871 { "icsAlarmTime", "icsAlarmTime",
873 XtOffset(AppDataPtr, icsAlarmTime), XtRImmediate,
875 { "useTelnet", "useTelnet", XtRBoolean, sizeof(Boolean),
876 XtOffset(AppDataPtr, useTelnet), XtRImmediate,
878 { "telnetProgram", "telnetProgram", XtRString, sizeof(String),
879 XtOffset(AppDataPtr, telnetProgram), XtRString, TELNET_PROGRAM },
880 { "gateway", "gateway", XtRString, sizeof(String),
881 XtOffset(AppDataPtr, gateway), XtRString, "" },
882 { "loadGameFile", "loadGameFile", XtRString, sizeof(String),
883 XtOffset(AppDataPtr, loadGameFile), XtRString, "" },
884 { "loadGameIndex", "loadGameIndex",
886 XtOffset(AppDataPtr, loadGameIndex), XtRImmediate,
888 { "saveGameFile", "saveGameFile", XtRString, sizeof(String),
889 XtOffset(AppDataPtr, saveGameFile), XtRString, "" },
890 { "autoRaiseBoard", "autoRaiseBoard", XtRBoolean,
891 sizeof(Boolean), XtOffset(AppDataPtr, autoRaiseBoard),
892 XtRImmediate, (XtPointer) True },
893 { "autoSaveGames", "autoSaveGames", XtRBoolean,
894 sizeof(Boolean), XtOffset(AppDataPtr, autoSaveGames),
895 XtRImmediate, (XtPointer) False },
896 { "blindfold", "blindfold", XtRBoolean,
897 sizeof(Boolean), XtOffset(AppDataPtr, blindfold),
898 XtRImmediate, (XtPointer) False },
899 { "loadPositionFile", "loadPositionFile", XtRString,
900 sizeof(String), XtOffset(AppDataPtr, loadPositionFile),
902 { "loadPositionIndex", "loadPositionIndex",
904 XtOffset(AppDataPtr, loadPositionIndex), XtRImmediate,
906 { "savePositionFile", "savePositionFile", XtRString,
907 sizeof(String), XtOffset(AppDataPtr, savePositionFile),
909 { "matchMode", "matchMode", XtRBoolean, sizeof(Boolean),
910 XtOffset(AppDataPtr, matchMode), XtRImmediate, (XtPointer) False },
911 { "matchGames", "matchGames", XtRInt, sizeof(int),
912 XtOffset(AppDataPtr, matchGames), XtRImmediate,
914 { "monoMode", "monoMode", XtRBoolean, sizeof(Boolean),
915 XtOffset(AppDataPtr, monoMode), XtRImmediate,
917 { "debugMode", "debugMode", XtRBoolean, sizeof(Boolean),
918 XtOffset(AppDataPtr, debugMode), XtRImmediate,
920 { "clockMode", "clockMode", XtRBoolean, sizeof(Boolean),
921 XtOffset(AppDataPtr, clockMode), XtRImmediate,
923 { "boardSize", "boardSize", XtRString, sizeof(String),
924 XtOffset(AppDataPtr, boardSize), XtRString, "" },
925 { "searchTime", "searchTime", XtRString, sizeof(String),
926 XtOffset(AppDataPtr, searchTime), XtRString,
928 { "searchDepth", "searchDepth", XtRInt, sizeof(int),
929 XtOffset(AppDataPtr, searchDepth), XtRImmediate,
931 { "showCoords", "showCoords", XtRBoolean, sizeof(Boolean),
932 XtOffset(AppDataPtr, showCoords), XtRImmediate,
934 { "showJail", "showJail", XtRInt, sizeof(int),
935 XtOffset(AppDataPtr, showJail), XtRImmediate,
937 { "showThinking", "showThinking", XtRBoolean, sizeof(Boolean),
938 XtOffset(AppDataPtr, showThinking), XtRImmediate,
940 { "ponderNextMove", "ponderNextMove", XtRBoolean, sizeof(Boolean),
941 XtOffset(AppDataPtr, ponderNextMove), XtRImmediate,
943 { "periodicUpdates", "periodicUpdates", XtRBoolean, sizeof(Boolean),
944 XtOffset(AppDataPtr, periodicUpdates), XtRImmediate,
946 { "clockFont", "clockFont", XtRString, sizeof(String),
947 XtOffset(AppDataPtr, clockFont), XtRString, CLOCK_FONT },
948 { "coordFont", "coordFont", XtRString, sizeof(String),
949 XtOffset(AppDataPtr, coordFont), XtRString, COORD_FONT },
950 { "font", "font", XtRString, sizeof(String),
951 XtOffset(AppDataPtr, font), XtRString, DEFAULT_FONT },
952 { "ringBellAfterMoves", "ringBellAfterMoves",
953 XtRBoolean, sizeof(Boolean),
954 XtOffset(AppDataPtr, ringBellAfterMoves),
955 XtRImmediate, (XtPointer) False },
956 { "autoCallFlag", "autoCallFlag", XtRBoolean,
957 sizeof(Boolean), XtOffset(AppDataPtr, autoCallFlag),
958 XtRImmediate, (XtPointer) False },
959 { "autoFlipView", "autoFlipView", XtRBoolean,
960 sizeof(Boolean), XtOffset(AppDataPtr, autoFlipView),
961 XtRImmediate, (XtPointer) True },
962 { "autoObserve", "autoObserve", XtRBoolean,
963 sizeof(Boolean), XtOffset(AppDataPtr, autoObserve),
964 XtRImmediate, (XtPointer) False },
965 { "autoComment", "autoComment", XtRBoolean,
966 sizeof(Boolean), XtOffset(AppDataPtr, autoComment),
967 XtRImmediate, (XtPointer) False },
968 { "getMoveList", "getMoveList", XtRBoolean,
969 sizeof(Boolean), XtOffset(AppDataPtr, getMoveList),
970 XtRImmediate, (XtPointer) True },
972 { "highlightDragging", "highlightDragging", XtRBoolean,
973 sizeof(Boolean), XtOffset(AppDataPtr, highlightDragging),
974 XtRImmediate, (XtPointer) False },
976 { "highlightLastMove", "highlightLastMove", XtRBoolean,
977 sizeof(Boolean), XtOffset(AppDataPtr, highlightLastMove),
978 XtRImmediate, (XtPointer) False },
979 { "premove", "premove", XtRBoolean,
980 sizeof(Boolean), XtOffset(AppDataPtr, premove),
981 XtRImmediate, (XtPointer) True },
982 { "testLegality", "testLegality", XtRBoolean,
983 sizeof(Boolean), XtOffset(AppDataPtr, testLegality),
984 XtRImmediate, (XtPointer) True },
985 { "flipView", "flipView", XtRBoolean,
986 sizeof(Boolean), XtOffset(AppDataPtr, flipView),
987 XtRImmediate, (XtPointer) False },
988 { "cmail", "cmailGameName", XtRString, sizeof(String),
989 XtOffset(AppDataPtr, cmailGameName), XtRString, "" },
990 { "alwaysPromoteToQueen", "alwaysPromoteToQueen", XtRBoolean,
991 sizeof(Boolean), XtOffset(AppDataPtr, alwaysPromoteToQueen),
992 XtRImmediate, (XtPointer) False },
993 { "oldSaveStyle", "oldSaveStyle", XtRBoolean,
994 sizeof(Boolean), XtOffset(AppDataPtr, oldSaveStyle),
995 XtRImmediate, (XtPointer) False },
996 { "quietPlay", "quietPlay", XtRBoolean,
997 sizeof(Boolean), XtOffset(AppDataPtr, quietPlay),
998 XtRImmediate, (XtPointer) False },
999 { "titleInWindow", "titleInWindow", XtRBoolean,
1000 sizeof(Boolean), XtOffset(AppDataPtr, titleInWindow),
1001 XtRImmediate, (XtPointer) False },
1002 { "localLineEditing", "localLineEditing", XtRBoolean,
1003 sizeof(Boolean), XtOffset(AppDataPtr, localLineEditing),
1004 XtRImmediate, (XtPointer) True }, /* not implemented, must be True */
1006 { "zippyTalk", "zippyTalk", XtRBoolean,
1007 sizeof(Boolean), XtOffset(AppDataPtr, zippyTalk),
1008 XtRImmediate, (XtPointer) ZIPPY_TALK },
1009 { "zippyPlay", "zippyPlay", XtRBoolean,
1010 sizeof(Boolean), XtOffset(AppDataPtr, zippyPlay),
1011 XtRImmediate, (XtPointer) ZIPPY_PLAY },
1012 { "zippyLines", "zippyLines", XtRString, sizeof(String),
1013 XtOffset(AppDataPtr, zippyLines), XtRString, ZIPPY_LINES },
1014 { "zippyPinhead", "zippyPinhead", XtRString, sizeof(String),
1015 XtOffset(AppDataPtr, zippyPinhead), XtRString, ZIPPY_PINHEAD },
1016 { "zippyPassword", "zippyPassword", XtRString, sizeof(String),
1017 XtOffset(AppDataPtr, zippyPassword), XtRString, ZIPPY_PASSWORD },
1018 { "zippyPassword2", "zippyPassword2", XtRString, sizeof(String),
1019 XtOffset(AppDataPtr, zippyPassword2), XtRString, ZIPPY_PASSWORD2 },
1020 { "zippyWrongPassword", "zippyWrongPassword", XtRString, sizeof(String),
1021 XtOffset(AppDataPtr, zippyWrongPassword), XtRString,
1022 ZIPPY_WRONG_PASSWORD },
1023 { "zippyAcceptOnly", "zippyAcceptOnly", XtRString, sizeof(String),
1024 XtOffset(AppDataPtr, zippyAcceptOnly), XtRString, ZIPPY_ACCEPT_ONLY },
1025 { "zippyUseI", "zippyUseI", XtRBoolean,
1026 sizeof(Boolean), XtOffset(AppDataPtr, zippyUseI),
1027 XtRImmediate, (XtPointer) ZIPPY_USE_I },
1028 { "zippyBughouse", "zippyBughouse", XtRInt,
1029 sizeof(int), XtOffset(AppDataPtr, zippyBughouse),
1030 XtRImmediate, (XtPointer) ZIPPY_BUGHOUSE },
1031 { "zippyNoplayCrafty", "zippyNoplayCrafty", XtRBoolean,
1032 sizeof(Boolean), XtOffset(AppDataPtr, zippyNoplayCrafty),
1033 XtRImmediate, (XtPointer) ZIPPY_NOPLAY_CRAFTY },
1034 { "zippyGameEnd", "zippyGameEnd", XtRString, sizeof(String),
1035 XtOffset(AppDataPtr, zippyGameEnd), XtRString, ZIPPY_GAME_END },
1036 { "zippyGameStart", "zippyGameStart", XtRString, sizeof(String),
1037 XtOffset(AppDataPtr, zippyGameStart), XtRString, ZIPPY_GAME_START },
1038 { "zippyAdjourn", "zippyAdjourn", XtRBoolean,
1039 sizeof(Boolean), XtOffset(AppDataPtr, zippyAdjourn),
1040 XtRImmediate, (XtPointer) ZIPPY_ADJOURN },
1041 { "zippyAbort", "zippyAbort", XtRBoolean,
1042 sizeof(Boolean), XtOffset(AppDataPtr, zippyAbort),
1043 XtRImmediate, (XtPointer) ZIPPY_ABORT },
1044 { "zippyVariants", "zippyVariants", XtRString, sizeof(String),
1045 XtOffset(AppDataPtr, zippyVariants), XtRString, ZIPPY_VARIANTS },
1046 { "zippyMaxGames", "zippyMaxGames", XtRInt, sizeof(int),
1047 XtOffset(AppDataPtr, zippyMaxGames), XtRImmediate,
1048 (XtPointer) ZIPPY_MAX_GAMES },
1049 { "zippyReplayTimeout", "zippyReplayTimeout", XtRInt, sizeof(int),
1050 XtOffset(AppDataPtr, zippyReplayTimeout), XtRImmediate,
1051 (XtPointer) ZIPPY_REPLAY_TIMEOUT },
1052 { "zippyShortGame", "zippyShortGame", XtRInt, sizeof(int),
1053 XtOffset(AppDataPtr, zippyShortGame), XtRImmediate,
1056 { "flashCount", "flashCount", XtRInt, sizeof(int),
1057 XtOffset(AppDataPtr, flashCount), XtRImmediate,
1058 (XtPointer) FLASH_COUNT },
1059 { "flashRate", "flashRate", XtRInt, sizeof(int),
1060 XtOffset(AppDataPtr, flashRate), XtRImmediate,
1061 (XtPointer) FLASH_RATE },
1062 { "pixmapDirectory", "pixmapDirectory", XtRString,
1063 sizeof(String), XtOffset(AppDataPtr, pixmapDirectory),
1065 { "msLoginDelay", "msLoginDelay", XtRInt, sizeof(int),
1066 XtOffset(AppDataPtr, msLoginDelay), XtRImmediate,
1067 (XtPointer) MS_LOGIN_DELAY },
1068 { "colorizeMessages", "colorizeMessages", XtRBoolean,
1069 sizeof(Boolean), XtOffset(AppDataPtr, colorize),
1070 XtRImmediate, (XtPointer) False },
1071 { "colorShout", "colorShout", XtRString,
1072 sizeof(String), XtOffset(AppDataPtr, colorShout),
1073 XtRString, COLOR_SHOUT },
1074 { "colorSShout", "colorSShout", XtRString,
1075 sizeof(String), XtOffset(AppDataPtr, colorSShout),
1076 XtRString, COLOR_SSHOUT },
1077 { "colorChannel1", "colorChannel1", XtRString,
1078 sizeof(String), XtOffset(AppDataPtr, colorChannel1),
1079 XtRString, COLOR_CHANNEL1 },
1080 { "colorChannel", "colorChannel", XtRString,
1081 sizeof(String), XtOffset(AppDataPtr, colorChannel),
1082 XtRString, COLOR_CHANNEL },
1083 { "colorKibitz", "colorKibitz", XtRString,
1084 sizeof(String), XtOffset(AppDataPtr, colorKibitz),
1085 XtRString, COLOR_KIBITZ },
1086 { "colorTell", "colorTell", XtRString,
1087 sizeof(String), XtOffset(AppDataPtr, colorTell),
1088 XtRString, COLOR_TELL },
1089 { "colorChallenge", "colorChallenge", XtRString,
1090 sizeof(String), XtOffset(AppDataPtr, colorChallenge),
1091 XtRString, COLOR_CHALLENGE },
1092 { "colorRequest", "colorRequest", XtRString,
1093 sizeof(String), XtOffset(AppDataPtr, colorRequest),
1094 XtRString, COLOR_REQUEST },
1095 { "colorSeek", "colorSeek", XtRString,
1096 sizeof(String), XtOffset(AppDataPtr, colorSeek),
1097 XtRString, COLOR_SEEK },
1098 { "colorNormal", "colorNormal", XtRString,
1099 sizeof(String), XtOffset(AppDataPtr, colorNormal),
1100 XtRString, COLOR_NORMAL },
1101 { "soundProgram", "soundProgram", XtRString,
1102 sizeof(String), XtOffset(AppDataPtr, soundProgram),
1103 XtRString, "play" },
1104 { "soundShout", "soundShout", XtRString,
1105 sizeof(String), XtOffset(AppDataPtr, soundShout),
1107 { "soundSShout", "soundSShout", XtRString,
1108 sizeof(String), XtOffset(AppDataPtr, soundSShout),
1110 { "soundChannel1", "soundChannel1", XtRString,
1111 sizeof(String), XtOffset(AppDataPtr, soundChannel1),
1113 { "soundChannel", "soundChannel", XtRString,
1114 sizeof(String), XtOffset(AppDataPtr, soundChannel),
1116 { "soundKibitz", "soundKibitz", XtRString,
1117 sizeof(String), XtOffset(AppDataPtr, soundKibitz),
1119 { "soundTell", "soundTell", XtRString,
1120 sizeof(String), XtOffset(AppDataPtr, soundTell),
1122 { "soundChallenge", "soundChallenge", XtRString,
1123 sizeof(String), XtOffset(AppDataPtr, soundChallenge),
1125 { "soundRequest", "soundRequest", XtRString,
1126 sizeof(String), XtOffset(AppDataPtr, soundRequest),
1128 { "soundSeek", "soundSeek", XtRString,
1129 sizeof(String), XtOffset(AppDataPtr, soundSeek),
1131 { "soundMove", "soundMove", XtRString,
1132 sizeof(String), XtOffset(AppDataPtr, soundMove),
1134 { "soundIcsWin", "soundIcsWin", XtRString,
1135 sizeof(String), XtOffset(AppDataPtr, soundIcsWin),
1137 { "soundIcsLoss", "soundIcsLoss", XtRString,
1138 sizeof(String), XtOffset(AppDataPtr, soundIcsLoss),
1140 { "soundIcsDraw", "soundIcsDraw", XtRString,
1141 sizeof(String), XtOffset(AppDataPtr, soundIcsDraw),
1143 { "soundIcsUnfinished", "soundIcsUnfinished", XtRString,
1144 sizeof(String), XtOffset(AppDataPtr, soundIcsUnfinished),
1146 { "soundIcsAlarm", "soundIcsAlarm", XtRString,
1147 sizeof(String), XtOffset(AppDataPtr, soundIcsAlarm),
1149 { "reuseFirst", "reuseFirst", XtRBoolean,
1150 sizeof(Boolean), XtOffset(AppDataPtr, reuseFirst),
1151 XtRImmediate, (XtPointer) True },
1152 { "reuseSecond", "reuseSecond", XtRBoolean,
1153 sizeof(Boolean), XtOffset(AppDataPtr, reuseSecond),
1154 XtRImmediate, (XtPointer) True },
1155 { "animateDragging", "animateDragging", XtRBoolean,
1156 sizeof(Boolean), XtOffset(AppDataPtr, animateDragging),
1157 XtRImmediate, (XtPointer) True },
1158 { "animateMoving", "animateMoving", XtRBoolean,
1159 sizeof(Boolean), XtOffset(AppDataPtr, animate),
1160 XtRImmediate, (XtPointer) True },
1161 { "animateSpeed", "animateSpeed", XtRInt,
1162 sizeof(int), XtOffset(AppDataPtr, animSpeed),
1163 XtRImmediate, (XtPointer)10 },
1164 { "popupExitMessage", "popupExitMessage", XtRBoolean,
1165 sizeof(Boolean), XtOffset(AppDataPtr, popupExitMessage),
1166 XtRImmediate, (XtPointer) True },
1167 { "popupMoveErrors", "popupMoveErrors", XtRBoolean,
1168 sizeof(Boolean), XtOffset(AppDataPtr, popupMoveErrors),
1169 XtRImmediate, (XtPointer) False },
1170 { "fontSizeTolerance", "fontSizeTolerance", XtRInt,
1171 sizeof(int), XtOffset(AppDataPtr, fontSizeTolerance),
1172 XtRImmediate, (XtPointer)4 },
1173 { "initialMode", "initialMode", XtRString,
1174 sizeof(String), XtOffset(AppDataPtr, initialMode),
1175 XtRImmediate, (XtPointer) "" },
1176 { "variant", "variant", XtRString,
1177 sizeof(String), XtOffset(AppDataPtr, variant),
1178 XtRImmediate, (XtPointer) "normal" },
1179 { "firstProtocolVersion", "firstProtocolVersion", XtRInt,
1180 sizeof(int), XtOffset(AppDataPtr, firstProtocolVersion),
1181 XtRImmediate, (XtPointer)PROTOVER },
1182 { "secondProtocolVersion", "secondProtocolVersion", XtRInt,
1183 sizeof(int), XtOffset(AppDataPtr, secondProtocolVersion),
1184 XtRImmediate, (XtPointer)PROTOVER },
1185 { "showButtonBar", "showButtonBar", XtRBoolean,
1186 sizeof(Boolean), XtOffset(AppDataPtr, showButtonBar),
1187 XtRImmediate, (XtPointer) True },
1188 { "lowTimeWarningColor", "lowTimeWarningColor", XtRString,
1189 sizeof(String), XtOffset(AppDataPtr, lowTimeWarningColor),
1190 XtRString, COLOR_LOWTIMEWARNING },
1191 { "lowTimeWarning", "lowTimeWarning", XtRBoolean,
1192 sizeof(Boolean), XtOffset(AppDataPtr, lowTimeWarning),
1193 XtRImmediate, (XtPointer) False },
1194 {"icsEngineAnalyze", "icsEngineAnalyze", XtRBoolean, /* [DM] icsEngineAnalyze */
1195 sizeof(Boolean), XtOffset(AppDataPtr, icsEngineAnalyze),
1196 XtRImmediate, (XtPointer) False },
1197 { "firstScoreAbs", "firstScoreAbs", XtRBoolean,
1198 sizeof(Boolean), XtOffset(AppDataPtr, firstScoreIsAbsolute),
1199 XtRImmediate, (XtPointer) False },
1200 { "secondScoreAbs", "secondScoreAbs", XtRBoolean,
1201 sizeof(Boolean), XtOffset(AppDataPtr, secondScoreIsAbsolute),
1202 XtRImmediate, (XtPointer) False },
1203 { "pgnExtendedInfo", "pgnExtendedInfo", XtRBoolean,
1204 sizeof(Boolean), XtOffset(AppDataPtr, saveExtendedInfoInPGN),
1205 XtRImmediate, (XtPointer) False },
1206 { "hideThinkingFromHuman", "hideThinkingFromHuman", XtRBoolean,
1207 sizeof(Boolean), XtOffset(AppDataPtr, hideThinkingFromHuman),
1208 XtRImmediate, (XtPointer) True },
1209 { "adjudicateLossThreshold", "adjudicateLossThreshold", XtRInt,
1210 sizeof(int), XtOffset(AppDataPtr, adjudicateLossThreshold),
1211 XtRImmediate, (XtPointer) 0},
1212 { "pgnEventHeader", "pgnEventHeader", XtRString,
1213 sizeof(String), XtOffset(AppDataPtr, pgnEventHeader),
1214 XtRImmediate, (XtPointer) "Computer Chess Game" },
1215 { "defaultFrcPosition", "defaultFrcPositon", XtRInt,
1216 sizeof(int), XtOffset(AppDataPtr, defaultFrcPosition),
1217 XtRImmediate, (XtPointer) -1},
1218 { "gameListTags", "gameListTags", XtRString,
1219 sizeof(String), XtOffset(AppDataPtr, gameListTags),
1220 XtRImmediate, (XtPointer) GLT_DEFAULT_TAGS },
1222 // [HGM] 4.3.xx options
1223 { "boardWidth", "boardWidth", XtRInt,
1224 sizeof(int), XtOffset(AppDataPtr, NrFiles),
1225 XtRImmediate, (XtPointer) -1},
1226 { "boardHeight", "boardHeight", XtRInt,
1227 sizeof(int), XtOffset(AppDataPtr, NrRanks),
1228 XtRImmediate, (XtPointer) -1},
1229 { "matchPause", "matchPause", XtRInt,
1230 sizeof(int), XtOffset(AppDataPtr, matchPause),
1231 XtRImmediate, (XtPointer) 10000},
1232 { "holdingsSize", "holdingsSize", XtRInt,
1233 sizeof(int), XtOffset(AppDataPtr, holdingsSize),
1234 XtRImmediate, (XtPointer) -1},
1235 { "flipBlack", "flipBlack", XtRBoolean,
1236 sizeof(Boolean), XtOffset(AppDataPtr, upsideDown),
1237 XtRImmediate, (XtPointer) False},
1238 { "allWhite", "allWhite", XtRBoolean,
1239 sizeof(Boolean), XtOffset(AppDataPtr, allWhite),
1240 XtRImmediate, (XtPointer) False},
1241 { "pieceToCharTable", "pieceToCharTable", XtRString,
1242 sizeof(String), XtOffset(AppDataPtr, pieceToCharTable),
1243 XtRImmediate, (XtPointer) 0},
1244 { "alphaRank", "alphaRank", XtRBoolean,
1245 sizeof(Boolean), XtOffset(AppDataPtr, alphaRank),
1246 XtRImmediate, (XtPointer) False},
1247 { "testClaims", "testClaims", XtRBoolean,
1248 sizeof(Boolean), XtOffset(AppDataPtr, testClaims),
1249 XtRImmediate, (XtPointer) True},
1250 { "checkMates", "checkMates", XtRBoolean,
1251 sizeof(Boolean), XtOffset(AppDataPtr, checkMates),
1252 XtRImmediate, (XtPointer) True},
1253 { "materialDraws", "materialDraws", XtRBoolean,
1254 sizeof(Boolean), XtOffset(AppDataPtr, materialDraws),
1255 XtRImmediate, (XtPointer) True},
1256 { "trivialDraws", "trivialDraws", XtRBoolean,
1257 sizeof(Boolean), XtOffset(AppDataPtr, trivialDraws),
1258 XtRImmediate, (XtPointer) False},
1259 { "ruleMoves", "ruleMoves", XtRInt,
1260 sizeof(int), XtOffset(AppDataPtr, ruleMoves),
1261 XtRImmediate, (XtPointer) 51},
1262 { "repeatsToDraw", "repeatsToDraw", XtRInt,
1263 sizeof(int), XtOffset(AppDataPtr, drawRepeats),
1264 XtRImmediate, (XtPointer) 6},
1265 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1266 sizeof(int), XtOffset(AppDataPtr, engineComments),
1267 XtRImmediate, (XtPointer) 1},
1268 { "userName", "userName", XtRString,
1269 sizeof(int), XtOffset(AppDataPtr, userName),
1270 XtRImmediate, (XtPointer) 0},
1271 { "autoKibitz", "autoKibitz", XtRBoolean,
1272 sizeof(Boolean), XtOffset(AppDataPtr, autoKibitz),
1273 XtRImmediate, (XtPointer) False},
1274 { "firstTimeOdds", "firstTimeOdds", XtRInt,
1275 sizeof(int), XtOffset(AppDataPtr, firstTimeOdds),
1276 XtRImmediate, (XtPointer) 1},
1277 { "secondTimeOdds", "secondTimeOdds", XtRInt,
1278 sizeof(int), XtOffset(AppDataPtr, secondTimeOdds),
1279 XtRImmediate, (XtPointer) 1},
1280 { "timeOddsMode", "timeOddsMode", XtRInt,
1281 sizeof(int), XtOffset(AppDataPtr, timeOddsMode),
1282 XtRImmediate, (XtPointer) 0},
1283 { "firstAccumulateTC", "firstAccumulateTC", XtRInt,
1284 sizeof(int), XtOffset(AppDataPtr, firstAccumulateTC),
1285 XtRImmediate, (XtPointer) 1},
1286 { "secondAccumulateTC", "secondAccumulateTC", XtRInt,
1287 sizeof(int), XtOffset(AppDataPtr, secondAccumulateTC),
1288 XtRImmediate, (XtPointer) 1},
1289 { "firstNPS", "firstNPS", XtRInt,
1290 sizeof(int), XtOffset(AppDataPtr, firstNPS),
1291 XtRImmediate, (XtPointer) -1},
1292 { "secondNPS", "secondNPS", XtRInt,
1293 sizeof(int), XtOffset(AppDataPtr, secondNPS),
1294 XtRImmediate, (XtPointer) -1},
1295 { "serverMoves", "serverMoves", XtRString,
1296 sizeof(String), XtOffset(AppDataPtr, serverMovesName),
1297 XtRImmediate, (XtPointer) 0},
1298 { "serverPause", "serverPause", XtRInt,
1299 sizeof(int), XtOffset(AppDataPtr, serverPause),
1300 XtRImmediate, (XtPointer) 0},
1301 { "suppressLoadMoves", "suppressLoadMoves", XtRBoolean,
1302 sizeof(Boolean), XtOffset(AppDataPtr, suppressLoadMoves),
1303 XtRImmediate, (XtPointer) False},
1304 { "userName", "userName", XtRString,
1305 sizeof(String), XtOffset(AppDataPtr, userName),
1306 XtRImmediate, (XtPointer) 0},
1307 { "egtFormats", "egtFormats", XtRString,
1308 sizeof(String), XtOffset(AppDataPtr, egtFormats),
1309 XtRImmediate, (XtPointer) 0},
1310 { "rewindIndex", "rewindIndex", XtRInt,
1311 sizeof(int), XtOffset(AppDataPtr, rewindIndex),
1312 XtRImmediate, (XtPointer) 0},
1313 { "sameColorGames", "sameColorGames", XtRInt,
1314 sizeof(int), XtOffset(AppDataPtr, sameColorGames),
1315 XtRImmediate, (XtPointer) 0},
1316 { "smpCores", "smpCores", XtRInt,
1317 sizeof(int), XtOffset(AppDataPtr, smpCores),
1318 XtRImmediate, (XtPointer) 1},
1319 { "niceEngines", "niceEngines", XtRInt,
1320 sizeof(int), XtOffset(AppDataPtr, niceEngines),
1321 XtRImmediate, (XtPointer) 0},
1322 { "nameOfDebugFile", "nameOfDebugFile", XtRString,
1323 sizeof(String), XtOffset(AppDataPtr, nameOfDebugFile),
1324 XtRImmediate, (XtPointer) "xboard.debug"},
1325 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1326 sizeof(int), XtOffset(AppDataPtr, engineComments),
1327 XtRImmediate, (XtPointer) 0},
1328 { "noGUI", "noGUI", XtRBoolean,
1329 sizeof(Boolean), XtOffset(AppDataPtr, noGUI),
1330 XtRImmediate, (XtPointer) 0},
1331 { "firstOptions", "firstOptions", XtRString,
1332 sizeof(String), XtOffset(AppDataPtr, firstOptions),
1333 XtRImmediate, (XtPointer) "" },
1334 { "secondOptions", "secondOptions", XtRString,
1335 sizeof(String), XtOffset(AppDataPtr, secondOptions),
1336 XtRImmediate, (XtPointer) "" },
1337 { "firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XtRString,
1338 sizeof(String), XtOffset(AppDataPtr, fenOverride1),
1339 XtRImmediate, (XtPointer) 0 },
1340 { "secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XtRString,
1341 sizeof(String), XtOffset(AppDataPtr, fenOverride2),
1342 XtRImmediate, (XtPointer) 0 },
1344 // [HGM] Winboard_x UCI options
1345 { "firstIsUCI", "firstIsUCI", XtRBoolean,
1346 sizeof(Boolean), XtOffset(AppDataPtr, firstIsUCI),
1347 XtRImmediate, (XtPointer) False},
1348 { "secondIsUCI", "secondIsUCI", XtRBoolean,
1349 sizeof(Boolean), XtOffset(AppDataPtr, secondIsUCI),
1350 XtRImmediate, (XtPointer) False},
1351 { "firstHasOwnBookUCI", "firstHasOwnBookUCI", XtRBoolean,
1352 sizeof(Boolean), XtOffset(AppDataPtr, firstHasOwnBookUCI),
1353 XtRImmediate, (XtPointer) True},
1354 { "secondHasOwnBookUCI", "secondHasOwnBookUCI", XtRBoolean,
1355 sizeof(Boolean), XtOffset(AppDataPtr, secondHasOwnBookUCI),
1356 XtRImmediate, (XtPointer) True},
1357 { "usePolyglotBook", "usePolyglotBook", XtRBoolean,
1358 sizeof(Boolean), XtOffset(AppDataPtr, usePolyglotBook),
1359 XtRImmediate, (XtPointer) False},
1360 { "defaultHashSize", "defaultHashSize", XtRInt,
1361 sizeof(int), XtOffset(AppDataPtr, defaultHashSize),
1362 XtRImmediate, (XtPointer) 64},
1363 { "defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XtRInt,
1364 sizeof(int), XtOffset(AppDataPtr, defaultCacheSizeEGTB),
1365 XtRImmediate, (XtPointer) 4},
1366 { "polyglotDir", "polyglotDir", XtRString,
1367 sizeof(String), XtOffset(AppDataPtr, polyglotDir),
1368 XtRImmediate, (XtPointer) "." },
1369 { "polyglotBook", "polyglotBook", XtRString,
1370 sizeof(String), XtOffset(AppDataPtr, polyglotBook),
1371 XtRImmediate, (XtPointer) "" },
1372 { "defaultPathEGTB", "defaultPathEGTB", XtRString,
1373 sizeof(String), XtOffset(AppDataPtr, defaultPathEGTB),
1374 XtRImmediate, (XtPointer) "/usr/local/share/egtb"},
1375 { "delayBeforeQuit", "delayBeforeQuit", XtRInt,
1376 sizeof(int), XtOffset(AppDataPtr, delayBeforeQuit),
1377 XtRImmediate, (XtPointer) 0},
1378 { "delayAfterQuit", "delayAfterQuit", XtRInt,
1379 sizeof(int), XtOffset(AppDataPtr, delayAfterQuit),
1380 XtRImmediate, (XtPointer) 0},
1383 XrmOptionDescRec shellOptions[] = {
1384 { "-whitePieceColor", "whitePieceColor", XrmoptionSepArg, NULL },
1385 { "-blackPieceColor", "blackPieceColor", XrmoptionSepArg, NULL },
1386 { "-lightSquareColor", "lightSquareColor", XrmoptionSepArg, NULL },
1387 { "-darkSquareColor", "darkSquareColor", XrmoptionSepArg, NULL },
1388 { "-highlightSquareColor", "highlightSquareColor", XrmoptionSepArg, NULL },
1389 { "-premoveHighlightColor", "premoveHighlightColor", XrmoptionSepArg,NULL},
1390 { "-movesPerSession", "movesPerSession", XrmoptionSepArg, NULL },
1391 { "-mps", "movesPerSession", XrmoptionSepArg, NULL },
1392 { "-timeIncrement", "timeIncrement", XrmoptionSepArg, NULL },
1393 { "-inc", "timeIncrement", XrmoptionSepArg, NULL },
1394 { "-initString", "initString", XrmoptionSepArg, NULL },
1395 { "-firstInitString", "initString", XrmoptionSepArg, NULL },
1396 { "-secondInitString", "secondInitString", XrmoptionSepArg, NULL },
1397 { "-firstComputerString", "firstComputerString", XrmoptionSepArg, NULL },
1398 { "-secondComputerString", "secondComputerString", XrmoptionSepArg, NULL },
1399 { "-firstChessProgram", "firstChessProgram", XrmoptionSepArg, NULL },
1400 { "-fcp", "firstChessProgram", XrmoptionSepArg, NULL },
1401 { "-secondChessProgram", "secondChessProgram", XrmoptionSepArg, NULL },
1402 { "-scp", "secondChessProgram", XrmoptionSepArg, NULL },
1403 { "-firstPlaysBlack", "firstPlaysBlack", XrmoptionSepArg, NULL },
1404 { "-fb", "firstPlaysBlack", XrmoptionNoArg, "True" },
1405 { "-xfb", "firstPlaysBlack", XrmoptionNoArg, "False" },
1406 { "-noChessProgram", "noChessProgram", XrmoptionSepArg, NULL },
1407 { "-ncp", "noChessProgram", XrmoptionNoArg, "True" },
1408 { "-xncp", "noChessProgram", XrmoptionNoArg, "False" },
1409 { "-firstHost", "firstHost", XrmoptionSepArg, NULL },
1410 { "-fh", "firstHost", XrmoptionSepArg, NULL },
1411 { "-secondHost", "secondHost", XrmoptionSepArg, NULL },
1412 { "-sh", "secondHost", XrmoptionSepArg, NULL },
1413 { "-firstDirectory", "firstDirectory", XrmoptionSepArg, NULL },
1414 { "-fd", "firstDirectory", XrmoptionSepArg, NULL },
1415 { "-secondDirectory", "secondDirectory", XrmoptionSepArg, NULL },
1416 { "-sd", "secondDirectory", XrmoptionSepArg, NULL },
1417 { "-bitmapDirectory", "bitmapDirectory", XrmoptionSepArg, NULL },
1418 { "-bm", "bitmapDirectory", XrmoptionSepArg, NULL },
1419 { "-remoteShell", "remoteShell", XrmoptionSepArg, NULL },
1420 { "-rsh", "remoteShell", XrmoptionSepArg, NULL },
1421 { "-remoteUser", "remoteUser", XrmoptionSepArg, NULL },
1422 { "-ruser", "remoteUser", XrmoptionSepArg, NULL },
1423 { "-timeDelay", "timeDelay", XrmoptionSepArg, NULL },
1424 { "-td", "timeDelay", XrmoptionSepArg, NULL },
1425 { "-timeControl", "timeControl", XrmoptionSepArg, NULL },
1426 { "-tc", "timeControl", XrmoptionSepArg, NULL },
1427 { "-internetChessServerMode", "internetChessServerMode",
1428 XrmoptionSepArg, NULL },
1429 { "-ics", "internetChessServerMode", XrmoptionNoArg, "True" },
1430 { "-xics", "internetChessServerMode", XrmoptionNoArg, "False" },
1431 { "-internetChessServerHost", "internetChessServerHost",
1432 XrmoptionSepArg, NULL },
1433 { "-icshost", "internetChessServerHost", XrmoptionSepArg, NULL },
1434 { "-internetChessServerPort", "internetChessServerPort",
1435 XrmoptionSepArg, NULL },
1436 { "-icsport", "internetChessServerPort", XrmoptionSepArg, NULL },
1437 { "-internetChessServerCommPort", "internetChessServerCommPort",
1438 XrmoptionSepArg, NULL },
1439 { "-icscomm", "internetChessServerCommPort", XrmoptionSepArg, NULL },
1440 { "-internetChessServerLogonScript", "internetChessServerLogonScript",
1441 XrmoptionSepArg, NULL },
1442 { "-icslogon", "internetChessServerLogonScript", XrmoptionSepArg, NULL },
1443 { "-internetChessServerHelper", "internetChessServerHelper",
1444 XrmoptionSepArg, NULL },
1445 { "-icshelper", "internetChessServerHelper", XrmoptionSepArg, NULL },
1446 { "-internetChessServerInputBox", "internetChessServerInputBox",
1447 XrmoptionSepArg, NULL },
1448 { "-icsinput", "internetChessServerInputBox", XrmoptionNoArg, "True" },
1449 { "-xicsinput", "internetChessServerInputBox", XrmoptionNoArg, "False" },
1450 { "-icsAlarm", "icsAlarm", XrmoptionSepArg, NULL },
1451 { "-alarm", "icsAlarm", XrmoptionNoArg, "True" },
1452 { "-xalarm", "icsAlarm", XrmoptionNoArg, "False" },
1453 { "-icsAlarmTime", "icsAlarmTime", XrmoptionSepArg, NULL },
1454 { "-useTelnet", "useTelnet", XrmoptionSepArg, NULL },
1455 { "-telnet", "useTelnet", XrmoptionNoArg, "True" },
1456 { "-xtelnet", "useTelnet", XrmoptionNoArg, "False" },
1457 { "-telnetProgram", "telnetProgram", XrmoptionSepArg, NULL },
1458 { "-gateway", "gateway", XrmoptionSepArg, NULL },
1459 { "-loadGameFile", "loadGameFile", XrmoptionSepArg, NULL },
1460 { "-lgf", "loadGameFile", XrmoptionSepArg, NULL },
1461 { "-loadGameIndex", "loadGameIndex", XrmoptionSepArg, NULL },
1462 { "-lgi", "loadGameIndex", XrmoptionSepArg, NULL },
1463 { "-saveGameFile", "saveGameFile", XrmoptionSepArg, NULL },
1464 { "-sgf", "saveGameFile", XrmoptionSepArg, NULL },
1465 { "-autoSaveGames", "autoSaveGames", XrmoptionSepArg, NULL },
1466 { "-autosave", "autoSaveGames", XrmoptionNoArg, "True" },
1467 { "-xautosave", "autoSaveGames", XrmoptionNoArg, "False" },
1468 { "-autoRaiseBoard", "autoRaiseBoard", XrmoptionSepArg, NULL },
1469 { "-autoraise", "autoRaiseBoard", XrmoptionNoArg, "True" },
1470 { "-xautoraise", "autoRaiseBoard", XrmoptionNoArg, "False" },
1471 { "-blindfold", "blindfold", XrmoptionSepArg, NULL },
1472 { "-blind", "blindfold", XrmoptionNoArg, "True" },
1473 { "-xblind", "blindfold", XrmoptionNoArg, "False" },
1474 { "-loadPositionFile", "loadPositionFile", XrmoptionSepArg, NULL },
1475 { "-lpf", "loadPositionFile", XrmoptionSepArg, NULL },
1476 { "-loadPositionIndex", "loadPositionIndex", XrmoptionSepArg, NULL },
1477 { "-lpi", "loadPositionIndex", XrmoptionSepArg, NULL },
1478 { "-savePositionFile", "savePositionFile", XrmoptionSepArg, NULL },
1479 { "-spf", "savePositionFile", XrmoptionSepArg, NULL },
1480 { "-matchMode", "matchMode", XrmoptionSepArg, NULL },
1481 { "-mm", "matchMode", XrmoptionNoArg, "True" },
1482 { "-xmm", "matchMode", XrmoptionNoArg, "False" },
1483 { "-matchGames", "matchGames", XrmoptionSepArg, NULL },
1484 { "-mg", "matchGames", XrmoptionSepArg, NULL },
1485 { "-monoMode", "monoMode", XrmoptionSepArg, NULL },
1486 { "-mono", "monoMode", XrmoptionNoArg, "True" },
1487 { "-xmono", "monoMode", XrmoptionNoArg, "False" },
1488 { "-debugMode", "debugMode", XrmoptionSepArg, NULL },
1489 { "-debug", "debugMode", XrmoptionNoArg, "True" },
1490 { "-xdebug", "debugMode", XrmoptionNoArg, "False" },
1491 { "-clockMode", "clockMode", XrmoptionSepArg, NULL },
1492 { "-clock", "clockMode", XrmoptionNoArg, "True" },
1493 { "-xclock", "clockMode", XrmoptionNoArg, "False" },
1494 { "-boardSize", "boardSize", XrmoptionSepArg, NULL },
1495 { "-size", "boardSize", XrmoptionSepArg, NULL },
1496 { "-searchTime", "searchTime", XrmoptionSepArg, NULL },
1497 { "-st", "searchTime", XrmoptionSepArg, NULL },
1498 { "-searchDepth", "searchDepth", XrmoptionSepArg, NULL },
1499 { "-depth", "searchDepth", XrmoptionSepArg, NULL },
1500 { "-showCoords", "showCoords", XrmoptionSepArg, NULL },
1501 { "-coords", "showCoords", XrmoptionNoArg, "True" },
1502 { "-xcoords", "showCoords", XrmoptionNoArg, "False" },
1504 { "-showJail", "showJail", XrmoptionSepArg, NULL },
1505 { "-jail", "showJail", XrmoptionNoArg, "1" },
1506 { "-sidejail", "showJail", XrmoptionNoArg, "2" },
1507 { "-xjail", "showJail", XrmoptionNoArg, "0" },
1509 { "-showThinking", "showThinking", XrmoptionSepArg, NULL },
1510 { "-thinking", "showThinking", XrmoptionNoArg, "True" },
1511 { "-xthinking", "showThinking", XrmoptionNoArg, "False" },
1512 { "-ponderNextMove", "ponderNextMove", XrmoptionSepArg, NULL },
1513 { "-ponder", "ponderNextMove", XrmoptionNoArg, "True" },
1514 { "-xponder", "ponderNextMove", XrmoptionNoArg, "False" },
1515 { "-periodicUpdates", "periodicUpdates", XrmoptionSepArg, NULL },
1516 { "-periodic", "periodicUpdates", XrmoptionNoArg, "True" },
1517 { "-xperiodic", "periodicUpdates", XrmoptionNoArg, "False" },
1518 { "-clockFont", "clockFont", XrmoptionSepArg, NULL },
1519 { "-coordFont", "coordFont", XrmoptionSepArg, NULL },
1520 { "-font", "font", XrmoptionSepArg, NULL },
1521 { "-ringBellAfterMoves", "ringBellAfterMoves", XrmoptionSepArg, NULL },
1522 { "-bell", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1523 { "-xbell", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1524 { "-movesound", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1525 { "-xmovesound", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1526 { "-autoCallFlag", "autoCallFlag", XrmoptionSepArg, NULL },
1527 { "-autoflag", "autoCallFlag", XrmoptionNoArg, "True" },
1528 { "-xautoflag", "autoCallFlag", XrmoptionNoArg, "False" },
1529 { "-autoFlipView", "autoFlipView", XrmoptionSepArg, NULL },
1530 { "-autoflip", "autoFlipView", XrmoptionNoArg, "True" },
1531 { "-xautoflip", "autoFlipView", XrmoptionNoArg, "False" },
1532 { "-autoObserve", "autoObserve", XrmoptionSepArg, NULL },
1533 { "-autobs", "autoObserve", XrmoptionNoArg, "True" },
1534 { "-xautobs", "autoObserve", XrmoptionNoArg, "False" },
1535 { "-autoComment", "autoComment", XrmoptionSepArg, NULL },
1536 { "-autocomm", "autoComment", XrmoptionNoArg, "True" },
1537 { "-xautocomm", "autoComment", XrmoptionNoArg, "False" },
1538 { "-getMoveList", "getMoveList", XrmoptionSepArg, NULL },
1539 { "-moves", "getMoveList", XrmoptionNoArg, "True" },
1540 { "-xmoves", "getMoveList", XrmoptionNoArg, "False" },
1542 { "-highlightDragging", "highlightDragging", XrmoptionSepArg, NULL },
1543 { "-highdrag", "highlightDragging", XrmoptionNoArg, "True" },
1544 { "-xhighdrag", "highlightDragging", XrmoptionNoArg, "False" },
1546 { "-highlightLastMove", "highlightLastMove", XrmoptionSepArg, NULL },
1547 { "-highlight", "highlightLastMove", XrmoptionNoArg, "True" },
1548 { "-xhighlight", "highlightLastMove", XrmoptionNoArg, "False" },
1549 { "-premove", "premove", XrmoptionSepArg, NULL },
1550 { "-pre", "premove", XrmoptionNoArg, "True" },
1551 { "-xpre", "premove", XrmoptionNoArg, "False" },
1552 { "-testLegality", "testLegality", XrmoptionSepArg, NULL },
1553 { "-legal", "testLegality", XrmoptionNoArg, "True" },
1554 { "-xlegal", "testLegality", XrmoptionNoArg, "False" },
1555 { "-flipView", "flipView", XrmoptionSepArg, NULL },
1556 { "-flip", "flipView", XrmoptionNoArg, "True" },
1557 { "-xflip", "flipView", XrmoptionNoArg, "False" },
1558 { "-cmail", "cmailGameName", XrmoptionSepArg, NULL },
1559 { "-alwaysPromoteToQueen", "alwaysPromoteToQueen",
1560 XrmoptionSepArg, NULL },
1561 { "-queen", "alwaysPromoteToQueen", XrmoptionNoArg, "True" },
1562 { "-xqueen", "alwaysPromoteToQueen", XrmoptionNoArg, "False" },
1563 { "-oldSaveStyle", "oldSaveStyle", XrmoptionSepArg, NULL },
1564 { "-oldsave", "oldSaveStyle", XrmoptionNoArg, "True" },
1565 { "-xoldsave", "oldSaveStyle", XrmoptionNoArg, "False" },
1566 { "-quietPlay", "quietPlay", XrmoptionSepArg, NULL },
1567 { "-quiet", "quietPlay", XrmoptionNoArg, "True" },
1568 { "-xquiet", "quietPlay", XrmoptionNoArg, "False" },
1569 { "-titleInWindow", "titleInWindow", XrmoptionSepArg, NULL },
1570 { "-title", "titleInWindow", XrmoptionNoArg, "True" },
1571 { "-xtitle", "titleInWindow", XrmoptionNoArg, "False" },
1573 { "-zippyTalk", "zippyTalk", XrmoptionSepArg, NULL },
1574 { "-zt", "zippyTalk", XrmoptionNoArg, "True" },
1575 { "-xzt", "zippyTalk", XrmoptionNoArg, "False" },
1576 { "-zippyPlay", "zippyPlay", XrmoptionSepArg, NULL },
1577 { "-zp", "zippyPlay", XrmoptionNoArg, "True" },
1578 { "-xzp", "zippyPlay", XrmoptionNoArg, "False" },
1579 { "-zippyLines", "zippyLines", XrmoptionSepArg, NULL },
1580 { "-zippyPinhead", "zippyPinhead", XrmoptionSepArg, NULL },
1581 { "-zippyPassword", "zippyPassword", XrmoptionSepArg, NULL },
1582 { "-zippyPassword2", "zippyPassword2", XrmoptionSepArg, NULL },
1583 { "-zippyWrongPassword", "zippyWrongPassword", XrmoptionSepArg, NULL },
1584 { "-zippyAcceptOnly", "zippyAcceptOnly", XrmoptionSepArg, NULL },
1585 { "-zippyUseI", "zippyUseI", XrmoptionSepArg, NULL },
1586 { "-zui", "zippyUseI", XrmoptionNoArg, "True" },
1587 { "-xzui", "zippyUseI", XrmoptionNoArg, "False" },
1588 { "-zippyBughouse", "zippyBughouse", XrmoptionSepArg, NULL },
1589 { "-zippyNoplayCrafty", "zippyNoplayCrafty", XrmoptionSepArg, NULL },
1590 { "-znc", "zippyNoplayCrafty", XrmoptionNoArg, "True" },
1591 { "-xznc", "zippyNoplayCrafty", XrmoptionNoArg, "False" },
1592 { "-zippyGameEnd", "zippyGameEnd", XrmoptionSepArg, NULL },
1593 { "-zippyGameStart", "zippyGameStart", XrmoptionSepArg, NULL },
1594 { "-zippyAdjourn", "zippyAdjourn", XrmoptionSepArg, NULL },
1595 { "-zadj", "zippyAdjourn", XrmoptionNoArg, "True" },
1596 { "-xzadj", "zippyAdjourn", XrmoptionNoArg, "False" },
1597 { "-zippyAbort", "zippyAbort", XrmoptionSepArg, NULL },
1598 { "-zab", "zippyAbort", XrmoptionNoArg, "True" },
1599 { "-xzab", "zippyAbort", XrmoptionNoArg, "False" },
1600 { "-zippyVariants", "zippyVariants", XrmoptionSepArg, NULL },
1601 { "-zippyMaxGames", "zippyMaxGames", XrmoptionSepArg, NULL },
1602 { "-zippyReplayTimeout", "zippyReplayTimeout", XrmoptionSepArg, NULL },
1603 { "-zippyShortGame", "zippyShortGame", XrmoptionSepArg, NULL },
1605 { "-flashCount", "flashCount", XrmoptionSepArg, NULL },
1606 { "-flash", "flashCount", XrmoptionNoArg, "3" },
1607 { "-xflash", "flashCount", XrmoptionNoArg, "0" },
1608 { "-flashRate", "flashRate", XrmoptionSepArg, NULL },
1609 { "-pixmapDirectory", "pixmapDirectory", XrmoptionSepArg, NULL },
1610 { "-msLoginDelay", "msLoginDelay", XrmoptionSepArg, NULL },
1611 { "-pixmap", "pixmapDirectory", XrmoptionSepArg, NULL },
1612 { "-colorizeMessages", "colorizeMessages", XrmoptionSepArg, NULL },
1613 { "-colorize", "colorizeMessages", XrmoptionNoArg, "True" },
1614 { "-xcolorize", "colorizeMessages", XrmoptionNoArg, "False" },
1615 { "-colorShout", "colorShout", XrmoptionSepArg, NULL },
1616 { "-colorSShout", "colorSShout", XrmoptionSepArg, NULL },
1617 { "-colorCShout", "colorSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1618 { "-colorChannel1", "colorChannel1", XrmoptionSepArg, NULL },
1619 { "-colorChannel", "colorChannel", XrmoptionSepArg, NULL },
1620 { "-colorKibitz", "colorKibitz", XrmoptionSepArg, NULL },
1621 { "-colorTell", "colorTell", XrmoptionSepArg, NULL },
1622 { "-colorChallenge", "colorChallenge", XrmoptionSepArg, NULL },
1623 { "-colorRequest", "colorRequest", XrmoptionSepArg, NULL },
1624 { "-colorSeek", "colorSeek", XrmoptionSepArg, NULL },
1625 { "-colorNormal", "colorNormal", XrmoptionSepArg, NULL },
1626 { "-soundProgram", "soundProgram", XrmoptionSepArg, NULL },
1627 { "-soundShout", "soundShout", XrmoptionSepArg, NULL },
1628 { "-soundSShout", "soundSShout", XrmoptionSepArg, NULL },
1629 { "-soundCShout", "soundSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1630 { "-soundChannel1", "soundChannel1", XrmoptionSepArg, NULL },
1631 { "-soundChannel", "soundChannel", XrmoptionSepArg, NULL },
1632 { "-soundKibitz", "soundKibitz", XrmoptionSepArg, NULL },
1633 { "-soundTell", "soundTell", XrmoptionSepArg, NULL },
1634 { "-soundChallenge", "soundChallenge", XrmoptionSepArg, NULL },
1635 { "-soundRequest", "soundRequest", XrmoptionSepArg, NULL },
1636 { "-soundSeek", "soundSeek", XrmoptionSepArg, NULL },
1637 { "-soundMove", "soundMove", XrmoptionSepArg, NULL },
1638 { "-soundIcsWin", "soundIcsWin", XrmoptionSepArg, NULL },
1639 { "-soundIcsLoss", "soundIcsLoss", XrmoptionSepArg, NULL },
1640 { "-soundIcsDraw", "soundIcsDraw", XrmoptionSepArg, NULL },
1641 { "-soundIcsUnfinished", "soundIcsUnfinished", XrmoptionSepArg, NULL },
1642 { "-soundIcsAlarm", "soundIcsAlarm", XrmoptionSepArg, NULL },
1643 { "-reuseFirst", "reuseFirst", XrmoptionSepArg, NULL },
1644 { "-reuseChessPrograms", "reuseFirst", XrmoptionSepArg, NULL }, /*compat*/
1645 { "-reuse", "reuseFirst", XrmoptionNoArg, "True" },
1646 { "-xreuse", "reuseFirst", XrmoptionNoArg, "False" },
1647 { "-reuseSecond", "reuseSecond", XrmoptionSepArg, NULL },
1648 { "-reuse2", "reuseSecond", XrmoptionNoArg, "True" },
1649 { "-xreuse2", "reuseSecond", XrmoptionNoArg, "False" },
1650 { "-animateMoving", "animateMoving", XrmoptionSepArg, NULL },
1651 { "-animate", "animateMoving", XrmoptionNoArg, "True" },
1652 { "-xanimate", "animateMoving", XrmoptionNoArg, "False" },
1653 { "-animateDragging", "animateDragging", XrmoptionSepArg, NULL },
1654 { "-drag", "animateDragging", XrmoptionNoArg, "True" },
1655 { "-xdrag", "animateDragging", XrmoptionNoArg, "False" },
1656 { "-animateSpeed", "animateSpeed", XrmoptionSepArg, NULL },
1657 { "-popupExitMessage", "popupExitMessage", XrmoptionSepArg, NULL },
1658 { "-exit", "popupExitMessage", XrmoptionNoArg, "True" },
1659 { "-xexit", "popupExitMessage", XrmoptionNoArg, "False" },
1660 { "-popupMoveErrors", "popupMoveErrors", XrmoptionSepArg, NULL },
1661 { "-popup", "popupMoveErrors", XrmoptionNoArg, "True" },
1662 { "-xpopup", "popupMoveErrors", XrmoptionNoArg, "False" },
1663 { "-fontSizeTolerance", "fontSizeTolerance", XrmoptionSepArg, NULL },
1664 { "-initialMode", "initialMode", XrmoptionSepArg, NULL },
1665 { "-mode", "initialMode", XrmoptionSepArg, NULL },
1666 { "-variant", "variant", XrmoptionSepArg, NULL },
1667 { "-firstProtocolVersion", "firstProtocolVersion", XrmoptionSepArg, NULL },
1668 { "-secondProtocolVersion","secondProtocolVersion",XrmoptionSepArg, NULL },
1669 { "-showButtonBar", "showButtonBar", XrmoptionSepArg, NULL },
1670 { "-buttons", "showButtonBar", XrmoptionNoArg, "True" },
1671 { "-xbuttons", "showButtonBar", XrmoptionNoArg, "False" },
1672 { "-lowTimeWarningColor", "lowTimeWarningColor", XrmoptionSepArg, NULL },
1673 { "-lowTimeWarning", "lowTimeWarning", XrmoptionSepArg, NULL },
1674 /* [AS,HR] New features */
1675 { "-firstScoreAbs", "firstScoreAbs", XrmoptionSepArg, NULL },
1676 { "-secondScoreAbs", "secondScoreAbs", XrmoptionSepArg, NULL },
1677 { "-pgnExtendedInfo", "pgnExtendedInfo", XrmoptionSepArg, NULL },
1678 { "-hideThinkingFromHuman", "hideThinkingFromHuman", XrmoptionSepArg, NULL },
1679 { "-adjudicateLossThreshold", "adjudicateLossThreshold", XrmoptionSepArg, NULL },
1680 { "-pgnEventHeader", "pgnEventHeader", XrmoptionSepArg, NULL },
1681 { "-firstIsUCI", "firstIsUCI", XrmoptionSepArg, NULL },
1682 { "-secondIsUCI", "secondIsUCI", XrmoptionSepArg, NULL },
1683 { "-fUCI", "firstIsUCI", XrmoptionNoArg, "True" },
1684 { "-sUCI", "secondIsUCI", XrmoptionNoArg, "True" },
1685 { "-firstHasOwnBookUCI", "firstHasOwnBookUCI", XrmoptionSepArg, NULL },
1686 { "-secondHasOwnBookUCI", "secondHasOwnBookUCI", XrmoptionSepArg, NULL },
1687 { "-fNoOwnBookUCI", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1688 { "-sNoOwnBookUCI", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1689 { "-firstXBook", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1690 { "-secondXBook", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1691 { "-polyglotDir", "polyglotDir", XrmoptionSepArg, NULL },
1692 { "-usePolyglotBook", "usePolyglotBook", XrmoptionSepArg, NULL },
1693 { "-polyglotBook", "polyglotBook", XrmoptionSepArg, NULL },
1694 { "-defaultHashSize", "defaultHashSize", XrmoptionSepArg, NULL },
1695 { "-defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XrmoptionSepArg, NULL },
1696 { "-defaultPathEGTB", "defaultPathEGTB", XrmoptionSepArg, NULL },
1697 { "-defaultFrcPosition", "defaultFrcPosition", XrmoptionSepArg, NULL },
1698 { "-gameListTags", "gameListTags", XrmoptionSepArg, NULL },
1699 // [HGM] I am sure AS added many more options, but we have to fish them out, from the list in winboard.c
1701 /* [HGM,HR] User-selectable board size */
1702 { "-boardWidth", "boardWidth", XrmoptionSepArg, NULL },
1703 { "-boardHeight", "boardHeight", XrmoptionSepArg, NULL },
1704 { "-matchPause", "matchPause", XrmoptionSepArg, NULL },
1706 /* [HGM] new arguments of 4.3.xx. All except first three are back-end options, which should work immediately */
1707 { "-holdingsSize", "holdingsSize", XrmoptionSepArg, NULL }, // requires extensive front-end changes to work
1708 { "-flipBlack", "flipBlack", XrmoptionSepArg, NULL }, // requires front-end changes to work
1709 { "-allWhite", "allWhite", XrmoptionSepArg, NULL }, // requires front-end changes to work
1710 { "-pieceToCharTable", "pieceToCharTable", XrmoptionSepArg, NULL },
1711 { "-alphaRank", "alphaRank", XrmoptionSepArg, NULL },
1712 { "-testClaims", "testClaims", XrmoptionSepArg, NULL },
1713 { "-checkMates", "checkMates", XrmoptionSepArg, NULL },
1714 { "-materialDraws", "materialDraws", XrmoptionSepArg, NULL },
1715 { "-trivialDraws", "trivialDraws", XrmoptionSepArg, NULL },
1716 { "-ruleMoves", "ruleMoves", XrmoptionSepArg, NULL },
1717 { "-repeatsToDraw", "repeatsToDraw", XrmoptionSepArg, NULL },
1718 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1719 { "-userName", "userName", XrmoptionSepArg, NULL },
1720 { "-autoKibitz", "autoKibitz", XrmoptionNoArg, "True" },
1721 { "-firstTimeOdds", "firstTimeOdds", XrmoptionSepArg, NULL },
1722 { "-secondTimeOdds", "secondTimeOdds", XrmoptionSepArg, NULL },
1723 { "-timeOddsMode", "timeOddsMode", XrmoptionSepArg, NULL },
1724 { "-firstAccumulateTC", "firstAccumulateTC", XrmoptionSepArg, NULL },
1725 { "-secondAccumulateTC", "secondAccumulateTC", XrmoptionSepArg, NULL },
1726 { "-firstNPS", "firstNPS", XrmoptionSepArg, NULL },
1727 { "-secondNPS", "secondNPS", XrmoptionSepArg, NULL },
1728 { "-serverMoves", "serverMoves", XrmoptionSepArg, NULL },
1729 { "-serverPause", "serverPause", XrmoptionSepArg, NULL },
1730 { "-suppressLoadMoves", "suppressLoadMoves", XrmoptionSepArg, NULL },
1731 { "-egtFormats", "egtFormats", XrmoptionSepArg, NULL },
1732 { "-userName", "userName", XrmoptionSepArg, NULL },
1733 { "-smpCores", "smpCores", XrmoptionSepArg, NULL },
1734 { "-sameColorGames", "sameColorGames", XrmoptionSepArg, NULL },
1735 { "-rewindIndex", "rewindIndex", XrmoptionSepArg, NULL },
1736 { "-niceEngines", "niceEngines", XrmoptionSepArg, NULL },
1737 { "-delayBeforeQuit", "delayBeforeQuit", XrmoptionSepArg, NULL },
1738 { "-delayAfterQuit", "delayAfterQuit", XrmoptionSepArg, NULL },
1739 { "-nameOfDebugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1740 { "-debugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1741 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1742 { "-noGUI", "noGUI", XrmoptionNoArg, "True" },
1743 { "-firstOptions", "firstOptions", XrmoptionSepArg, NULL },
1744 { "-secondOptions", "secondOptions", XrmoptionSepArg, NULL },
1745 { "-firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1746 { "-secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1750 XtActionsRec boardActions[] = {
1751 { "HandleUserMove", HandleUserMove },
1752 { "AnimateUserMove", AnimateUserMove },
1753 { "FileNameAction", FileNameAction },
1754 { "AskQuestionProc", AskQuestionProc },
1755 { "AskQuestionReplyAction", AskQuestionReplyAction },
1756 { "PieceMenuPopup", PieceMenuPopup },
1757 { "WhiteClock", WhiteClock },
1758 { "BlackClock", BlackClock },
1759 { "Iconify", Iconify },
1760 { "LoadSelectedProc", LoadSelectedProc },
1761 { "LoadPositionProc", LoadPositionProc },
1762 { "LoadNextPositionProc", LoadNextPositionProc },
1763 { "LoadPrevPositionProc", LoadPrevPositionProc },
1764 { "ReloadPositionProc", ReloadPositionProc },
1765 { "CopyPositionProc", CopyPositionProc },
1766 { "PastePositionProc", PastePositionProc },
1767 { "CopyGameProc", CopyGameProc },
1768 { "PasteGameProc", PasteGameProc },
1769 { "SaveGameProc", SaveGameProc },
1770 { "SavePositionProc", SavePositionProc },
1771 { "MailMoveProc", MailMoveProc },
1772 { "ReloadCmailMsgProc", ReloadCmailMsgProc },
1773 { "MachineWhiteProc", MachineWhiteProc },
1774 { "MachineBlackProc", MachineBlackProc },
1775 { "AnalysisModeProc", AnalyzeModeProc },
1776 { "AnalyzeFileProc", AnalyzeFileProc },
1777 { "TwoMachinesProc", TwoMachinesProc },
1778 { "IcsClientProc", IcsClientProc },
1779 { "EditGameProc", EditGameProc },
1780 { "EditPositionProc", EditPositionProc },
1781 { "TrainingProc", EditPositionProc },
1782 { "EngineOutputProc", EngineOutputProc}, // [HGM] Winboard_x engine-output window
1783 { "ShowGameListProc", ShowGameListProc },
1784 { "ShowMoveListProc", HistoryShowProc},
1785 { "EditTagsProc", EditCommentProc },
1786 { "EditCommentProc", EditCommentProc },
1787 { "IcsAlarmProc", IcsAlarmProc },
1788 { "IcsInputBoxProc", IcsInputBoxProc },
1789 { "AcceptProc", AcceptProc },
1790 { "DeclineProc", DeclineProc },
1791 { "RematchProc", RematchProc },
1792 { "CallFlagProc", CallFlagProc },
1793 { "DrawProc", DrawProc },
1794 { "AdjournProc", AdjournProc },
1795 { "AbortProc", AbortProc },
1796 { "ResignProc", ResignProc },
1797 { "AdjuWhiteProc", AdjuWhiteProc },
1798 { "AdjuBlackProc", AdjuBlackProc },
1799 { "AdjuDrawProc", AdjuDrawProc },
1800 { "EnterKeyProc", EnterKeyProc },
1801 { "StopObservingProc", StopObservingProc },
1802 { "StopExaminingProc", StopExaminingProc },
1803 { "BackwardProc", BackwardProc },
1804 { "ForwardProc", ForwardProc },
1805 { "ToStartProc", ToStartProc },
1806 { "ToEndProc", ToEndProc },
1807 { "RevertProc", RevertProc },
1808 { "TruncateGameProc", TruncateGameProc },
1809 { "MoveNowProc", MoveNowProc },
1810 { "RetractMoveProc", RetractMoveProc },
1811 { "AlwaysQueenProc", AlwaysQueenProc },
1812 { "AnimateDraggingProc", AnimateDraggingProc },
1813 { "AnimateMovingProc", AnimateMovingProc },
1814 { "AutoflagProc", AutoflagProc },
1815 { "AutoflipProc", AutoflipProc },
1816 { "AutobsProc", AutobsProc },
1817 { "AutoraiseProc", AutoraiseProc },
1818 { "AutosaveProc", AutosaveProc },
1819 { "BlindfoldProc", BlindfoldProc },
1820 { "FlashMovesProc", FlashMovesProc },
1821 { "FlipViewProc", FlipViewProc },
1822 { "GetMoveListProc", GetMoveListProc },
1824 { "HighlightDraggingProc", HighlightDraggingProc },
1826 { "HighlightLastMoveProc", HighlightLastMoveProc },
1827 { "IcsAlarmProc", IcsAlarmProc },
1828 { "MoveSoundProc", MoveSoundProc },
1829 { "OldSaveStyleProc", OldSaveStyleProc },
1830 { "PeriodicUpdatesProc", PeriodicUpdatesProc },
1831 { "PonderNextMoveProc", PonderNextMoveProc },
1832 { "PopupExitMessageProc", PopupExitMessageProc },
1833 { "PopupMoveErrorsProc", PopupMoveErrorsProc },
1834 { "PremoveProc", PremoveProc },
1835 { "QuietPlayProc", QuietPlayProc },
1836 { "ShowThinkingProc", ShowThinkingProc },
1837 { "HideThinkingProc", HideThinkingProc },
1838 { "TestLegalityProc", TestLegalityProc },
1839 { "InfoProc", InfoProc },
1840 { "ManProc", ManProc },
1841 { "HintProc", HintProc },
1842 { "BookProc", BookProc },
1843 { "AboutGameProc", AboutGameProc },
1844 { "DebugProc", DebugProc },
1845 { "NothingProc", NothingProc },
1846 { "CommentPopDown", (XtActionProc) CommentPopDown },
1847 { "EditCommentPopDown", (XtActionProc) EditCommentPopDown },
1848 { "TagsPopDown", (XtActionProc) TagsPopDown },
1849 { "ErrorPopDown", (XtActionProc) ErrorPopDown },
1850 { "ICSInputBoxPopDown", (XtActionProc) ICSInputBoxPopDown },
1851 { "AnalysisPopDown", (XtActionProc) AnalysisPopDown },
1852 { "FileNamePopDown", (XtActionProc) FileNamePopDown },
1853 { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown },
1854 { "GameListPopDown", (XtActionProc) GameListPopDown },
1855 { "PromotionPopDown", (XtActionProc) PromotionPopDown },
1856 { "HistoryPopDown", (XtActionProc) HistoryPopDown },
1857 { "EngineOutputPopDown", (XtActionProc) EngineOutputPopDown },
1858 { "ShufflePopDown", (XtActionProc) ShufflePopDown },
1859 { "EnginePopDown", (XtActionProc) EnginePopDown },
1860 { "UciPopDown", (XtActionProc) UciPopDown },
1861 { "TimeControlPopDown", (XtActionProc) TimeControlPopDown },
1862 { "NewVariantPopDown", (XtActionProc) NewVariantPopDown },
1863 { "SettingsPopDown", (XtActionProc) SettingsPopDown },
1867 char ICSInputTranslations[] =
1868 "<Key>Return: EnterKeyProc() \n";
1870 String xboardResources[] = {
1871 "*fileName*value.translations: #override\\n <Key>Return: FileNameAction()",
1872 "*question*value.translations: #override\\n <Key>Return: AskQuestionReplyAction()",
1873 "*errorpopup*translations: #override\\n <Key>Return: ErrorPopDown()",
1877 static char *cnames[9] = { "black", "red", "green", "yellow", "blue",
1878 "magenta", "cyan", "white" };
1882 TextColors textColors[(int)NColorClasses];
1884 /* String is: "fg, bg, attr". Which is 0, 1, 2 */
1886 parse_color(str, which)
1890 char *p, buf[100], *d;
1893 if (strlen(str) > 99) /* watch bounds on buf */
1898 for (i=0; i<which; ++i) {
1905 /* Could be looking at something like:
1907 .. in which case we want to stop on a comma also */
1908 while (*p && *p != ',' && !isalpha(*p) && !isdigit(*p))
1912 return -1; /* Use default for empty field */
1915 if (which == 2 || isdigit(*p))
1918 while (*p && isalpha(*p))
1923 for (i=0; i<8; ++i) {
1924 if (!StrCaseCmp(buf, cnames[i]))
1925 return which? (i+40) : (i+30);
1927 if (!StrCaseCmp(buf, "default")) return -1;
1929 fprintf(stderr, _("%s: unrecognized color %s\n"), programName, buf);
1934 parse_cpair(cc, str)
1938 if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {
1939 fprintf(stderr, _("%s: can't parse foreground color in `%s'\n"),
1944 /* bg and attr are optional */
1945 textColors[(int)cc].bg = parse_color(str, 1);
1946 if ((textColors[(int)cc].attr = parse_color(str, 2)) < 0) {
1947 textColors[(int)cc].attr = 0;
1953 /* Arrange to catch delete-window events */
1954 Atom wm_delete_window;
1956 CatchDeleteWindow(Widget w, String procname)
1959 XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
1960 snprintf(buf, sizeof(buf), "<Message>WM_PROTOCOLS: %s() \n", procname);
1961 XtAugmentTranslations(w, XtParseTranslationTable(buf));
1967 /* this should raise the board to the top */
1968 gtk_window_present(GTK_WINDOW(GUI_Window));
1973 // eventually, all layout determining code should go into a subroutine, but until then IDSIZE remains undefined
1975 #define BoardSize int
1976 void InitDrawingSizes(BoardSize boardSize, int flags)
1977 { // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
1978 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
1980 XtGeometryResult gres;
1983 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
1984 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
1986 timerWidth = (boardWidth - sep) / 2;
1988 if (appData.titleInWindow)
1993 w = boardWidth - 2*bor;
1997 w = boardWidth - w - sep - 2*bor - 2; // WIDTH_FUDGE
2001 if(!formWidget) return;
2004 * Inhibit shell resizing.
2007 // [HGM] pieces: tailor piece bitmaps to needs of specific variant
2010 for(i=0; i<4; i++) {
2012 for(p=0; p<=(int)WhiteKing; p++)
2013 xpmPieceBitmap[i][p] = xpmPieceBitmap2[i][p]; // defaults
2014 if(gameInfo.variant == VariantShogi) {
2015 xpmPieceBitmap[i][(int)WhiteCannon] = xpmPieceBitmap2[i][(int)WhiteKing+1];
2016 xpmPieceBitmap[i][(int)WhiteNightrider] = xpmPieceBitmap2[i][(int)WhiteKing+2];
2017 xpmPieceBitmap[i][(int)WhiteSilver] = xpmPieceBitmap2[i][(int)WhiteKing+3];
2018 xpmPieceBitmap[i][(int)WhiteGrasshopper] = xpmPieceBitmap2[i][(int)WhiteKing+4];
2019 xpmPieceBitmap[i][(int)WhiteQueen] = xpmPieceBitmap2[i][(int)WhiteLance];
2022 if(gameInfo.variant == VariantGothic) {
2023 xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteSilver];
2027 // [HGM] why are thee ximMasks used at all? the ximPieceBitmaps seem to be never used!
2028 for(p=0; p<=(int)WhiteKing; p++)
2029 ximMaskPm[p] = ximMaskPm2[p]; // defaults
2030 if(gameInfo.variant == VariantShogi) {
2031 ximMaskPm[(int)WhiteCannon] = ximMaskPm2[(int)WhiteKing+1];
2032 ximMaskPm[(int)WhiteNightrider] = ximMaskPm2[(int)WhiteKing+2];
2033 ximMaskPm[(int)WhiteSilver] = ximMaskPm2[(int)WhiteKing+3];
2034 ximMaskPm[(int)WhiteGrasshopper] = ximMaskPm2[(int)WhiteKing+4];
2035 ximMaskPm[(int)WhiteQueen] = ximMaskPm2[(int)WhiteLance];
2038 if(gameInfo.variant == VariantGothic) {
2039 ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[i][(int)WhiteSilver];
2045 for(i=0; i<2; i++) {
2047 for(p=0; p<=(int)WhiteKing; p++)
2048 pieceBitmap[i][p] = pieceBitmap2[i][p]; // defaults
2049 if(gameInfo.variant == VariantShogi) {
2050 pieceBitmap[i][(int)WhiteCannon] = pieceBitmap2[i][(int)WhiteKing+1];
2051 pieceBitmap[i][(int)WhiteNightrider] = pieceBitmap2[i][(int)WhiteKing+2];
2052 pieceBitmap[i][(int)WhiteSilver] = pieceBitmap2[i][(int)WhiteKing+3];
2053 pieceBitmap[i][(int)WhiteGrasshopper] = pieceBitmap2[i][(int)WhiteKing+4];
2054 pieceBitmap[i][(int)WhiteQueen] = pieceBitmap2[i][(int)WhiteLance];
2057 if(gameInfo.variant == VariantGothic) {
2058 pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteSilver];
2074 int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
2075 XSetWindowAttributes window_attributes;
2077 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2078 XrmValue vFrom, vTo;
2079 XtGeometryResult gres;
2082 int forceMono = False;
2086 // [HGM] before anything else, expand any indirection files amongst options
2087 char *argvCopy[1000]; // 1000 seems enough
2088 char newArgs[10000]; // holds actual characters
2091 srandom(time(0)); // [HGM] book: make random truly random
2094 for(i=0; i<argc; i++) {
2095 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2096 //fprintf(stderr, "arg %s\n", argv[i]);
2097 if(argv[i][0] != '@') argvCopy[j++] = argv[i]; else {
2099 FILE *f = fopen(argv[i]+1, "rb");
2100 if(f == NULL) { fprintf(stderr, _("ignore %s\n"), argv[i]); continue; } // do not expand non-existing
2101 argvCopy[j++] = newArgs + k; // get ready for first argument from file
2102 while((c = fgetc(f)) != EOF) { // each line of file inserts 1 argument in the list
2104 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2105 newArgs[k++] = 0; // terminate current arg
2106 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2107 argvCopy[j++] = newArgs + k; // get ready for next
2109 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2122 if(appData.debugMode,1) { // OK, appData is not initialized here yet...
2123 for(i=0; i<argc; i++) fprintf(stderr, "argv[%2d] = '%s'\n", i, argv[i]);
2129 setbuf(stdout, NULL);
2130 setbuf(stderr, NULL);
2133 programName = strrchr(argv[0], '/');
2134 if (programName == NULL)
2135 programName = argv[0];
2140 XtSetLanguageProc(NULL, NULL, NULL);
2141 bindtextdomain(PACKAGE, LOCALEDIR);
2142 textdomain(PACKAGE);
2146 XtAppInitialize(&appContext, "XBoard", shellOptions,
2147 XtNumber(shellOptions),
2148 &argc, argv, xboardResources, NULL, 0);
2152 gtk_init (&argc, &argv);
2154 /* parse glade file to build widgets */
2156 builder = gtk_builder_new ();
2157 gtk_builder_add_from_file (builder, "gtk-interface.xml", NULL);
2159 /* test if everything worked ok */
2161 GUI_Window = GTK_WIDGET (gtk_builder_get_object (builder, "MainWindow"));
2162 if(!GUI_Window) printf("Error: gtk_builder didn't work!\n");
2163 GUI_Board = GTK_WIDGET (gtk_builder_get_object (builder, "Board"));
2164 if(!GUI_Board) printf("Error: gtk_builder didn't work!\n");
2165 GUI_Whiteclock = GTK_WIDGET (gtk_builder_get_object (builder, "WhiteClock"));
2166 if(!GUI_Whiteclock) printf("Error: gtk_builder didn't work!\n");
2167 GUI_Blackclock = GTK_WIDGET (gtk_builder_get_object (builder, "BlackClock"));
2168 if(!GUI_Blackclock) printf("Error: gtk_builder didn't work!\n");
2170 gtk_builder_connect_signals (builder, NULL);
2172 // don't unref the builder, since we use it to get references to widgets
2173 // g_object_unref (G_OBJECT (builder));
2175 /* end parse glade file */
2179 fprintf(stderr, _("%s: unrecognized argument %s\n"),
2180 programName, argv[1]);
2181 fprintf(stderr, "Recognized options:\n");
2182 for(i = 0; i < XtNumber(shellOptions); i++)
2184 j = fprintf(stderr, " %s%s", shellOptions[i].option,
2185 (shellOptions[i].argKind == XrmoptionSepArg
2187 if (i++ < XtNumber(shellOptions))
2189 fprintf(stderr, "%*c%s%s\n", 40 - j, ' ',
2190 shellOptions[i].option,
2191 (shellOptions[i].argKind == XrmoptionSepArg
2196 fprintf(stderr, "\n");
2202 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL)
2208 if (chdir(chessDir) != 0)
2210 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
2217 if (p == NULL) p = "/tmp";
2218 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
2219 gameCopyFilename = (char*) malloc(i);
2220 gamePasteFilename = (char*) malloc(i);
2221 snprintf(gameCopyFilename,i, "%s/.xboard%05uc.pgn", p, getpid());
2222 snprintf(gamePasteFilename,i, "%s/.xboard%05up.pgn", p, getpid());
2224 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
2225 clientResources, XtNumber(clientResources),
2228 if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) {
2229 /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */
2230 if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL) {
2231 printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile);
2234 setbuf(debugFP, NULL);
2237 /* [HGM,HR] make sure board size is acceptable */
2238 if(appData.NrFiles > BOARD_SIZE ||
2239 appData.NrRanks > BOARD_SIZE )
2240 DisplayFatalError(_("Recompile with BOARD_SIZE > 12, to support this size"), 0, 2);
2243 /* This feature does not work; animation needs a rewrite */
2244 appData.highlightDragging = FALSE;
2248 xDisplay = XtDisplay(shellWidget);
2249 xScreen = DefaultScreen(xDisplay);
2250 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
2252 gameInfo.variant = StringToVariant(appData.variant);
2253 InitPosition(FALSE);
2257 * Determine boardSize
2259 gameInfo.boardWidth = gameInfo.boardHeight = 8; // [HGM] boardsize: make sure we start as 8x8
2262 // [HGM] as long as we have not created the possibility to change size while running, start with requested size
2263 gameInfo.boardWidth = appData.NrFiles > 0 ? appData.NrFiles : 8;
2264 gameInfo.boardHeight = appData.NrRanks > 0 ? appData.NrRanks : 8;
2265 gameInfo.holdingsWidth = appData.holdingsSize > 0 ? 2 : 0;
2270 InitDrawingSizes(-1, 0); // [HGM] initsize: make this into a subroutine
2272 if (isdigit(appData.boardSize[0])) {
2273 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
2274 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
2275 &fontPxlSize, &smallLayout, &tinyLayout);
2277 fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
2278 programName, appData.boardSize);
2282 /* Find some defaults; use the nearest known size */
2283 SizeDefaults *szd, *nearest;
2284 int distance = 99999;
2285 nearest = szd = sizeDefaults;
2286 while (szd->name != NULL) {
2287 if (abs(szd->squareSize - squareSize) < distance) {
2289 distance = abs(szd->squareSize - squareSize);
2290 if (distance == 0) break;
2294 if (i < 2) lineGap = nearest->lineGap;
2295 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
2296 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
2297 if (i < 5) fontPxlSize = nearest->fontPxlSize;
2298 if (i < 6) smallLayout = nearest->smallLayout;
2299 if (i < 7) tinyLayout = nearest->tinyLayout;
2302 SizeDefaults *szd = sizeDefaults;
2303 if (*appData.boardSize == NULLCHAR) {
2304 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize ||
2305 DisplayHeight(xDisplay, xScreen) < szd->minScreenSize) {
2308 if (szd->name == NULL) szd--;
2310 while (szd->name != NULL &&
2311 StrCaseCmp(szd->name, appData.boardSize) != 0) szd++;
2312 if (szd->name == NULL) {
2313 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
2314 programName, appData.boardSize);
2318 squareSize = szd->squareSize;
2319 lineGap = szd->lineGap;
2320 clockFontPxlSize = szd->clockFontPxlSize;
2321 coordFontPxlSize = szd->coordFontPxlSize;
2322 fontPxlSize = szd->fontPxlSize;
2323 smallLayout = szd->smallLayout;
2324 tinyLayout = szd->tinyLayout;
2327 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2328 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2329 if (appData.showJail == 1) {
2330 /* Jail on top and bottom */
2331 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2332 XtSetArg(boardArgs[2], XtNheight,
2333 boardHeight + 2*(lineGap + squareSize));
2334 } else if (appData.showJail == 2) {
2336 XtSetArg(boardArgs[1], XtNwidth,
2337 boardWidth + 2*(lineGap + squareSize));
2338 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2341 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2342 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2346 * Determine what fonts to use.
2348 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
2349 clockFontID = XLoadFont(xDisplay, appData.clockFont);
2350 clockFontStruct = XQueryFont(xDisplay, clockFontID);
2351 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
2352 coordFontID = XLoadFont(xDisplay, appData.coordFont);
2353 coordFontStruct = XQueryFont(xDisplay, coordFontID);
2354 appData.font = FindFont(appData.font, fontPxlSize);
2355 countFontID = XLoadFont(xDisplay, appData.coordFont); // [HGM] holdings
2356 countFontStruct = XQueryFont(xDisplay, countFontID);
2357 // appData.font = FindFont(appData.font, fontPxlSize);
2359 xdb = XtDatabase(xDisplay);
2360 XrmPutStringResource(&xdb, "*font", appData.font);
2363 * Detect if there are not enough colors available and adapt.
2365 if (DefaultDepth(xDisplay, xScreen) <= 2) {
2366 appData.monoMode = True;
2369 if (!appData.monoMode) {
2370 vFrom.addr = (caddr_t) appData.lightSquareColor;
2371 vFrom.size = strlen(appData.lightSquareColor);
2372 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2373 if (vTo.addr == NULL) {
2374 appData.monoMode = True;
2377 lightSquareColor = *(Pixel *) vTo.addr;
2380 if (!appData.monoMode) {
2381 vFrom.addr = (caddr_t) appData.darkSquareColor;
2382 vFrom.size = strlen(appData.darkSquareColor);
2383 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2384 if (vTo.addr == NULL) {
2385 appData.monoMode = True;
2388 darkSquareColor = *(Pixel *) vTo.addr;
2391 if (!appData.monoMode) {
2392 vFrom.addr = (caddr_t) appData.whitePieceColor;
2393 vFrom.size = strlen(appData.whitePieceColor);
2394 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2395 if (vTo.addr == NULL) {
2396 appData.monoMode = True;
2399 whitePieceColor = *(Pixel *) vTo.addr;
2402 if (!appData.monoMode) {
2403 vFrom.addr = (caddr_t) appData.blackPieceColor;
2404 vFrom.size = strlen(appData.blackPieceColor);
2405 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2406 if (vTo.addr == NULL) {
2407 appData.monoMode = True;
2410 blackPieceColor = *(Pixel *) vTo.addr;
2414 if (!appData.monoMode) {
2415 vFrom.addr = (caddr_t) appData.highlightSquareColor;
2416 vFrom.size = strlen(appData.highlightSquareColor);
2417 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2418 if (vTo.addr == NULL) {
2419 appData.monoMode = True;
2422 highlightSquareColor = *(Pixel *) vTo.addr;
2426 if (!appData.monoMode) {
2427 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
2428 vFrom.size = strlen(appData.premoveHighlightColor);
2429 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2430 if (vTo.addr == NULL) {
2431 appData.monoMode = True;
2434 premoveHighlightColor = *(Pixel *) vTo.addr;
2439 fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2442 if (appData.bitmapDirectory == NULL ||
2443 appData.bitmapDirectory[0] == NULLCHAR)
2444 appData.bitmapDirectory = DEF_BITMAP_DIR;
2447 if (appData.lowTimeWarning && !appData.monoMode) {
2448 vFrom.addr = (caddr_t) appData.lowTimeWarningColor;
2449 vFrom.size = strlen(appData.lowTimeWarningColor);
2450 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2451 if (vTo.addr == NULL)
2452 appData.monoMode = True;
2454 lowTimeWarningColor = *(Pixel *) vTo.addr;
2457 if (appData.monoMode && appData.debugMode) {
2458 fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2459 (unsigned long) XWhitePixel(xDisplay, xScreen),
2460 (unsigned long) XBlackPixel(xDisplay, xScreen));
2463 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
2464 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
2465 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
2466 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
2467 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
2468 parse_cpair(ColorTell, appData.colorTell) < 0 ||
2469 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
2470 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
2471 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
2472 parse_cpair(ColorNormal, appData.colorNormal) < 0)
2474 if (appData.colorize) {
2476 _("%s: can't parse color names; disabling colorization\n"),
2479 appData.colorize = FALSE;
2481 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2482 textColors[ColorNone].attr = 0;
2484 // XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2490 layoutName = "tinyLayout";
2491 } else if (smallLayout) {
2492 layoutName = "smallLayout";
2494 layoutName = "normalLayout";
2497 if (appData.titleInWindow) {
2498 /* todo check what this appdata does */
2501 if (appData.showButtonBar) {
2502 /* TODO hide button bar if requested */
2506 * gtk set properties of widgets
2509 /* set board size */
2510 gtk_widget_set_size_request(GTK_WIDGET(GUI_Board),
2511 boardWidth,boardHeight);
2513 /* end gtk set properties of widgets */
2515 if (appData.titleInWindow)
2520 if (appData.showButtonBar)
2527 if (appData.showButtonBar)
2536 // [HGM] it seems the layout code ends here, but perhaps the color stuff is size independent and would
2537 // not need to go into InitDrawingSizes().
2540 /* set some checkboxes in the menu according to appData */
2542 if (appData.alwaysPromoteToQueen)
2543 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Always Queen")),TRUE);
2545 if (appData.animateDragging)
2546 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Animate Dragging")),TRUE);
2548 if (appData.animate)
2549 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Animate Moving")),TRUE);
2551 if (appData.autoComment)
2552 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Comment")),TRUE);
2554 if (appData.autoCallFlag)
2555 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Flag")),TRUE);
2557 if (appData.autoFlipView)
2558 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Flip View")),TRUE);
2560 if (appData.autoObserve)
2561 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Observe")),TRUE);
2563 if (appData.autoRaiseBoard)
2564 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Raise Board")),TRUE);
2566 if (appData.autoSaveGames)
2567 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Save")),TRUE);
2569 if (appData.saveGameFile[0] != NULLCHAR)
2571 /* Can't turn this off from menu */
2572 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Save")),TRUE);
2573 gtk_action_set_sensitive(GTK_ACTION (gtk_builder_get_object (builder, "menuOptions.Auto Save")),FALSE);
2576 if (appData.blindfold)
2577 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Blindfold")),TRUE);
2579 if (appData.flashCount > 0)
2580 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Flash Moves")),TRUE);
2582 if (appData.getMoveList)
2583 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Get Move List")),TRUE);
2586 if (appData.highlightDragging)
2587 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Highlight Dragging")),TRUE);
2590 if (appData.highlightLastMove)
2591 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Highlight Last Move")),TRUE);
2593 if (appData.icsAlarm)
2594 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.ICS Alarm")),TRUE);
2596 if (appData.ringBellAfterMoves)
2597 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Move Sound")),TRUE);
2599 if (appData.oldSaveStyle)
2600 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Old Save Style")),TRUE);
2602 if (appData.periodicUpdates)
2603 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Periodic Updates")),TRUE);
2605 if (appData.ponderNextMove)
2606 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Ponder Next Move")),TRUE);
2608 if (appData.popupExitMessage)
2609 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Popup Exit Message")),TRUE);
2611 if (appData.popupMoveErrors)
2612 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Popup Move Errors")),TRUE);
2614 if (appData.premove)
2615 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Premove")),TRUE);
2617 if (appData.quietPlay)
2618 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Quit Play")),TRUE);
2620 if (appData.showCoords)
2621 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Show Coords")),TRUE);
2623 if (appData.showThinking)
2624 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Show Thinking")),TRUE);
2626 if (appData.testLegality)
2627 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Test Legality")),TRUE);
2629 /* end setting check boxes */
2632 /* load square colors */
2633 SVGLightSquare = load_pixbuf("svg/LightSquare.svg",squareSize);
2634 SVGDarkSquare = load_pixbuf("svg/DarkSquare.svg",squareSize);
2635 SVGNeutralSquare = load_pixbuf("svg/NeutralSquare.svg",squareSize);
2637 /* use two icons to indicate if it is white's or black's turn */
2638 WhiteIcon = load_pixbuf("svg/icon_white.svg",0);
2639 BlackIcon = load_pixbuf("svg/icon_black.svg",0);
2640 WindowIcon = WhiteIcon;
2641 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
2643 /* do resizing to a fixed aspect ratio */
2648 GUI_SetAspectRatio(0.7);
2650 /* realize window */
2651 gtk_widget_show (GUI_Window);
2657 if (appData.animate || appData.animateDragging)
2662 if (errorExitStatus == -1) {
2663 if (appData.icsActive) {
2664 /* We now wait until we see "login:" from the ICS before
2665 sending the logon script (problems with timestamp otherwise) */
2666 /*ICSInitScript();*/
2667 if (appData.icsInputBox) ICSInputBoxPopUp();
2670 signal(SIGINT, IntSigHandler);
2671 signal(SIGTERM, IntSigHandler);
2672 if (*appData.cmailGameName != NULLCHAR) {
2673 signal(SIGUSR1, CmailSigHandler);
2676 gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes()
2680 * Create a cursor for the board widget.
2681 * (This needs to be called after the window has been created to have access to board-window)
2684 BoardCursor = gdk_cursor_new(GDK_HAND2);
2685 gdk_window_set_cursor(GUI_Board->window, BoardCursor);
2686 gdk_cursor_destroy(BoardCursor);
2691 if (appData.debugMode) fclose(debugFP); // [DM] debug
2698 if (appData.icsActive && oldICSInteractionTitle != NULL) {
2699 DisplayIcsInteractionTitle(oldICSInteractionTitle);
2701 unlink(gameCopyFilename);
2702 unlink(gamePasteFilename);
2713 CmailSigHandler(sig)
2719 signal(SIGUSR1, SIG_IGN); /* suspend handler */
2721 /* Activate call-back function CmailSigHandlerCallBack() */
2722 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
2724 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
2728 CmailSigHandlerCallBack(isr, closure, message, count, error)
2736 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
2738 /**** end signal code ****/
2748 f = fopen(appData.icsLogon, "r");
2754 strcat(buf, appData.icsLogon);
2755 f = fopen(buf, "r");
2759 ProcessICSInitScript(f);
2766 EditCommentPopDown();
2777 SetMenuEnables(enab)
2782 if (!builder) return;
2783 while (enab->name != NULL) {
2784 o = gtk_builder_get_object(builder, enab->name);
2785 if(GTK_IS_WIDGET(o))
2786 gtk_widget_set_sensitive(GTK_WIDGET (o),enab->value);
2789 if(GTK_IS_ACTION(o))
2790 gtk_action_set_sensitive(GTK_ACTION (o),enab->value);
2792 DisplayError(enab->name, 0);
2798 Enables icsEnables[] = {
2799 { "menuFile.Mail Move", False },
2800 { "menuFile.Reload CMail Message", False },
2801 { "menuMode.Machine Black", False },
2802 { "menuMode.Machine White", False },
2803 { "menuMode.Analysis Mode", False },
2804 { "menuMode.Analyze File", False },
2805 { "menuMode.Two Machines", False },
2807 { "menuHelp.Hint", False },
2808 { "menuHelp.Book", False },
2809 { "menuStep.Move Now", False },
2810 { "menuOptions.Periodic Updates", False },
2811 { "menuOptions.Hide Thinking", False },
2812 { "menuOptions.Ponder Next Move", False },
2817 Enables ncpEnables[] = {
2818 { "menuFile.Mail Move", False },
2819 { "menuFile.Reload CMail Message", False },
2820 { "menuMode.Machine White", False },
2821 { "menuMode.Machine Black", False },
2822 { "menuMode.Analysis Mode", False },
2823 { "menuMode.Analyze File", False },
2824 { "menuMode.Two Machines", False },
2825 { "menuMode.ICS Client", False },
2826 { "menuMode.ICS Input Box", False },
2827 { "Action", False },
2828 { "menuStep.Revert", False },
2829 { "menuStep.Move Now", False },
2830 { "menuStep.Retract Move", False },
2831 { "menuOptions.Auto Comment", False },
2832 { "menuOptions.Auto Flag", False },
2833 { "menuOptions.Auto Flip View", False },
2834 { "menuOptions.Auto Observe", False },
2835 { "menuOptions.Auto Raise Board", False },
2836 { "menuOptions.Get Move List", False },
2837 { "menuOptions.ICS Alarm", False },
2838 { "menuOptions.Move Sound", False },
2839 { "menuOptions.Quiet Play", False },
2840 { "menuOptions.Hide Thinking", False },
2841 { "menuOptions.Periodic Updates", False },
2842 { "menuOptions.Ponder Next Move", False },
2843 { "menuHelp.Hint", False },
2844 { "menuHelp.Book", False },
2848 Enables gnuEnables[] = {
2849 { "menuMode.ICS Client", False },
2850 { "menuMode.ICS Input Box", False },
2851 { "menuAction.Accept", False },
2852 { "menuAction.Decline", False },
2853 { "menuAction.Rematch", False },
2854 { "menuAction.Adjourn", False },
2855 { "menuAction.Stop Examining", False },
2856 { "menuAction.Stop Observing", False },
2857 { "menuStep.Revert", False },
2858 { "menuOptions.Auto Comment", False },
2859 { "menuOptions.Auto Observe", False },
2860 { "menuOptions.Auto Raise Board", False },
2861 { "menuOptions.Get Move List", False },
2862 { "menuOptions.Premove", False },
2863 { "menuOptions.Quiet Play", False },
2865 /* The next two options rely on SetCmailMode being called *after* */
2866 /* SetGNUMode so that when GNU is being used to give hints these */
2867 /* menu options are still available */
2869 { "menuFile.Mail Move", False },
2870 { "menuFile.Reload CMail Message", False },
2874 Enables cmailEnables[] = {
2876 { "menuAction.Call Flag", False },
2877 { "menuAction.Draw", True },
2878 { "menuAction.Adjourn", False },
2879 { "menuAction.Abort", False },
2880 { "menuAction.Stop Observing", False },
2881 { "menuAction.Stop Examining", False },
2882 { "menuFile.Mail Move", True },
2883 { "menuFile.Reload CMail Message", True },
2887 Enables trainingOnEnables[] = {
2888 { "menuMode.Edit Comment", False },
2889 { "menuMode.Pause", False },
2890 { "menuStep.Forward", False },
2891 { "menuStep.Backward", False },
2892 { "menuStep.Forward to End", False },
2893 { "menuStep.Back to Start", False },
2894 { "menuStep.Move Now", False },
2895 { "menuStep.Truncate Game", False },
2899 Enables trainingOffEnables[] = {
2900 { "menuMode.Edit Comment", True },
2901 { "menuMode.Pause", True },
2902 { "menuStep.Forward", True },
2903 { "menuStep.Backward", True },
2904 { "menuStep.Forward to End", True },
2905 { "menuStep.Back to Start", True },
2906 { "menuStep.Move Now", True },
2907 { "menuStep.Truncate Game", True },
2911 Enables machineThinkingEnables[] = {
2912 { "menuFile.Load Game", False },
2913 { "menuFile.Load Next Game", False },
2914 { "menuFile.Load Previous Game", False },
2915 { "menuFile.Reload Same Game", False },
2916 { "menuFile.Paste Game", False },
2917 { "menuFile.Load Position", False },
2918 { "menuFile.Load Next Position", False },
2919 { "menuFile.Load Previous Position", False },
2920 { "menuFile.Reload Same Position", False },
2921 { "menuFile.Paste Position", False },
2922 { "menuMode.Machine White", False },
2923 { "menuMode.Machine Black", False },
2924 { "menuMode.Two Machines", False },
2925 { "menuStep.Retract Move", False },
2929 Enables userThinkingEnables[] = {
2930 { "menuFile.Load Game", True },
2931 { "menuFile.Load Next Game", True },
2932 { "menuFile.Load Previous Game", True },
2933 { "menuFile.Reload Same Game", True },
2934 { "menuFile.Paste Game", True },
2935 { "menuFile.Load Position", True },
2936 { "menuFile.Load Next Position", True },
2937 { "menuFile.Load Previous Position", True },
2938 { "menuFile.Reload Same Position", True },
2939 { "menuFile.Paste Position", True },
2940 { "menuMode.Machine White", True },
2941 { "menuMode.Machine Black", True },
2942 { "menuMode.Two Machines", True },
2943 { "menuStep.Retract Move", True },
2949 SetMenuEnables(icsEnables);
2952 if (appData.zippyPlay && !appData.noChessProgram) /* [DM] icsEngineAnalyze */
2953 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
2960 SetMenuEnables(ncpEnables);
2966 SetMenuEnables(gnuEnables);
2972 SetMenuEnables(cmailEnables);
2978 SetMenuEnables(trainingOnEnables);
2979 if (appData.showButtonBar) {
2980 XtSetSensitive(buttonBarWidget, False);
2986 SetTrainingModeOff()
2988 SetMenuEnables(trainingOffEnables);
2989 if (appData.showButtonBar) {
2990 XtSetSensitive(buttonBarWidget, True);
2995 SetUserThinkingEnables()
2997 if (appData.noChessProgram) return;
2998 SetMenuEnables(userThinkingEnables);
3002 SetMachineThinkingEnables()
3004 if (appData.noChessProgram) return;
3005 SetMenuEnables(machineThinkingEnables);
3007 case MachinePlaysBlack:
3008 case MachinePlaysWhite:
3009 case TwoMachinesPlay:
3010 XtSetSensitive(XtNameToWidget(menuBarWidget,
3011 ModeToWidgetName(gameMode)), True);
3018 #define Abs(n) ((n)<0 ? -(n) : (n))
3021 * Find a font that matches "pattern" that is as close as
3022 * possible to the targetPxlSize. Prefer fonts that are k
3023 * pixels smaller to fonts that are k pixels larger. The
3024 * pattern must be in the X Consortium standard format,
3025 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
3026 * The return value should be freed with XtFree when no
3029 char *FindFont(pattern, targetPxlSize)
3033 char **fonts, *p, *best, *scalable, *scalableTail;
3034 int i, j, nfonts, minerr, err, pxlSize;
3037 char **missing_list;
3039 char *def_string, *base_fnt_lst, strInt[3];
3041 XFontStruct **fnt_list;
3043 base_fnt_lst = calloc(1, strlen(pattern) + 3);
3044 sprintf(strInt, "%d", targetPxlSize);
3045 p = strstr(pattern, "--");
3046 strncpy(base_fnt_lst, pattern, p - pattern + 2);
3047 strcat(base_fnt_lst, strInt);
3048 strcat(base_fnt_lst, strchr(p + 2, '-'));
3050 if ((fntSet = XCreateFontSet(xDisplay,
3054 &def_string)) == NULL) {
3056 fprintf(stderr, _("Unable to create font set.\n"));
3060 nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
3062 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
3064 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
3065 programName, pattern);
3073 for (i=0; i<nfonts; i++) {
3076 if (*p != '-') continue;
3078 if (*p == NULLCHAR) break;
3079 if (*p++ == '-') j++;
3081 if (j < 7) continue;
3084 scalable = fonts[i];
3087 err = pxlSize - targetPxlSize;
3088 if (Abs(err) < Abs(minerr) ||
3089 (minerr > 0 && err < 0 && -err == minerr)) {
3095 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
3096 /* If the error is too big and there is a scalable font,
3097 use the scalable font. */
3098 int headlen = scalableTail - scalable;
3099 p = (char *) XtMalloc(strlen(scalable) + 10);
3100 while (isdigit(*scalableTail)) scalableTail++;
3101 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
3103 p = (char *) XtMalloc(strlen(best) + 1);
3106 if (appData.debugMode) {
3107 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
3108 pattern, targetPxlSize, p);
3111 if (missing_count > 0)
3112 XFreeStringList(missing_list);
3113 XFreeFontSet(xDisplay, fntSet);
3115 XFreeFontNames(fonts);
3122 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
3123 | GCBackground | GCFunction | GCPlaneMask;
3124 XGCValues gc_values;
3127 gc_values.plane_mask = AllPlanes;
3128 gc_values.line_width = lineGap;
3129 gc_values.line_style = LineSolid;
3130 gc_values.function = GXcopy;
3132 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3133 gc_values.background = XWhitePixel(xDisplay, xScreen);
3134 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
3135 XSetFont(xDisplay, coordGC, coordFontID);
3137 if (appData.monoMode) {
3138 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3139 gc_values.background = XBlackPixel(xDisplay, xScreen);
3140 lightSquareGC = wbPieceGC
3141 = XtGetGC(shellWidget, value_mask, &gc_values);
3143 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3144 gc_values.background = XWhitePixel(xDisplay, xScreen);
3145 darkSquareGC = bwPieceGC
3146 = XtGetGC(shellWidget, value_mask, &gc_values);
3148 if (DefaultDepth(xDisplay, xScreen) == 1) {
3149 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3150 gc_values.function = GXcopyInverted;
3151 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3152 gc_values.function = GXcopy;
3153 if (XBlackPixel(xDisplay, xScreen) == 1) {
3154 bwPieceGC = darkSquareGC;
3155 wbPieceGC = copyInvertedGC;
3157 bwPieceGC = copyInvertedGC;
3158 wbPieceGC = lightSquareGC;
3162 gc_values.foreground = lightSquareColor;
3163 gc_values.background = darkSquareColor;
3164 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3166 gc_values.foreground = darkSquareColor;
3167 gc_values.background = lightSquareColor;
3168 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3170 gc_values.foreground = jailSquareColor;
3171 gc_values.background = jailSquareColor;
3172 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3174 gc_values.foreground = whitePieceColor;
3175 gc_values.background = darkSquareColor;
3176 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3178 gc_values.foreground = whitePieceColor;
3179 gc_values.background = lightSquareColor;
3180 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3182 gc_values.foreground = whitePieceColor;
3183 gc_values.background = jailSquareColor;
3184 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3186 gc_values.foreground = blackPieceColor;
3187 gc_values.background = darkSquareColor;
3188 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3190 gc_values.foreground = blackPieceColor;
3191 gc_values.background = lightSquareColor;
3192 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3194 gc_values.foreground = blackPieceColor;
3195 gc_values.background = jailSquareColor;
3196 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3203 WhitePawn, WhiteKnight, WhiteBishop, WhiteRook, WhiteQueen, WhiteKing,
3204 BlackPawn, BlackKnight, BlackBishop, BlackRook, BlackQueen, BlackKing,
3207 SVGpieces[WhitePawn] = load_pixbuf("svg/WhitePawn.svg",squareSize);
3208 SVGpieces[WhiteKnight] = load_pixbuf("svg/WhiteKnight.svg",squareSize);
3209 SVGpieces[WhiteBishop] = load_pixbuf("svg/WhiteBishop.svg",squareSize);
3210 SVGpieces[WhiteRook] = load_pixbuf("svg/WhiteRook.svg",squareSize);
3211 SVGpieces[WhiteQueen] = load_pixbuf("svg/WhiteQueen.svg",squareSize);
3212 SVGpieces[WhiteKing] = load_pixbuf("svg/WhiteKing.svg",squareSize);
3214 SVGpieces[BlackPawn] = load_pixbuf("svg/BlackPawn.svg",squareSize);
3215 SVGpieces[BlackKnight] = load_pixbuf("svg/BlackKnight.svg",squareSize);
3216 SVGpieces[BlackBishop] = load_pixbuf("svg/BlackBishop.svg",squareSize);
3217 SVGpieces[BlackRook] = load_pixbuf("svg/BlackRook.svg",squareSize);
3218 SVGpieces[BlackQueen] = load_pixbuf("svg/BlackQueen.svg",squareSize);
3219 SVGpieces[BlackKing] = load_pixbuf("svg/BlackKing.svg",squareSize);
3225 static void MenuBarSelect(w, addr, index)
3230 XtActionProc proc = (XtActionProc) addr;
3232 (proc)(NULL, NULL, NULL, NULL);
3235 void CreateMenuBarPopup(parent, name, mb)
3245 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3248 XtSetArg(args[j], XtNleftMargin, 20); j++;
3249 XtSetArg(args[j], XtNrightMargin, 20); j++;
3251 while (mi->string != NULL) {
3252 if (strcmp(mi->string, "----") == 0) {
3253 entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
3256 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string)));
3257 entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass,
3259 XtAddCallback(entry, XtNcallback,
3260 (XtCallbackProc) MenuBarSelect,
3261 (caddr_t) mi->proc);
3267 Widget CreateMenuBar(mb)
3271 Widget anchor, menuBar;
3273 char menuName[MSG_SIZ];
3276 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3277 XtSetArg(args[j], XtNvSpace, 0); j++;
3278 XtSetArg(args[j], XtNborderWidth, 0); j++;
3279 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
3280 formWidget, args, j);
3282 while (mb->name != NULL) {
3283 strcpy(menuName, "menu");
3284 strcat(menuName, mb->name);
3286 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
3289 shortName[0] = _(mb->name)[0];
3290 shortName[1] = NULLCHAR;
3291 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
3294 XtSetArg(args[j], XtNlabel, XtNewString(_(mb->name))); j++;
3297 XtSetArg(args[j], XtNborderWidth, 0); j++;
3298 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
3300 CreateMenuBarPopup(menuBar, menuName, mb);
3306 Widget CreateButtonBar(mi)
3310 Widget button, buttonBar;
3314 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3316 XtSetArg(args[j], XtNhSpace, 0); j++;
3318 XtSetArg(args[j], XtNborderWidth, 0); j++;
3319 XtSetArg(args[j], XtNvSpace, 0); j++;
3320 buttonBar = XtCreateWidget("buttonBar", boxWidgetClass,
3321 formWidget, args, j);
3323 while (mi->string != NULL) {
3326 XtSetArg(args[j], XtNinternalWidth, 2); j++;
3327 XtSetArg(args[j], XtNborderWidth, 0); j++;
3329 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string))); j++;
3330 button = XtCreateManagedWidget(mi->string, commandWidgetClass,
3331 buttonBar, args, j);
3332 XtAddCallback(button, XtNcallback,
3333 (XtCallbackProc) MenuBarSelect,
3334 (caddr_t) mi->proc);
3341 CreatePieceMenu(name, color)
3348 ChessSquare selection;
3350 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3351 boardWidget, args, 0);
3353 for (i = 0; i < PIECE_MENU_SIZE; i++) {
3354 String item = pieceMenuStrings[color][i];
3356 if (strcmp(item, "----") == 0) {
3357 entry = XtCreateManagedWidget(item, smeLineObjectClass,
3360 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3361 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3363 selection = pieceMenuTranslation[color][i];
3364 XtAddCallback(entry, XtNcallback,
3365 (XtCallbackProc) PieceMenuSelect,
3366 (caddr_t) selection);
3367 if (selection == WhitePawn || selection == BlackPawn) {
3368 XtSetArg(args[0], XtNpopupOnEntry, entry);
3369 XtSetValues(menu, args, 1);
3382 ChessSquare selection;
3384 // whitePieceMenu = CreatePieceMenu("menuW", 0);
3385 // blackPieceMenu = CreatePieceMenu("menuB", 1);
3387 // XtRegisterGrabAction(PieceMenuPopup, True,
3388 // (unsigned)(ButtonPressMask|ButtonReleaseMask),
3389 // GrabModeAsync, GrabModeAsync);
3391 // XtSetArg(args[0], XtNlabel, _("Drop"));
3392 // dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
3393 // boardWidget, args, 1);
3394 // for (i = 0; i < DROP_MENU_SIZE; i++) {
3395 // String item = dropMenuStrings[i];
3397 // if (strcmp(item, "----") == 0) {
3398 // entry = XtCreateManagedWidget(item, smeLineObjectClass,
3399 // dropMenu, NULL, 0);
3401 // XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3402 // entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3403 // dropMenu, args, 1);
3404 // selection = dropMenuTranslation[i];
3405 // XtAddCallback(entry, XtNcallback,
3406 // (XtCallbackProc) DropMenuSelect,
3407 // (caddr_t) selection);
3412 void SetupDropMenu()
3420 for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
3421 entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
3422 p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
3423 dmEnables[i].piece);
3424 XtSetSensitive(entry, p != NULL || !appData.testLegality
3425 /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
3426 && !appData.icsActive));
3428 while (p && *p++ == dmEnables[i].piece) count++;
3429 snprintf(label, sizeof(label), "%s %d", dmEnables[i].widget, count);
3431 XtSetArg(args[j], XtNlabel, label); j++;
3432 XtSetValues(entry, args, j);
3436 void PieceMenuPopup(w, event, params, num_params)
3440 Cardinal *num_params;
3443 if (event->type != ButtonPress) return;
3444 if (errorUp) ErrorPopDown();
3448 whichMenu = params[0];
3450 case IcsPlayingWhite:
3451 case IcsPlayingBlack:
3453 case MachinePlaysWhite:
3454 case MachinePlaysBlack:
3455 if (appData.testLegality &&
3456 gameInfo.variant != VariantBughouse &&
3457 gameInfo.variant != VariantCrazyhouse) return;
3459 whichMenu = "menuD";
3465 if (((pmFromX = EventToSquare(event->xbutton.x, BOARD_WIDTH)) < 0) ||
3466 ((pmFromY = EventToSquare(event->xbutton.y, BOARD_HEIGHT)) < 0)) {
3467 pmFromX = pmFromY = -1;
3471 pmFromX = BOARD_WIDTH - 1 - pmFromX;
3473 pmFromY = BOARD_HEIGHT - 1 - pmFromY;
3475 XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
3478 static void PieceMenuSelect(w, piece, junk)
3483 if (pmFromX < 0 || pmFromY < 0) return;
3484 EditPositionMenuEvent(piece, pmFromX, pmFromY);
3487 static void DropMenuSelect(w, piece, junk)
3492 if (pmFromX < 0 || pmFromY < 0) return;
3493 DropMenuEvent(piece, pmFromX, pmFromY);
3496 void WhiteClock(w, event, prms, nprms)
3502 if (gameMode == EditPosition || gameMode == IcsExamining) {
3503 SetWhiteToPlayEvent();
3504 } else if (gameMode == IcsPlayingBlack || gameMode == MachinePlaysWhite) {
3509 void BlackClock(w, event, prms, nprms)
3515 if (gameMode == EditPosition || gameMode == IcsExamining) {
3516 SetBlackToPlayEvent();
3517 } else if (gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) {
3524 * If the user selects on a border boundary, return -1; if off the board,
3525 * return -2. Otherwise map the event coordinate to the square.
3527 int EventToSquare(x, limit)
3535 if ((x % (squareSize + lineGap)) >= squareSize)
3537 x /= (squareSize + lineGap);
3543 static void do_flash_delay(msec)
3549 static void drawHighlight(file, rank, line_type)
3550 int file, rank, line_type;
3555 if (lineGap == 0 || appData.blindfold) return;
3559 x = lineGap/2 + ((BOARD_WIDTH-1)-file) *
3560 (squareSize + lineGap);
3561 y = lineGap/2 + rank * (squareSize + lineGap);
3565 x = lineGap/2 + file * (squareSize + lineGap);
3566 y = lineGap/2 + ((BOARD_HEIGHT-1)-rank) *
3567 (squareSize + lineGap);
3571 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3573 /* draw the highlight */
3574 cairo_move_to (cr, x, y);
3575 cairo_rel_line_to (cr, 0,squareSize+lineGap);
3576 cairo_rel_line_to (cr, squareSize+lineGap,0);
3577 cairo_rel_line_to (cr, 0,-squareSize-lineGap);
3578 cairo_close_path (cr);
3580 cairo_set_line_width (cr, lineGap);
3583 /* TODO: use appdata colors */
3584 case LINE_TYPE_HIGHLIGHT:
3585 cairo_set_source_rgba (cr, 1, 1, 0, 1.0);
3588 cairo_set_source_rgba (cr, 1, 0, 0, 1.0);
3590 case LINE_TYPE_NORMAL:
3592 cairo_set_source_rgba (cr, 0, 1, 0, 1.0);
3603 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
3604 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
3607 SetHighlights(fromX, fromY, toX, toY)
3608 int fromX, fromY, toX, toY;
3610 if (hi1X != fromX || hi1Y != fromY)
3612 if (hi1X >= 0 && hi1Y >= 0)
3614 drawHighlight(hi1X, hi1Y, LINE_TYPE_NORMAL);
3616 if (fromX >= 0 && fromY >= 0)
3618 drawHighlight(fromX, fromY, LINE_TYPE_HIGHLIGHT);
3621 if (hi2X != toX || hi2Y != toY)
3623 if (hi2X >= 0 && hi2Y >= 0)
3625 drawHighlight(hi2X, hi2Y, LINE_TYPE_NORMAL);
3627 if (toX >= 0 && toY >= 0)
3629 drawHighlight(toX, toY, LINE_TYPE_HIGHLIGHT);
3643 SetHighlights(-1, -1, -1, -1);
3648 SetPremoveHighlights(fromX, fromY, toX, toY)
3649 int fromX, fromY, toX, toY;
3651 if (pm1X != fromX || pm1Y != fromY)
3653 if (pm1X >= 0 && pm1Y >= 0)
3655 drawHighlight(pm1X, pm1Y, LINE_TYPE_NORMAL);
3657 if (fromX >= 0 && fromY >= 0)
3659 drawHighlight(fromX, fromY, LINE_TYPE_PRE);
3662 if (pm2X != toX || pm2Y != toY)
3664 if (pm2X >= 0 && pm2Y >= 0)
3666 drawHighlight(pm2X, pm2Y, LINE_TYPE_NORMAL);
3668 if (toX >= 0 && toY >= 0)
3670 drawHighlight(toX, toY, LINE_TYPE_PRE);
3683 ClearPremoveHighlights()
3685 SetPremoveHighlights(-1, -1, -1, -1);
3688 static void BlankSquare(x, y, color, piece, dest)
3696 pb = SVGLightSquare;
3701 case 2: /* neutral */
3703 pb = SVGNeutralSquare;
3706 gdk_draw_pixbuf(GDK_WINDOW(GUI_Board->window),NULL,pb,0,0,x,y,-1,-1, GDK_RGB_DITHER_NORMAL, 0, 0);
3709 static void DrawPiece(piece, square_color, x, y, dest)
3711 int square_color, x, y;
3714 gdk_draw_pixbuf(GDK_WINDOW(GUI_Board->window),NULL,
3715 GDK_PIXBUF(SVGpieces[piece]),0,0,x,y,-1,-1,
3716 GDK_RGB_DITHER_NORMAL, 0, 0);
3720 /* [HR] determine square color depending on chess variant. */
3721 static int SquareColor(row, column)
3726 if (gameInfo.variant == VariantXiangqi) {
3727 if (column >= 3 && column <= 5 && row >= 0 && row <= 2) {
3729 } else if (column >= 3 && column <= 5 && row >= 7 && row <= 9) {
3731 } else if (row <= 4) {
3737 square_color = ((column + row) % 2) == 1;
3740 /* [hgm] holdings: next line makes all holdings squares light */
3741 if(column < BOARD_LEFT || column >= BOARD_RGHT) square_color = 1;
3743 return square_color;
3746 void DrawSquare(row, column, piece, do_flash)
3747 int row, column, do_flash;
3750 int square_color, x, y;
3755 /* Calculate delay in milliseconds (2-delays per complete flash) */
3756 flash_delay = 500 / appData.flashRate;
3758 /* calculate x and y coordinates from row and column */
3761 x = lineGap + ((BOARD_WIDTH-1)-column) *
3762 (squareSize + lineGap);
3763 y = lineGap + row * (squareSize + lineGap);
3767 x = lineGap + column * (squareSize + lineGap);
3768 y = lineGap + ((BOARD_HEIGHT-1)-row) *
3769 (squareSize + lineGap);
3772 square_color = SquareColor(row, column);
3774 // [HGM] holdings: blank out area between board and holdings
3775 if ( column == BOARD_LEFT-1 || column == BOARD_RGHT
3776 || (column == BOARD_LEFT-2 && row < BOARD_HEIGHT-gameInfo.holdingsSize)
3777 || (column == BOARD_RGHT+1 && row >= gameInfo.holdingsSize) )
3779 BlankSquare(x, y, 2, EmptySquare, xBoardWindow);
3781 // [HGM] print piece counts next to holdings
3782 string[1] = NULLCHAR;
3785 cairo_text_extents_t extents;
3790 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3792 string[0] = '0' + piece;
3794 /* TODO this has to go into the font-selection */
3795 cairo_select_font_face (cr, "Sans",
3796 CAIRO_FONT_SLANT_NORMAL,
3797 CAIRO_FONT_WEIGHT_NORMAL);
3799 cairo_set_font_size (cr, 12.0);
3800 cairo_text_extents (cr, string, &extents);
3803 if (column == (flipView ? BOARD_LEFT-1 : BOARD_RGHT) )
3805 xpos= x + squareSize - extents.width - 2;
3806 ypos= y + extents.y_bearing + 1;
3808 if (column == (flipView ? BOARD_RGHT : BOARD_LEFT-1) && piece > 1)
3811 ypos = y + extents.y_bearing + 1;
3814 /* TODO mono mode? */
3815 cairo_move_to (cr, xpos, ypos);
3816 cairo_text_path (cr, string);
3817 cairo_set_source_rgb (cr, 1.0, 1.0, 1);
3818 cairo_fill_preserve (cr);
3819 cairo_set_source_rgb (cr, 0, 0, 0);
3820 cairo_set_line_width (cr, 0.1);
3830 /* square on the board */
3831 if (piece == EmptySquare || appData.blindfold)
3833 BlankSquare(x, y, square_color, piece, xBoardWindow);
3837 if (do_flash && appData.flashCount > 0)
3839 for (i=0; i<appData.flashCount; ++i)
3842 DrawPiece(piece, square_color, x, y, xBoardWindow);
3843 do_flash_delay(flash_delay);
3845 BlankSquare(x, y, square_color, piece, xBoardWindow);
3846 do_flash_delay(flash_delay);
3849 DrawPiece(piece, square_color, x, y, xBoardWindow);
3853 /* show coordinates if necessary */
3854 if(appData.showCoords)
3856 cairo_text_extents_t extents;
3860 /* TODO this has to go into the font-selection */
3861 cairo_select_font_face (cr, "Sans",
3862 CAIRO_FONT_SLANT_NORMAL,
3863 CAIRO_FONT_WEIGHT_NORMAL);
3864 cairo_set_font_size (cr, 12.0);
3866 string[1] = NULLCHAR;
3869 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3871 if (row == (flipView ? BOARD_HEIGHT-1 : 0) &&
3872 column >= BOARD_LEFT && column < BOARD_RGHT)
3874 string[0] = 'a' + column - BOARD_LEFT;
3875 cairo_text_extents (cr, string, &extents);
3877 xpos = x + squareSize - extents.width - 2;
3878 ypos = y + squareSize - extents.height - extents.y_bearing - 1;
3880 if (appData.monoMode)
3887 cairo_move_to (cr, xpos, ypos);
3888 cairo_text_path (cr, string);
3889 cairo_set_source_rgb (cr, 0.0, 0.0, 0);
3890 cairo_fill_preserve (cr);
3891 cairo_set_source_rgb (cr, 0, 1.0, 0);
3892 cairo_set_line_width (cr, 0.1);
3895 if ( column == (flipView ? BOARD_RGHT-1 : BOARD_LEFT))
3898 string[0] = ONE + row;
3899 cairo_text_extents (cr, string, &extents);
3902 ypos = y + extents.height + 1;
3904 if (appData.monoMode)
3911 cairo_move_to (cr, xpos, ypos);
3912 cairo_text_path (cr, string);
3913 cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
3914 cairo_fill_preserve (cr);
3915 cairo_set_source_rgb (cr, 0, 0, 1.0);
3916 cairo_set_line_width (cr, 0.1);
3928 /* Returns 1 if there are "too many" differences between b1 and b2
3929 (i.e. more than 1 move was made) */
3930 static int too_many_diffs(b1, b2)
3936 for (i=0; i<BOARD_HEIGHT; ++i) {
3937 for (j=0; j<BOARD_WIDTH; ++j) {
3938 if (b1[i][j] != b2[i][j]) {
3939 if (++c > 4) /* Castling causes 4 diffs */
3948 /* Matrix describing castling maneuvers */
3949 /* Row, ColRookFrom, ColKingFrom, ColRookTo, ColKingTo */
3950 static int castling_matrix[4][5] = {
3951 { 0, 0, 4, 3, 2 }, /* 0-0-0, white */
3952 { 0, 7, 4, 5, 6 }, /* 0-0, white */
3953 { 7, 0, 4, 3, 2 }, /* 0-0-0, black */
3954 { 7, 7, 4, 5, 6 } /* 0-0, black */
3957 /* Checks whether castling occurred. If it did, *rrow and *rcol
3958 are set to the destination (row,col) of the rook that moved.
3960 Returns 1 if castling occurred, 0 if not.
3962 Note: Only handles a max of 1 castling move, so be sure
3963 to call too_many_diffs() first.
3965 static int check_castle_draw(newb, oldb, rrow, rcol)
3972 /* For each type of castling... */
3973 for (i=0; i<4; ++i) {
3974 r = castling_matrix[i];
3976 /* Check the 4 squares involved in the castling move */
3978 for (j=1; j<=4; ++j) {
3979 if (newb[r[0]][r[j]] == oldb[r[0]][r[j]]) {
3986 /* All 4 changed, so it must be a castling move */
3995 static int damage[BOARD_SIZE][BOARD_SIZE];
3998 * event handler for redrawing the board
4000 void DrawPosition( repaint, board)
4001 /*Boolean*/int repaint;
4005 static int lastFlipView = 0;
4006 static int lastBoardValid = 0;
4007 static Board lastBoard;
4010 if (board == NULL) {
4011 if (!lastBoardValid) return;
4014 if (!lastBoardValid || lastFlipView != flipView) {
4015 // XtSetArg(args[0], XtNleftBitmap, (flipView ? xMarkPixmap : None));
4016 // XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flip View"),
4021 * It would be simpler to clear the window with XClearWindow()
4022 * but this causes a very distracting flicker.
4025 if (!repaint && lastBoardValid && lastFlipView == flipView)
4027 /* If too much changes (begin observing new game, etc.), don't
4029 do_flash = too_many_diffs(board, lastBoard) ? 0 : 1;
4031 /* Special check for castling so we don't flash both the king
4032 and the rook (just flash the king). */
4035 if (check_castle_draw(board, lastBoard, &rrow, &rcol))
4037 /* Draw rook with NO flashing. King will be drawn flashing later */
4038 DrawSquare(rrow, rcol, board[rrow][rcol], 0);
4039 lastBoard[rrow][rcol] = board[rrow][rcol];
4043 /* First pass -- Draw (newly) empty squares and repair damage.
4044 This prevents you from having a piece show up twice while it
4045 is flashing on its new square */
4046 for (i = 0; i < BOARD_HEIGHT; i++)
4047 for (j = 0; j < BOARD_WIDTH; j++)
4048 if ((board[i][j] != lastBoard[i][j] && board[i][j] == EmptySquare)
4051 DrawSquare(i, j, board[i][j], 0);
4052 damage[i][j] = False;
4055 /* Second pass -- Draw piece(s) in new position and flash them */
4056 for (i = 0; i < BOARD_HEIGHT; i++)
4057 for (j = 0; j < BOARD_WIDTH; j++)
4058 if (board[i][j] != lastBoard[i][j])
4060 DrawSquare(i, j, board[i][j], do_flash);
4072 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
4074 cairo_set_line_width (cr, lineGap);
4076 /* TODO: use appdata colors */
4077 cairo_set_source_rgba (cr, 0, 1, 0, 1.0);
4081 for (i = 0; i < BOARD_HEIGHT + 1; i++)
4084 x2 = lineGap + BOARD_WIDTH * (squareSize + lineGap);
4085 y1 = y2 = lineGap / 2 + (i * (squareSize + lineGap));
4087 cairo_move_to (cr, x1, y1);
4088 cairo_rel_line_to (cr, x2,0);
4092 for (j = 0; j < BOARD_WIDTH + 1; j++)
4095 y2 = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
4096 x1 = x2 = lineGap / 2 + (j * (squareSize + lineGap));
4098 cairo_move_to (cr, x1, y1);
4099 cairo_rel_line_to (cr, 0, y2);
4108 for (i = 0; i < BOARD_HEIGHT; i++)
4109 for (j = 0; j < BOARD_WIDTH; j++)
4111 DrawSquare(i, j, board[i][j], 0);
4112 damage[i][j] = False;
4116 CopyBoard(lastBoard, board);
4118 lastFlipView = flipView;
4120 /* Draw highlights */
4121 if (pm1X >= 0 && pm1Y >= 0)
4123 drawHighlight(pm1X, pm1Y, LINE_TYPE_PRE);
4125 if (pm2X >= 0 && pm2Y >= 0)
4127 drawHighlight(pm2X, pm2Y, LINE_TYPE_PRE);
4129 if (hi1X >= 0 && hi1Y >= 0)
4131 drawHighlight(hi1X, hi1Y, LINE_TYPE_HIGHLIGHT);
4133 if (hi2X >= 0 && hi2Y >= 0)
4135 drawHighlight(hi2X, hi2Y, LINE_TYPE_HIGHLIGHT);
4138 /* If piece being dragged around board, must redraw that too */
4145 * event handler for parsing user moves
4147 // [HGM] This routine will need quite some reworking. Although the backend still supports the old
4148 // way of doing things, by calling UserMoveEvent() to test the legality of the move and then perform
4149 // it at the end, and doing all kind of preliminary tests here (e.g. to weed out self-captures), it
4150 // should be made to use the new way, of calling UserMoveTest early to determine the legality of the
4151 // move, (which will weed out the illegal selfcaptures and moves into the holdings, and flag promotions),
4152 // and at the end FinishMove() to perform the move after optional promotion popups.
4153 // For now I patched it to allow self-capture with King, and suppress clicks between board and holdings.
4154 void HandleUserMove(w, event, prms, nprms)
4161 Boolean saveAnimate;
4162 static int second = 0;
4164 if (w != boardWidget || errorExitStatus != -1) return;
4166 if (event->type == ButtonPress) ErrorPopDown();
4169 if (event->type == ButtonPress) {
4170 XtPopdown(promotionShell);
4171 XtDestroyWidget(promotionShell);
4172 promotionUp = False;
4180 x = EventToSquare(event->xbutton.x, BOARD_WIDTH);
4181 y = EventToSquare(event->xbutton.y, BOARD_HEIGHT);
4182 if (!flipView && y >= 0) {
4183 y = BOARD_HEIGHT - 1 - y;
4185 if (flipView && x >= 0) {
4186 x = BOARD_WIDTH - 1 - x;
4189 /* [HGM] holdings: next 5 lines: ignore all clicks between board and holdings */
4190 if(event->type == ButtonPress
4191 && ( x == BOARD_LEFT-1 || x == BOARD_RGHT
4192 || x == BOARD_LEFT-2 && y < BOARD_HEIGHT-gameInfo.holdingsSize
4193 || x == BOARD_RGHT+1 && y >= gameInfo.holdingsSize) )
4197 if (event->type == ButtonPress) {
4199 if (OKToStartUserMove(x, y)) {
4203 DragPieceBegin(event->xbutton.x, event->xbutton.y);
4204 if (appData.highlightDragging) {
4205 SetHighlights(x, y, -1, -1);
4213 if (event->type == ButtonPress && gameMode != EditPosition &&
4218 /* Check if clicking again on the same color piece */
4219 fromP = boards[currentMove][fromY][fromX];
4220 toP = boards[currentMove][y][x];
4221 if ((WhitePawn <= fromP && fromP < WhiteKing && // [HGM] this test should go, as UserMoveTest now does it.
4222 WhitePawn <= toP && toP <= WhiteKing) || // For now I made it less critical by exempting King
4223 (BlackPawn <= fromP && fromP < BlackKing && // moves, to not interfere with FRC castlings.
4224 BlackPawn <= toP && toP <= BlackKing)) {
4225 /* Clicked again on same color piece -- changed his mind */
4226 second = (x == fromX && y == fromY);
4227 if (appData.highlightDragging) {
4228 SetHighlights(x, y, -1, -1);
4232 if (OKToStartUserMove(x, y)) {
4235 DragPieceBegin(event->xbutton.x, event->xbutton.y);
4241 if (event->type == ButtonRelease && x == fromX && y == fromY) {
4242 DragPieceEnd(event->xbutton.x, event->xbutton.y);
4243 if (appData.animateDragging) {
4244 /* Undo animation damage if any */
4245 DrawPosition(FALSE, NULL);
4248 /* Second up/down in same square; just abort move */
4253 ClearPremoveHighlights();
4255 /* First upclick in same square; start click-click mode */
4256 SetHighlights(x, y, -1, -1);
4261 /* Completed move */
4264 saveAnimate = appData.animate;
4265 if (event->type == ButtonPress) {
4266 /* Finish clickclick move */
4267 if (appData.animate || appData.highlightLastMove) {
4268 SetHighlights(fromX, fromY, toX, toY);
4273 /* Finish drag move */
4274 if (appData.highlightLastMove) {
4275 SetHighlights(fromX, fromY, toX, toY);
4279 DragPieceEnd(event->xbutton.x, event->xbutton.y);
4280 /* Don't animate move and drag both */
4281 appData.animate = FALSE;
4283 if (IsPromotion(fromX, fromY, toX, toY)) {
4284 if (appData.alwaysPromoteToQueen) {
4285 UserMoveEvent(fromX, fromY, toX, toY, 'q');
4286 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
4287 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
4290 SetHighlights(fromX, fromY, toX, toY);
4294 UserMoveEvent(fromX, fromY, toX, toY, NULLCHAR);
4295 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
4296 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
4299 appData.animate = saveAnimate;
4300 if (appData.animate || appData.animateDragging) {
4301 /* Undo animation damage if needed */
4302 DrawPosition(FALSE, NULL);
4306 void AnimateUserMove (Widget w, XEvent * event,
4307 String * params, Cardinal * nParams)
4309 DragPieceMove(event->xmotion.x, event->xmotion.y);
4312 Widget CommentCreate(name, text, mutable, callback, lines)
4314 int /*Boolean*/ mutable;
4315 XtCallbackProc callback;
4319 Widget shell, layout, form, edit, b_ok, b_cancel, b_clear, b_close, b_edit;
4324 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4325 XtGetValues(boardWidget, args, j);
4328 XtSetArg(args[j], XtNresizable, True); j++;
4331 XtCreatePopupShell(name, topLevelShellWidgetClass,
4332 shellWidget, args, j);
4335 XtCreatePopupShell(name, transientShellWidgetClass,
4336 shellWidget, args, j);
4339 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
4340 layoutArgs, XtNumber(layoutArgs));
4342 XtCreateManagedWidget("form", formWidgetClass, layout,
4343 formArgs, XtNumber(formArgs));
4347 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
4348 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
4350 XtSetArg(args[j], XtNstring, text); j++;
4351 XtSetArg(args[j], XtNtop, XtChainTop); j++;
4352 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4353 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4354 XtSetArg(args[j], XtNright, XtChainRight); j++;
4355 XtSetArg(args[j], XtNresizable, True); j++;
4356 XtSetArg(args[j], XtNwidth, bw_width); j++; /*force wider than buttons*/
4358 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
4360 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
4361 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
4363 XtSetArg(args[j], XtNautoFill, True); j++;
4364 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
4366 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
4370 XtSetArg(args[j], XtNfromVert, edit); j++;
4371 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4372 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4373 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4374 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4376 XtCreateManagedWidget(_("ok"), commandWidgetClass, form, args, j);
4377 XtAddCallback(b_ok, XtNcallback, callback, (XtPointer) 0);
4380 XtSetArg(args[j], XtNfromVert, edit); j++;
4381 XtSetArg(args[j], XtNfromHoriz, b_ok); j++;
4382 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4383 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4384 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4385 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4387 XtCreateManagedWidget(_("cancel"), commandWidgetClass, form, args, j);
4388 XtAddCallback(b_cancel, XtNcallback, callback, (XtPointer) 0);
4391 XtSetArg(args[j], XtNfromVert, edit); j++;
4392 XtSetArg(args[j], XtNfromHoriz, b_cancel); j++;
4393 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4394 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4395 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4396 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4398 XtCreateManagedWidget(_("clear"), commandWidgetClass, form, args, j);
4399 XtAddCallback(b_clear, XtNcallback, callback, (XtPointer) 0);
4402 XtSetArg(args[j], XtNfromVert, edit); j++;
4403 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4404 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4405 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4406 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4408 XtCreateManagedWidget(_("close"), commandWidgetClass, form, args, j);
4409 XtAddCallback(b_close, XtNcallback, callback, (XtPointer) 0);
4412 XtSetArg(args[j], XtNfromVert, edit); j++;
4413 XtSetArg(args[j], XtNfromHoriz, b_close); j++;
4414 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4415 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4416 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4417 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4419 XtCreateManagedWidget(_("edit"), commandWidgetClass, form, args, j);
4420 XtAddCallback(b_edit, XtNcallback, callback, (XtPointer) 0);
4423 XtRealizeWidget(shell);
4425 if (commentX == -1) {
4428 Dimension pw_height;
4429 Dimension ew_height;
4432 XtSetArg(args[j], XtNheight, &ew_height); j++;
4433 XtGetValues(edit, args, j);
4436 XtSetArg(args[j], XtNheight, &pw_height); j++;
4437 XtGetValues(shell, args, j);
4438 commentH = pw_height + (lines - 1) * ew_height;
4439 commentW = bw_width - 16;
4441 XSync(xDisplay, False);
4443 /* This code seems to tickle an X bug if it is executed too soon
4444 after xboard starts up. The coordinates get transformed as if
4445 the main window was positioned at (0, 0).
4447 XtTranslateCoords(shellWidget,
4448 (bw_width - commentW) / 2, 0 - commentH / 2,
4449 &commentX, &commentY);
4451 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
4452 RootWindowOfScreen(XtScreen(shellWidget)),
4453 (bw_width - commentW) / 2, 0 - commentH / 2,
4458 if (commentY < 0) commentY = 0; /*avoid positioning top offscreen*/
4461 XtSetArg(args[j], XtNheight, commentH); j++;
4462 XtSetArg(args[j], XtNwidth, commentW); j++;
4463 XtSetArg(args[j], XtNx, commentX); j++;
4464 XtSetArg(args[j], XtNy, commentY); j++;
4465 XtSetValues(shell, args, j);
4466 XtSetKeyboardFocus(shell, edit);
4471 /* Used for analysis window and ICS input window */
4472 Widget MiscCreate(name, text, mutable, callback, lines)
4474 int /*Boolean*/ mutable;
4475 XtCallbackProc callback;
4479 Widget shell, layout, form, edit;
4481 Dimension bw_width, pw_height, ew_height, w, h;
4487 XtSetArg(args[j], XtNresizable, True); j++;
4490 XtCreatePopupShell(name, topLevelShellWidgetClass,
4491 shellWidget, args, j);
4494 XtCreatePopupShell(name, transientShellWidgetClass,
4495 shellWidget, args, j);
4498 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
4499 layoutArgs, XtNumber(layoutArgs));
4501 XtCreateManagedWidget("form", formWidgetClass, layout,
4502 formArgs, XtNumber(formArgs));
4506 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
4507 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
4509 XtSetArg(args[j], XtNstring, text); j++;
4510 XtSetArg(args[j], XtNtop, XtChainTop); j++;
4511 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4512 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4513 XtSetArg(args[j], XtNright, XtChainRight); j++;
4514 XtSetArg(args[j], XtNresizable, True); j++;
4516 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
4518 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
4519 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
4521 XtSetArg(args[j], XtNautoFill, True); j++;
4522 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
4524 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
4526 XtRealizeWidget(shell);
4529 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4530 XtGetValues(boardWidget, args, j);
4533 XtSetArg(args[j], XtNheight, &ew_height); j++;
4534 XtGetValues(edit, args, j);
4537 XtSetArg(args[j], XtNheight, &pw_height); j++;
4538 XtGetValues(shell, args, j);
4539 h = pw_height + (lines - 1) * ew_height;
4542 XSync(xDisplay, False);
4544 /* This code seems to tickle an X bug if it is executed too soon
4545 after xboard starts up. The coordinates get transformed as if
4546 the main window was positioned at (0, 0).
4548 XtTranslateCoords(shellWidget, (bw_width - w) / 2, 0 - h / 2, &x, &y);
4550 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
4551 RootWindowOfScreen(XtScreen(shellWidget)),
4552 (bw_width - w) / 2, 0 - h / 2, &xx, &yy, &junk);
4556 if (y < 0) y = 0; /*avoid positioning top offscreen*/
4559 XtSetArg(args[j], XtNheight, h); j++;
4560 XtSetArg(args[j], XtNwidth, w); j++;
4561 XtSetArg(args[j], XtNx, x); j++;
4562 XtSetArg(args[j], XtNy, y); j++;
4563 XtSetValues(shell, args, j);
4569 static int savedIndex; /* gross that this is global */
4571 void EditCommentPopUp(index, title, text)
4580 if (text == NULL) text = "";
4582 if (editShell == NULL) {
4584 CommentCreate(title, text, True, EditCommentCallback, 4);
4585 XtRealizeWidget(editShell);
4586 CatchDeleteWindow(editShell, "EditCommentPopDown");
4588 edit = XtNameToWidget(editShell, "*form.text");
4590 XtSetArg(args[j], XtNstring, text); j++;
4591 XtSetValues(edit, args, j);
4593 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4594 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4595 XtSetValues(editShell, args, j);
4598 XtPopup(editShell, XtGrabNone);
4602 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
4603 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
4607 void EditCommentCallback(w, client_data, call_data)
4609 XtPointer client_data, call_data;
4617 XtSetArg(args[j], XtNlabel, &name); j++;
4618 XtGetValues(w, args, j);
4620 if (strcmp(name, _("ok")) == 0) {
4621 edit = XtNameToWidget(editShell, "*form.text");
4623 XtSetArg(args[j], XtNstring, &val); j++;
4624 XtGetValues(edit, args, j);
4625 ReplaceComment(savedIndex, val);
4626 EditCommentPopDown();
4627 } else if (strcmp(name, _("cancel")) == 0) {
4628 EditCommentPopDown();
4629 } else if (strcmp(name, _("clear")) == 0) {
4630 edit = XtNameToWidget(editShell, "*form.text");
4631 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
4632 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
4636 void EditCommentPopDown()
4641 if (!editUp) return;
4643 XtSetArg(args[j], XtNx, &commentX); j++;
4644 XtSetArg(args[j], XtNy, &commentY); j++;
4645 XtSetArg(args[j], XtNheight, &commentH); j++;
4646 XtSetArg(args[j], XtNwidth, &commentW); j++;
4647 XtGetValues(editShell, args, j);
4648 XtPopdown(editShell);
4651 XtSetArg(args[j], XtNleftBitmap, None); j++;
4652 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
4656 void ICSInputBoxPopUp()
4661 char *title = _("ICS Input");
4664 if (ICSInputShell == NULL) {
4665 ICSInputShell = MiscCreate(title, "", True, NULL, 1);
4666 tr = XtParseTranslationTable(ICSInputTranslations);
4667 edit = XtNameToWidget(ICSInputShell, "*form.text");
4668 XtOverrideTranslations(edit, tr);
4669 XtRealizeWidget(ICSInputShell);
4670 CatchDeleteWindow(ICSInputShell, "ICSInputBoxPopDown");
4673 edit = XtNameToWidget(ICSInputShell, "*form.text");
4675 XtSetArg(args[j], XtNstring, ""); j++;
4676 XtSetValues(edit, args, j);
4678 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4679 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4680 XtSetValues(ICSInputShell, args, j);
4683 XtPopup(ICSInputShell, XtGrabNone);
4684 XtSetKeyboardFocus(ICSInputShell, edit);
4686 ICSInputBoxUp = True;
4688 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
4689 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
4693 void ICSInputSendText()
4700 edit = XtNameToWidget(ICSInputShell, "*form.text");
4702 XtSetArg(args[j], XtNstring, &val); j++;
4703 XtGetValues(edit, args, j);
4704 SendMultiLineToICS(val);
4705 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
4706 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
4709 void ICSInputBoxPopDown()
4714 if (!ICSInputBoxUp) return;
4716 XtPopdown(ICSInputShell);
4717 ICSInputBoxUp = False;
4719 XtSetArg(args[j], XtNleftBitmap, None); j++;
4720 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
4724 void CommentPopUp(title, text)
4731 if (commentShell == NULL) {
4733 CommentCreate(title, text, False, CommentCallback, 4);
4734 XtRealizeWidget(commentShell);
4735 CatchDeleteWindow(commentShell, "CommentPopDown");
4737 edit = XtNameToWidget(commentShell, "*form.text");
4739 XtSetArg(args[j], XtNstring, text); j++;
4740 XtSetValues(edit, args, j);
4742 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4743 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4744 XtSetValues(commentShell, args, j);
4747 XtPopup(commentShell, XtGrabNone);
4748 XSync(xDisplay, False);
4753 void AnalysisPopUp(title, text)
4760 if (analysisShell == NULL) {
4761 analysisShell = MiscCreate(title, text, False, NULL, 4);
4762 XtRealizeWidget(analysisShell);
4763 CatchDeleteWindow(analysisShell, "AnalysisPopDown");
4766 edit = XtNameToWidget(analysisShell, "*form.text");
4768 XtSetArg(args[j], XtNstring, text); j++;
4769 XtSetValues(edit, args, j);
4771 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4772 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4773 XtSetValues(analysisShell, args, j);
4777 XtPopup(analysisShell, XtGrabNone);
4779 XSync(xDisplay, False);
4784 void CommentCallback(w, client_data, call_data)
4786 XtPointer client_data, call_data;
4793 XtSetArg(args[j], XtNlabel, &name); j++;
4794 XtGetValues(w, args, j);
4796 if (strcmp(name, _("close")) == 0) {
4798 } else if (strcmp(name, _("edit")) == 0) {
4805 void CommentPopDown()
4810 if (!commentUp) return;
4812 XtSetArg(args[j], XtNx, &commentX); j++;
4813 XtSetArg(args[j], XtNy, &commentY); j++;
4814 XtSetArg(args[j], XtNwidth, &commentW); j++;
4815 XtSetArg(args[j], XtNheight, &commentH); j++;
4816 XtGetValues(commentShell, args, j);
4817 XtPopdown(commentShell);
4818 XSync(xDisplay, False);
4822 void AnalysisPopDown()
4824 if (!analysisUp) return;
4825 XtPopdown(analysisShell);
4826 XSync(xDisplay, False);
4828 if (appData.icsEngineAnalyze) ExitAnalyzeMode(); /* [DM] icsEngineAnalyze */
4832 void FileNamePopUp(label, def, proc, openMode)
4839 Widget popup, layout, dialog, edit;
4845 fileProc = proc; /* I can't see a way not */
4846 fileOpenMode = openMode; /* to use globals here */
4849 XtSetArg(args[i], XtNresizable, True); i++;
4850 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
4851 XtSetArg(args[i], XtNtitle, XtNewString(_("File name prompt"))); i++;
4852 fileNameShell = popup =
4853 XtCreatePopupShell("File name prompt", transientShellWidgetClass,
4854 shellWidget, args, i);
4857 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
4858 layoutArgs, XtNumber(layoutArgs));
4861 XtSetArg(args[i], XtNlabel, label); i++;
4862 XtSetArg(args[i], XtNvalue, def); i++;
4863 XtSetArg(args[i], XtNborderWidth, 0); i++;
4864 dialog = XtCreateManagedWidget("fileName", dialogWidgetClass,
4867 XawDialogAddButton(dialog, _("ok"), FileNameCallback, (XtPointer) dialog);
4868 XawDialogAddButton(dialog, _("cancel"), FileNameCallback,
4869 (XtPointer) dialog);
4871 XtRealizeWidget(popup);
4872 CatchDeleteWindow(popup, "FileNamePopDown");
4874 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
4875 &x, &y, &win_x, &win_y, &mask);
4877 XtSetArg(args[0], XtNx, x - 10);
4878 XtSetArg(args[1], XtNy, y - 30);
4879 XtSetValues(popup, args, 2);
4881 XtPopup(popup, XtGrabExclusive);
4884 edit = XtNameToWidget(dialog, "*value");
4885 XtSetKeyboardFocus(popup, edit);
4888 void FileNamePopDown()
4890 if (!filenameUp) return;
4891 XtPopdown(fileNameShell);
4892 XtDestroyWidget(fileNameShell);
4897 void FileNameCallback(w, client_data, call_data)
4899 XtPointer client_data, call_data;
4904 XtSetArg(args[0], XtNlabel, &name);
4905 XtGetValues(w, args, 1);
4907 if (strcmp(name, _("cancel")) == 0) {
4912 FileNameAction(w, NULL, NULL, NULL);
4915 void FileNameAction(w, event, prms, nprms)
4927 name = XawDialogGetValueString(w = XtParent(w));
4929 if ((name != NULL) && (*name != NULLCHAR)) {
4931 XtPopdown(w = XtParent(XtParent(w)));
4935 p = strrchr(buf, ' ');
4942 fullname = ExpandPathName(buf);
4944 ErrorPopUp(_("Error"), _("Can't open file"), FALSE);
4947 f = fopen(fullname, fileOpenMode);
4949 DisplayError(_("Failed to open file"), errno);
4951 (void) (*fileProc)(f, index, buf);
4958 XtPopdown(w = XtParent(XtParent(w)));
4964 void PromotionPopUp()
4967 Widget dialog, layout;
4969 Dimension bw_width, pw_width;
4973 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4974 XtGetValues(boardWidget, args, j);
4977 XtSetArg(args[j], XtNresizable, True); j++;
4978 XtSetArg(args[j], XtNtitle, XtNewString(_("Promotion"))); j++;
4980 XtCreatePopupShell("Promotion", transientShellWidgetClass,
4981 shellWidget, args, j);
4983 XtCreateManagedWidget(layoutName, formWidgetClass, promotionShell,
4984 layoutArgs, XtNumber(layoutArgs));
4987 XtSetArg(args[j], XtNlabel, _("Promote to what?")); j++;
4988 XtSetArg(args[j], XtNborderWidth, 0); j++;
4989 dialog = XtCreateManagedWidget("promotion", dialogWidgetClass,
4992 if(gameInfo.variant != VariantShogi) {
4993 XawDialogAddButton(dialog, _("Queen"), PromotionCallback,
4994 (XtPointer) dialog);
4995 XawDialogAddButton(dialog, _("Rook"), PromotionCallback,
4996 (XtPointer) dialog);
4997 XawDialogAddButton(dialog, _("Bishop"), PromotionCallback,
4998 (XtPointer) dialog);
4999 XawDialogAddButton(dialog, _("Knight"), PromotionCallback,
5000 (XtPointer) dialog);
5001 if (!appData.testLegality || gameInfo.variant == VariantSuicide ||
5002 gameInfo.variant == VariantGiveaway) {
5003 XawDialogAddButton(dialog, _("King"), PromotionCallback,
5004 (XtPointer) dialog);
5006 if(gameInfo.variant == VariantCapablanca ||
5007 gameInfo.variant == VariantGothic ||
5008 gameInfo.variant == VariantCapaRandom) {
5009 XawDialogAddButton(dialog, _("Archbishop"), PromotionCallback,
5010 (XtPointer) dialog);
5011 XawDialogAddButton(dialog, _("Chancellor"), PromotionCallback,
5012 (XtPointer) dialog);
5014 } else // [HGM] shogi
5016 XawDialogAddButton(dialog, _("Promote"), PromotionCallback,
5017 (XtPointer) dialog);
5018 XawDialogAddButton(dialog, _("Defer"), PromotionCallback,
5019 (XtPointer) dialog);
5021 XawDialogAddButton(dialog, _("cancel"), PromotionCallback,
5022 (XtPointer) dialog);
5024 XtRealizeWidget(promotionShell);
5025 CatchDeleteWindow(promotionShell, "PromotionPopDown");
5028 XtSetArg(args[j], XtNwidth, &pw_width); j++;
5029 XtGetValues(promotionShell, args, j);
5031 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
5032 lineGap + squareSize/3 +
5033 ((toY == BOARD_HEIGHT-1) ^ (flipView) ?
5034 0 : 6*(squareSize + lineGap)), &x, &y);
5037 XtSetArg(args[j], XtNx, x); j++;
5038 XtSetArg(args[j], XtNy, y); j++;
5039 XtSetValues(promotionShell, args, j);
5041 XtPopup(promotionShell, XtGrabNone);
5046 void PromotionPopDown()
5048 if (!promotionUp) return;
5049 XtPopdown(promotionShell);
5050 XtDestroyWidget(promotionShell);
5051 promotionUp = False;
5054 void PromotionCallback(w, client_data, call_data)
5056 XtPointer client_data, call_data;
5062 XtSetArg(args[0], XtNlabel, &name);
5063 XtGetValues(w, args, 1);
5067 if (fromX == -1) return;
5069 if (strcmp(name, _("cancel")) == 0) {
5073 } else if (strcmp(name, _("Knight")) == 0) {
5075 } else if (strcmp(name, _("Promote")) == 0) {
5077 } else if (strcmp(name, _("Defer")) == 0) {
5080 promoChar = ToLower(name[0]);
5083 UserMoveEvent(fromX, fromY, toX, toY, promoChar);
5085 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
5086 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
5091 void ErrorCallback(w, client_data, call_data)
5093 XtPointer client_data, call_data;
5096 XtPopdown(w = XtParent(XtParent(XtParent(w))));
5098 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5104 if (!errorUp) return;
5106 XtPopdown(errorShell);
5107 XtDestroyWidget(errorShell);
5108 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5111 void ErrorPopUp(title, label, modal)
5112 char *title, *label;
5117 dialog = gtk_message_dialog_new(GTK_WINDOW(GUI_Window),
5118 GTK_DIALOG_DESTROY_WITH_PARENT,
5123 gtk_window_set_title(GTK_WINDOW(dialog),(gchar *) title);
5126 gtk_dialog_run(GTK_DIALOG(dialog));
5127 gtk_widget_destroy(GTK_WIDGET(dialog));
5131 g_signal_connect_swapped (dialog, "response",
5132 G_CALLBACK (ErrorPopDownProc),
5135 gtk_widget_show(GTK_WIDGET(dialog));
5139 /* Disable all user input other than deleting the window */
5140 static int frozen = 0;
5144 /* Grab by a widget that doesn't accept input */
5145 // XtAddGrab(messageWidget, TRUE, FALSE);
5149 /* Undo a FreezeUI */
5152 if (!frozen) return;
5153 // XtRemoveGrab(messageWidget);
5157 char *ModeToWidgetName(mode)
5161 case BeginningOfGame:
5162 if (appData.icsActive)
5163 return "menuMode.ICS Client";
5164 else if (appData.noChessProgram ||
5165 *appData.cmailGameName != NULLCHAR)
5166 return "menuMode.Edit Game";
5168 return "menuMode.Machine Black";
5169 case MachinePlaysBlack:
5170 return "menuMode.Machine Black";
5171 case MachinePlaysWhite:
5172 return "menuMode.Machine White";
5174 return "menuMode.Analysis Mode";
5176 return "menuMode.Analyze File";
5177 case TwoMachinesPlay:
5178 return "menuMode.Two Machines";
5180 return "menuMode.Edit Game";
5181 case PlayFromGameFile:
5182 return "menuFile.Load Game";
5184 return "menuMode.Edit Position";
5186 return "menuMode.Training";
5187 case IcsPlayingWhite:
5188 case IcsPlayingBlack:
5192 return "menuMode.ICS Client";
5199 void ModeHighlight()
5201 static int oldPausing = FALSE;
5202 static GameMode oldmode = (GameMode) -1;
5205 // todo this toggling of the pause button doesn't seem to work?
5206 // e.g. select pause from buttonbar doesn't activate menumode.pause
5208 // if (!boardWidget || !XtIsRealized(boardWidget)) return;
5210 if (pausing != oldPausing) {
5211 oldPausing = pausing;
5212 gtk_button_set_relief(GTK_BUTTON (gtk_builder_get_object (builder, "menuMode.Pause")),pausing?GTK_RELIEF_NORMAL:GTK_RELIEF_NONE);
5213 /* toggle background color in showbuttonbar */
5214 if (appData.showButtonBar) {
5216 gtk_button_pressed(GTK_BUTTON (gtk_builder_get_object (builder, "buttonbar.Pause")));
5218 gtk_button_released(GTK_BUTTON (gtk_builder_get_object (builder, "buttonbar.Pause")));
5223 wname = ModeToWidgetName(oldmode);
5225 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, wname)),True);
5229 /* Maybe all the enables should be handled here, not just this one */
5230 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuMode.Training")),
5231 gameMode == Training || gameMode == PlayFromGameFile);
5236 * Button/menu procedures
5239 int LoadGamePopUp(f, gameNumber, title)
5244 cmailMsgLoaded = FALSE;
5245 if (gameNumber == 0) {
5246 int error = GameListBuild(f);
5248 DisplayError(_("Cannot build game list"), error);
5249 } else if (!ListEmpty(&gameList) &&
5250 ((ListGame *) gameList.tailPred)->number > 1) {
5251 GameListPopUp(f, title);
5257 return LoadGame(f, gameNumber, title, FALSE);
5261 void LoadNextPositionProc(w, event, prms, nprms)
5270 void LoadPrevPositionProc(w, event, prms, nprms)
5279 void ReloadPositionProc(w, event, prms, nprms)
5288 void LoadPositionProc(w, event, prms, nprms)
5294 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
5297 FileNamePopUp(_("Load position file name?"), "", LoadPosition, "rb");
5300 void SaveGameProc(w, event, prms, nprms)
5306 FileNamePopUp(_("Save game file name?"),
5307 DefaultFileName(appData.oldSaveStyle ? "game" : "pgn"),
5311 void SavePositionProc(w, event, prms, nprms)
5317 FileNamePopUp(_("Save position file name?"),
5318 DefaultFileName(appData.oldSaveStyle ? "pos" : "fen"),
5322 void ReloadCmailMsgProc(w, event, prms, nprms)
5328 ReloadCmailMsgEvent(FALSE);
5331 void MailMoveProc(w, event, prms, nprms)
5340 /* this variable is shared between CopyPositionProc and SendPositionSelection */
5341 static char *selected_fen_position=NULL;
5344 SendPositionSelection(Widget w, Atom *selection, Atom *target,
5345 Atom *type_return, XtPointer *value_return,
5346 unsigned long *length_return, int *format_return)
5348 char *selection_tmp;
5350 if (!selected_fen_position) return False; /* should never happen */
5351 if (*target == XA_STRING){
5352 /* note: since no XtSelectionDoneProc was registered, Xt will
5353 * automatically call XtFree on the value returned. So have to
5354 * make a copy of it allocated with XtMalloc */
5355 selection_tmp= XtMalloc(strlen(selected_fen_position)+16);
5356 strcpy(selection_tmp, selected_fen_position);
5358 *value_return=selection_tmp;
5359 *length_return=strlen(selection_tmp);
5360 *type_return=XA_STRING;
5361 *format_return = 8; /* bits per byte */
5368 /* note: when called from menu all parameters are NULL, so no clue what the
5369 * Widget which was clicked on was, or what the click event was
5371 void CopyPositionProc(w, event, prms, nprms)
5379 if (selected_fen_position) free(selected_fen_position);
5380 selected_fen_position = (char *)PositionToFEN(currentMove, NULL);
5381 if (!selected_fen_position) return;
5382 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
5384 SendPositionSelection,
5385 NULL/* lose_ownership_proc */ ,
5386 NULL/* transfer_done_proc */);
5388 free(selected_fen_position);
5389 selected_fen_position=NULL;
5393 /* function called when the data to Paste is ready */
5395 PastePositionCB(Widget w, XtPointer client_data, Atom *selection,
5396 Atom *type, XtPointer value, unsigned long *len, int *format)
5399 if (value==NULL || *len==0) return; /* nothing had been selected to copy */
5400 fenstr[*len]='\0'; /* normally this string is terminated, but be safe */
5401 EditPositionPasteFEN(fenstr);
5405 /* called when Paste Position button is pressed,
5406 * all parameters will be NULL */
5407 void PastePositionProc(w, event, prms, nprms)
5413 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
5414 /* (XtSelectionCallbackProc) */ PastePositionCB,
5415 NULL, /* client_data passed to PastePositionCB */
5417 /* better to use the time field from the event that triggered the
5418 * call to this function, but that isn't trivial to get
5426 SendGameSelection(Widget w, Atom *selection, Atom *target,
5427 Atom *type_return, XtPointer *value_return,
5428 unsigned long *length_return, int *format_return)
5430 char *selection_tmp;
5432 if (*target == XA_STRING){
5433 FILE* f = fopen(gameCopyFilename, "r");
5436 if (f == NULL) return False;
5440 selection_tmp = XtMalloc(len + 1);
5441 count = fread(selection_tmp, 1, len, f);
5443 XtFree(selection_tmp);
5446 selection_tmp[len] = NULLCHAR;
5447 *value_return = selection_tmp;
5448 *length_return = len;
5449 *type_return = XA_STRING;
5450 *format_return = 8; /* bits per byte */
5457 /* note: when called from menu all parameters are NULL, so no clue what the
5458 * Widget which was clicked on was, or what the click event was
5460 void CopyGameProc(w, event, prms, nprms)
5468 ret = SaveGameToFile(gameCopyFilename, FALSE);
5471 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
5474 NULL/* lose_ownership_proc */ ,
5475 NULL/* transfer_done_proc */);
5478 /* function called when the data to Paste is ready */
5480 PasteGameCB(Widget w, XtPointer client_data, Atom *selection,
5481 Atom *type, XtPointer value, unsigned long *len, int *format)
5484 if (value == NULL || *len == 0) {
5485 return; /* nothing had been selected to copy */
5487 f = fopen(gamePasteFilename, "w");
5489 DisplayError(_("Can't open temp file"), errno);
5492 fwrite(value, 1, *len, f);
5495 LoadGameFromFile(gamePasteFilename, 0, gamePasteFilename, TRUE);
5498 /* called when Paste Game button is pressed,
5499 * all parameters will be NULL */
5500 void PasteGameProc(w, event, prms, nprms)
5506 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
5507 /* (XtSelectionCallbackProc) */ PasteGameCB,
5508 NULL, /* client_data passed to PasteGameCB */
5510 /* better to use the time field from the event that triggered the
5511 * call to this function, but that isn't trivial to get
5521 SaveGameProc(NULL, NULL, NULL, NULL);
5524 void MachineBlackProc(w, event, prms, nprms)
5530 MachineBlackEvent();
5533 void MachineWhiteProc(w, event, prms, nprms)
5539 MachineWhiteEvent();
5542 void AnalyzeModeProc(w, event, prms, nprms)
5550 if (!first.analysisSupport) {
5551 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
5552 DisplayError(buf, 0);
5555 /* [DM] icsEngineAnalyze [HGM] This is horrible code; reverse the gameMode and isEngineAnalyze tests! */
5556 if (appData.icsActive) {
5557 if (gameMode != IcsObserving) {
5558 sprintf(buf,_("You are not observing a game"));
5559 DisplayError(buf, 0);
5561 if (appData.icsEngineAnalyze) {
5562 if (appData.debugMode)
5563 fprintf(debugFP, _("Found unexpected active ICS engine analyze \n"));
5569 /* if enable, use want disable icsEngineAnalyze */
5570 if (appData.icsEngineAnalyze) {
5575 appData.icsEngineAnalyze = TRUE;
5576 if (appData.debugMode)
5577 fprintf(debugFP, _("ICS engine analyze starting... \n"));
5579 if (!appData.showThinking)
5580 ShowThinkingProc(w,event,prms,nprms);
5585 void AnalyzeFileProc(w, event, prms, nprms)
5591 if (!first.analysisSupport) {
5593 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
5594 DisplayError(buf, 0);
5599 if (!appData.showThinking)
5600 ShowThinkingProc(w,event,prms,nprms);
5603 FileNamePopUp(_("File to analyze"), "", LoadGamePopUp, "rb");
5604 AnalysisPeriodicEvent(1);
5607 void TwoMachinesProc(w, event, prms, nprms)
5616 void IcsClientProc(w, event, prms, nprms)
5625 void EditGameProc(w, event, prms, nprms)
5634 void EditPositionProc(w, event, prms, nprms)
5640 EditPositionEvent();
5643 void TrainingProc(w, event, prms, nprms)
5652 void EditCommentProc(w, event, prms, nprms)
5659 EditCommentPopDown();
5665 void IcsInputBoxProc(w, event, prms, nprms)
5671 if (ICSInputBoxUp) {
5672 ICSInputBoxPopDown();
5678 void AcceptProc(w, event, prms, nprms)
5687 void DeclineProc(w, event, prms, nprms)
5696 void RematchProc(w, event, prms, nprms)
5705 void CallFlagProc(w, event, prms, nprms)
5714 void DrawProc(w, event, prms, nprms)
5723 void AbortProc(w, event, prms, nprms)
5732 void AdjournProc(w, event, prms, nprms)
5741 void ResignProc(w, event, prms, nprms)
5750 void AdjuWhiteProc(w, event, prms, nprms)
5756 UserAdjudicationEvent(+1);
5759 void AdjuBlackProc(w, event, prms, nprms)
5765 UserAdjudicationEvent(-1);
5768 void AdjuDrawProc(w, event, prms, nprms)
5774 UserAdjudicationEvent(0);
5777 void EnterKeyProc(w, event, prms, nprms)
5783 if (ICSInputBoxUp == True)
5787 void StopObservingProc(w, event, prms, nprms)
5793 StopObservingEvent();
5796 void StopExaminingProc(w, event, prms, nprms)
5802 StopExaminingEvent();
5806 void ForwardProc(w, event, prms, nprms)
5816 void BackwardProc(w, event, prms, nprms)
5825 void ToStartProc(w, event, prms, nprms)
5834 void ToEndProc(w, event, prms, nprms)
5843 void RevertProc(w, event, prms, nprms)
5852 void TruncateGameProc(w, event, prms, nprms)
5858 TruncateGameEvent();
5860 void RetractMoveProc(w, event, prms, nprms)
5869 void MoveNowProc(w, event, prms, nprms)
5879 void AlwaysQueenProc(w, event, prms, nprms)
5887 appData.alwaysPromoteToQueen = !appData.alwaysPromoteToQueen;
5889 if (appData.alwaysPromoteToQueen) {
5890 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5892 XtSetArg(args[0], XtNleftBitmap, None);
5894 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
5898 void AnimateDraggingProc(w, event, prms, nprms)
5906 appData.animateDragging = !appData.animateDragging;
5908 if (appData.animateDragging) {
5909 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5912 XtSetArg(args[0], XtNleftBitmap, None);
5914 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Dragging"),
5918 void AnimateMovingProc(w, event, prms, nprms)
5926 appData.animate = !appData.animate;
5928 if (appData.animate) {
5929 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5932 XtSetArg(args[0], XtNleftBitmap, None);
5934 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
5938 void AutocommProc(w, event, prms, nprms)
5946 appData.autoComment = !appData.autoComment;
5948 if (appData.autoComment) {
5949 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5951 XtSetArg(args[0], XtNleftBitmap, None);
5953 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
5958 void AutoflagProc(w, event, prms, nprms)
5966 appData.autoCallFlag = !appData.autoCallFlag;
5968 if (appData.autoCallFlag) {
5969 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5971 XtSetArg(args[0], XtNleftBitmap, None);
5973 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
5977 void AutoflipProc(w, event, prms, nprms)
5985 appData.autoFlipView = !appData.autoFlipView;
5987 if (appData.autoFlipView) {
5988 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5990 XtSetArg(args[0], XtNleftBitmap, None);
5992 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flip View"),
5996 void AutobsProc(w, event, prms, nprms)
6004 appData.autoObserve = !appData.autoObserve;
6006 if (appData.autoObserve) {
6007 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6009 XtSetArg(args[0], XtNleftBitmap, None);
6011 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
6015 void AutoraiseProc(w, event, prms, nprms)
6023 appData.autoRaiseBoard = !appData.autoRaiseBoard;
6025 if (appData.autoRaiseBoard) {
6026 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6028 XtSetArg(args[0], XtNleftBitmap, None);
6030 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Raise Board"),
6034 void AutosaveProc(w, event, prms, nprms)
6042 appData.autoSaveGames = !appData.autoSaveGames;
6044 if (appData.autoSaveGames) {
6045 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6047 XtSetArg(args[0], XtNleftBitmap, None);
6049 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
6053 void BlindfoldProc(w, event, prms, nprms)
6061 appData.blindfold = !appData.blindfold;
6063 if (appData.blindfold) {
6064 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6066 XtSetArg(args[0], XtNleftBitmap, None);
6068 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Blindfold"),
6071 DrawPosition(True, NULL);
6074 void TestLegalityProc(w, event, prms, nprms)
6082 appData.testLegality = !appData.testLegality;
6084 if (appData.testLegality) {
6085 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6087 XtSetArg(args[0], XtNleftBitmap, None);
6089 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Test Legality"),
6094 void FlashMovesProc(w, event, prms, nprms)
6102 if (appData.flashCount == 0) {
6103 appData.flashCount = 3;
6105 appData.flashCount = -appData.flashCount;
6108 if (appData.flashCount > 0) {
6109 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6111 XtSetArg(args[0], XtNleftBitmap, None);
6113 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flash Moves"),
6117 void FlipViewProc(w, event, prms, nprms)
6123 flipView = !flipView;
6124 DrawPosition(True, NULL);
6127 void GetMoveListProc(w, event, prms, nprms)
6135 appData.getMoveList = !appData.getMoveList;
6137 if (appData.getMoveList) {
6138 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6141 XtSetArg(args[0], XtNleftBitmap, None);
6143 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
6148 void HighlightDraggingProc(w, event, prms, nprms)
6156 appData.highlightDragging = !appData.highlightDragging;
6158 if (appData.highlightDragging) {
6159 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6161 XtSetArg(args[0], XtNleftBitmap, None);
6163 XtSetValues(XtNameToWidget(menuBarWidget,
6164 "menuOptions.Highlight Dragging"), args, 1);
6168 void HighlightLastMoveProc(w, event, prms, nprms)
6176 appData.highlightLastMove = !appData.highlightLastMove;
6178 if (appData.highlightLastMove) {
6179 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6181 XtSetArg(args[0], XtNleftBitmap, None);
6183 XtSetValues(XtNameToWidget(menuBarWidget,
6184 "menuOptions.Highlight Last Move"), args, 1);
6187 void IcsAlarmProc(w, event, prms, nprms)
6195 appData.icsAlarm = !appData.icsAlarm;
6197 if (appData.icsAlarm) {
6198 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6200 XtSetArg(args[0], XtNleftBitmap, None);
6202 XtSetValues(XtNameToWidget(menuBarWidget,
6203 "menuOptions.ICS Alarm"), args, 1);
6206 void MoveSoundProc(w, event, prms, nprms)
6214 appData.ringBellAfterMoves = !appData.ringBellAfterMoves;
6216 if (appData.ringBellAfterMoves) {
6217 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6219 XtSetArg(args[0], XtNleftBitmap, None);
6221 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
6226 void OldSaveStyleProc(w, event, prms, nprms)
6234 appData.oldSaveStyle = !appData.oldSaveStyle;
6236 if (appData.oldSaveStyle) {
6237 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6239 XtSetArg(args[0], XtNleftBitmap, None);
6241 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Old Save Style"),
6245 void PeriodicUpdatesProc(w, event, prms, nprms)
6253 PeriodicUpdatesEvent(!appData.periodicUpdates);
6255 if (appData.periodicUpdates) {
6256 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6258 XtSetArg(args[0], XtNleftBitmap, None);
6260 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Periodic Updates"),
6264 void PonderNextMoveProc(w, event, prms, nprms)
6272 PonderNextMoveEvent(!appData.ponderNextMove);
6274 if (appData.ponderNextMove) {
6275 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6277 XtSetArg(args[0], XtNleftBitmap, None);
6279 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Ponder Next Move"),
6283 void PopupExitMessageProc(w, event, prms, nprms)
6291 appData.popupExitMessage = !appData.popupExitMessage;
6293 if (appData.popupExitMessage) {
6294 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6296 XtSetArg(args[0], XtNleftBitmap, None);
6298 XtSetValues(XtNameToWidget(menuBarWidget,
6299 "menuOptions.Popup Exit Message"), args, 1);
6302 void PopupMoveErrorsProc(w, event, prms, nprms)
6310 appData.popupMoveErrors = !appData.popupMoveErrors;
6312 if (appData.popupMoveErrors) {
6313 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6315 XtSetArg(args[0], XtNleftBitmap, None);
6317 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Popup Move Errors"),
6321 void PremoveProc(w, event, prms, nprms)
6329 appData.premove = !appData.premove;
6331 if (appData.premove) {
6332 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6334 XtSetArg(args[0], XtNleftBitmap, None);
6336 XtSetValues(XtNameToWidget(menuBarWidget,
6337 "menuOptions.Premove"), args, 1);
6340 void QuietPlayProc(w, event, prms, nprms)
6348 appData.quietPlay = !appData.quietPlay;
6350 if (appData.quietPlay) {
6351 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6353 XtSetArg(args[0], XtNleftBitmap, None);
6355 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Quiet Play"),
6359 void ShowThinkingProc(w, event, prms, nprms)
6367 appData.showThinking = !appData.showThinking; // [HGM] thinking: tken out of ShowThinkingEvent
6368 ShowThinkingEvent();
6370 // [HGM] thinking: currently no suc menu item; replaced by Hide Thinking (From Human)
6371 if (appData.showThinking) {
6372 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6374 XtSetArg(args[0], XtNleftBitmap, None);
6376 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Thinking"),
6381 void HideThinkingProc(w, event, prms, nprms)
6389 appData.hideThinkingFromHuman = !appData.hideThinkingFromHuman; // [HGM] thinking: tken out of ShowThinkingEvent
6390 ShowThinkingEvent();
6392 if (appData.hideThinkingFromHuman) {
6393 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6395 XtSetArg(args[0], XtNleftBitmap, None);
6397 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
6401 void InfoProc(w, event, prms, nprms)
6408 snprintf(buf, sizeof(buf), "xterm -e info --directory %s --directory . -f %s &",
6413 void ManProc(w, event, prms, nprms)
6421 if (nprms && *nprms > 0)
6425 snprintf(buf, sizeof(buf), "xterm -e man %s &", name);
6429 void HintProc(w, event, prms, nprms)
6438 void BookProc(w, event, prms, nprms)
6447 void DebugProc(w, event, prms, nprms)
6453 appData.debugMode = !appData.debugMode;
6456 void AboutGameProc(w, event, prms, nprms)
6465 void NothingProc(w, event, prms, nprms)
6474 void Iconify(w, event, prms, nprms)
6483 XtSetArg(args[0], XtNiconic, True);
6484 XtSetValues(shellWidget, args, 1);
6487 void DisplayMessage(message, extMessage)
6488 gchar *message, *extMessage;
6495 snprintf(buf, sizeof(buf), "%s %s", message, extMessage);
6498 message = extMessage;
6501 gtk_label_set_text( GTK_LABEL(gtk_builder_get_object (builder, "Messages")),message);
6504 void DisplayTitle(text)
6509 char title[MSG_SIZ];
6512 if (text == NULL) text = "";
6514 if (appData.titleInWindow) {
6516 XtSetArg(args[i], XtNlabel, text); i++;
6517 XtSetValues(titleWidget, args, i);
6520 if (*text != NULLCHAR) {
6522 strcpy(title, text);
6523 } else if (appData.icsActive) {
6524 snprintf(icon, sizeof(icon), "%s", appData.icsHost);
6525 snprintf(title, sizeof(title), "%s: %s", programName, appData.icsHost);
6526 } else if (appData.cmailGameName[0] != NULLCHAR) {
6527 snprintf(icon, sizeof(icon), "%s", "CMail");
6528 snprintf(title,sizeof(title), "%s: %s", programName, "CMail");
6530 // [HGM] license: This stuff should really be done in back-end, but WinBoard already had a pop-up for it
6531 } else if (gameInfo.variant == VariantGothic) {
6532 strcpy(icon, programName);
6533 strcpy(title, GOTHIC);
6536 } else if (gameInfo.variant == VariantFalcon) {
6537 strcpy(icon, programName);
6538 strcpy(title, FALCON);
6540 } else if (appData.noChessProgram) {
6541 strcpy(icon, programName);
6542 strcpy(title, programName);
6544 strcpy(icon, first.tidy);
6545 snprintf(title,sizeof(title), "%s: %s", programName, first.tidy);
6548 XtSetArg(args[i], XtNiconName, (XtArgVal) icon); i++;
6549 XtSetArg(args[i], XtNtitle, (XtArgVal) title); i++;
6550 XtSetValues(shellWidget, args, i);
6554 void DisplayError(message, error)
6561 if (appData.debugMode || appData.matchMode) {
6562 fprintf(stderr, "%s: %s\n", programName, message);
6565 if (appData.debugMode || appData.matchMode) {
6566 fprintf(stderr, "%s: %s: %s\n",
6567 programName, message, strerror(error));
6569 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
6572 ErrorPopUp(_("Error"), message, FALSE);
6576 void DisplayMoveError(message)
6581 DrawPosition(FALSE, NULL);
6582 if (appData.debugMode || appData.matchMode) {
6583 fprintf(stderr, "%s: %s\n", programName, message);
6585 if (appData.popupMoveErrors) {
6586 ErrorPopUp(_("Error"), message, FALSE);
6588 DisplayMessage(message, "");
6593 void DisplayFatalError(message, error, status)
6599 errorExitStatus = status;
6601 fprintf(stderr, "%s: %s\n", programName, message);
6603 fprintf(stderr, "%s: %s: %s\n",
6604 programName, message, strerror(error));
6605 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
6608 if (appData.popupExitMessage && boardWidget && XtIsRealized(boardWidget)) {
6609 ErrorPopUp(status ? _("Fatal Error") : _("Exiting"), message, TRUE);
6615 void DisplayInformation(message)
6619 ErrorPopUp(_("Information"), message, TRUE);
6622 void DisplayNote(message)
6626 ErrorPopUp(_("Note"), message, FALSE);
6630 NullXErrorCheck(dpy, error_event)
6632 XErrorEvent *error_event;
6637 void DisplayIcsInteractionTitle(message)
6640 if (oldICSInteractionTitle == NULL) {
6641 /* Magic to find the old window title, adapted from vim */
6642 char *wina = getenv("WINDOWID");
6644 Window win = (Window) atoi(wina);
6645 Window root, parent, *children;
6646 unsigned int nchildren;
6647 int (*oldHandler)() = XSetErrorHandler(NullXErrorCheck);
6649 if (XFetchName(xDisplay, win, &oldICSInteractionTitle)) break;
6650 if (!XQueryTree(xDisplay, win, &root, &parent,
6651 &children, &nchildren)) break;
6652 if (children) XFree((void *)children);
6653 if (parent == root || parent == 0) break;
6656 XSetErrorHandler(oldHandler);
6658 if (oldICSInteractionTitle == NULL) {
6659 oldICSInteractionTitle = "xterm";
6662 printf("\033]0;%s\007", message);
6666 char pendingReplyPrefix[MSG_SIZ];
6667 ProcRef pendingReplyPR;
6669 void AskQuestionProc(w, event, prms, nprms)
6676 fprintf(stderr, _("AskQuestionProc needed 4 parameters, got %d\n"),
6680 AskQuestionEvent(prms[0], prms[1], prms[2], prms[3]);
6683 void AskQuestionPopDown()
6685 if (!askQuestionUp) return;
6686 XtPopdown(askQuestionShell);
6687 XtDestroyWidget(askQuestionShell);
6688 askQuestionUp = False;
6691 void AskQuestionReplyAction(w, event, prms, nprms)
6701 reply = XawDialogGetValueString(w = XtParent(w));
6702 strcpy(buf, pendingReplyPrefix);
6703 if (*buf) strcat(buf, " ");
6706 OutputToProcess(pendingReplyPR, buf, strlen(buf), &err);
6707 AskQuestionPopDown();
6709 if (err) DisplayFatalError(_("Error writing to chess program"), err, 0);
6712 void AskQuestionCallback(w, client_data, call_data)
6714 XtPointer client_data, call_data;
6719 XtSetArg(args[0], XtNlabel, &name);
6720 XtGetValues(w, args, 1);
6722 if (strcmp(name, _("cancel")) == 0) {
6723 AskQuestionPopDown();
6725 AskQuestionReplyAction(w, NULL, NULL, NULL);
6729 void AskQuestion(title, question, replyPrefix, pr)
6730 char *title, *question, *replyPrefix;
6734 Widget popup, layout, dialog, edit;
6740 strcpy(pendingReplyPrefix, replyPrefix);
6741 pendingReplyPR = pr;
6744 XtSetArg(args[i], XtNresizable, True); i++;
6745 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
6746 askQuestionShell = popup =
6747 XtCreatePopupShell(title, transientShellWidgetClass,
6748 shellWidget, args, i);
6751 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
6752 layoutArgs, XtNumber(layoutArgs));
6755 XtSetArg(args[i], XtNlabel, question); i++;
6756 XtSetArg(args[i], XtNvalue, ""); i++;
6757 XtSetArg(args[i], XtNborderWidth, 0); i++;
6758 dialog = XtCreateManagedWidget("question", dialogWidgetClass,
6761 XawDialogAddButton(dialog, _("enter"), AskQuestionCallback,
6762 (XtPointer) dialog);
6763 XawDialogAddButton(dialog, _("cancel"), AskQuestionCallback,
6764 (XtPointer) dialog);
6766 XtRealizeWidget(popup);
6767 CatchDeleteWindow(popup, "AskQuestionPopDown");
6769 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
6770 &x, &y, &win_x, &win_y, &mask);
6772 XtSetArg(args[0], XtNx, x - 10);
6773 XtSetArg(args[1], XtNy, y - 30);
6774 XtSetValues(popup, args, 2);
6776 XtPopup(popup, XtGrabExclusive);
6777 askQuestionUp = True;
6779 edit = XtNameToWidget(dialog, "*value");
6780 XtSetKeyboardFocus(popup, edit);
6788 if (*name == NULLCHAR) {
6790 } else if (strcmp(name, "$") == 0) {
6791 putc(BELLCHAR, stderr);
6794 snprintf(buf, sizeof(buf), "%s '%s' &", appData.soundProgram, name);
6802 PlaySound(appData.soundMove);
6808 PlaySound(appData.soundIcsWin);
6814 PlaySound(appData.soundIcsLoss);
6820 PlaySound(appData.soundIcsDraw);
6824 PlayIcsUnfinishedSound()
6826 PlaySound(appData.soundIcsUnfinished);
6832 PlaySound(appData.soundIcsAlarm);
6838 system("stty echo");
6844 system("stty -echo");
6848 Colorize(cc, continuation)
6853 int count, outCount, error;
6855 if (textColors[(int)cc].bg > 0) {
6856 if (textColors[(int)cc].fg > 0) {
6857 sprintf(buf, "\033[0;%d;%d;%dm", textColors[(int)cc].attr,
6858 textColors[(int)cc].fg, textColors[(int)cc].bg);
6860 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
6861 textColors[(int)cc].bg);
6864 if (textColors[(int)cc].fg > 0) {
6865 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
6866 textColors[(int)cc].fg);
6868 sprintf(buf, "\033[0;%dm", textColors[(int)cc].attr);
6871 count = strlen(buf);
6872 outCount = OutputToProcess(NoProc, buf, count, &error);
6873 if (outCount < count) {
6874 DisplayFatalError(_("Error writing to display"), error, 1);
6877 if (continuation) return;
6880 PlaySound(appData.soundShout);
6883 PlaySound(appData.soundSShout);
6886 PlaySound(appData.soundChannel1);
6889 PlaySound(appData.soundChannel);
6892 PlaySound(appData.soundKibitz);
6895 PlaySound(appData.soundTell);
6897 case ColorChallenge:
6898 PlaySound(appData.soundChallenge);
6901 PlaySound(appData.soundRequest);
6904 PlaySound(appData.soundSeek);
6915 return getpwuid(getuid())->pw_name;
6918 static char *ExpandPathName(path)
6921 static char static_buf[2000];
6922 char *d, *s, buf[2000];
6928 while (*s && isspace(*s))
6937 if (*(s+1) == '/') {
6938 strcpy(d, getpwuid(getuid())->pw_dir);
6943 *strchr(buf, '/') = 0;
6944 pwd = getpwnam(buf);
6947 fprintf(stderr, _("ERROR: Unknown user %s (in path %s)\n"),
6951 strcpy(d, pwd->pw_dir);
6952 strcat(d, strchr(s+1, '/'));
6963 static char host_name[MSG_SIZ];
6965 #if HAVE_GETHOSTNAME
6966 gethostname(host_name, MSG_SIZ);
6968 #else /* not HAVE_GETHOSTNAME */
6969 # if HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H
6970 sysinfo(SI_HOSTNAME, host_name, MSG_SIZ);
6972 # else /* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
6974 # endif/* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
6975 #endif /* not HAVE_GETHOSTNAME */
6978 gint delayedEventTimerTag = 0;
6979 DelayedEventCallback delayedEventCallback = 0;
6982 FireDelayedEvent(data)
6985 delayedEventTimerTag = 0;
6986 delayedEventCallback();
6990 ScheduleDelayedEvent(cb, millisec)
6991 DelayedEventCallback cb; long millisec;
6993 delayedEventCallback = cb;
6994 delayedEventTimerTag =
6995 gtk_timeout_add(millisec,(GtkFunction) FireDelayedEvent, NULL);
6998 DelayedEventCallback
7001 if (delayedEventTimerTag)
7003 return delayedEventCallback;
7012 CancelDelayedEvent()
7014 if (delayedEventTimerTag)
7016 gtk_timeout_remove(delayedEventTimerTag);
7017 delayedEventTimerTag = 0;
7022 gint loadGameTimerTag = 0;
7024 int LoadGameTimerRunning()
7026 return loadGameTimerTag != 0;
7029 int StopLoadGameTimer()
7031 if (loadGameTimerTag != 0) {
7032 gtk_timeout_remove(loadGameTimerTag);
7033 loadGameTimerTag = 0;
7041 LoadGameTimerCallback(data)
7044 loadGameTimerTag = 0;
7049 StartLoadGameTimer(millisec)
7053 gtk_timeout_add( millisec, (GtkFunction) LoadGameTimerCallback, NULL);
7056 gint analysisClockTag = 0;
7059 AnalysisClockCallback(data)
7062 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile
7063 || appData.icsEngineAnalyze)
7065 AnalysisPeriodicEvent(0);
7066 StartAnalysisClock();
7071 StartAnalysisClock()
7074 gtk_timeout_add( 2000,(GtkFunction) AnalysisClockCallback, NULL);
7077 gint clockTimerTag = 0;
7079 int ClockTimerRunning()
7081 return clockTimerTag != 0;
7084 int StopClockTimer()
7086 if (clockTimerTag != 0)
7088 gtk_timeout_remove(clockTimerTag);
7099 ClockTimerCallback(data)
7108 StartClockTimer(millisec)
7111 clockTimerTag = gtk_timeout_add(millisec,(GtkFunction) ClockTimerCallback,NULL);
7116 DisplayTimerLabel(w, color, timer, highlight)
7125 if (appData.clockMode) {
7126 sprintf(buf, "%s: %s", color, TimeString(timer));
7128 sprintf(buf, "%s ", color);
7130 gtk_label_set_text(GTK_LABEL(w),buf);
7132 /* check for low time warning */
7133 // Pixel foregroundOrWarningColor = timerForegroundPixel;
7136 // appData.lowTimeWarning &&
7137 // (timer / 1000) < appData.icsAlarmTime)
7138 // foregroundOrWarningColor = lowTimeWarningColor;
7140 // if (appData.clockMode) {
7141 // sprintf(buf, "%s: %s", color, TimeString(timer));
7142 // XtSetArg(args[0], XtNlabel, buf);
7144 // sprintf(buf, "%s ", color);
7145 // XtSetArg(args[0], XtNlabel, buf);
7150 // XtSetArg(args[1], XtNbackground, foregroundOrWarningColor);
7151 // XtSetArg(args[2], XtNforeground, timerBackgroundPixel);
7153 // XtSetArg(args[1], XtNbackground, timerBackgroundPixel);
7154 // XtSetArg(args[2], XtNforeground, foregroundOrWarningColor);
7157 // XtSetValues(w, args, 3);
7162 DisplayWhiteClock(timeRemaining, highlight)
7166 if(appData.noGUI) return;
7168 DisplayTimerLabel(GUI_Whiteclock, _("White"), timeRemaining, highlight);
7169 if (highlight && WindowIcon == BlackIcon)
7171 WindowIcon = WhiteIcon;
7172 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
7177 DisplayBlackClock(timeRemaining, highlight)
7181 if(appData.noGUI) return;
7183 DisplayTimerLabel(GUI_Blackclock, _("Black"), timeRemaining, highlight);
7184 if (highlight && WindowIcon == WhiteIcon)
7186 WindowIcon = BlackIcon;
7187 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
7205 int StartChildProcess(cmdLine, dir, pr)
7212 int to_prog[2], from_prog[2];
7216 if (appData.debugMode) {
7217 fprintf(stderr, "StartChildProcess (dir=\"%s\") %s\n",dir, cmdLine);
7220 /* We do NOT feed the cmdLine to the shell; we just
7221 parse it into blank-separated arguments in the
7222 most simple-minded way possible.
7225 strcpy(buf, cmdLine);
7230 if (p == NULL) break;
7235 SetUpChildIO(to_prog, from_prog);
7237 if ((pid = fork()) == 0) {
7239 // [HGM] PSWBTM: made order resistant against case where fd of created pipe was 0 or 1
7240 close(to_prog[1]); // first close the unused pipe ends
7241 close(from_prog[0]);
7242 dup2(to_prog[0], 0); // to_prog was created first, nd is the only one to use 0 or 1
7243 dup2(from_prog[1], 1);
7244 if(to_prog[0] >= 2) close(to_prog[0]); // if 0 or 1, the dup2 already cosed the original
7245 close(from_prog[1]); // and closing again loses one of the pipes!
7246 if(fileno(stderr) >= 2) // better safe than sorry...
7247 dup2(1, fileno(stderr)); /* force stderr to the pipe */
7249 if (dir[0] != NULLCHAR && chdir(dir) != 0) {
7254 nice(appData.niceEngines); // [HGM] nice: adjust priority of engine proc
7256 execvp(argv[0], argv);
7258 /* If we get here, exec failed */
7263 /* Parent process */
7265 close(from_prog[1]);
7267 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7270 cp->fdFrom = from_prog[0];
7271 cp->fdTo = to_prog[1];
7276 // [HGM] kill: implement the 'hard killing' of AS's Winboard_x
7277 static RETSIGTYPE AlarmCallBack(int n)
7283 DestroyChildProcess(pr, signalType)
7287 ChildProc *cp = (ChildProc *) pr;
7289 if (cp->kind != CPReal) return;
7291 if (signalType == 10) { // [HGM] kill: if it does not terminate in 3 sec, kill
7292 signal(SIGALRM, AlarmCallBack);
7294 if(wait((int *) 0) == -1) { // process does not terminate on its own accord
7295 kill(cp->pid, SIGKILL); // kill it forcefully
7296 wait((int *) 0); // and wait again
7300 kill(cp->pid, signalType == 9 ? SIGKILL : SIGTERM); // [HGM] kill: use hard kill if so requested
7302 /* Process is exiting either because of the kill or because of
7303 a quit command sent by the backend; either way, wait for it to die.
7312 InterruptChildProcess(pr)
7315 ChildProc *cp = (ChildProc *) pr;
7317 if (cp->kind != CPReal) return;
7318 (void) kill(cp->pid, SIGINT); /* stop it thinking */
7321 int OpenTelnet(host, port, pr)
7326 char cmdLine[MSG_SIZ];
7328 if (port[0] == NULLCHAR) {
7329 snprintf(cmdLine, sizeof(cmdLine), "%s %s", appData.telnetProgram, host);
7331 snprintf(cmdLine, sizeof(cmdLine), "%s %s %s", appData.telnetProgram, host, port);
7333 return StartChildProcess(cmdLine, "", pr);
7336 int OpenTCP(host, port, pr)
7342 DisplayFatalError(_("Socket support is not configured in"), 0, 2);
7343 #else /* !OMIT_SOCKETS */
7345 struct sockaddr_in sa;
7347 unsigned short uport;
7350 if ((s = socket(AF_INET, SOCK_STREAM, 6)) < 0) {
7354 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
7355 sa.sin_family = AF_INET;
7356 sa.sin_addr.s_addr = INADDR_ANY;
7357 uport = (unsigned short) 0;
7358 sa.sin_port = htons(uport);
7359 if (bind(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)) < 0) {
7363 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
7364 if (!(hp = gethostbyname(host))) {
7366 if (sscanf(host, "%d.%d.%d.%d", &b0, &b1, &b2, &b3) == 4) {
7367 hp = (struct hostent *) calloc(1, sizeof(struct hostent));
7368 hp->h_addrtype = AF_INET;
7370 hp->h_addr_list = (char **) calloc(2, sizeof(char *));
7371 hp->h_addr_list[0] = (char *) malloc(4);
7372 hp->h_addr_list[0][0] = b0;
7373 hp->h_addr_list[0][1] = b1;
7374 hp->h_addr_list[0][2] = b2;
7375 hp->h_addr_list[0][3] = b3;
7380 sa.sin_family = hp->h_addrtype;
7381 uport = (unsigned short) atoi(port);
7382 sa.sin_port = htons(uport);
7383 memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);
7385 if (connect(s, (struct sockaddr *) &sa,
7386 sizeof(struct sockaddr_in)) < 0) {
7390 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7397 #endif /* !OMIT_SOCKETS */
7402 int OpenCommPort(name, pr)
7409 fd = open(name, 2, 0);
7410 if (fd < 0) return errno;
7412 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7422 int OpenLoopback(pr)
7428 SetUpChildIO(to, from);
7430 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7433 cp->fdFrom = to[0]; /* note not from[0]; we are doing a loopback */
7440 int OpenRcmd(host, user, cmd, pr)
7441 char *host, *user, *cmd;
7444 DisplayFatalError(_("internal rcmd not implemented for Unix"), 0, 1);
7448 #define INPUT_SOURCE_BUF_SIZE 8192
7457 char buf[INPUT_SOURCE_BUF_SIZE];
7462 DoInputCallback(closure, source, xid)
7467 InputSource *is = (InputSource *) closure;
7472 if (is->lineByLine) {
7473 count = read(is->fd, is->unused,
7474 INPUT_SOURCE_BUF_SIZE - (is->unused - is->buf));
7476 (is->func)(is, is->closure, is->buf, count, count ? errno : 0);
7479 is->unused += count;
7481 while (p < is->unused) {
7482 q = memchr(p, '\n', is->unused - p);
7483 if (q == NULL) break;
7485 (is->func)(is, is->closure, p, q - p, 0);
7489 while (p < is->unused) {
7494 count = read(is->fd, is->buf, INPUT_SOURCE_BUF_SIZE);
7499 (is->func)(is, is->closure, is->buf, count, error);
7503 InputSourceRef AddInputSource(pr, lineByLine, func, closure)
7510 ChildProc *cp = (ChildProc *) pr;
7512 is = (InputSource *) calloc(1, sizeof(InputSource));
7513 is->lineByLine = lineByLine;
7517 is->fd = fileno(stdin);
7519 is->kind = cp->kind;
7520 is->fd = cp->fdFrom;
7523 is->unused = is->buf;
7526 is->xid = XtAppAddInput(appContext, is->fd,
7527 (XtPointer) (XtInputReadMask),
7528 (XtInputCallbackProc) DoInputCallback,
7530 is->closure = closure;
7531 return (InputSourceRef) is;
7535 RemoveInputSource(isr)
7538 InputSource *is = (InputSource *) isr;
7540 if (is->xid == 0) return;
7541 XtRemoveInput(is->xid);
7545 int OutputToProcess(pr, message, count, outError)
7551 ChildProc *cp = (ChildProc *) pr;
7555 outCount = fwrite(message, 1, count, stdout);
7557 outCount = write(cp->fdTo, message, count);
7567 /* Output message to process, with "ms" milliseconds of delay
7568 between each character. This is needed when sending the logon
7569 script to ICC, which for some reason doesn't like the
7570 instantaneous send. */
7571 int OutputToProcessDelayed(pr, message, count, outError, msdelay)
7578 ChildProc *cp = (ChildProc *) pr;
7583 r = write(cp->fdTo, message++, 1);
7596 /**** Animation code by Hugh Fisher, DCS, ANU.
7598 Known problem: if a window overlapping the board is
7599 moved away while a piece is being animated underneath,
7600 the newly exposed area won't be updated properly.
7601 I can live with this.
7603 Known problem: if you look carefully at the animation
7604 of pieces in mono mode, they are being drawn as solid
7605 shapes without interior detail while moving. Fixing
7606 this would be a major complication for minimal return.
7609 /* Masks for XPM pieces. Black and white pieces can have
7610 different shapes, but in the interest of retaining my
7611 sanity pieces must have the same outline on both light
7612 and dark squares, and all pieces must use the same
7613 background square colors/images. */
7615 static int xpmDone = 0;
7618 CreateAnimMasks (pieceDepth)
7625 unsigned long plane;
7628 /* just return for gtk at the moment */
7631 /* Need a bitmap just to get a GC with right depth */
7632 buf = XCreatePixmap(xDisplay, xBoardWindow,
7634 values.foreground = 1;
7635 values.background = 0;
7636 /* Don't use XtGetGC, not read only */
7637 maskGC = XCreateGC(xDisplay, buf,
7638 GCForeground | GCBackground, &values);
7639 XFreePixmap(xDisplay, buf);
7641 buf = XCreatePixmap(xDisplay, xBoardWindow,
7642 squareSize, squareSize, pieceDepth);
7643 values.foreground = XBlackPixel(xDisplay, xScreen);
7644 values.background = XWhitePixel(xDisplay, xScreen);
7645 bufGC = XCreateGC(xDisplay, buf,
7646 GCForeground | GCBackground, &values);
7648 for (piece = WhitePawn; piece <= BlackKing; piece++) {
7649 /* Begin with empty mask */
7650 if(!xpmDone) // [HGM] pieces: keep using existing
7651 xpmMask[piece] = XCreatePixmap(xDisplay, xBoardWindow,
7652 squareSize, squareSize, 1);
7653 XSetFunction(xDisplay, maskGC, GXclear);
7654 XFillRectangle(xDisplay, xpmMask[piece], maskGC,
7655 0, 0, squareSize, squareSize);
7657 /* Take a copy of the piece */
7662 XSetFunction(xDisplay, bufGC, GXcopy);
7663 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn],
7665 0, 0, squareSize, squareSize, 0, 0);
7667 /* XOR the background (light) over the piece */
7668 XSetFunction(xDisplay, bufGC, GXxor);
7670 XCopyArea(xDisplay, xpmLightSquare, buf, bufGC,
7671 0, 0, squareSize, squareSize, 0, 0);
7673 XSetForeground(xDisplay, bufGC, lightSquareColor);
7674 XFillRectangle(xDisplay, buf, bufGC, 0, 0, squareSize, squareSize);
7677 /* We now have an inverted piece image with the background
7678 erased. Construct mask by just selecting all the non-zero
7679 pixels - no need to reconstruct the original image. */
7680 XSetFunction(xDisplay, maskGC, GXor);
7682 /* Might be quicker to download an XImage and create bitmap
7683 data from it rather than this N copies per piece, but it
7684 only takes a fraction of a second and there is a much
7685 longer delay for loading the pieces. */
7686 for (n = 0; n < pieceDepth; n ++) {
7687 XCopyPlane(xDisplay, buf, xpmMask[piece], maskGC,
7688 0, 0, squareSize, squareSize,
7694 XFreePixmap(xDisplay, buf);
7695 XFreeGC(xDisplay, bufGC);
7696 XFreeGC(xDisplay, maskGC);
7700 InitAnimState (anim, info)
7702 XWindowAttributes * info;
7707 /* Each buffer is square size, same depth as window */
7708 // anim->saveBuf = XCreatePixmap(xDisplay, xBoardWindow,
7709 // squareSize, squareSize, info->depth);
7710 // anim->newBuf = XCreatePixmap(xDisplay, xBoardWindow,
7711 // squareSize, squareSize, info->depth);
7713 // /* Create a plain GC for blitting */
7714 // mask = GCForeground | GCBackground | GCFunction |
7715 // GCPlaneMask | GCGraphicsExposures;
7716 // values.foreground = XBlackPixel(xDisplay, xScreen);
7717 // values.background = XWhitePixel(xDisplay, xScreen);
7718 // values.function = GXcopy;
7719 // values.plane_mask = AllPlanes;
7720 // values.graphics_exposures = False;
7721 // anim->blitGC = XCreateGC(xDisplay, xBoardWindow, mask, &values);
7723 // /* Piece will be copied from an existing context at
7724 // the start of each new animation/drag. */
7725 // anim->pieceGC = XCreateGC(xDisplay, xBoardWindow, 0, &values);
7727 // /* Outline will be a read-only copy of an existing */
7728 // anim->outlineGC = None;
7734 static VariantClass old = (VariantClass) -1; // [HGM] pieces: redo every time variant changes
7735 XWindowAttributes info;
7737 /* for gtk at the moment just ... */
7740 if (xpmDone && gameInfo.variant == old) return;
7741 if(xpmDone) old = gameInfo.variant; // first time pieces might not be created yet
7742 // XGetWindowAttributes(xDisplay, xBoardWindow, &info);
7744 // InitAnimState(&game, &info);
7745 // InitAnimState(&player, &info);
7747 /* For XPM pieces, we need bitmaps to use as masks. */
7749 // CreateAnimMasks(info.depth);
7755 static Boolean frameWaiting;
7757 static RETSIGTYPE FrameAlarm (sig)
7760 frameWaiting = False;
7761 /* In case System-V style signals. Needed?? */
7762 signal(SIGALRM, FrameAlarm);
7769 struct itimerval delay;
7771 XSync(xDisplay, False);
7774 frameWaiting = True;
7775 signal(SIGALRM, FrameAlarm);
7776 delay.it_interval.tv_sec =
7777 delay.it_value.tv_sec = time / 1000;
7778 delay.it_interval.tv_usec =
7779 delay.it_value.tv_usec = (time % 1000) * 1000;
7780 setitimer(ITIMER_REAL, &delay, NULL);
7782 /* Ugh -- busy-wait! --tpm */
7783 while (frameWaiting);
7785 while (frameWaiting) pause();
7787 delay.it_interval.tv_sec = delay.it_value.tv_sec = 0;
7788 delay.it_interval.tv_usec = delay.it_value.tv_usec = 0;
7789 setitimer(ITIMER_REAL, &delay, NULL);
7799 XSync(xDisplay, False);
7801 usleep(time * 1000);
7806 /* Convert board position to corner of screen rect and color */
7809 ScreenSquare(column, row, pt, color)
7810 int column; int row; XPoint * pt; int * color;
7813 pt->x = lineGap + ((BOARD_WIDTH-1)-column) * (squareSize + lineGap);
7814 pt->y = lineGap + row * (squareSize + lineGap);
7816 pt->x = lineGap + column * (squareSize + lineGap);
7817 pt->y = lineGap + ((BOARD_HEIGHT-1)-row) * (squareSize + lineGap);
7819 *color = SquareColor(row, column);
7822 /* Convert window coords to square */
7825 BoardSquare(x, y, column, row)
7826 int x; int y; int * column; int * row;
7828 *column = EventToSquare(x, BOARD_WIDTH);
7829 if (flipView && *column >= 0)
7830 *column = BOARD_WIDTH - 1 - *column;
7831 *row = EventToSquare(y, BOARD_HEIGHT);
7832 if (!flipView && *row >= 0)
7833 *row = BOARD_HEIGHT - 1 - *row;
7838 #undef Max /* just in case */
7840 #define Max(a, b) ((a) > (b) ? (a) : (b))
7841 #define Min(a, b) ((a) < (b) ? (a) : (b))
7844 SetRect(rect, x, y, width, height)
7845 XRectangle * rect; int x; int y; int width; int height;
7849 rect->width = width;
7850 rect->height = height;
7853 /* Test if two frames overlap. If they do, return
7854 intersection rect within old and location of
7855 that rect within new. */
7858 Intersect(old, new, size, area, pt)
7859 XPoint * old; XPoint * new;
7860 int size; XRectangle * area; XPoint * pt;
7862 if (old->x > new->x + size || new->x > old->x + size ||
7863 old->y > new->y + size || new->y > old->y + size) {
7866 SetRect(area, Max(new->x - old->x, 0), Max(new->y - old->y, 0),
7867 size - abs(old->x - new->x), size - abs(old->y - new->y));
7868 pt->x = Max(old->x - new->x, 0);
7869 pt->y = Max(old->y - new->y, 0);
7874 /* For two overlapping frames, return the rect(s)
7875 in the old that do not intersect with the new. */
7878 CalcUpdateRects(old, new, size, update, nUpdates)
7879 XPoint * old; XPoint * new; int size;
7880 XRectangle update[]; int * nUpdates;
7884 /* If old = new (shouldn't happen) then nothing to draw */
7885 if (old->x == new->x && old->y == new->y) {
7889 /* Work out what bits overlap. Since we know the rects
7890 are the same size we don't need a full intersect calc. */
7892 /* Top or bottom edge? */
7893 if (new->y > old->y) {
7894 SetRect(&(update[count]), old->x, old->y, size, new->y - old->y);
7896 } else if (old->y > new->y) {
7897 SetRect(&(update[count]), old->x, old->y + size - (old->y - new->y),
7898 size, old->y - new->y);
7901 /* Left or right edge - don't overlap any update calculated above. */
7902 if (new->x > old->x) {
7903 SetRect(&(update[count]), old->x, Max(new->y, old->y),
7904 new->x - old->x, size - abs(new->y - old->y));
7906 } else if (old->x > new->x) {
7907 SetRect(&(update[count]), new->x + size, Max(new->y, old->y),
7908 old->x - new->x, size - abs(new->y - old->y));
7915 /* Generate a series of frame coords from start->mid->finish.
7916 The movement rate doubles until the half way point is
7917 reached, then halves back down to the final destination,
7918 which gives a nice slow in/out effect. The algorithmn
7919 may seem to generate too many intermediates for short
7920 moves, but remember that the purpose is to attract the
7921 viewers attention to the piece about to be moved and
7922 then to where it ends up. Too few frames would be less
7926 Tween(start, mid, finish, factor, frames, nFrames)
7927 XPoint * start; XPoint * mid;
7928 XPoint * finish; int factor;
7929 XPoint frames[]; int * nFrames;
7931 int fraction, n, count;
7935 /* Slow in, stepping 1/16th, then 1/8th, ... */
7937 for (n = 0; n < factor; n++)
7939 for (n = 0; n < factor; n++) {
7940 frames[count].x = start->x + (mid->x - start->x) / fraction;
7941 frames[count].y = start->y + (mid->y - start->y) / fraction;
7943 fraction = fraction / 2;
7947 frames[count] = *mid;
7950 /* Slow out, stepping 1/2, then 1/4, ... */
7952 for (n = 0; n < factor; n++) {
7953 frames[count].x = finish->x - (finish->x - mid->x) / fraction;
7954 frames[count].y = finish->y - (finish->y - mid->y) / fraction;
7956 fraction = fraction * 2;
7961 /* Draw a piece on the screen without disturbing what's there */
7964 SelectGCMask(piece, clip, outline, mask)
7965 ChessSquare piece; GC * clip; GC * outline; Pixmap * mask;
7969 /* Bitmap for piece being moved. */
7970 if (appData.monoMode) {
7971 *mask = *pieceToSolid(piece);
7972 } else if (useImages) {
7974 *mask = xpmMask[piece];
7976 *mask = ximMaskPm[piece];
7979 *mask = *pieceToSolid(piece);
7982 /* GC for piece being moved. Square color doesn't matter, but
7983 since it gets modified we make a copy of the original. */
7985 if (appData.monoMode)
7990 if (appData.monoMode)
7995 XCopyGC(xDisplay, source, 0xFFFFFFFF, *clip);
7997 /* Outline only used in mono mode and is not modified */
7999 *outline = bwPieceGC;
8001 *outline = wbPieceGC;
8005 OverlayPiece(piece, clip, outline, dest)
8006 ChessSquare piece; GC clip; GC outline; Drawable dest;
8011 /* Draw solid rectangle which will be clipped to shape of piece */
8012 XFillRectangle(xDisplay, dest, clip,
8013 0, 0, squareSize, squareSize);
8014 if (appData.monoMode)
8015 /* Also draw outline in contrasting color for black
8016 on black / white on white cases */
8017 XCopyPlane(xDisplay, *pieceToOutline(piece), dest, outline,
8018 0, 0, squareSize, squareSize, 0, 0, 1);
8020 /* Copy the piece */
8025 XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
8027 0, 0, squareSize, squareSize,
8032 /* Animate the movement of a single piece */
8035 BeginAnimation(anim, piece, startColor, start)
8043 /* The old buffer is initialised with the start square (empty) */
8044 BlankSquare(0, 0, startColor, EmptySquare, anim->saveBuf);
8045 anim->prevFrame = *start;
8047 /* The piece will be drawn using its own bitmap as a matte */
8048 SelectGCMask(piece, &anim->pieceGC, &anim->outlineGC, &mask);
8049 XSetClipMask(xDisplay, anim->pieceGC, mask);
8053 AnimationFrame(anim, frame, piece)
8058 XRectangle updates[4];
8063 /* Save what we are about to draw into the new buffer */
8064 XCopyArea(xDisplay, xBoardWindow, anim->newBuf, anim->blitGC,
8065 frame->x, frame->y, squareSize, squareSize,
8068 /* Erase bits of the previous frame */
8069 if (Intersect(&anim->prevFrame, frame, squareSize, &overlap, &pt)) {
8070 /* Where the new frame overlapped the previous,
8071 the contents in newBuf are wrong. */
8072 XCopyArea(xDisplay, anim->saveBuf, anim->newBuf, anim->blitGC,
8073 overlap.x, overlap.y,
8074 overlap.width, overlap.height,
8076 /* Repaint the areas in the old that don't overlap new */
8077 CalcUpdateRects(&anim->prevFrame, frame, squareSize, updates, &count);
8078 for (i = 0; i < count; i++)
8079 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
8080 updates[i].x - anim->prevFrame.x,
8081 updates[i].y - anim->prevFrame.y,
8082 updates[i].width, updates[i].height,
8083 updates[i].x, updates[i].y);
8085 /* Easy when no overlap */
8086 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
8087 0, 0, squareSize, squareSize,
8088 anim->prevFrame.x, anim->prevFrame.y);
8091 /* Save this frame for next time round */
8092 XCopyArea(xDisplay, anim->newBuf, anim->saveBuf, anim->blitGC,
8093 0, 0, squareSize, squareSize,
8095 anim->prevFrame = *frame;
8097 /* Draw piece over original screen contents, not current,
8098 and copy entire rect. Wipes out overlapping piece images. */
8099 OverlayPiece(piece, anim->pieceGC, anim->outlineGC, anim->newBuf);
8100 XCopyArea(xDisplay, anim->newBuf, xBoardWindow, anim->blitGC,
8101 0, 0, squareSize, squareSize,
8102 frame->x, frame->y);
8106 EndAnimation (anim, finish)
8110 XRectangle updates[4];
8115 /* The main code will redraw the final square, so we
8116 only need to erase the bits that don't overlap. */
8117 if (Intersect(&anim->prevFrame, finish, squareSize, &overlap, &pt)) {
8118 CalcUpdateRects(&anim->prevFrame, finish, squareSize, updates, &count);
8119 for (i = 0; i < count; i++)
8120 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
8121 updates[i].x - anim->prevFrame.x,
8122 updates[i].y - anim->prevFrame.y,
8123 updates[i].width, updates[i].height,
8124 updates[i].x, updates[i].y);
8126 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
8127 0, 0, squareSize, squareSize,
8128 anim->prevFrame.x, anim->prevFrame.y);
8133 FrameSequence(anim, piece, startColor, start, finish, frames, nFrames)
8135 ChessSquare piece; int startColor;
8136 XPoint * start; XPoint * finish;
8137 XPoint frames[]; int nFrames;
8141 BeginAnimation(anim, piece, startColor, start);
8142 for (n = 0; n < nFrames; n++) {
8143 AnimationFrame(anim, &(frames[n]), piece);
8144 FrameDelay(appData.animSpeed);
8146 EndAnimation(anim, finish);
8149 /* Main control logic for deciding what to animate and how */
8152 AnimateMove(board, fromX, fromY, toX, toY)
8161 XPoint start, finish, mid;
8162 XPoint frames[kFactor * 2 + 1];
8163 int nFrames, startColor, endColor;
8165 /* Are we animating? */
8166 if (!appData.animate || appData.blindfold)
8169 if(board[toY][toX] == WhiteRook && board[fromY][fromX] == WhiteKing ||
8170 board[toY][toX] == BlackRook && board[fromY][fromX] == BlackKing)
8171 return; // [HGM] FRC: no animtion of FRC castlings, as to-square is not true to-square
8173 if (fromY < 0 || fromX < 0 || toX < 0 || toY < 0) return;
8174 piece = board[fromY][fromX];
8175 if (piece >= EmptySquare) return;
8180 hop = (piece == WhiteKnight || piece == BlackKnight);
8183 if (appData.debugMode) {
8184 fprintf(debugFP, hop ? _("AnimateMove: piece %d hops from %d,%d to %d,%d \n") :
8185 _("AnimateMove: piece %d slides from %d,%d to %d,%d \n"),
8186 piece, fromX, fromY, toX, toY); }
8188 ScreenSquare(fromX, fromY, &start, &startColor);
8189 ScreenSquare(toX, toY, &finish, &endColor);
8192 /* Knight: make diagonal movement then straight */
8193 if (abs(toY - fromY) < abs(toX - fromX)) {
8194 mid.x = start.x + (finish.x - start.x) / 2;
8198 mid.y = start.y + (finish.y - start.y) / 2;
8201 mid.x = start.x + (finish.x - start.x) / 2;
8202 mid.y = start.y + (finish.y - start.y) / 2;
8205 /* Don't use as many frames for very short moves */
8206 if (abs(toY - fromY) + abs(toX - fromX) <= 2)
8207 Tween(&start, &mid, &finish, kFactor - 1, frames, &nFrames);
8209 Tween(&start, &mid, &finish, kFactor, frames, &nFrames);
8210 FrameSequence(&game, piece, startColor, &start, &finish, frames, nFrames);
8212 /* Be sure end square is redrawn */
8213 damage[toY][toX] = True;
8217 DragPieceBegin(x, y)
8220 int boardX, boardY, color;
8223 /* Are we animating? */
8224 if (!appData.animateDragging || appData.blindfold)
8227 /* Figure out which square we start in and the
8228 mouse position relative to top left corner. */
8229 BoardSquare(x, y, &boardX, &boardY);
8230 player.startBoardX = boardX;
8231 player.startBoardY = boardY;
8232 ScreenSquare(boardX, boardY, &corner, &color);
8233 player.startSquare = corner;
8234 player.startColor = color;
8236 /* Start from exactly where the piece is. This can be confusing
8237 if you start dragging far from the center of the square; most
8238 or all of the piece can be over a different square from the one
8239 the mouse pointer is in. */
8240 player.mouseDelta.x = x - corner.x;
8241 player.mouseDelta.y = y - corner.y;
8243 /* As soon as we start dragging, the piece will jump slightly to
8244 be centered over the mouse pointer. */
8245 player.mouseDelta.x = squareSize/2;
8246 player.mouseDelta.y = squareSize/2;
8248 /* Initialise animation */
8249 player.dragPiece = PieceForSquare(boardX, boardY);
8251 if (player.dragPiece >= 0 && player.dragPiece < EmptySquare) {
8252 player.dragActive = True;
8253 BeginAnimation(&player, player.dragPiece, color, &corner);
8254 /* Mark this square as needing to be redrawn. Note that
8255 we don't remove the piece though, since logically (ie
8256 as seen by opponent) the move hasn't been made yet. */
8257 if(boardX == BOARD_RGHT+1 && PieceForSquare(boardX-1, boardY) > 1 ||
8258 boardX == BOARD_LEFT-2 && PieceForSquare(boardX+1, boardY) > 1)
8259 XCopyArea(xDisplay, xBoardWindow, player.saveBuf, player.blitGC,
8260 corner.x, corner.y, squareSize, squareSize,
8261 0, 0); // [HGM] zh: unstack in stead of grab
8262 damage[boardY][boardX] = True;
8264 player.dragActive = False;
8274 /* Are we animating? */
8275 if (!appData.animateDragging || appData.blindfold)
8279 if (! player.dragActive)
8281 /* Move piece, maintaining same relative position
8282 of mouse within square */
8283 corner.x = x - player.mouseDelta.x;
8284 corner.y = y - player.mouseDelta.y;
8285 AnimationFrame(&player, &corner, player.dragPiece);
8287 if (appData.highlightDragging) {
8289 BoardSquare(x, y, &boardX, &boardY);
8290 SetHighlights(fromX, fromY, boardX, boardY);
8299 int boardX, boardY, color;
8302 /* Are we animating? */
8303 if (!appData.animateDragging || appData.blindfold)
8307 if (! player.dragActive)
8309 /* Last frame in sequence is square piece is
8310 placed on, which may not match mouse exactly. */
8311 BoardSquare(x, y, &boardX, &boardY);
8312 ScreenSquare(boardX, boardY, &corner, &color);
8313 EndAnimation(&player, &corner);
8315 /* Be sure end square is redrawn */
8316 damage[boardY][boardX] = True;
8318 /* This prevents weird things happening with fast successive
8319 clicks which on my Sun at least can cause motion events
8320 without corresponding press/release. */
8321 player.dragActive = False;
8324 /* Handle expose event while piece being dragged */
8329 if (!player.dragActive || appData.blindfold)
8332 /* What we're doing: logically, the move hasn't been made yet,
8333 so the piece is still in it's original square. But visually
8334 it's being dragged around the board. So we erase the square
8335 that the piece is on and draw it at the last known drag point. */
8336 BlankSquare(player.startSquare.x, player.startSquare.y,
8337 player.startColor, EmptySquare, xBoardWindow);
8338 AnimationFrame(&player, &player.prevFrame, player.dragPiece);
8339 damage[player.startBoardY][player.startBoardX] = TRUE;
8343 SetProgramStats( FrontEndProgramStats * stats )
8346 // [HGM] done, but perhaps backend should call this directly?
8347 EngineOutputUpdate( stats );