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 void CreateGrid P((void));
254 int EventToSquare P((int x, int limit));
255 void DrawSquare P((int row, int column, ChessSquare piece, int do_flash));
256 void HandleUserMove P((Widget w, XEvent *event,
257 String *prms, Cardinal *nprms));
258 void AnimateUserMove P((Widget w, XEvent * event,
259 String * params, Cardinal * nParams));
260 void WhiteClock P((Widget w, XEvent *event,
261 String *prms, Cardinal *nprms));
262 void BlackClock P((Widget w, XEvent *event,
263 String *prms, Cardinal *nprms));
264 void DrawPositionProc P((Widget w, XEvent *event,
265 String *prms, Cardinal *nprms));
266 void CommentPopUp P((char *title, char *label));
267 void CommentPopDown P((void));
268 void CommentCallback P((Widget w, XtPointer client_data,
269 XtPointer call_data));
270 void ICSInputBoxPopUp P((void));
271 void ICSInputBoxPopDown P((void));
272 void FileNamePopUp P((char *label, char *def,
273 FileProc proc, char *openMode));
274 void FileNamePopDown P((void));
275 void FileNameCallback P((Widget w, XtPointer client_data,
276 XtPointer call_data));
277 void FileNameAction P((Widget w, XEvent *event,
278 String *prms, Cardinal *nprms));
279 void AskQuestionReplyAction P((Widget w, XEvent *event,
280 String *prms, Cardinal *nprms));
281 void AskQuestionProc P((Widget w, XEvent *event,
282 String *prms, Cardinal *nprms));
283 void AskQuestionPopDown P((void));
284 void PromotionPopUp P((void));
285 void PromotionPopDown P((void));
286 void PromotionCallback P((Widget w, XtPointer client_data,
287 XtPointer call_data));
288 void EditCommentPopDown P((void));
289 void EditCommentCallback P((Widget w, XtPointer client_data,
290 XtPointer call_data));
291 void SelectCommand P((Widget w, XtPointer client_data, XtPointer call_data));
292 void LoadPositionProc P((Widget w, XEvent *event,
293 String *prms, Cardinal *nprms));
294 void LoadNextPositionProc P((Widget w, XEvent *event, String *prms,
296 void LoadPrevPositionProc P((Widget w, XEvent *event, String *prms,
298 void ReloadPositionProc P((Widget w, XEvent *event, String *prms,
300 void CopyPositionProc P((Widget w, XEvent *event, String *prms,
302 void PastePositionProc P((Widget w, XEvent *event, String *prms,
304 void CopyGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
305 void PasteGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
306 void SaveGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
307 void SavePositionProc P((Widget w, XEvent *event,
308 String *prms, Cardinal *nprms));
309 void MailMoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
310 void ReloadCmailMsgProc P((Widget w, XEvent *event, String *prms,
312 void MachineBlackProc P((Widget w, XEvent *event, String *prms,
314 void MachineWhiteProc P((Widget w, XEvent *event,
315 String *prms, Cardinal *nprms));
316 void AnalyzeModeProc P((Widget w, XEvent *event,
317 String *prms, Cardinal *nprms));
318 void AnalyzeFileProc P((Widget w, XEvent *event,
319 String *prms, Cardinal *nprms));
320 void TwoMachinesProc P((Widget w, XEvent *event, String *prms,
322 void IcsClientProc P((Widget w, XEvent *event, String *prms,
324 void EditGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
325 void EditPositionProc P((Widget w, XEvent *event,
326 String *prms, Cardinal *nprms));
327 void TrainingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
328 void EditCommentProc P((Widget w, XEvent *event,
329 String *prms, Cardinal *nprms));
330 void IcsInputBoxProc P((Widget w, XEvent *event,
331 String *prms, Cardinal *nprms));
332 void AcceptProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
333 void DeclineProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
334 void RematchProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
335 void CallFlagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
336 void DrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
337 void AbortProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
338 void AdjournProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
339 void ResignProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
340 void AdjuWhiteProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
341 void AdjuBlackProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
342 void AdjuDrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
343 void EnterKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
344 void StopObservingProc P((Widget w, XEvent *event, String *prms,
346 void StopExaminingProc P((Widget w, XEvent *event, String *prms,
348 void BackwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
349 void ForwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
350 void ToStartProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
351 void ToEndProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
352 void RevertProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
353 void TruncateGameProc P((Widget w, XEvent *event, String *prms,
355 void RetractMoveProc P((Widget w, XEvent *event, String *prms,
357 void MoveNowProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
358 void AlwaysQueenProc P((Widget w, XEvent *event, String *prms,
360 void AnimateDraggingProc P((Widget w, XEvent *event, String *prms,
362 void AnimateMovingProc P((Widget w, XEvent *event, String *prms,
364 void AutocommProc P((Widget w, XEvent *event, String *prms,
366 void AutoflagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
367 void AutoflipProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
368 void AutobsProc P((Widget w, XEvent *event, String *prms,
370 void AutoraiseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
371 void AutosaveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
372 void BlindfoldProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
373 void FlashMovesProc P((Widget w, XEvent *event, String *prms,
375 void FlipViewProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
376 void GetMoveListProc P((Widget w, XEvent *event, String *prms,
378 void HighlightDraggingProc P((Widget w, XEvent *event, String *prms,
380 void HighlightLastMoveProc P((Widget w, XEvent *event, String *prms,
382 void MoveSoundProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
383 void IcsAlarmProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
384 void OldSaveStyleProc P((Widget w, XEvent *event, String *prms,
386 void PeriodicUpdatesProc P((Widget w, XEvent *event, String *prms,
388 void PonderNextMoveProc P((Widget w, XEvent *event, String *prms,
390 void PopupMoveErrorsProc P((Widget w, XEvent *event, String *prms,
392 void PopupExitMessageProc P((Widget w, XEvent *event, String *prms,
394 void PremoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
395 void QuietPlayProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
396 void ShowThinkingProc P((Widget w, XEvent *event, String *prms,
398 void HideThinkingProc P((Widget w, XEvent *event, String *prms,
400 void TestLegalityProc P((Widget w, XEvent *event, String *prms,
402 void InfoProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
403 void ManProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
404 void HintProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
405 void BookProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
406 void AboutGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
407 void DebugProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
408 void NothingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
409 void Iconify P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
410 void DisplayMove P((int moveNumber));
411 void DisplayTitle P((char *title));
412 void ICSInitScript P((void));
413 int LoadGamePopUp P((FILE *f, int gameNumber, char *title));
414 void ErrorPopUp P((char *title, char *text, int modal));
415 void ErrorPopDown P((void));
416 static char *ExpandPathName P((char *path));
417 static void CreateAnimVars P((void));
418 void DragPieceBegin P((int x, int y));
419 static void DragPieceMove P((int x, int y));
420 void DragPieceEnd P((int x, int y));
421 static void DrawDragPiece P((void));
422 char *ModeToWidgetName P((GameMode mode));
423 void EngineOutputUpdate( FrontEndProgramStats * stats );
424 void ShuffleMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
425 void EngineMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
426 void UciMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
427 void TimeControlProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
428 void NewVariantProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
429 void FirstSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
430 void SecondSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
431 void ShufflePopDown P(());
432 void EnginePopDown P(());
433 void UciPopDown P(());
434 void TimeControlPopDown P(());
435 void NewVariantPopDown P(());
436 void SettingsPopDown P(());
438 * XBoard depends on Xt R4 or higher
440 int xtVersion = XtSpecificationRelease;
445 Pixel lightSquareColor, darkSquareColor, whitePieceColor, blackPieceColor,
446 jailSquareColor, highlightSquareColor, premoveHighlightColor;
447 Pixel lowTimeWarningColor;
448 GC lightSquareGC, darkSquareGC, jailSquareGC, lineGC, wdPieceGC, wlPieceGC,
449 bdPieceGC, blPieceGC, wbPieceGC, bwPieceGC, coordGC, highlineGC,
450 wjPieceGC, bjPieceGC, prelineGC, countGC;
451 Pixmap iconPixmap, wIconPixmap, bIconPixmap, xMarkPixmap;
452 Widget shellWidget, layoutWidget, formWidget, boardWidget, messageWidget,
453 whiteTimerWidget, blackTimerWidget, titleWidget, widgetList[16],
454 commentShell, promotionShell, whitePieceMenu, blackPieceMenu, dropMenu,
455 menuBarWidget, buttonBarWidget, editShell, errorShell, analysisShell,
456 ICSInputShell, fileNameShell, askQuestionShell;
457 GdkSegment gridSegments[(BOARD_SIZE + 1) * 2];
458 XSegment jailGridSegments[(BOARD_SIZE + 3) * 2];
459 Font clockFontID, coordFontID, countFontID;
460 XFontStruct *clockFontStruct, *coordFontStruct, *countFontStruct;
461 XtAppContext appContext;
463 char *oldICSInteractionTitle;
467 char installDir[] = "."; // [HGM] UCI: needed for UCI; probably needs run-time initializtion
469 Position commentX = -1, commentY = -1;
470 Dimension commentW, commentH;
472 int squareSize, smallLayout = 0, tinyLayout = 0,
473 marginW, marginH, // [HGM] for run-time resizing
474 fromX = -1, fromY = -1, toX, toY, commentUp = False, analysisUp = False,
475 ICSInputBoxUp = False, askQuestionUp = False,
476 filenameUp = False, promotionUp = False, pmFromX = -1, pmFromY = -1,
477 editUp = False, errorUp = False, errorExitStatus = -1, lineGap;
478 Pixel timerForegroundPixel, timerBackgroundPixel;
479 Pixel buttonForegroundPixel, buttonBackgroundPixel;
480 char *chessDir, *programName, *programVersion,
481 *gameCopyFilename, *gamePasteFilename;
485 Pixmap pieceBitmap[2][(int)BlackPawn];
486 Pixmap pieceBitmap2[2][(int)BlackPawn+4]; /* [HGM] pieces */
487 Pixmap xpmPieceBitmap[4][(int)BlackPawn]; /* LL, LD, DL, DD actually used*/
488 Pixmap xpmPieceBitmap2[4][(int)BlackPawn+4]; /* LL, LD, DL, DD set to select from */
489 Pixmap xpmLightSquare, xpmDarkSquare, xpmJailSquare;
490 int useImages=0, useImageSqs;
491 XImage *ximPieceBitmap[4][(int)BlackPawn+4]; /* LL, LD, DL, DD */
492 Pixmap ximMaskPm[(int)BlackPawn]; /* clipmasks, used for XIM pieces */
493 Pixmap ximMaskPm2[(int)BlackPawn+4]; /* clipmasks, used for XIM pieces */
494 XImage *ximLightSquare, *ximDarkSquare;
497 #define pieceToSolid(piece) &pieceBitmap[SOLID][(piece) % (int)BlackPawn]
498 #define pieceToOutline(piece) &pieceBitmap[OUTLINE][(piece) % (int)BlackPawn]
500 #define White(piece) ((int)(piece) < (int)BlackPawn)
502 /* Variables for doing smooth animation. This whole thing
503 would be much easier if the board was double-buffered,
504 but that would require a fairly major rewrite. */
509 GC blitGC, pieceGC, outlineGC;
510 XPoint startSquare, prevFrame, mouseDelta;
514 int startBoardX, startBoardY;
517 /* There can be two pieces being animated at once: a player
518 can begin dragging a piece before the remote opponent has moved. */
520 static AnimState game, player;
522 /* Bitmaps for use as masks when drawing XPM pieces.
523 Need one for each black and white piece. */
524 static Pixmap xpmMask[BlackKing + 1];
526 /* This magic number is the number of intermediate frames used
527 in each half of the animation. For short moves it's reduced
528 by 1. The total number of frames will be factor * 2 + 1. */
531 SizeDefaults sizeDefaults[] = SIZE_DEFAULTS;
533 MenuItem fileMenu[] = {
534 {N_("New Shuffle Game ..."), ShuffleMenuProc},
535 {N_("New Variant ..."), NewVariantProc}, // [HGM] variant: not functional yet
536 {"----", NothingProc},
537 {N_("Save Game"), SaveGameProc},
538 {"----", NothingProc},
539 {N_("Copy Game"), CopyGameProc},
540 {N_("Paste Game"), PasteGameProc},
541 {"----", NothingProc},
542 {N_("Load Position"), LoadPositionProc},
543 {N_("Load Next Position"), LoadNextPositionProc},
544 {N_("Load Previous Position"), LoadPrevPositionProc},
545 {N_("Reload Same Position"), ReloadPositionProc},
546 {N_("Save Position"), SavePositionProc},
547 {"----", NothingProc},
548 {N_("Copy Position"), CopyPositionProc},
549 {N_("Paste Position"), PastePositionProc},
550 {"----", NothingProc},
551 {N_("Mail Move"), MailMoveProc},
552 {N_("Reload CMail Message"), ReloadCmailMsgProc},
553 {"----", NothingProc},
557 MenuItem modeMenu[] = {
558 {N_("Machine White"), MachineWhiteProc},
559 {N_("Machine Black"), MachineBlackProc},
560 {N_("Two Machines"), TwoMachinesProc},
561 {N_("Analysis Mode"), AnalyzeModeProc},
562 {N_("Analyze File"), AnalyzeFileProc },
563 {N_("ICS Client"), IcsClientProc},
564 {N_("Edit Game"), EditGameProc},
565 {N_("Edit Position"), EditPositionProc},
566 {N_("Training"), TrainingProc},
567 {"----", NothingProc},
568 {N_("Show Engine Output"), EngineOutputProc},
569 {N_("Show Evaluation Graph"), NothingProc}, // [HGM] evalgr: not functional yet
570 {N_("Show Game List"), ShowGameListProc},
571 {"Show Move History", HistoryShowProc}, // [HGM] hist: activate 4.2.7 code
572 {"----", NothingProc},
573 {N_("Edit Tags"), EditTagsProc},
574 {N_("Edit Comment"), EditCommentProc},
575 {N_("ICS Input Box"), IcsInputBoxProc},
579 MenuItem actionMenu[] = {
580 {N_("Accept"), AcceptProc},
581 {N_("Decline"), DeclineProc},
582 {N_("Rematch"), RematchProc},
583 {"----", NothingProc},
584 {N_("Call Flag"), CallFlagProc},
585 {N_("Draw"), DrawProc},
586 {N_("Adjourn"), AdjournProc},
587 {N_("Abort"), AbortProc},
588 {N_("Resign"), ResignProc},
589 {"----", NothingProc},
590 {N_("Stop Observing"), StopObservingProc},
591 {N_("Stop Examining"), StopExaminingProc},
592 {"----", NothingProc},
593 {N_("Adjudicate to White"), AdjuWhiteProc},
594 {N_("Adjudicate to Black"), AdjuBlackProc},
595 {N_("Adjudicate Draw"), AdjuDrawProc},
599 MenuItem stepMenu[] = {
600 {N_("Backward"), BackwardProc},
601 {N_("Forward"), ForwardProc},
602 {N_("Back to Start"), ToStartProc},
603 {N_("Forward to End"), ToEndProc},
604 {N_("Revert"), RevertProc},
605 {N_("Truncate Game"), TruncateGameProc},
606 {"----", NothingProc},
607 {N_("Move Now"), MoveNowProc},
608 {N_("Retract Move"), RetractMoveProc},
612 MenuItem optionsMenu[] = {
613 {N_("Flip View"), FlipViewProc},
614 {"----", NothingProc},
615 {N_("Adjudications ..."), EngineMenuProc},
616 {N_("General Settings ..."), UciMenuProc},
617 {N_("Engine #1 Settings ..."), FirstSettingsProc},
618 {N_("Engine #2 Settings ..."), SecondSettingsProc},
619 {N_("Time Control ..."), TimeControlProc},
620 {"----", NothingProc},
621 {N_("Always Queen"), AlwaysQueenProc},
622 {N_("Animate Dragging"), AnimateDraggingProc},
623 {N_("Animate Moving"), AnimateMovingProc},
624 {N_("Auto Comment"), AutocommProc},
625 {N_("Auto Flag"), AutoflagProc},
626 {N_("Auto Flip View"), AutoflipProc},
627 {N_("Auto Observe"), AutobsProc},
628 {N_("Auto Raise Board"), AutoraiseProc},
629 {N_("Auto Save"), AutosaveProc},
630 {N_("Blindfold"), BlindfoldProc},
631 {N_("Flash Moves"), FlashMovesProc},
632 {N_("Get Move List"), GetMoveListProc},
634 {N_("Highlight Dragging"), HighlightDraggingProc},
636 {N_("Highlight Last Move"), HighlightLastMoveProc},
637 {N_("Move Sound"), MoveSoundProc},
638 {N_("ICS Alarm"), IcsAlarmProc},
639 {N_("Old Save Style"), OldSaveStyleProc},
640 {N_("Periodic Updates"), PeriodicUpdatesProc},
641 {N_("Ponder Next Move"), PonderNextMoveProc},
642 {N_("Popup Exit Message"), PopupExitMessageProc},
643 {N_("Popup Move Errors"), PopupMoveErrorsProc},
644 {N_("Premove"), PremoveProc},
645 {N_("Quiet Play"), QuietPlayProc},
646 {N_("Hide Thinking"), HideThinkingProc},
647 {N_("Test Legality"), TestLegalityProc},
651 MenuItem helpMenu[] = {
652 {N_("Info XBoard"), InfoProc},
653 {N_("Man XBoard"), ManProc},
654 {"----", NothingProc},
655 {N_("Hint"), HintProc},
656 {N_("Book"), BookProc},
657 {"----", NothingProc},
662 {N_("File"), fileMenu},
663 {N_("Mode"), modeMenu},
664 {N_("Action"), actionMenu},
665 {N_("Step"), stepMenu},
666 {N_("Options"), optionsMenu},
667 {N_("Help"), helpMenu},
671 #define PAUSE_BUTTON N_("P")
672 MenuItem buttonBar[] = {
675 // {PAUSE_BUTTON, PauseProc},
681 #define PIECE_MENU_SIZE 18
682 String pieceMenuStrings[2][PIECE_MENU_SIZE] = {
683 { N_("White"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
684 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
685 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
686 N_("Empty square"), N_("Clear board") },
687 { N_("Black"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
688 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
689 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
690 N_("Empty square"), N_("Clear board") }
692 /* must be in same order as PieceMenuStrings! */
693 ChessSquare pieceMenuTranslation[2][PIECE_MENU_SIZE] = {
694 { WhitePlay, (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
695 WhiteRook, WhiteQueen, WhiteKing, (ChessSquare) 0, WhiteAlfil,
696 WhiteCannon, WhiteAngel, WhiteMarshall, (ChessSquare) 0,
697 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
698 { BlackPlay, (ChessSquare) 0, BlackPawn, BlackKnight, BlackBishop,
699 BlackRook, BlackQueen, BlackKing, (ChessSquare) 0, BlackAlfil,
700 BlackCannon, BlackAngel, BlackMarshall, (ChessSquare) 0,
701 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
704 #define DROP_MENU_SIZE 6
705 String dropMenuStrings[DROP_MENU_SIZE] = {
706 "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"), N_("Queen")
708 /* must be in same order as PieceMenuStrings! */
709 ChessSquare dropMenuTranslation[DROP_MENU_SIZE] = {
710 (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
711 WhiteRook, WhiteQueen
719 DropMenuEnables dmEnables[] = {
737 { XtNborderWidth, 0 },
738 { XtNdefaultDistance, 0 },
742 { XtNborderWidth, 0 },
743 { XtNresizable, (XtArgVal) True },
747 { XtNborderWidth, 0 },
753 { XtNjustify, (XtArgVal) XtJustifyRight },
754 { XtNlabel, (XtArgVal) "..." },
755 { XtNresizable, (XtArgVal) True },
756 { XtNresize, (XtArgVal) False }
759 Arg messageArgs[] = {
760 { XtNjustify, (XtArgVal) XtJustifyLeft },
761 { XtNlabel, (XtArgVal) "..." },
762 { XtNresizable, (XtArgVal) True },
763 { XtNresize, (XtArgVal) False }
767 { XtNborderWidth, 0 },
768 { XtNjustify, (XtArgVal) XtJustifyLeft }
771 XtResource clientResources[] = {
772 { "whitePieceColor", "whitePieceColor", XtRString, sizeof(String),
773 XtOffset(AppDataPtr, whitePieceColor), XtRString,
775 { "blackPieceColor", "blackPieceColor", XtRString, sizeof(String),
776 XtOffset(AppDataPtr, blackPieceColor), XtRString,
778 { "lightSquareColor", "lightSquareColor", XtRString,
779 sizeof(String), XtOffset(AppDataPtr, lightSquareColor),
780 XtRString, LIGHT_SQUARE_COLOR },
781 { "darkSquareColor", "darkSquareColor", XtRString, sizeof(String),
782 XtOffset(AppDataPtr, darkSquareColor), XtRString,
784 { "highlightSquareColor", "highlightSquareColor", XtRString,
785 sizeof(String), XtOffset(AppDataPtr, highlightSquareColor),
786 XtRString, HIGHLIGHT_SQUARE_COLOR },
787 { "premoveHighlightColor", "premoveHighlightColor", XtRString,
788 sizeof(String), XtOffset(AppDataPtr, premoveHighlightColor),
789 XtRString, PREMOVE_HIGHLIGHT_COLOR },
790 { "movesPerSession", "movesPerSession", XtRInt, sizeof(int),
791 XtOffset(AppDataPtr, movesPerSession), XtRImmediate,
792 (XtPointer) MOVES_PER_SESSION },
793 { "timeIncrement", "timeIncrement", XtRInt, sizeof(int),
794 XtOffset(AppDataPtr, timeIncrement), XtRImmediate,
795 (XtPointer) TIME_INCREMENT },
796 { "initString", "initString", XtRString, sizeof(String),
797 XtOffset(AppDataPtr, initString), XtRString, INIT_STRING },
798 { "secondInitString", "secondInitString", XtRString, sizeof(String),
799 XtOffset(AppDataPtr, secondInitString), XtRString, INIT_STRING },
800 { "firstComputerString", "firstComputerString", XtRString,
801 sizeof(String), XtOffset(AppDataPtr, firstComputerString), XtRString,
803 { "secondComputerString", "secondComputerString", XtRString,
804 sizeof(String), XtOffset(AppDataPtr, secondComputerString), XtRString,
806 { "firstChessProgram", "firstChessProgram", XtRString,
807 sizeof(String), XtOffset(AppDataPtr, firstChessProgram),
808 XtRString, FIRST_CHESS_PROGRAM },
809 { "secondChessProgram", "secondChessProgram", XtRString,
810 sizeof(String), XtOffset(AppDataPtr, secondChessProgram),
811 XtRString, SECOND_CHESS_PROGRAM },
812 { "firstPlaysBlack", "firstPlaysBlack", XtRBoolean,
813 sizeof(Boolean), XtOffset(AppDataPtr, firstPlaysBlack),
814 XtRImmediate, (XtPointer) False },
815 { "noChessProgram", "noChessProgram", XtRBoolean,
816 sizeof(Boolean), XtOffset(AppDataPtr, noChessProgram),
817 XtRImmediate, (XtPointer) False },
818 { "firstHost", "firstHost", XtRString, sizeof(String),
819 XtOffset(AppDataPtr, firstHost), XtRString, FIRST_HOST },
820 { "secondHost", "secondHost", XtRString, sizeof(String),
821 XtOffset(AppDataPtr, secondHost), XtRString, SECOND_HOST },
822 { "firstDirectory", "firstDirectory", XtRString, sizeof(String),
823 XtOffset(AppDataPtr, firstDirectory), XtRString, "." },
824 { "secondDirectory", "secondDirectory", XtRString, sizeof(String),
825 XtOffset(AppDataPtr, secondDirectory), XtRString, "." },
826 { "bitmapDirectory", "bitmapDirectory", XtRString,
827 sizeof(String), XtOffset(AppDataPtr, bitmapDirectory),
829 { "remoteShell", "remoteShell", XtRString, sizeof(String),
830 XtOffset(AppDataPtr, remoteShell), XtRString, REMOTE_SHELL },
831 { "remoteUser", "remoteUser", XtRString, sizeof(String),
832 XtOffset(AppDataPtr, remoteUser), XtRString, "" },
833 { "timeDelay", "timeDelay", XtRFloat, sizeof(float),
834 XtOffset(AppDataPtr, timeDelay), XtRString,
835 (XtPointer) TIME_DELAY_QUOTE },
836 { "timeControl", "timeControl", XtRString, sizeof(String),
837 XtOffset(AppDataPtr, timeControl), XtRString,
838 (XtPointer) TIME_CONTROL },
839 { "internetChessServerMode", "internetChessServerMode",
840 XtRBoolean, sizeof(Boolean),
841 XtOffset(AppDataPtr, icsActive), XtRImmediate,
843 { "internetChessServerHost", "internetChessServerHost",
844 XtRString, sizeof(String),
845 XtOffset(AppDataPtr, icsHost),
846 XtRString, (XtPointer) ICS_HOST },
847 { "internetChessServerPort", "internetChessServerPort",
848 XtRString, sizeof(String),
849 XtOffset(AppDataPtr, icsPort), XtRString,
850 (XtPointer) ICS_PORT },
851 { "internetChessServerCommPort", "internetChessServerCommPort",
852 XtRString, sizeof(String),
853 XtOffset(AppDataPtr, icsCommPort), XtRString,
855 { "internetChessServerLogonScript", "internetChessServerLogonScript",
856 XtRString, sizeof(String),
857 XtOffset(AppDataPtr, icsLogon), XtRString,
859 { "internetChessServerHelper", "internetChessServerHelper",
860 XtRString, sizeof(String),
861 XtOffset(AppDataPtr, icsHelper), XtRString, "" },
862 { "internetChessServerInputBox", "internetChessServerInputBox",
863 XtRBoolean, sizeof(Boolean),
864 XtOffset(AppDataPtr, icsInputBox), XtRImmediate,
866 { "icsAlarm", "icsAlarm",
867 XtRBoolean, sizeof(Boolean),
868 XtOffset(AppDataPtr, icsAlarm), XtRImmediate,
870 { "icsAlarmTime", "icsAlarmTime",
872 XtOffset(AppDataPtr, icsAlarmTime), XtRImmediate,
874 { "useTelnet", "useTelnet", XtRBoolean, sizeof(Boolean),
875 XtOffset(AppDataPtr, useTelnet), XtRImmediate,
877 { "telnetProgram", "telnetProgram", XtRString, sizeof(String),
878 XtOffset(AppDataPtr, telnetProgram), XtRString, TELNET_PROGRAM },
879 { "gateway", "gateway", XtRString, sizeof(String),
880 XtOffset(AppDataPtr, gateway), XtRString, "" },
881 { "loadGameFile", "loadGameFile", XtRString, sizeof(String),
882 XtOffset(AppDataPtr, loadGameFile), XtRString, "" },
883 { "loadGameIndex", "loadGameIndex",
885 XtOffset(AppDataPtr, loadGameIndex), XtRImmediate,
887 { "saveGameFile", "saveGameFile", XtRString, sizeof(String),
888 XtOffset(AppDataPtr, saveGameFile), XtRString, "" },
889 { "autoRaiseBoard", "autoRaiseBoard", XtRBoolean,
890 sizeof(Boolean), XtOffset(AppDataPtr, autoRaiseBoard),
891 XtRImmediate, (XtPointer) True },
892 { "autoSaveGames", "autoSaveGames", XtRBoolean,
893 sizeof(Boolean), XtOffset(AppDataPtr, autoSaveGames),
894 XtRImmediate, (XtPointer) False },
895 { "blindfold", "blindfold", XtRBoolean,
896 sizeof(Boolean), XtOffset(AppDataPtr, blindfold),
897 XtRImmediate, (XtPointer) False },
898 { "loadPositionFile", "loadPositionFile", XtRString,
899 sizeof(String), XtOffset(AppDataPtr, loadPositionFile),
901 { "loadPositionIndex", "loadPositionIndex",
903 XtOffset(AppDataPtr, loadPositionIndex), XtRImmediate,
905 { "savePositionFile", "savePositionFile", XtRString,
906 sizeof(String), XtOffset(AppDataPtr, savePositionFile),
908 { "matchMode", "matchMode", XtRBoolean, sizeof(Boolean),
909 XtOffset(AppDataPtr, matchMode), XtRImmediate, (XtPointer) False },
910 { "matchGames", "matchGames", XtRInt, sizeof(int),
911 XtOffset(AppDataPtr, matchGames), XtRImmediate,
913 { "monoMode", "monoMode", XtRBoolean, sizeof(Boolean),
914 XtOffset(AppDataPtr, monoMode), XtRImmediate,
916 { "debugMode", "debugMode", XtRBoolean, sizeof(Boolean),
917 XtOffset(AppDataPtr, debugMode), XtRImmediate,
919 { "clockMode", "clockMode", XtRBoolean, sizeof(Boolean),
920 XtOffset(AppDataPtr, clockMode), XtRImmediate,
922 { "boardSize", "boardSize", XtRString, sizeof(String),
923 XtOffset(AppDataPtr, boardSize), XtRString, "" },
924 { "searchTime", "searchTime", XtRString, sizeof(String),
925 XtOffset(AppDataPtr, searchTime), XtRString,
927 { "searchDepth", "searchDepth", XtRInt, sizeof(int),
928 XtOffset(AppDataPtr, searchDepth), XtRImmediate,
930 { "showCoords", "showCoords", XtRBoolean, sizeof(Boolean),
931 XtOffset(AppDataPtr, showCoords), XtRImmediate,
933 { "showJail", "showJail", XtRInt, sizeof(int),
934 XtOffset(AppDataPtr, showJail), XtRImmediate,
936 { "showThinking", "showThinking", XtRBoolean, sizeof(Boolean),
937 XtOffset(AppDataPtr, showThinking), XtRImmediate,
939 { "ponderNextMove", "ponderNextMove", XtRBoolean, sizeof(Boolean),
940 XtOffset(AppDataPtr, ponderNextMove), XtRImmediate,
942 { "periodicUpdates", "periodicUpdates", XtRBoolean, sizeof(Boolean),
943 XtOffset(AppDataPtr, periodicUpdates), XtRImmediate,
945 { "clockFont", "clockFont", XtRString, sizeof(String),
946 XtOffset(AppDataPtr, clockFont), XtRString, CLOCK_FONT },
947 { "coordFont", "coordFont", XtRString, sizeof(String),
948 XtOffset(AppDataPtr, coordFont), XtRString, COORD_FONT },
949 { "font", "font", XtRString, sizeof(String),
950 XtOffset(AppDataPtr, font), XtRString, DEFAULT_FONT },
951 { "ringBellAfterMoves", "ringBellAfterMoves",
952 XtRBoolean, sizeof(Boolean),
953 XtOffset(AppDataPtr, ringBellAfterMoves),
954 XtRImmediate, (XtPointer) False },
955 { "autoCallFlag", "autoCallFlag", XtRBoolean,
956 sizeof(Boolean), XtOffset(AppDataPtr, autoCallFlag),
957 XtRImmediate, (XtPointer) False },
958 { "autoFlipView", "autoFlipView", XtRBoolean,
959 sizeof(Boolean), XtOffset(AppDataPtr, autoFlipView),
960 XtRImmediate, (XtPointer) True },
961 { "autoObserve", "autoObserve", XtRBoolean,
962 sizeof(Boolean), XtOffset(AppDataPtr, autoObserve),
963 XtRImmediate, (XtPointer) False },
964 { "autoComment", "autoComment", XtRBoolean,
965 sizeof(Boolean), XtOffset(AppDataPtr, autoComment),
966 XtRImmediate, (XtPointer) False },
967 { "getMoveList", "getMoveList", XtRBoolean,
968 sizeof(Boolean), XtOffset(AppDataPtr, getMoveList),
969 XtRImmediate, (XtPointer) True },
971 { "highlightDragging", "highlightDragging", XtRBoolean,
972 sizeof(Boolean), XtOffset(AppDataPtr, highlightDragging),
973 XtRImmediate, (XtPointer) False },
975 { "highlightLastMove", "highlightLastMove", XtRBoolean,
976 sizeof(Boolean), XtOffset(AppDataPtr, highlightLastMove),
977 XtRImmediate, (XtPointer) False },
978 { "premove", "premove", XtRBoolean,
979 sizeof(Boolean), XtOffset(AppDataPtr, premove),
980 XtRImmediate, (XtPointer) True },
981 { "testLegality", "testLegality", XtRBoolean,
982 sizeof(Boolean), XtOffset(AppDataPtr, testLegality),
983 XtRImmediate, (XtPointer) True },
984 { "flipView", "flipView", XtRBoolean,
985 sizeof(Boolean), XtOffset(AppDataPtr, flipView),
986 XtRImmediate, (XtPointer) False },
987 { "cmail", "cmailGameName", XtRString, sizeof(String),
988 XtOffset(AppDataPtr, cmailGameName), XtRString, "" },
989 { "alwaysPromoteToQueen", "alwaysPromoteToQueen", XtRBoolean,
990 sizeof(Boolean), XtOffset(AppDataPtr, alwaysPromoteToQueen),
991 XtRImmediate, (XtPointer) False },
992 { "oldSaveStyle", "oldSaveStyle", XtRBoolean,
993 sizeof(Boolean), XtOffset(AppDataPtr, oldSaveStyle),
994 XtRImmediate, (XtPointer) False },
995 { "quietPlay", "quietPlay", XtRBoolean,
996 sizeof(Boolean), XtOffset(AppDataPtr, quietPlay),
997 XtRImmediate, (XtPointer) False },
998 { "titleInWindow", "titleInWindow", XtRBoolean,
999 sizeof(Boolean), XtOffset(AppDataPtr, titleInWindow),
1000 XtRImmediate, (XtPointer) False },
1001 { "localLineEditing", "localLineEditing", XtRBoolean,
1002 sizeof(Boolean), XtOffset(AppDataPtr, localLineEditing),
1003 XtRImmediate, (XtPointer) True }, /* not implemented, must be True */
1005 { "zippyTalk", "zippyTalk", XtRBoolean,
1006 sizeof(Boolean), XtOffset(AppDataPtr, zippyTalk),
1007 XtRImmediate, (XtPointer) ZIPPY_TALK },
1008 { "zippyPlay", "zippyPlay", XtRBoolean,
1009 sizeof(Boolean), XtOffset(AppDataPtr, zippyPlay),
1010 XtRImmediate, (XtPointer) ZIPPY_PLAY },
1011 { "zippyLines", "zippyLines", XtRString, sizeof(String),
1012 XtOffset(AppDataPtr, zippyLines), XtRString, ZIPPY_LINES },
1013 { "zippyPinhead", "zippyPinhead", XtRString, sizeof(String),
1014 XtOffset(AppDataPtr, zippyPinhead), XtRString, ZIPPY_PINHEAD },
1015 { "zippyPassword", "zippyPassword", XtRString, sizeof(String),
1016 XtOffset(AppDataPtr, zippyPassword), XtRString, ZIPPY_PASSWORD },
1017 { "zippyPassword2", "zippyPassword2", XtRString, sizeof(String),
1018 XtOffset(AppDataPtr, zippyPassword2), XtRString, ZIPPY_PASSWORD2 },
1019 { "zippyWrongPassword", "zippyWrongPassword", XtRString, sizeof(String),
1020 XtOffset(AppDataPtr, zippyWrongPassword), XtRString,
1021 ZIPPY_WRONG_PASSWORD },
1022 { "zippyAcceptOnly", "zippyAcceptOnly", XtRString, sizeof(String),
1023 XtOffset(AppDataPtr, zippyAcceptOnly), XtRString, ZIPPY_ACCEPT_ONLY },
1024 { "zippyUseI", "zippyUseI", XtRBoolean,
1025 sizeof(Boolean), XtOffset(AppDataPtr, zippyUseI),
1026 XtRImmediate, (XtPointer) ZIPPY_USE_I },
1027 { "zippyBughouse", "zippyBughouse", XtRInt,
1028 sizeof(int), XtOffset(AppDataPtr, zippyBughouse),
1029 XtRImmediate, (XtPointer) ZIPPY_BUGHOUSE },
1030 { "zippyNoplayCrafty", "zippyNoplayCrafty", XtRBoolean,
1031 sizeof(Boolean), XtOffset(AppDataPtr, zippyNoplayCrafty),
1032 XtRImmediate, (XtPointer) ZIPPY_NOPLAY_CRAFTY },
1033 { "zippyGameEnd", "zippyGameEnd", XtRString, sizeof(String),
1034 XtOffset(AppDataPtr, zippyGameEnd), XtRString, ZIPPY_GAME_END },
1035 { "zippyGameStart", "zippyGameStart", XtRString, sizeof(String),
1036 XtOffset(AppDataPtr, zippyGameStart), XtRString, ZIPPY_GAME_START },
1037 { "zippyAdjourn", "zippyAdjourn", XtRBoolean,
1038 sizeof(Boolean), XtOffset(AppDataPtr, zippyAdjourn),
1039 XtRImmediate, (XtPointer) ZIPPY_ADJOURN },
1040 { "zippyAbort", "zippyAbort", XtRBoolean,
1041 sizeof(Boolean), XtOffset(AppDataPtr, zippyAbort),
1042 XtRImmediate, (XtPointer) ZIPPY_ABORT },
1043 { "zippyVariants", "zippyVariants", XtRString, sizeof(String),
1044 XtOffset(AppDataPtr, zippyVariants), XtRString, ZIPPY_VARIANTS },
1045 { "zippyMaxGames", "zippyMaxGames", XtRInt, sizeof(int),
1046 XtOffset(AppDataPtr, zippyMaxGames), XtRImmediate,
1047 (XtPointer) ZIPPY_MAX_GAMES },
1048 { "zippyReplayTimeout", "zippyReplayTimeout", XtRInt, sizeof(int),
1049 XtOffset(AppDataPtr, zippyReplayTimeout), XtRImmediate,
1050 (XtPointer) ZIPPY_REPLAY_TIMEOUT },
1051 { "zippyShortGame", "zippyShortGame", XtRInt, sizeof(int),
1052 XtOffset(AppDataPtr, zippyShortGame), XtRImmediate,
1055 { "flashCount", "flashCount", XtRInt, sizeof(int),
1056 XtOffset(AppDataPtr, flashCount), XtRImmediate,
1057 (XtPointer) FLASH_COUNT },
1058 { "flashRate", "flashRate", XtRInt, sizeof(int),
1059 XtOffset(AppDataPtr, flashRate), XtRImmediate,
1060 (XtPointer) FLASH_RATE },
1061 { "pixmapDirectory", "pixmapDirectory", XtRString,
1062 sizeof(String), XtOffset(AppDataPtr, pixmapDirectory),
1064 { "msLoginDelay", "msLoginDelay", XtRInt, sizeof(int),
1065 XtOffset(AppDataPtr, msLoginDelay), XtRImmediate,
1066 (XtPointer) MS_LOGIN_DELAY },
1067 { "colorizeMessages", "colorizeMessages", XtRBoolean,
1068 sizeof(Boolean), XtOffset(AppDataPtr, colorize),
1069 XtRImmediate, (XtPointer) False },
1070 { "colorShout", "colorShout", XtRString,
1071 sizeof(String), XtOffset(AppDataPtr, colorShout),
1072 XtRString, COLOR_SHOUT },
1073 { "colorSShout", "colorSShout", XtRString,
1074 sizeof(String), XtOffset(AppDataPtr, colorSShout),
1075 XtRString, COLOR_SSHOUT },
1076 { "colorChannel1", "colorChannel1", XtRString,
1077 sizeof(String), XtOffset(AppDataPtr, colorChannel1),
1078 XtRString, COLOR_CHANNEL1 },
1079 { "colorChannel", "colorChannel", XtRString,
1080 sizeof(String), XtOffset(AppDataPtr, colorChannel),
1081 XtRString, COLOR_CHANNEL },
1082 { "colorKibitz", "colorKibitz", XtRString,
1083 sizeof(String), XtOffset(AppDataPtr, colorKibitz),
1084 XtRString, COLOR_KIBITZ },
1085 { "colorTell", "colorTell", XtRString,
1086 sizeof(String), XtOffset(AppDataPtr, colorTell),
1087 XtRString, COLOR_TELL },
1088 { "colorChallenge", "colorChallenge", XtRString,
1089 sizeof(String), XtOffset(AppDataPtr, colorChallenge),
1090 XtRString, COLOR_CHALLENGE },
1091 { "colorRequest", "colorRequest", XtRString,
1092 sizeof(String), XtOffset(AppDataPtr, colorRequest),
1093 XtRString, COLOR_REQUEST },
1094 { "colorSeek", "colorSeek", XtRString,
1095 sizeof(String), XtOffset(AppDataPtr, colorSeek),
1096 XtRString, COLOR_SEEK },
1097 { "colorNormal", "colorNormal", XtRString,
1098 sizeof(String), XtOffset(AppDataPtr, colorNormal),
1099 XtRString, COLOR_NORMAL },
1100 { "soundProgram", "soundProgram", XtRString,
1101 sizeof(String), XtOffset(AppDataPtr, soundProgram),
1102 XtRString, "play" },
1103 { "soundShout", "soundShout", XtRString,
1104 sizeof(String), XtOffset(AppDataPtr, soundShout),
1106 { "soundSShout", "soundSShout", XtRString,
1107 sizeof(String), XtOffset(AppDataPtr, soundSShout),
1109 { "soundChannel1", "soundChannel1", XtRString,
1110 sizeof(String), XtOffset(AppDataPtr, soundChannel1),
1112 { "soundChannel", "soundChannel", XtRString,
1113 sizeof(String), XtOffset(AppDataPtr, soundChannel),
1115 { "soundKibitz", "soundKibitz", XtRString,
1116 sizeof(String), XtOffset(AppDataPtr, soundKibitz),
1118 { "soundTell", "soundTell", XtRString,
1119 sizeof(String), XtOffset(AppDataPtr, soundTell),
1121 { "soundChallenge", "soundChallenge", XtRString,
1122 sizeof(String), XtOffset(AppDataPtr, soundChallenge),
1124 { "soundRequest", "soundRequest", XtRString,
1125 sizeof(String), XtOffset(AppDataPtr, soundRequest),
1127 { "soundSeek", "soundSeek", XtRString,
1128 sizeof(String), XtOffset(AppDataPtr, soundSeek),
1130 { "soundMove", "soundMove", XtRString,
1131 sizeof(String), XtOffset(AppDataPtr, soundMove),
1133 { "soundIcsWin", "soundIcsWin", XtRString,
1134 sizeof(String), XtOffset(AppDataPtr, soundIcsWin),
1136 { "soundIcsLoss", "soundIcsLoss", XtRString,
1137 sizeof(String), XtOffset(AppDataPtr, soundIcsLoss),
1139 { "soundIcsDraw", "soundIcsDraw", XtRString,
1140 sizeof(String), XtOffset(AppDataPtr, soundIcsDraw),
1142 { "soundIcsUnfinished", "soundIcsUnfinished", XtRString,
1143 sizeof(String), XtOffset(AppDataPtr, soundIcsUnfinished),
1145 { "soundIcsAlarm", "soundIcsAlarm", XtRString,
1146 sizeof(String), XtOffset(AppDataPtr, soundIcsAlarm),
1148 { "reuseFirst", "reuseFirst", XtRBoolean,
1149 sizeof(Boolean), XtOffset(AppDataPtr, reuseFirst),
1150 XtRImmediate, (XtPointer) True },
1151 { "reuseSecond", "reuseSecond", XtRBoolean,
1152 sizeof(Boolean), XtOffset(AppDataPtr, reuseSecond),
1153 XtRImmediate, (XtPointer) True },
1154 { "animateDragging", "animateDragging", XtRBoolean,
1155 sizeof(Boolean), XtOffset(AppDataPtr, animateDragging),
1156 XtRImmediate, (XtPointer) True },
1157 { "animateMoving", "animateMoving", XtRBoolean,
1158 sizeof(Boolean), XtOffset(AppDataPtr, animate),
1159 XtRImmediate, (XtPointer) True },
1160 { "animateSpeed", "animateSpeed", XtRInt,
1161 sizeof(int), XtOffset(AppDataPtr, animSpeed),
1162 XtRImmediate, (XtPointer)10 },
1163 { "popupExitMessage", "popupExitMessage", XtRBoolean,
1164 sizeof(Boolean), XtOffset(AppDataPtr, popupExitMessage),
1165 XtRImmediate, (XtPointer) True },
1166 { "popupMoveErrors", "popupMoveErrors", XtRBoolean,
1167 sizeof(Boolean), XtOffset(AppDataPtr, popupMoveErrors),
1168 XtRImmediate, (XtPointer) False },
1169 { "fontSizeTolerance", "fontSizeTolerance", XtRInt,
1170 sizeof(int), XtOffset(AppDataPtr, fontSizeTolerance),
1171 XtRImmediate, (XtPointer)4 },
1172 { "initialMode", "initialMode", XtRString,
1173 sizeof(String), XtOffset(AppDataPtr, initialMode),
1174 XtRImmediate, (XtPointer) "" },
1175 { "variant", "variant", XtRString,
1176 sizeof(String), XtOffset(AppDataPtr, variant),
1177 XtRImmediate, (XtPointer) "normal" },
1178 { "firstProtocolVersion", "firstProtocolVersion", XtRInt,
1179 sizeof(int), XtOffset(AppDataPtr, firstProtocolVersion),
1180 XtRImmediate, (XtPointer)PROTOVER },
1181 { "secondProtocolVersion", "secondProtocolVersion", XtRInt,
1182 sizeof(int), XtOffset(AppDataPtr, secondProtocolVersion),
1183 XtRImmediate, (XtPointer)PROTOVER },
1184 { "showButtonBar", "showButtonBar", XtRBoolean,
1185 sizeof(Boolean), XtOffset(AppDataPtr, showButtonBar),
1186 XtRImmediate, (XtPointer) True },
1187 { "lowTimeWarningColor", "lowTimeWarningColor", XtRString,
1188 sizeof(String), XtOffset(AppDataPtr, lowTimeWarningColor),
1189 XtRString, COLOR_LOWTIMEWARNING },
1190 { "lowTimeWarning", "lowTimeWarning", XtRBoolean,
1191 sizeof(Boolean), XtOffset(AppDataPtr, lowTimeWarning),
1192 XtRImmediate, (XtPointer) False },
1193 {"icsEngineAnalyze", "icsEngineAnalyze", XtRBoolean, /* [DM] icsEngineAnalyze */
1194 sizeof(Boolean), XtOffset(AppDataPtr, icsEngineAnalyze),
1195 XtRImmediate, (XtPointer) False },
1196 { "firstScoreAbs", "firstScoreAbs", XtRBoolean,
1197 sizeof(Boolean), XtOffset(AppDataPtr, firstScoreIsAbsolute),
1198 XtRImmediate, (XtPointer) False },
1199 { "secondScoreAbs", "secondScoreAbs", XtRBoolean,
1200 sizeof(Boolean), XtOffset(AppDataPtr, secondScoreIsAbsolute),
1201 XtRImmediate, (XtPointer) False },
1202 { "pgnExtendedInfo", "pgnExtendedInfo", XtRBoolean,
1203 sizeof(Boolean), XtOffset(AppDataPtr, saveExtendedInfoInPGN),
1204 XtRImmediate, (XtPointer) False },
1205 { "hideThinkingFromHuman", "hideThinkingFromHuman", XtRBoolean,
1206 sizeof(Boolean), XtOffset(AppDataPtr, hideThinkingFromHuman),
1207 XtRImmediate, (XtPointer) True },
1208 { "adjudicateLossThreshold", "adjudicateLossThreshold", XtRInt,
1209 sizeof(int), XtOffset(AppDataPtr, adjudicateLossThreshold),
1210 XtRImmediate, (XtPointer) 0},
1211 { "pgnEventHeader", "pgnEventHeader", XtRString,
1212 sizeof(String), XtOffset(AppDataPtr, pgnEventHeader),
1213 XtRImmediate, (XtPointer) "Computer Chess Game" },
1214 { "defaultFrcPosition", "defaultFrcPositon", XtRInt,
1215 sizeof(int), XtOffset(AppDataPtr, defaultFrcPosition),
1216 XtRImmediate, (XtPointer) -1},
1217 { "gameListTags", "gameListTags", XtRString,
1218 sizeof(String), XtOffset(AppDataPtr, gameListTags),
1219 XtRImmediate, (XtPointer) GLT_DEFAULT_TAGS },
1221 // [HGM] 4.3.xx options
1222 { "boardWidth", "boardWidth", XtRInt,
1223 sizeof(int), XtOffset(AppDataPtr, NrFiles),
1224 XtRImmediate, (XtPointer) -1},
1225 { "boardHeight", "boardHeight", XtRInt,
1226 sizeof(int), XtOffset(AppDataPtr, NrRanks),
1227 XtRImmediate, (XtPointer) -1},
1228 { "matchPause", "matchPause", XtRInt,
1229 sizeof(int), XtOffset(AppDataPtr, matchPause),
1230 XtRImmediate, (XtPointer) 10000},
1231 { "holdingsSize", "holdingsSize", XtRInt,
1232 sizeof(int), XtOffset(AppDataPtr, holdingsSize),
1233 XtRImmediate, (XtPointer) -1},
1234 { "flipBlack", "flipBlack", XtRBoolean,
1235 sizeof(Boolean), XtOffset(AppDataPtr, upsideDown),
1236 XtRImmediate, (XtPointer) False},
1237 { "allWhite", "allWhite", XtRBoolean,
1238 sizeof(Boolean), XtOffset(AppDataPtr, allWhite),
1239 XtRImmediate, (XtPointer) False},
1240 { "pieceToCharTable", "pieceToCharTable", XtRString,
1241 sizeof(String), XtOffset(AppDataPtr, pieceToCharTable),
1242 XtRImmediate, (XtPointer) 0},
1243 { "alphaRank", "alphaRank", XtRBoolean,
1244 sizeof(Boolean), XtOffset(AppDataPtr, alphaRank),
1245 XtRImmediate, (XtPointer) False},
1246 { "testClaims", "testClaims", XtRBoolean,
1247 sizeof(Boolean), XtOffset(AppDataPtr, testClaims),
1248 XtRImmediate, (XtPointer) True},
1249 { "checkMates", "checkMates", XtRBoolean,
1250 sizeof(Boolean), XtOffset(AppDataPtr, checkMates),
1251 XtRImmediate, (XtPointer) True},
1252 { "materialDraws", "materialDraws", XtRBoolean,
1253 sizeof(Boolean), XtOffset(AppDataPtr, materialDraws),
1254 XtRImmediate, (XtPointer) True},
1255 { "trivialDraws", "trivialDraws", XtRBoolean,
1256 sizeof(Boolean), XtOffset(AppDataPtr, trivialDraws),
1257 XtRImmediate, (XtPointer) False},
1258 { "ruleMoves", "ruleMoves", XtRInt,
1259 sizeof(int), XtOffset(AppDataPtr, ruleMoves),
1260 XtRImmediate, (XtPointer) 51},
1261 { "repeatsToDraw", "repeatsToDraw", XtRInt,
1262 sizeof(int), XtOffset(AppDataPtr, drawRepeats),
1263 XtRImmediate, (XtPointer) 6},
1264 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1265 sizeof(int), XtOffset(AppDataPtr, engineComments),
1266 XtRImmediate, (XtPointer) 1},
1267 { "userName", "userName", XtRString,
1268 sizeof(int), XtOffset(AppDataPtr, userName),
1269 XtRImmediate, (XtPointer) 0},
1270 { "autoKibitz", "autoKibitz", XtRBoolean,
1271 sizeof(Boolean), XtOffset(AppDataPtr, autoKibitz),
1272 XtRImmediate, (XtPointer) False},
1273 { "firstTimeOdds", "firstTimeOdds", XtRInt,
1274 sizeof(int), XtOffset(AppDataPtr, firstTimeOdds),
1275 XtRImmediate, (XtPointer) 1},
1276 { "secondTimeOdds", "secondTimeOdds", XtRInt,
1277 sizeof(int), XtOffset(AppDataPtr, secondTimeOdds),
1278 XtRImmediate, (XtPointer) 1},
1279 { "timeOddsMode", "timeOddsMode", XtRInt,
1280 sizeof(int), XtOffset(AppDataPtr, timeOddsMode),
1281 XtRImmediate, (XtPointer) 0},
1282 { "firstAccumulateTC", "firstAccumulateTC", XtRInt,
1283 sizeof(int), XtOffset(AppDataPtr, firstAccumulateTC),
1284 XtRImmediate, (XtPointer) 1},
1285 { "secondAccumulateTC", "secondAccumulateTC", XtRInt,
1286 sizeof(int), XtOffset(AppDataPtr, secondAccumulateTC),
1287 XtRImmediate, (XtPointer) 1},
1288 { "firstNPS", "firstNPS", XtRInt,
1289 sizeof(int), XtOffset(AppDataPtr, firstNPS),
1290 XtRImmediate, (XtPointer) -1},
1291 { "secondNPS", "secondNPS", XtRInt,
1292 sizeof(int), XtOffset(AppDataPtr, secondNPS),
1293 XtRImmediate, (XtPointer) -1},
1294 { "serverMoves", "serverMoves", XtRString,
1295 sizeof(String), XtOffset(AppDataPtr, serverMovesName),
1296 XtRImmediate, (XtPointer) 0},
1297 { "serverPause", "serverPause", XtRInt,
1298 sizeof(int), XtOffset(AppDataPtr, serverPause),
1299 XtRImmediate, (XtPointer) 0},
1300 { "suppressLoadMoves", "suppressLoadMoves", XtRBoolean,
1301 sizeof(Boolean), XtOffset(AppDataPtr, suppressLoadMoves),
1302 XtRImmediate, (XtPointer) False},
1303 { "userName", "userName", XtRString,
1304 sizeof(String), XtOffset(AppDataPtr, userName),
1305 XtRImmediate, (XtPointer) 0},
1306 { "egtFormats", "egtFormats", XtRString,
1307 sizeof(String), XtOffset(AppDataPtr, egtFormats),
1308 XtRImmediate, (XtPointer) 0},
1309 { "rewindIndex", "rewindIndex", XtRInt,
1310 sizeof(int), XtOffset(AppDataPtr, rewindIndex),
1311 XtRImmediate, (XtPointer) 0},
1312 { "sameColorGames", "sameColorGames", XtRInt,
1313 sizeof(int), XtOffset(AppDataPtr, sameColorGames),
1314 XtRImmediate, (XtPointer) 0},
1315 { "smpCores", "smpCores", XtRInt,
1316 sizeof(int), XtOffset(AppDataPtr, smpCores),
1317 XtRImmediate, (XtPointer) 1},
1318 { "niceEngines", "niceEngines", XtRInt,
1319 sizeof(int), XtOffset(AppDataPtr, niceEngines),
1320 XtRImmediate, (XtPointer) 0},
1321 { "nameOfDebugFile", "nameOfDebugFile", XtRString,
1322 sizeof(String), XtOffset(AppDataPtr, nameOfDebugFile),
1323 XtRImmediate, (XtPointer) "xboard.debug"},
1324 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1325 sizeof(int), XtOffset(AppDataPtr, engineComments),
1326 XtRImmediate, (XtPointer) 0},
1327 { "noGUI", "noGUI", XtRBoolean,
1328 sizeof(Boolean), XtOffset(AppDataPtr, noGUI),
1329 XtRImmediate, (XtPointer) 0},
1330 { "firstOptions", "firstOptions", XtRString,
1331 sizeof(String), XtOffset(AppDataPtr, firstOptions),
1332 XtRImmediate, (XtPointer) "" },
1333 { "secondOptions", "secondOptions", XtRString,
1334 sizeof(String), XtOffset(AppDataPtr, secondOptions),
1335 XtRImmediate, (XtPointer) "" },
1336 { "firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XtRString,
1337 sizeof(String), XtOffset(AppDataPtr, fenOverride1),
1338 XtRImmediate, (XtPointer) 0 },
1339 { "secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XtRString,
1340 sizeof(String), XtOffset(AppDataPtr, fenOverride2),
1341 XtRImmediate, (XtPointer) 0 },
1343 // [HGM] Winboard_x UCI options
1344 { "firstIsUCI", "firstIsUCI", XtRBoolean,
1345 sizeof(Boolean), XtOffset(AppDataPtr, firstIsUCI),
1346 XtRImmediate, (XtPointer) False},
1347 { "secondIsUCI", "secondIsUCI", XtRBoolean,
1348 sizeof(Boolean), XtOffset(AppDataPtr, secondIsUCI),
1349 XtRImmediate, (XtPointer) False},
1350 { "firstHasOwnBookUCI", "firstHasOwnBookUCI", XtRBoolean,
1351 sizeof(Boolean), XtOffset(AppDataPtr, firstHasOwnBookUCI),
1352 XtRImmediate, (XtPointer) True},
1353 { "secondHasOwnBookUCI", "secondHasOwnBookUCI", XtRBoolean,
1354 sizeof(Boolean), XtOffset(AppDataPtr, secondHasOwnBookUCI),
1355 XtRImmediate, (XtPointer) True},
1356 { "usePolyglotBook", "usePolyglotBook", XtRBoolean,
1357 sizeof(Boolean), XtOffset(AppDataPtr, usePolyglotBook),
1358 XtRImmediate, (XtPointer) False},
1359 { "defaultHashSize", "defaultHashSize", XtRInt,
1360 sizeof(int), XtOffset(AppDataPtr, defaultHashSize),
1361 XtRImmediate, (XtPointer) 64},
1362 { "defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XtRInt,
1363 sizeof(int), XtOffset(AppDataPtr, defaultCacheSizeEGTB),
1364 XtRImmediate, (XtPointer) 4},
1365 { "polyglotDir", "polyglotDir", XtRString,
1366 sizeof(String), XtOffset(AppDataPtr, polyglotDir),
1367 XtRImmediate, (XtPointer) "." },
1368 { "polyglotBook", "polyglotBook", XtRString,
1369 sizeof(String), XtOffset(AppDataPtr, polyglotBook),
1370 XtRImmediate, (XtPointer) "" },
1371 { "defaultPathEGTB", "defaultPathEGTB", XtRString,
1372 sizeof(String), XtOffset(AppDataPtr, defaultPathEGTB),
1373 XtRImmediate, (XtPointer) "/usr/local/share/egtb"},
1374 { "delayBeforeQuit", "delayBeforeQuit", XtRInt,
1375 sizeof(int), XtOffset(AppDataPtr, delayBeforeQuit),
1376 XtRImmediate, (XtPointer) 0},
1377 { "delayAfterQuit", "delayAfterQuit", XtRInt,
1378 sizeof(int), XtOffset(AppDataPtr, delayAfterQuit),
1379 XtRImmediate, (XtPointer) 0},
1382 XrmOptionDescRec shellOptions[] = {
1383 { "-whitePieceColor", "whitePieceColor", XrmoptionSepArg, NULL },
1384 { "-blackPieceColor", "blackPieceColor", XrmoptionSepArg, NULL },
1385 { "-lightSquareColor", "lightSquareColor", XrmoptionSepArg, NULL },
1386 { "-darkSquareColor", "darkSquareColor", XrmoptionSepArg, NULL },
1387 { "-highlightSquareColor", "highlightSquareColor", XrmoptionSepArg, NULL },
1388 { "-premoveHighlightColor", "premoveHighlightColor", XrmoptionSepArg,NULL},
1389 { "-movesPerSession", "movesPerSession", XrmoptionSepArg, NULL },
1390 { "-mps", "movesPerSession", XrmoptionSepArg, NULL },
1391 { "-timeIncrement", "timeIncrement", XrmoptionSepArg, NULL },
1392 { "-inc", "timeIncrement", XrmoptionSepArg, NULL },
1393 { "-initString", "initString", XrmoptionSepArg, NULL },
1394 { "-firstInitString", "initString", XrmoptionSepArg, NULL },
1395 { "-secondInitString", "secondInitString", XrmoptionSepArg, NULL },
1396 { "-firstComputerString", "firstComputerString", XrmoptionSepArg, NULL },
1397 { "-secondComputerString", "secondComputerString", XrmoptionSepArg, NULL },
1398 { "-firstChessProgram", "firstChessProgram", XrmoptionSepArg, NULL },
1399 { "-fcp", "firstChessProgram", XrmoptionSepArg, NULL },
1400 { "-secondChessProgram", "secondChessProgram", XrmoptionSepArg, NULL },
1401 { "-scp", "secondChessProgram", XrmoptionSepArg, NULL },
1402 { "-firstPlaysBlack", "firstPlaysBlack", XrmoptionSepArg, NULL },
1403 { "-fb", "firstPlaysBlack", XrmoptionNoArg, "True" },
1404 { "-xfb", "firstPlaysBlack", XrmoptionNoArg, "False" },
1405 { "-noChessProgram", "noChessProgram", XrmoptionSepArg, NULL },
1406 { "-ncp", "noChessProgram", XrmoptionNoArg, "True" },
1407 { "-xncp", "noChessProgram", XrmoptionNoArg, "False" },
1408 { "-firstHost", "firstHost", XrmoptionSepArg, NULL },
1409 { "-fh", "firstHost", XrmoptionSepArg, NULL },
1410 { "-secondHost", "secondHost", XrmoptionSepArg, NULL },
1411 { "-sh", "secondHost", XrmoptionSepArg, NULL },
1412 { "-firstDirectory", "firstDirectory", XrmoptionSepArg, NULL },
1413 { "-fd", "firstDirectory", XrmoptionSepArg, NULL },
1414 { "-secondDirectory", "secondDirectory", XrmoptionSepArg, NULL },
1415 { "-sd", "secondDirectory", XrmoptionSepArg, NULL },
1416 { "-bitmapDirectory", "bitmapDirectory", XrmoptionSepArg, NULL },
1417 { "-bm", "bitmapDirectory", XrmoptionSepArg, NULL },
1418 { "-remoteShell", "remoteShell", XrmoptionSepArg, NULL },
1419 { "-rsh", "remoteShell", XrmoptionSepArg, NULL },
1420 { "-remoteUser", "remoteUser", XrmoptionSepArg, NULL },
1421 { "-ruser", "remoteUser", XrmoptionSepArg, NULL },
1422 { "-timeDelay", "timeDelay", XrmoptionSepArg, NULL },
1423 { "-td", "timeDelay", XrmoptionSepArg, NULL },
1424 { "-timeControl", "timeControl", XrmoptionSepArg, NULL },
1425 { "-tc", "timeControl", XrmoptionSepArg, NULL },
1426 { "-internetChessServerMode", "internetChessServerMode",
1427 XrmoptionSepArg, NULL },
1428 { "-ics", "internetChessServerMode", XrmoptionNoArg, "True" },
1429 { "-xics", "internetChessServerMode", XrmoptionNoArg, "False" },
1430 { "-internetChessServerHost", "internetChessServerHost",
1431 XrmoptionSepArg, NULL },
1432 { "-icshost", "internetChessServerHost", XrmoptionSepArg, NULL },
1433 { "-internetChessServerPort", "internetChessServerPort",
1434 XrmoptionSepArg, NULL },
1435 { "-icsport", "internetChessServerPort", XrmoptionSepArg, NULL },
1436 { "-internetChessServerCommPort", "internetChessServerCommPort",
1437 XrmoptionSepArg, NULL },
1438 { "-icscomm", "internetChessServerCommPort", XrmoptionSepArg, NULL },
1439 { "-internetChessServerLogonScript", "internetChessServerLogonScript",
1440 XrmoptionSepArg, NULL },
1441 { "-icslogon", "internetChessServerLogonScript", XrmoptionSepArg, NULL },
1442 { "-internetChessServerHelper", "internetChessServerHelper",
1443 XrmoptionSepArg, NULL },
1444 { "-icshelper", "internetChessServerHelper", XrmoptionSepArg, NULL },
1445 { "-internetChessServerInputBox", "internetChessServerInputBox",
1446 XrmoptionSepArg, NULL },
1447 { "-icsinput", "internetChessServerInputBox", XrmoptionNoArg, "True" },
1448 { "-xicsinput", "internetChessServerInputBox", XrmoptionNoArg, "False" },
1449 { "-icsAlarm", "icsAlarm", XrmoptionSepArg, NULL },
1450 { "-alarm", "icsAlarm", XrmoptionNoArg, "True" },
1451 { "-xalarm", "icsAlarm", XrmoptionNoArg, "False" },
1452 { "-icsAlarmTime", "icsAlarmTime", XrmoptionSepArg, NULL },
1453 { "-useTelnet", "useTelnet", XrmoptionSepArg, NULL },
1454 { "-telnet", "useTelnet", XrmoptionNoArg, "True" },
1455 { "-xtelnet", "useTelnet", XrmoptionNoArg, "False" },
1456 { "-telnetProgram", "telnetProgram", XrmoptionSepArg, NULL },
1457 { "-gateway", "gateway", XrmoptionSepArg, NULL },
1458 { "-loadGameFile", "loadGameFile", XrmoptionSepArg, NULL },
1459 { "-lgf", "loadGameFile", XrmoptionSepArg, NULL },
1460 { "-loadGameIndex", "loadGameIndex", XrmoptionSepArg, NULL },
1461 { "-lgi", "loadGameIndex", XrmoptionSepArg, NULL },
1462 { "-saveGameFile", "saveGameFile", XrmoptionSepArg, NULL },
1463 { "-sgf", "saveGameFile", XrmoptionSepArg, NULL },
1464 { "-autoSaveGames", "autoSaveGames", XrmoptionSepArg, NULL },
1465 { "-autosave", "autoSaveGames", XrmoptionNoArg, "True" },
1466 { "-xautosave", "autoSaveGames", XrmoptionNoArg, "False" },
1467 { "-autoRaiseBoard", "autoRaiseBoard", XrmoptionSepArg, NULL },
1468 { "-autoraise", "autoRaiseBoard", XrmoptionNoArg, "True" },
1469 { "-xautoraise", "autoRaiseBoard", XrmoptionNoArg, "False" },
1470 { "-blindfold", "blindfold", XrmoptionSepArg, NULL },
1471 { "-blind", "blindfold", XrmoptionNoArg, "True" },
1472 { "-xblind", "blindfold", XrmoptionNoArg, "False" },
1473 { "-loadPositionFile", "loadPositionFile", XrmoptionSepArg, NULL },
1474 { "-lpf", "loadPositionFile", XrmoptionSepArg, NULL },
1475 { "-loadPositionIndex", "loadPositionIndex", XrmoptionSepArg, NULL },
1476 { "-lpi", "loadPositionIndex", XrmoptionSepArg, NULL },
1477 { "-savePositionFile", "savePositionFile", XrmoptionSepArg, NULL },
1478 { "-spf", "savePositionFile", XrmoptionSepArg, NULL },
1479 { "-matchMode", "matchMode", XrmoptionSepArg, NULL },
1480 { "-mm", "matchMode", XrmoptionNoArg, "True" },
1481 { "-xmm", "matchMode", XrmoptionNoArg, "False" },
1482 { "-matchGames", "matchGames", XrmoptionSepArg, NULL },
1483 { "-mg", "matchGames", XrmoptionSepArg, NULL },
1484 { "-monoMode", "monoMode", XrmoptionSepArg, NULL },
1485 { "-mono", "monoMode", XrmoptionNoArg, "True" },
1486 { "-xmono", "monoMode", XrmoptionNoArg, "False" },
1487 { "-debugMode", "debugMode", XrmoptionSepArg, NULL },
1488 { "-debug", "debugMode", XrmoptionNoArg, "True" },
1489 { "-xdebug", "debugMode", XrmoptionNoArg, "False" },
1490 { "-clockMode", "clockMode", XrmoptionSepArg, NULL },
1491 { "-clock", "clockMode", XrmoptionNoArg, "True" },
1492 { "-xclock", "clockMode", XrmoptionNoArg, "False" },
1493 { "-boardSize", "boardSize", XrmoptionSepArg, NULL },
1494 { "-size", "boardSize", XrmoptionSepArg, NULL },
1495 { "-searchTime", "searchTime", XrmoptionSepArg, NULL },
1496 { "-st", "searchTime", XrmoptionSepArg, NULL },
1497 { "-searchDepth", "searchDepth", XrmoptionSepArg, NULL },
1498 { "-depth", "searchDepth", XrmoptionSepArg, NULL },
1499 { "-showCoords", "showCoords", XrmoptionSepArg, NULL },
1500 { "-coords", "showCoords", XrmoptionNoArg, "True" },
1501 { "-xcoords", "showCoords", XrmoptionNoArg, "False" },
1503 { "-showJail", "showJail", XrmoptionSepArg, NULL },
1504 { "-jail", "showJail", XrmoptionNoArg, "1" },
1505 { "-sidejail", "showJail", XrmoptionNoArg, "2" },
1506 { "-xjail", "showJail", XrmoptionNoArg, "0" },
1508 { "-showThinking", "showThinking", XrmoptionSepArg, NULL },
1509 { "-thinking", "showThinking", XrmoptionNoArg, "True" },
1510 { "-xthinking", "showThinking", XrmoptionNoArg, "False" },
1511 { "-ponderNextMove", "ponderNextMove", XrmoptionSepArg, NULL },
1512 { "-ponder", "ponderNextMove", XrmoptionNoArg, "True" },
1513 { "-xponder", "ponderNextMove", XrmoptionNoArg, "False" },
1514 { "-periodicUpdates", "periodicUpdates", XrmoptionSepArg, NULL },
1515 { "-periodic", "periodicUpdates", XrmoptionNoArg, "True" },
1516 { "-xperiodic", "periodicUpdates", XrmoptionNoArg, "False" },
1517 { "-clockFont", "clockFont", XrmoptionSepArg, NULL },
1518 { "-coordFont", "coordFont", XrmoptionSepArg, NULL },
1519 { "-font", "font", XrmoptionSepArg, NULL },
1520 { "-ringBellAfterMoves", "ringBellAfterMoves", XrmoptionSepArg, NULL },
1521 { "-bell", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1522 { "-xbell", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1523 { "-movesound", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1524 { "-xmovesound", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1525 { "-autoCallFlag", "autoCallFlag", XrmoptionSepArg, NULL },
1526 { "-autoflag", "autoCallFlag", XrmoptionNoArg, "True" },
1527 { "-xautoflag", "autoCallFlag", XrmoptionNoArg, "False" },
1528 { "-autoFlipView", "autoFlipView", XrmoptionSepArg, NULL },
1529 { "-autoflip", "autoFlipView", XrmoptionNoArg, "True" },
1530 { "-xautoflip", "autoFlipView", XrmoptionNoArg, "False" },
1531 { "-autoObserve", "autoObserve", XrmoptionSepArg, NULL },
1532 { "-autobs", "autoObserve", XrmoptionNoArg, "True" },
1533 { "-xautobs", "autoObserve", XrmoptionNoArg, "False" },
1534 { "-autoComment", "autoComment", XrmoptionSepArg, NULL },
1535 { "-autocomm", "autoComment", XrmoptionNoArg, "True" },
1536 { "-xautocomm", "autoComment", XrmoptionNoArg, "False" },
1537 { "-getMoveList", "getMoveList", XrmoptionSepArg, NULL },
1538 { "-moves", "getMoveList", XrmoptionNoArg, "True" },
1539 { "-xmoves", "getMoveList", XrmoptionNoArg, "False" },
1541 { "-highlightDragging", "highlightDragging", XrmoptionSepArg, NULL },
1542 { "-highdrag", "highlightDragging", XrmoptionNoArg, "True" },
1543 { "-xhighdrag", "highlightDragging", XrmoptionNoArg, "False" },
1545 { "-highlightLastMove", "highlightLastMove", XrmoptionSepArg, NULL },
1546 { "-highlight", "highlightLastMove", XrmoptionNoArg, "True" },
1547 { "-xhighlight", "highlightLastMove", XrmoptionNoArg, "False" },
1548 { "-premove", "premove", XrmoptionSepArg, NULL },
1549 { "-pre", "premove", XrmoptionNoArg, "True" },
1550 { "-xpre", "premove", XrmoptionNoArg, "False" },
1551 { "-testLegality", "testLegality", XrmoptionSepArg, NULL },
1552 { "-legal", "testLegality", XrmoptionNoArg, "True" },
1553 { "-xlegal", "testLegality", XrmoptionNoArg, "False" },
1554 { "-flipView", "flipView", XrmoptionSepArg, NULL },
1555 { "-flip", "flipView", XrmoptionNoArg, "True" },
1556 { "-xflip", "flipView", XrmoptionNoArg, "False" },
1557 { "-cmail", "cmailGameName", XrmoptionSepArg, NULL },
1558 { "-alwaysPromoteToQueen", "alwaysPromoteToQueen",
1559 XrmoptionSepArg, NULL },
1560 { "-queen", "alwaysPromoteToQueen", XrmoptionNoArg, "True" },
1561 { "-xqueen", "alwaysPromoteToQueen", XrmoptionNoArg, "False" },
1562 { "-oldSaveStyle", "oldSaveStyle", XrmoptionSepArg, NULL },
1563 { "-oldsave", "oldSaveStyle", XrmoptionNoArg, "True" },
1564 { "-xoldsave", "oldSaveStyle", XrmoptionNoArg, "False" },
1565 { "-quietPlay", "quietPlay", XrmoptionSepArg, NULL },
1566 { "-quiet", "quietPlay", XrmoptionNoArg, "True" },
1567 { "-xquiet", "quietPlay", XrmoptionNoArg, "False" },
1568 { "-titleInWindow", "titleInWindow", XrmoptionSepArg, NULL },
1569 { "-title", "titleInWindow", XrmoptionNoArg, "True" },
1570 { "-xtitle", "titleInWindow", XrmoptionNoArg, "False" },
1572 { "-zippyTalk", "zippyTalk", XrmoptionSepArg, NULL },
1573 { "-zt", "zippyTalk", XrmoptionNoArg, "True" },
1574 { "-xzt", "zippyTalk", XrmoptionNoArg, "False" },
1575 { "-zippyPlay", "zippyPlay", XrmoptionSepArg, NULL },
1576 { "-zp", "zippyPlay", XrmoptionNoArg, "True" },
1577 { "-xzp", "zippyPlay", XrmoptionNoArg, "False" },
1578 { "-zippyLines", "zippyLines", XrmoptionSepArg, NULL },
1579 { "-zippyPinhead", "zippyPinhead", XrmoptionSepArg, NULL },
1580 { "-zippyPassword", "zippyPassword", XrmoptionSepArg, NULL },
1581 { "-zippyPassword2", "zippyPassword2", XrmoptionSepArg, NULL },
1582 { "-zippyWrongPassword", "zippyWrongPassword", XrmoptionSepArg, NULL },
1583 { "-zippyAcceptOnly", "zippyAcceptOnly", XrmoptionSepArg, NULL },
1584 { "-zippyUseI", "zippyUseI", XrmoptionSepArg, NULL },
1585 { "-zui", "zippyUseI", XrmoptionNoArg, "True" },
1586 { "-xzui", "zippyUseI", XrmoptionNoArg, "False" },
1587 { "-zippyBughouse", "zippyBughouse", XrmoptionSepArg, NULL },
1588 { "-zippyNoplayCrafty", "zippyNoplayCrafty", XrmoptionSepArg, NULL },
1589 { "-znc", "zippyNoplayCrafty", XrmoptionNoArg, "True" },
1590 { "-xznc", "zippyNoplayCrafty", XrmoptionNoArg, "False" },
1591 { "-zippyGameEnd", "zippyGameEnd", XrmoptionSepArg, NULL },
1592 { "-zippyGameStart", "zippyGameStart", XrmoptionSepArg, NULL },
1593 { "-zippyAdjourn", "zippyAdjourn", XrmoptionSepArg, NULL },
1594 { "-zadj", "zippyAdjourn", XrmoptionNoArg, "True" },
1595 { "-xzadj", "zippyAdjourn", XrmoptionNoArg, "False" },
1596 { "-zippyAbort", "zippyAbort", XrmoptionSepArg, NULL },
1597 { "-zab", "zippyAbort", XrmoptionNoArg, "True" },
1598 { "-xzab", "zippyAbort", XrmoptionNoArg, "False" },
1599 { "-zippyVariants", "zippyVariants", XrmoptionSepArg, NULL },
1600 { "-zippyMaxGames", "zippyMaxGames", XrmoptionSepArg, NULL },
1601 { "-zippyReplayTimeout", "zippyReplayTimeout", XrmoptionSepArg, NULL },
1602 { "-zippyShortGame", "zippyShortGame", XrmoptionSepArg, NULL },
1604 { "-flashCount", "flashCount", XrmoptionSepArg, NULL },
1605 { "-flash", "flashCount", XrmoptionNoArg, "3" },
1606 { "-xflash", "flashCount", XrmoptionNoArg, "0" },
1607 { "-flashRate", "flashRate", XrmoptionSepArg, NULL },
1608 { "-pixmapDirectory", "pixmapDirectory", XrmoptionSepArg, NULL },
1609 { "-msLoginDelay", "msLoginDelay", XrmoptionSepArg, NULL },
1610 { "-pixmap", "pixmapDirectory", XrmoptionSepArg, NULL },
1611 { "-colorizeMessages", "colorizeMessages", XrmoptionSepArg, NULL },
1612 { "-colorize", "colorizeMessages", XrmoptionNoArg, "True" },
1613 { "-xcolorize", "colorizeMessages", XrmoptionNoArg, "False" },
1614 { "-colorShout", "colorShout", XrmoptionSepArg, NULL },
1615 { "-colorSShout", "colorSShout", XrmoptionSepArg, NULL },
1616 { "-colorCShout", "colorSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1617 { "-colorChannel1", "colorChannel1", XrmoptionSepArg, NULL },
1618 { "-colorChannel", "colorChannel", XrmoptionSepArg, NULL },
1619 { "-colorKibitz", "colorKibitz", XrmoptionSepArg, NULL },
1620 { "-colorTell", "colorTell", XrmoptionSepArg, NULL },
1621 { "-colorChallenge", "colorChallenge", XrmoptionSepArg, NULL },
1622 { "-colorRequest", "colorRequest", XrmoptionSepArg, NULL },
1623 { "-colorSeek", "colorSeek", XrmoptionSepArg, NULL },
1624 { "-colorNormal", "colorNormal", XrmoptionSepArg, NULL },
1625 { "-soundProgram", "soundProgram", XrmoptionSepArg, NULL },
1626 { "-soundShout", "soundShout", XrmoptionSepArg, NULL },
1627 { "-soundSShout", "soundSShout", XrmoptionSepArg, NULL },
1628 { "-soundCShout", "soundSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1629 { "-soundChannel1", "soundChannel1", XrmoptionSepArg, NULL },
1630 { "-soundChannel", "soundChannel", XrmoptionSepArg, NULL },
1631 { "-soundKibitz", "soundKibitz", XrmoptionSepArg, NULL },
1632 { "-soundTell", "soundTell", XrmoptionSepArg, NULL },
1633 { "-soundChallenge", "soundChallenge", XrmoptionSepArg, NULL },
1634 { "-soundRequest", "soundRequest", XrmoptionSepArg, NULL },
1635 { "-soundSeek", "soundSeek", XrmoptionSepArg, NULL },
1636 { "-soundMove", "soundMove", XrmoptionSepArg, NULL },
1637 { "-soundIcsWin", "soundIcsWin", XrmoptionSepArg, NULL },
1638 { "-soundIcsLoss", "soundIcsLoss", XrmoptionSepArg, NULL },
1639 { "-soundIcsDraw", "soundIcsDraw", XrmoptionSepArg, NULL },
1640 { "-soundIcsUnfinished", "soundIcsUnfinished", XrmoptionSepArg, NULL },
1641 { "-soundIcsAlarm", "soundIcsAlarm", XrmoptionSepArg, NULL },
1642 { "-reuseFirst", "reuseFirst", XrmoptionSepArg, NULL },
1643 { "-reuseChessPrograms", "reuseFirst", XrmoptionSepArg, NULL }, /*compat*/
1644 { "-reuse", "reuseFirst", XrmoptionNoArg, "True" },
1645 { "-xreuse", "reuseFirst", XrmoptionNoArg, "False" },
1646 { "-reuseSecond", "reuseSecond", XrmoptionSepArg, NULL },
1647 { "-reuse2", "reuseSecond", XrmoptionNoArg, "True" },
1648 { "-xreuse2", "reuseSecond", XrmoptionNoArg, "False" },
1649 { "-animateMoving", "animateMoving", XrmoptionSepArg, NULL },
1650 { "-animate", "animateMoving", XrmoptionNoArg, "True" },
1651 { "-xanimate", "animateMoving", XrmoptionNoArg, "False" },
1652 { "-animateDragging", "animateDragging", XrmoptionSepArg, NULL },
1653 { "-drag", "animateDragging", XrmoptionNoArg, "True" },
1654 { "-xdrag", "animateDragging", XrmoptionNoArg, "False" },
1655 { "-animateSpeed", "animateSpeed", XrmoptionSepArg, NULL },
1656 { "-popupExitMessage", "popupExitMessage", XrmoptionSepArg, NULL },
1657 { "-exit", "popupExitMessage", XrmoptionNoArg, "True" },
1658 { "-xexit", "popupExitMessage", XrmoptionNoArg, "False" },
1659 { "-popupMoveErrors", "popupMoveErrors", XrmoptionSepArg, NULL },
1660 { "-popup", "popupMoveErrors", XrmoptionNoArg, "True" },
1661 { "-xpopup", "popupMoveErrors", XrmoptionNoArg, "False" },
1662 { "-fontSizeTolerance", "fontSizeTolerance", XrmoptionSepArg, NULL },
1663 { "-initialMode", "initialMode", XrmoptionSepArg, NULL },
1664 { "-mode", "initialMode", XrmoptionSepArg, NULL },
1665 { "-variant", "variant", XrmoptionSepArg, NULL },
1666 { "-firstProtocolVersion", "firstProtocolVersion", XrmoptionSepArg, NULL },
1667 { "-secondProtocolVersion","secondProtocolVersion",XrmoptionSepArg, NULL },
1668 { "-showButtonBar", "showButtonBar", XrmoptionSepArg, NULL },
1669 { "-buttons", "showButtonBar", XrmoptionNoArg, "True" },
1670 { "-xbuttons", "showButtonBar", XrmoptionNoArg, "False" },
1671 { "-lowTimeWarningColor", "lowTimeWarningColor", XrmoptionSepArg, NULL },
1672 { "-lowTimeWarning", "lowTimeWarning", XrmoptionSepArg, NULL },
1673 /* [AS,HR] New features */
1674 { "-firstScoreAbs", "firstScoreAbs", XrmoptionSepArg, NULL },
1675 { "-secondScoreAbs", "secondScoreAbs", XrmoptionSepArg, NULL },
1676 { "-pgnExtendedInfo", "pgnExtendedInfo", XrmoptionSepArg, NULL },
1677 { "-hideThinkingFromHuman", "hideThinkingFromHuman", XrmoptionSepArg, NULL },
1678 { "-adjudicateLossThreshold", "adjudicateLossThreshold", XrmoptionSepArg, NULL },
1679 { "-pgnEventHeader", "pgnEventHeader", XrmoptionSepArg, NULL },
1680 { "-firstIsUCI", "firstIsUCI", XrmoptionSepArg, NULL },
1681 { "-secondIsUCI", "secondIsUCI", XrmoptionSepArg, NULL },
1682 { "-fUCI", "firstIsUCI", XrmoptionNoArg, "True" },
1683 { "-sUCI", "secondIsUCI", XrmoptionNoArg, "True" },
1684 { "-firstHasOwnBookUCI", "firstHasOwnBookUCI", XrmoptionSepArg, NULL },
1685 { "-secondHasOwnBookUCI", "secondHasOwnBookUCI", XrmoptionSepArg, NULL },
1686 { "-fNoOwnBookUCI", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1687 { "-sNoOwnBookUCI", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1688 { "-firstXBook", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1689 { "-secondXBook", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1690 { "-polyglotDir", "polyglotDir", XrmoptionSepArg, NULL },
1691 { "-usePolyglotBook", "usePolyglotBook", XrmoptionSepArg, NULL },
1692 { "-polyglotBook", "polyglotBook", XrmoptionSepArg, NULL },
1693 { "-defaultHashSize", "defaultHashSize", XrmoptionSepArg, NULL },
1694 { "-defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XrmoptionSepArg, NULL },
1695 { "-defaultPathEGTB", "defaultPathEGTB", XrmoptionSepArg, NULL },
1696 { "-defaultFrcPosition", "defaultFrcPosition", XrmoptionSepArg, NULL },
1697 { "-gameListTags", "gameListTags", XrmoptionSepArg, NULL },
1698 // [HGM] I am sure AS added many more options, but we have to fish them out, from the list in winboard.c
1700 /* [HGM,HR] User-selectable board size */
1701 { "-boardWidth", "boardWidth", XrmoptionSepArg, NULL },
1702 { "-boardHeight", "boardHeight", XrmoptionSepArg, NULL },
1703 { "-matchPause", "matchPause", XrmoptionSepArg, NULL },
1705 /* [HGM] new arguments of 4.3.xx. All except first three are back-end options, which should work immediately */
1706 { "-holdingsSize", "holdingsSize", XrmoptionSepArg, NULL }, // requires extensive front-end changes to work
1707 { "-flipBlack", "flipBlack", XrmoptionSepArg, NULL }, // requires front-end changes to work
1708 { "-allWhite", "allWhite", XrmoptionSepArg, NULL }, // requires front-end changes to work
1709 { "-pieceToCharTable", "pieceToCharTable", XrmoptionSepArg, NULL },
1710 { "-alphaRank", "alphaRank", XrmoptionSepArg, NULL },
1711 { "-testClaims", "testClaims", XrmoptionSepArg, NULL },
1712 { "-checkMates", "checkMates", XrmoptionSepArg, NULL },
1713 { "-materialDraws", "materialDraws", XrmoptionSepArg, NULL },
1714 { "-trivialDraws", "trivialDraws", XrmoptionSepArg, NULL },
1715 { "-ruleMoves", "ruleMoves", XrmoptionSepArg, NULL },
1716 { "-repeatsToDraw", "repeatsToDraw", XrmoptionSepArg, NULL },
1717 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1718 { "-userName", "userName", XrmoptionSepArg, NULL },
1719 { "-autoKibitz", "autoKibitz", XrmoptionNoArg, "True" },
1720 { "-firstTimeOdds", "firstTimeOdds", XrmoptionSepArg, NULL },
1721 { "-secondTimeOdds", "secondTimeOdds", XrmoptionSepArg, NULL },
1722 { "-timeOddsMode", "timeOddsMode", XrmoptionSepArg, NULL },
1723 { "-firstAccumulateTC", "firstAccumulateTC", XrmoptionSepArg, NULL },
1724 { "-secondAccumulateTC", "secondAccumulateTC", XrmoptionSepArg, NULL },
1725 { "-firstNPS", "firstNPS", XrmoptionSepArg, NULL },
1726 { "-secondNPS", "secondNPS", XrmoptionSepArg, NULL },
1727 { "-serverMoves", "serverMoves", XrmoptionSepArg, NULL },
1728 { "-serverPause", "serverPause", XrmoptionSepArg, NULL },
1729 { "-suppressLoadMoves", "suppressLoadMoves", XrmoptionSepArg, NULL },
1730 { "-egtFormats", "egtFormats", XrmoptionSepArg, NULL },
1731 { "-userName", "userName", XrmoptionSepArg, NULL },
1732 { "-smpCores", "smpCores", XrmoptionSepArg, NULL },
1733 { "-sameColorGames", "sameColorGames", XrmoptionSepArg, NULL },
1734 { "-rewindIndex", "rewindIndex", XrmoptionSepArg, NULL },
1735 { "-niceEngines", "niceEngines", XrmoptionSepArg, NULL },
1736 { "-delayBeforeQuit", "delayBeforeQuit", XrmoptionSepArg, NULL },
1737 { "-delayAfterQuit", "delayAfterQuit", XrmoptionSepArg, NULL },
1738 { "-nameOfDebugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1739 { "-debugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1740 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1741 { "-noGUI", "noGUI", XrmoptionNoArg, "True" },
1742 { "-firstOptions", "firstOptions", XrmoptionSepArg, NULL },
1743 { "-secondOptions", "secondOptions", XrmoptionSepArg, NULL },
1744 { "-firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1745 { "-secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1749 XtActionsRec boardActions[] = {
1750 { "DrawPosition", DrawPositionProc },
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 },
1866 char globalTranslations[] =
1867 ":<Key>R: ResignProc() \n \
1868 :<Key>F: ToEndProc() \n \
1869 :<Key>f: ForwardProc() \n \
1870 :<Key>B: ToStartProc() \n \
1871 :<Key>b: BackwardProc() \n \
1872 :<Key>d: DrawProc() \n \
1873 :<Key>t: CallFlagProc() \n \
1874 :<Key>i: Iconify() \n \
1875 :<Key>c: Iconify() \n \
1876 :<Key>v: FlipViewProc() \n \
1877 <KeyDown>Control_L: BackwardProc() \n \
1878 <KeyUp>Control_L: ForwardProc() \n \
1879 <KeyDown>Control_R: BackwardProc() \n \
1880 <KeyUp>Control_R: ForwardProc() \n \
1881 Shift<Key>1: AskQuestionProc(\"Direct command\",\
1882 \"Send to chess program:\",,1) \n \
1883 Shift<Key>2: AskQuestionProc(\"Direct command\",\
1884 \"Send to second chess program:\",,2) \n";
1886 char boardTranslations[] =
1887 "<Btn1Down>: HandleUserMove() \n \
1888 <Btn1Up>: HandleUserMove() \n \
1889 <Btn1Motion>: AnimateUserMove() \n \
1890 Shift<Btn2Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD)\
1891 PieceMenuPopup(menuB) \n \
1892 Any<Btn2Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD) \
1893 PieceMenuPopup(menuW) \n \
1894 Shift<Btn3Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD)\
1895 PieceMenuPopup(menuW) \n \
1896 Any<Btn3Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD) \
1897 PieceMenuPopup(menuB) \n";
1899 char whiteTranslations[] = "<BtnDown>: WhiteClock()\n";
1900 char blackTranslations[] = "<BtnDown>: BlackClock()\n";
1902 char ICSInputTranslations[] =
1903 "<Key>Return: EnterKeyProc() \n";
1905 String xboardResources[] = {
1906 "*fileName*value.translations: #override\\n <Key>Return: FileNameAction()",
1907 "*question*value.translations: #override\\n <Key>Return: AskQuestionReplyAction()",
1908 "*errorpopup*translations: #override\\n <Key>Return: ErrorPopDown()",
1913 /* Max possible square size */
1914 #define MAXSQSIZE 256
1916 static int xpm_avail[MAXSQSIZE];
1918 #ifdef HAVE_DIR_STRUCT
1920 /* Extract piece size from filename */
1922 xpm_getsize(name, len, ext)
1933 if ((p=strchr(name, '.')) == NULL ||
1934 StrCaseCmp(p+1, ext) != 0)
1940 while (*p && isdigit(*p))
1947 /* Setup xpm_avail */
1949 xpm_getavail(dirname, ext)
1957 for (i=0; i<MAXSQSIZE; ++i)
1960 if (appData.debugMode)
1961 fprintf(stderr, "XPM dir:%s:ext:%s:\n", dirname, ext);
1963 dir = opendir(dirname);
1966 fprintf(stderr, _("%s: Can't access XPM directory %s\n"),
1967 programName, dirname);
1971 while ((ent=readdir(dir)) != NULL) {
1972 i = xpm_getsize(ent->d_name, NAMLEN(ent), ext);
1973 if (i > 0 && i < MAXSQSIZE)
1983 xpm_print_avail(fp, ext)
1989 fprintf(fp, _("Available `%s' sizes:\n"), ext);
1990 for (i=1; i<MAXSQSIZE; ++i) {
1996 /* Return XPM piecesize closest to size */
1998 xpm_closest_to(dirname, size, ext)
2004 int sm_diff = MAXSQSIZE;
2008 xpm_getavail(dirname, ext);
2010 if (appData.debugMode)
2011 xpm_print_avail(stderr, ext);
2013 for (i=1; i<MAXSQSIZE; ++i) {
2016 diff = (diff<0) ? -diff : diff;
2017 if (diff < sm_diff) {
2025 fprintf(stderr, _("Error: No `%s' files!\n"), ext);
2031 #else /* !HAVE_DIR_STRUCT */
2032 /* If we are on a system without a DIR struct, we can't
2033 read the directory, so we can't collect a list of
2034 filenames, etc., so we can't do any size-fitting. */
2036 xpm_closest_to(dirname, size, ext)
2041 fprintf(stderr, _("\
2042 Warning: No DIR structure found on this system --\n\
2043 Unable to autosize for XPM/XIM pieces.\n\
2044 Please report this error to frankm@hiwaay.net.\n\
2045 Include system type & operating system in message.\n"));
2048 #endif /* HAVE_DIR_STRUCT */
2050 static char *cnames[9] = { "black", "red", "green", "yellow", "blue",
2051 "magenta", "cyan", "white" };
2055 TextColors textColors[(int)NColorClasses];
2057 /* String is: "fg, bg, attr". Which is 0, 1, 2 */
2059 parse_color(str, which)
2063 char *p, buf[100], *d;
2066 if (strlen(str) > 99) /* watch bounds on buf */
2071 for (i=0; i<which; ++i) {
2078 /* Could be looking at something like:
2080 .. in which case we want to stop on a comma also */
2081 while (*p && *p != ',' && !isalpha(*p) && !isdigit(*p))
2085 return -1; /* Use default for empty field */
2088 if (which == 2 || isdigit(*p))
2091 while (*p && isalpha(*p))
2096 for (i=0; i<8; ++i) {
2097 if (!StrCaseCmp(buf, cnames[i]))
2098 return which? (i+40) : (i+30);
2100 if (!StrCaseCmp(buf, "default")) return -1;
2102 fprintf(stderr, _("%s: unrecognized color %s\n"), programName, buf);
2107 parse_cpair(cc, str)
2111 if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {
2112 fprintf(stderr, _("%s: can't parse foreground color in `%s'\n"),
2117 /* bg and attr are optional */
2118 textColors[(int)cc].bg = parse_color(str, 1);
2119 if ((textColors[(int)cc].attr = parse_color(str, 2)) < 0) {
2120 textColors[(int)cc].attr = 0;
2126 /* Arrange to catch delete-window events */
2127 Atom wm_delete_window;
2129 CatchDeleteWindow(Widget w, String procname)
2132 XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
2133 snprintf(buf, sizeof(buf), "<Message>WM_PROTOCOLS: %s() \n", procname);
2134 XtAugmentTranslations(w, XtParseTranslationTable(buf));
2140 /* this should raise the board to the top */
2141 gtk_window_present(GTK_WINDOW(GUI_Window));
2146 // eventually, all layout determining code should go into a subroutine, but until then IDSIZE remains undefined
2148 #define BoardSize int
2149 void InitDrawingSizes(BoardSize boardSize, int flags)
2150 { // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
2151 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2153 XtGeometryResult gres;
2156 // if(!formWidget) return;
2159 * Enable shell resizing.
2161 // shellArgs[0].value = (XtArgVal) &w;
2162 // shellArgs[1].value = (XtArgVal) &h;
2163 // XtGetValues(shellWidget, shellArgs, 2);
2165 // shellArgs[4].value = 2*w; shellArgs[2].value = 10;
2166 // shellArgs[5].value = 2*h; shellArgs[3].value = 10;
2167 // XtSetValues(shellWidget, &shellArgs[2], 4);
2169 // XtSetArg(args[0], XtNdefaultDistance, &sep);
2170 // XtGetValues(formWidget, args, 1);
2172 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2173 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2176 // XtSetArg(args[0], XtNwidth, boardWidth);
2177 // XtSetArg(args[1], XtNheight, boardHeight);
2178 // XtSetValues(boardWidget, args, 2);
2180 timerWidth = (boardWidth - sep) / 2;
2181 // XtSetArg(args[0], XtNwidth, timerWidth);
2182 // XtSetValues(whiteTimerWidget, args, 1);
2183 // XtSetValues(blackTimerWidget, args, 1);
2185 // XawFormDoLayout(formWidget, False);
2187 if (appData.titleInWindow) {
2189 // XtSetArg(args[i], XtNborderWidth, &bor); i++;
2190 // XtSetArg(args[i], XtNheight, &h); i++;
2191 // XtGetValues(titleWidget, args, i);
2193 w = boardWidth - 2*bor;
2195 // XtSetArg(args[0], XtNwidth, &w);
2196 // XtGetValues(menuBarWidget, args, 1);
2197 w = boardWidth - w - sep - 2*bor - 2; // WIDTH_FUDGE
2200 // gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2201 // if (gres != XtGeometryYes && appData.debugMode) {
2203 // _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2204 // programName, gres, w, h, wr, hr);
2207 if(!formWidget) return;
2209 // XawFormDoLayout(formWidget, True);
2212 * Inhibit shell resizing.
2214 shellArgs[0].value = w = (XtArgVal) boardWidth + marginW;
2215 shellArgs[1].value = h = (XtArgVal) boardHeight + marginH;
2216 shellArgs[4].value = shellArgs[2].value = w;
2217 shellArgs[5].value = shellArgs[3].value = h;
2218 // XtSetValues(shellWidget, &shellArgs[0], 6);
2220 // [HGM] pieces: tailor piece bitmaps to needs of specific variant
2223 for(i=0; i<4; i++) {
2225 for(p=0; p<=(int)WhiteKing; p++)
2226 xpmPieceBitmap[i][p] = xpmPieceBitmap2[i][p]; // defaults
2227 if(gameInfo.variant == VariantShogi) {
2228 xpmPieceBitmap[i][(int)WhiteCannon] = xpmPieceBitmap2[i][(int)WhiteKing+1];
2229 xpmPieceBitmap[i][(int)WhiteNightrider] = xpmPieceBitmap2[i][(int)WhiteKing+2];
2230 xpmPieceBitmap[i][(int)WhiteSilver] = xpmPieceBitmap2[i][(int)WhiteKing+3];
2231 xpmPieceBitmap[i][(int)WhiteGrasshopper] = xpmPieceBitmap2[i][(int)WhiteKing+4];
2232 xpmPieceBitmap[i][(int)WhiteQueen] = xpmPieceBitmap2[i][(int)WhiteLance];
2235 if(gameInfo.variant == VariantGothic) {
2236 xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteSilver];
2240 // [HGM] why are thee ximMasks used at all? the ximPieceBitmaps seem to be never used!
2241 for(p=0; p<=(int)WhiteKing; p++)
2242 ximMaskPm[p] = ximMaskPm2[p]; // defaults
2243 if(gameInfo.variant == VariantShogi) {
2244 ximMaskPm[(int)WhiteCannon] = ximMaskPm2[(int)WhiteKing+1];
2245 ximMaskPm[(int)WhiteNightrider] = ximMaskPm2[(int)WhiteKing+2];
2246 ximMaskPm[(int)WhiteSilver] = ximMaskPm2[(int)WhiteKing+3];
2247 ximMaskPm[(int)WhiteGrasshopper] = ximMaskPm2[(int)WhiteKing+4];
2248 ximMaskPm[(int)WhiteQueen] = ximMaskPm2[(int)WhiteLance];
2251 if(gameInfo.variant == VariantGothic) {
2252 ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[i][(int)WhiteSilver];
2258 for(i=0; i<2; i++) {
2260 for(p=0; p<=(int)WhiteKing; p++)
2261 pieceBitmap[i][p] = pieceBitmap2[i][p]; // defaults
2262 if(gameInfo.variant == VariantShogi) {
2263 pieceBitmap[i][(int)WhiteCannon] = pieceBitmap2[i][(int)WhiteKing+1];
2264 pieceBitmap[i][(int)WhiteNightrider] = pieceBitmap2[i][(int)WhiteKing+2];
2265 pieceBitmap[i][(int)WhiteSilver] = pieceBitmap2[i][(int)WhiteKing+3];
2266 pieceBitmap[i][(int)WhiteGrasshopper] = pieceBitmap2[i][(int)WhiteKing+4];
2267 pieceBitmap[i][(int)WhiteQueen] = pieceBitmap2[i][(int)WhiteLance];
2270 if(gameInfo.variant == VariantGothic) {
2271 pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteSilver];
2287 int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
2288 XSetWindowAttributes window_attributes;
2290 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2291 XrmValue vFrom, vTo;
2292 XtGeometryResult gres;
2295 int forceMono = False;
2298 // [HGM] before anything else, expand any indirection files amongst options
2299 char *argvCopy[1000]; // 1000 seems enough
2300 char newArgs[10000]; // holds actual characters
2303 srandom(time(0)); // [HGM] book: make random truly random
2306 for(i=0; i<argc; i++) {
2307 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2308 //fprintf(stderr, "arg %s\n", argv[i]);
2309 if(argv[i][0] != '@') argvCopy[j++] = argv[i]; else {
2311 FILE *f = fopen(argv[i]+1, "rb");
2312 if(f == NULL) { fprintf(stderr, _("ignore %s\n"), argv[i]); continue; } // do not expand non-existing
2313 argvCopy[j++] = newArgs + k; // get ready for first argument from file
2314 while((c = fgetc(f)) != EOF) { // each line of file inserts 1 argument in the list
2316 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2317 newArgs[k++] = 0; // terminate current arg
2318 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2319 argvCopy[j++] = newArgs + k; // get ready for next
2321 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2334 if(appData.debugMode,1) { // OK, appData is not initialized here yet...
2335 for(i=0; i<argc; i++) fprintf(stderr, "argv[%2d] = '%s'\n", i, argv[i]);
2341 setbuf(stdout, NULL);
2342 setbuf(stderr, NULL);
2345 programName = strrchr(argv[0], '/');
2346 if (programName == NULL)
2347 programName = argv[0];
2352 XtSetLanguageProc(NULL, NULL, NULL);
2353 bindtextdomain(PACKAGE, LOCALEDIR);
2354 textdomain(PACKAGE);
2358 XtAppInitialize(&appContext, "XBoard", shellOptions,
2359 XtNumber(shellOptions),
2360 &argc, argv, xboardResources, NULL, 0);
2362 gtk_init (&argc, &argv);
2364 /* parse glade file */
2366 builder = gtk_builder_new ();
2367 gtk_builder_add_from_file (builder, "gtk-interface.xml", NULL);
2369 GUI_Window = GTK_WIDGET (gtk_builder_get_object (builder, "MainWindow"));
2370 if(!GUI_Window) printf("Error: gtk_builder didn't work!\n");
2371 GUI_Board = GTK_WIDGET (gtk_builder_get_object (builder, "Board"));
2372 if(!GUI_Board) printf("Error: gtk_builder didn't work!\n");
2373 GUI_Whiteclock = GTK_WIDGET (gtk_builder_get_object (builder, "WhiteClock"));
2374 if(!GUI_Whiteclock) printf("Error: gtk_builder didn't work!\n");
2375 GUI_Blackclock = GTK_WIDGET (gtk_builder_get_object (builder, "BlackClock"));
2376 if(!GUI_Blackclock) printf("Error: gtk_builder didn't work!\n");
2378 gtk_builder_connect_signals (builder, NULL);
2379 // don't unref the builder, since we use it to get references to widgets
2380 // g_object_unref (G_OBJECT (builder));
2382 /* end parse glade file */
2385 fprintf(stderr, _("%s: unrecognized argument %s\n"),
2386 programName, argv[1]);
2387 fprintf(stderr, "Recognized options:\n");
2388 for(i = 0; i < XtNumber(shellOptions); i++) {
2389 j = fprintf(stderr, " %s%s", shellOptions[i].option,
2390 (shellOptions[i].argKind == XrmoptionSepArg
2392 if (i++ < XtNumber(shellOptions)) {
2393 fprintf(stderr, "%*c%s%s\n", 40 - j, ' ',
2394 shellOptions[i].option,
2395 (shellOptions[i].argKind == XrmoptionSepArg
2398 fprintf(stderr, "\n");
2404 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
2407 if (chdir(chessDir) != 0) {
2408 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
2415 if (p == NULL) p = "/tmp";
2416 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
2417 gameCopyFilename = (char*) malloc(i);
2418 gamePasteFilename = (char*) malloc(i);
2419 snprintf(gameCopyFilename,i, "%s/.xboard%05uc.pgn", p, getpid());
2420 snprintf(gamePasteFilename,i, "%s/.xboard%05up.pgn", p, getpid());
2422 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
2423 clientResources, XtNumber(clientResources),
2426 if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) {
2427 /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */
2428 if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL) {
2429 printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile);
2432 setbuf(debugFP, NULL);
2435 /* [HGM,HR] make sure board size is acceptable */
2436 if(appData.NrFiles > BOARD_SIZE ||
2437 appData.NrRanks > BOARD_SIZE )
2438 DisplayFatalError(_("Recompile with BOARD_SIZE > 12, to support this size"), 0, 2);
2441 /* This feature does not work; animation needs a rewrite */
2442 appData.highlightDragging = FALSE;
2446 xDisplay = XtDisplay(shellWidget);
2447 xScreen = DefaultScreen(xDisplay);
2448 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
2450 gameInfo.variant = StringToVariant(appData.variant);
2451 InitPosition(FALSE);
2454 * Determine boardSize
2456 gameInfo.boardWidth = gameInfo.boardHeight = 8; // [HGM] boardsize: make sure we start as 8x8
2459 // [HGM] as long as we have not created the possibility to change size while running, start with requested size
2460 gameInfo.boardWidth = appData.NrFiles > 0 ? appData.NrFiles : 8;
2461 gameInfo.boardHeight = appData.NrRanks > 0 ? appData.NrRanks : 8;
2462 gameInfo.holdingsWidth = appData.holdingsSize > 0 ? 2 : 0;
2467 InitDrawingSizes(-1, 0); // [HGM] initsize: make this into a subroutine
2469 if (isdigit(appData.boardSize[0])) {
2470 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
2471 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
2472 &fontPxlSize, &smallLayout, &tinyLayout);
2474 fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
2475 programName, appData.boardSize);
2479 /* Find some defaults; use the nearest known size */
2480 SizeDefaults *szd, *nearest;
2481 int distance = 99999;
2482 nearest = szd = sizeDefaults;
2483 while (szd->name != NULL) {
2484 if (abs(szd->squareSize - squareSize) < distance) {
2486 distance = abs(szd->squareSize - squareSize);
2487 if (distance == 0) break;
2491 if (i < 2) lineGap = nearest->lineGap;
2492 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
2493 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
2494 if (i < 5) fontPxlSize = nearest->fontPxlSize;
2495 if (i < 6) smallLayout = nearest->smallLayout;
2496 if (i < 7) tinyLayout = nearest->tinyLayout;
2499 SizeDefaults *szd = sizeDefaults;
2500 if (*appData.boardSize == NULLCHAR) {
2501 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize ||
2502 DisplayHeight(xDisplay, xScreen) < szd->minScreenSize) {
2505 if (szd->name == NULL) szd--;
2507 while (szd->name != NULL &&
2508 StrCaseCmp(szd->name, appData.boardSize) != 0) szd++;
2509 if (szd->name == NULL) {
2510 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
2511 programName, appData.boardSize);
2515 squareSize = szd->squareSize;
2516 lineGap = szd->lineGap;
2517 clockFontPxlSize = szd->clockFontPxlSize;
2518 coordFontPxlSize = szd->coordFontPxlSize;
2519 fontPxlSize = szd->fontPxlSize;
2520 smallLayout = szd->smallLayout;
2521 tinyLayout = szd->tinyLayout;
2524 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2525 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2526 if (appData.showJail == 1) {
2527 /* Jail on top and bottom */
2528 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2529 XtSetArg(boardArgs[2], XtNheight,
2530 boardHeight + 2*(lineGap + squareSize));
2531 } else if (appData.showJail == 2) {
2533 XtSetArg(boardArgs[1], XtNwidth,
2534 boardWidth + 2*(lineGap + squareSize));
2535 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2538 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2539 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2543 * Determine what fonts to use.
2545 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
2546 clockFontID = XLoadFont(xDisplay, appData.clockFont);
2547 clockFontStruct = XQueryFont(xDisplay, clockFontID);
2548 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
2549 coordFontID = XLoadFont(xDisplay, appData.coordFont);
2550 coordFontStruct = XQueryFont(xDisplay, coordFontID);
2551 appData.font = FindFont(appData.font, fontPxlSize);
2552 countFontID = XLoadFont(xDisplay, appData.coordFont); // [HGM] holdings
2553 countFontStruct = XQueryFont(xDisplay, countFontID);
2554 // appData.font = FindFont(appData.font, fontPxlSize);
2556 xdb = XtDatabase(xDisplay);
2557 XrmPutStringResource(&xdb, "*font", appData.font);
2560 * Detect if there are not enough colors available and adapt.
2562 if (DefaultDepth(xDisplay, xScreen) <= 2) {
2563 appData.monoMode = True;
2566 if (!appData.monoMode) {
2567 vFrom.addr = (caddr_t) appData.lightSquareColor;
2568 vFrom.size = strlen(appData.lightSquareColor);
2569 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2570 if (vTo.addr == NULL) {
2571 appData.monoMode = True;
2574 lightSquareColor = *(Pixel *) vTo.addr;
2577 if (!appData.monoMode) {
2578 vFrom.addr = (caddr_t) appData.darkSquareColor;
2579 vFrom.size = strlen(appData.darkSquareColor);
2580 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2581 if (vTo.addr == NULL) {
2582 appData.monoMode = True;
2585 darkSquareColor = *(Pixel *) vTo.addr;
2588 if (!appData.monoMode) {
2589 vFrom.addr = (caddr_t) appData.whitePieceColor;
2590 vFrom.size = strlen(appData.whitePieceColor);
2591 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2592 if (vTo.addr == NULL) {
2593 appData.monoMode = True;
2596 whitePieceColor = *(Pixel *) vTo.addr;
2599 if (!appData.monoMode) {
2600 vFrom.addr = (caddr_t) appData.blackPieceColor;
2601 vFrom.size = strlen(appData.blackPieceColor);
2602 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2603 if (vTo.addr == NULL) {
2604 appData.monoMode = True;
2607 blackPieceColor = *(Pixel *) vTo.addr;
2611 if (!appData.monoMode) {
2612 vFrom.addr = (caddr_t) appData.highlightSquareColor;
2613 vFrom.size = strlen(appData.highlightSquareColor);
2614 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2615 if (vTo.addr == NULL) {
2616 appData.monoMode = True;
2619 highlightSquareColor = *(Pixel *) vTo.addr;
2623 if (!appData.monoMode) {
2624 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
2625 vFrom.size = strlen(appData.premoveHighlightColor);
2626 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2627 if (vTo.addr == NULL) {
2628 appData.monoMode = True;
2631 premoveHighlightColor = *(Pixel *) vTo.addr;
2636 fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2639 if (appData.bitmapDirectory == NULL ||
2640 appData.bitmapDirectory[0] == NULLCHAR)
2641 appData.bitmapDirectory = DEF_BITMAP_DIR;
2644 if (appData.lowTimeWarning && !appData.monoMode) {
2645 vFrom.addr = (caddr_t) appData.lowTimeWarningColor;
2646 vFrom.size = strlen(appData.lowTimeWarningColor);
2647 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2648 if (vTo.addr == NULL)
2649 appData.monoMode = True;
2651 lowTimeWarningColor = *(Pixel *) vTo.addr;
2654 if (appData.monoMode && appData.debugMode) {
2655 fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2656 (unsigned long) XWhitePixel(xDisplay, xScreen),
2657 (unsigned long) XBlackPixel(xDisplay, xScreen));
2660 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
2661 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
2662 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
2663 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
2664 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
2665 parse_cpair(ColorTell, appData.colorTell) < 0 ||
2666 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
2667 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
2668 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
2669 parse_cpair(ColorNormal, appData.colorNormal) < 0)
2671 if (appData.colorize) {
2673 _("%s: can't parse color names; disabling colorization\n"),
2676 appData.colorize = FALSE;
2678 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2679 textColors[ColorNone].attr = 0;
2681 // XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2687 layoutName = "tinyLayout";
2688 } else if (smallLayout) {
2689 layoutName = "smallLayout";
2691 layoutName = "normalLayout";
2693 /* Outer layoutWidget is there only to provide a name for use in
2694 resources that depend on the layout style */
2696 XtCreateManagedWidget(layoutName, formWidgetClass, shellWidget,
2697 layoutArgs, XtNumber(layoutArgs));
2699 XtCreateManagedWidget("form", formWidgetClass, layoutWidget,
2700 formArgs, XtNumber(formArgs));
2701 XtSetArg(args[0], XtNdefaultDistance, &sep);
2702 XtGetValues(formWidget, args, 1);
2705 widgetList[j++] = menuBarWidget = CreateMenuBar(menuBar);
2706 XtSetArg(args[0], XtNtop, XtChainTop);
2707 XtSetArg(args[1], XtNbottom, XtChainTop);
2708 XtSetValues(menuBarWidget, args, 2);
2710 widgetList[j++] = whiteTimerWidget =
2711 XtCreateWidget("whiteTime", labelWidgetClass,
2712 formWidget, timerArgs, XtNumber(timerArgs));
2713 XtSetArg(args[0], XtNfont, clockFontStruct);
2714 XtSetArg(args[1], XtNtop, XtChainTop);
2715 XtSetArg(args[2], XtNbottom, XtChainTop);
2716 XtSetValues(whiteTimerWidget, args, 3);
2718 widgetList[j++] = blackTimerWidget =
2719 XtCreateWidget("blackTime", labelWidgetClass,
2720 formWidget, timerArgs, XtNumber(timerArgs));
2721 XtSetArg(args[0], XtNfont, clockFontStruct);
2722 XtSetArg(args[1], XtNtop, XtChainTop);
2723 XtSetArg(args[2], XtNbottom, XtChainTop);
2724 XtSetValues(blackTimerWidget, args, 3);
2726 if (appData.titleInWindow) {
2727 widgetList[j++] = titleWidget =
2728 XtCreateWidget("title", labelWidgetClass, formWidget,
2729 titleArgs, XtNumber(titleArgs));
2730 XtSetArg(args[0], XtNtop, XtChainTop);
2731 XtSetArg(args[1], XtNbottom, XtChainTop);
2732 XtSetValues(titleWidget, args, 2);
2735 if (appData.showButtonBar) {
2736 widgetList[j++] = buttonBarWidget = CreateButtonBar(buttonBar);
2737 XtSetArg(args[0], XtNleft, XtChainRight); // [HGM] glue to right window edge
2738 XtSetArg(args[1], XtNright, XtChainRight); // for good run-time sizing
2739 XtSetArg(args[2], XtNtop, XtChainTop);
2740 XtSetArg(args[3], XtNbottom, XtChainTop);
2741 XtSetValues(buttonBarWidget, args, 4);
2744 // widgetList[j++] = messageWidget =
2745 // XtCreateWidget("message", labelWidgetClass, formWidget,
2746 // messageArgs, XtNumber(messageArgs));
2747 // XtSetArg(args[0], XtNtop, XtChainTop);
2748 // XtSetArg(args[1], XtNbottom, XtChainTop);
2749 // XtSetValues(messageWidget, args, 2);
2751 // widgetList[j++] = boardWidget =
2752 // XtCreateWidget("board", widgetClass, formWidget, boardArgs,
2753 // XtNumber(boardArgs));
2755 // XtManageChildren(widgetList, j);
2757 // timerWidth = (boardWidth - sep) / 2;
2758 // XtSetArg(args[0], XtNwidth, timerWidth);
2759 // XtSetValues(whiteTimerWidget, args, 1);
2760 // XtSetValues(blackTimerWidget, args, 1);
2762 // XtSetArg(args[0], XtNbackground, &timerBackgroundPixel);
2763 // XtSetArg(args[1], XtNforeground, &timerForegroundPixel);
2764 // XtGetValues(whiteTimerWidget, args, 2);
2766 // if (appData.showButtonBar) {
2767 // XtSetArg(args[0], XtNbackground, &buttonBackgroundPixel);
2768 // XtSetArg(args[1], XtNforeground, &buttonForegroundPixel);
2769 // XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
2774 * gtk set properties of widgets
2777 /* set board size */
2778 gtk_widget_set_size_request(GTK_WIDGET(GUI_Board),
2779 boardWidth,boardHeight);
2781 /* end gtk set properties of widgets */
2784 * formWidget uses these constraints but they are stored
2788 // XtSetArg(args[i], XtNfromHoriz, 0); i++;
2789 // XtSetValues(menuBarWidget, args, i);
2790 // if (appData.titleInWindow) {
2791 // if (smallLayout) {
2793 // XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2794 // XtSetValues(whiteTimerWidget, args, i);
2796 // XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2797 // XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2798 // XtSetValues(blackTimerWidget, args, i);
2800 // XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2801 // XtSetArg(args[i], XtNjustify, XtJustifyLeft); i++;
2802 // XtSetValues(titleWidget, args, i);
2804 // XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2805 // XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2806 // XtSetValues(messageWidget, args, i);
2807 // if (appData.showButtonBar) {
2809 // XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2810 // XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2811 // XtSetValues(buttonBarWidget, args, i);
2815 // XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2816 // XtSetValues(whiteTimerWidget, args, i);
2818 // XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2819 // XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2820 // XtSetValues(blackTimerWidget, args, i);
2822 // XtSetArg(args[i], XtNfromHoriz, menuBarWidget); i++;
2823 // XtSetValues(titleWidget, args, i);
2825 // XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2826 // XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2827 // XtSetValues(messageWidget, args, i);
2828 // if (appData.showButtonBar) {
2830 // XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2831 // XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2832 // XtSetValues(buttonBarWidget, args, i);
2838 // XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2839 // XtSetValues(whiteTimerWidget, args, i);
2841 // XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2842 // XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2843 // XtSetValues(blackTimerWidget, args, i);
2845 // XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2846 // XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2847 // XtSetValues(messageWidget, args, i);
2848 // if (appData.showButtonBar) {
2850 // XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2851 // XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2852 // XtSetValues(buttonBarWidget, args, i);
2856 // XtSetArg(args[0], XtNfromVert, messageWidget);
2857 // XtSetArg(args[1], XtNtop, XtChainTop);
2858 // XtSetArg(args[2], XtNbottom, XtChainBottom);
2859 // XtSetArg(args[3], XtNleft, XtChainLeft);
2860 // XtSetArg(args[4], XtNright, XtChainRight);
2861 // XtSetValues(boardWidget, args, 5);
2863 // XtRealizeWidget(shellWidget);
2867 * Correct the width of the message and title widgets.
2868 * It is not known why some systems need the extra fudge term.
2869 * The value "2" is probably larger than needed.
2871 // XawFormDoLayout(formWidget, False);
2873 #define WIDTH_FUDGE 2
2875 // XtSetArg(args[i], XtNborderWidth, &bor); i++;
2876 // XtSetArg(args[i], XtNheight, &h); i++;
2877 // XtGetValues(messageWidget, args, i);
2878 if (appData.showButtonBar) {
2880 // XtSetArg(args[i], XtNwidth, &w); i++;
2881 // XtGetValues(buttonBarWidget, args, i);
2882 // w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2884 // w = boardWidth - 2*bor + 1; /*!! +1 compensates for kludge below */
2887 // gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2888 if (gres != XtGeometryYes && appData.debugMode) {
2889 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2890 programName, gres, w, h, wr, hr);
2893 /* !! Horrible hack to work around bug in XFree86 4.0.1 (X11R6.4.3) */
2894 /* The size used for the child widget in layout lags one resize behind
2895 its true size, so we resize a second time, 1 pixel smaller. Yeech! */
2897 // gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2898 if (gres != XtGeometryYes && appData.debugMode) {
2899 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2900 programName, gres, w, h, wr, hr);
2903 // XtSetArg(args[0], XtNleft, XtChainLeft); // [HGM] glue ends for good run-time sizing
2904 // XtSetArg(args[1], XtNright, XtChainRight);
2905 // XtSetValues(messageWidget, args, 2);
2907 if (appData.titleInWindow) {
2909 // XtSetArg(args[i], XtNborderWidth, &bor); i++;
2910 // XtSetArg(args[i], XtNheight, &h); i++;
2911 // XtGetValues(titleWidget, args, i);
2913 w = boardWidth - 2*bor;
2915 // XtSetArg(args[0], XtNwidth, &w);
2916 // XtGetValues(menuBarWidget, args, 1);
2917 // w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2920 // gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2921 if (gres != XtGeometryYes && appData.debugMode) {
2923 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2924 programName, gres, w, h, wr, hr);
2927 // XawFormDoLayout(formWidget, True);
2929 // xBoardWindow = XtWindow(boardWidget);
2931 // [HGM] it seems the layout code ends here, but perhaps the color stuff is size independent and would
2932 // not need to go into InitDrawingSizes().
2935 if (appData.alwaysPromoteToQueen) {
2936 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Always Queen")),TRUE);
2938 if (appData.animateDragging) {
2939 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Animate Dragging")),TRUE);
2941 if (appData.animate) {
2942 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Animate Moving")),TRUE);
2944 if (appData.autoComment) {
2945 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Comment")),TRUE);
2947 if (appData.autoCallFlag) {
2948 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Flag")),TRUE);
2950 if (appData.autoFlipView) {
2951 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Flip View")),TRUE);
2953 if (appData.autoObserve) {
2954 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Observe")),TRUE);
2956 if (appData.autoRaiseBoard) {
2957 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Raise Board")),TRUE);
2959 if (appData.autoSaveGames) {
2960 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Save")),TRUE);
2962 if (appData.saveGameFile[0] != NULLCHAR) {
2963 /* Can't turn this off from menu */
2964 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Save")),TRUE);
2965 gtk_action_set_sensitive(GTK_ACTION (gtk_builder_get_object (builder, "menuOptions.Auto Save")),FALSE);
2967 if (appData.blindfold) {
2968 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Blindfold")),TRUE);
2970 if (appData.flashCount > 0) {
2971 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Flash Moves")),TRUE);
2973 if (appData.getMoveList) {
2974 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Get Move List")),TRUE);
2977 if (appData.highlightDragging) {
2978 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Highlight Dragging")),TRUE);
2981 if (appData.highlightLastMove) {
2982 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Highlight Last Move")),TRUE);
2984 if (appData.icsAlarm) {
2985 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.ICS Alarm")),TRUE);
2987 if (appData.ringBellAfterMoves) {
2988 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Move Sound")),TRUE);
2990 if (appData.oldSaveStyle) {
2991 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Old Save Style")),TRUE);
2993 if (appData.periodicUpdates) {
2994 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Periodic Updates")),TRUE);
2996 if (appData.ponderNextMove) {
2997 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Ponder Next Move")),TRUE);
2999 if (appData.popupExitMessage) {
3000 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Popup Exit Message")),TRUE);
3002 if (appData.popupMoveErrors) {
3003 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Popup Move Errors")),TRUE);
3005 if (appData.premove) {
3006 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Premove")),TRUE);
3008 if (appData.quietPlay) {
3009 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Quit Play")),TRUE);
3011 if (appData.showCoords) {
3012 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Show Coords")),TRUE);
3014 if (appData.showThinking) {
3015 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Show Thinking")),TRUE);
3017 if (appData.testLegality) {
3018 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Test Legality")),TRUE);
3024 // ReadBitmap(&wIconPixmap, "icon_white.bm",
3025 // icon_white_bits, icon_white_width, icon_white_height);
3026 // ReadBitmap(&bIconPixmap, "icon_black.bm",
3027 // icon_black_bits, icon_black_width, icon_black_height);
3028 // iconPixmap = wIconPixmap;
3030 // XtSetArg(args[i], XtNiconPixmap, iconPixmap); i++;
3031 // XtSetValues(shellWidget, args, i);
3034 /* load square colors */
3035 SVGLightSquare = load_pixbuf("svg/LightSquare.svg",squareSize);
3036 SVGDarkSquare = load_pixbuf("svg/DarkSquare.svg",squareSize);
3037 SVGNeutralSquare = load_pixbuf("svg/NeutralSquare.svg",squareSize);
3039 /* use two icons to indicate if it is white's or black's turn */
3040 WhiteIcon = load_pixbuf("svg/icon_white.svg",0);
3041 BlackIcon = load_pixbuf("svg/icon_black.svg",0);
3042 WindowIcon = WhiteIcon;
3043 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
3045 /* do resizing to a fixed aspect ratio */
3046 GUI_SetAspectRatio(0.8);
3048 /* realize window */
3049 gtk_widget_show (GUI_Window);
3057 if (appData.animate || appData.animateDragging)
3060 // XtAugmentTranslations(formWidget,
3061 // XtParseTranslationTable(globalTranslations));
3062 // XtAugmentTranslations(boardWidget,
3063 // XtParseTranslationTable(boardTranslations));
3064 // XtAugmentTranslations(whiteTimerWidget,
3065 // XtParseTranslationTable(whiteTranslations));
3066 // XtAugmentTranslations(blackTimerWidget,
3067 // XtParseTranslationTable(blackTranslations));
3071 if (errorExitStatus == -1) {
3072 if (appData.icsActive) {
3073 /* We now wait until we see "login:" from the ICS before
3074 sending the logon script (problems with timestamp otherwise) */
3075 /*ICSInitScript();*/
3076 if (appData.icsInputBox) ICSInputBoxPopUp();
3079 signal(SIGINT, IntSigHandler);
3080 signal(SIGTERM, IntSigHandler);
3081 if (*appData.cmailGameName != NULLCHAR) {
3082 signal(SIGUSR1, CmailSigHandler);
3085 gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes()
3089 * Create a cursor for the board widget.
3090 * (This needs to be called after the window has been created to have access to board-window)
3093 BoardCursor = gdk_cursor_new(GDK_HAND2);
3094 gdk_window_set_cursor(GUI_Board->window, BoardCursor);
3095 gdk_cursor_destroy(BoardCursor);
3100 if (appData.debugMode) fclose(debugFP); // [DM] debug
3107 if (appData.icsActive && oldICSInteractionTitle != NULL) {
3108 DisplayIcsInteractionTitle(oldICSInteractionTitle);
3110 unlink(gameCopyFilename);
3111 unlink(gamePasteFilename);
3122 CmailSigHandler(sig)
3128 signal(SIGUSR1, SIG_IGN); /* suspend handler */
3130 /* Activate call-back function CmailSigHandlerCallBack() */
3131 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
3133 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
3137 CmailSigHandlerCallBack(isr, closure, message, count, error)
3145 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
3147 /**** end signal code ****/
3157 f = fopen(appData.icsLogon, "r");
3163 strcat(buf, appData.icsLogon);
3164 f = fopen(buf, "r");
3168 ProcessICSInitScript(f);
3175 EditCommentPopDown();
3186 SetMenuEnables(enab)
3191 if (!builder) return;
3192 while (enab->name != NULL) {
3193 o = gtk_builder_get_object(builder, enab->name);
3194 if(GTK_IS_WIDGET(o))
3195 gtk_widget_set_sensitive(GTK_WIDGET (o),enab->value);
3198 if(GTK_IS_ACTION(o))
3199 gtk_action_set_sensitive(GTK_ACTION (o),enab->value);
3201 DisplayError(enab->name, 0);
3207 Enables icsEnables[] = {
3208 { "menuFile.Mail Move", False },
3209 { "menuFile.Reload CMail Message", False },
3210 { "menuMode.Machine Black", False },
3211 { "menuMode.Machine White", False },
3212 { "menuMode.Analysis Mode", False },
3213 { "menuMode.Analyze File", False },
3214 { "menuMode.Two Machines", False },
3216 { "menuHelp.Hint", False },
3217 { "menuHelp.Book", False },
3218 { "menuStep.Move Now", False },
3219 { "menuOptions.Periodic Updates", False },
3220 { "menuOptions.Hide Thinking", False },
3221 { "menuOptions.Ponder Next Move", False },
3226 Enables ncpEnables[] = {
3227 { "menuFile.Mail Move", False },
3228 { "menuFile.Reload CMail Message", False },
3229 { "menuMode.Machine White", False },
3230 { "menuMode.Machine Black", False },
3231 { "menuMode.Analysis Mode", False },
3232 { "menuMode.Analyze File", False },
3233 { "menuMode.Two Machines", False },
3234 { "menuMode.ICS Client", False },
3235 { "menuMode.ICS Input Box", False },
3236 { "Action", False },
3237 { "menuStep.Revert", False },
3238 { "menuStep.Move Now", False },
3239 { "menuStep.Retract Move", False },
3240 { "menuOptions.Auto Comment", False },
3241 { "menuOptions.Auto Flag", False },
3242 { "menuOptions.Auto Flip View", False },
3243 { "menuOptions.Auto Observe", False },
3244 { "menuOptions.Auto Raise Board", False },
3245 { "menuOptions.Get Move List", False },
3246 { "menuOptions.ICS Alarm", False },
3247 { "menuOptions.Move Sound", False },
3248 { "menuOptions.Quiet Play", False },
3249 { "menuOptions.Hide Thinking", False },
3250 { "menuOptions.Periodic Updates", False },
3251 { "menuOptions.Ponder Next Move", False },
3252 { "menuHelp.Hint", False },
3253 { "menuHelp.Book", False },
3257 Enables gnuEnables[] = {
3258 { "menuMode.ICS Client", False },
3259 { "menuMode.ICS Input Box", False },
3260 { "menuAction.Accept", False },
3261 { "menuAction.Decline", False },
3262 { "menuAction.Rematch", False },
3263 { "menuAction.Adjourn", False },
3264 { "menuAction.Stop Examining", False },
3265 { "menuAction.Stop Observing", False },
3266 { "menuStep.Revert", False },
3267 { "menuOptions.Auto Comment", False },
3268 { "menuOptions.Auto Observe", False },
3269 { "menuOptions.Auto Raise Board", False },
3270 { "menuOptions.Get Move List", False },
3271 { "menuOptions.Premove", False },
3272 { "menuOptions.Quiet Play", False },
3274 /* The next two options rely on SetCmailMode being called *after* */
3275 /* SetGNUMode so that when GNU is being used to give hints these */
3276 /* menu options are still available */
3278 { "menuFile.Mail Move", False },
3279 { "menuFile.Reload CMail Message", False },
3283 Enables cmailEnables[] = {
3285 { "menuAction.Call Flag", False },
3286 { "menuAction.Draw", True },
3287 { "menuAction.Adjourn", False },
3288 { "menuAction.Abort", False },
3289 { "menuAction.Stop Observing", False },
3290 { "menuAction.Stop Examining", False },
3291 { "menuFile.Mail Move", True },
3292 { "menuFile.Reload CMail Message", True },
3296 Enables trainingOnEnables[] = {
3297 { "menuMode.Edit Comment", False },
3298 { "menuMode.Pause", False },
3299 { "menuStep.Forward", False },
3300 { "menuStep.Backward", False },
3301 { "menuStep.Forward to End", False },
3302 { "menuStep.Back to Start", False },
3303 { "menuStep.Move Now", False },
3304 { "menuStep.Truncate Game", False },
3308 Enables trainingOffEnables[] = {
3309 { "menuMode.Edit Comment", True },
3310 { "menuMode.Pause", True },
3311 { "menuStep.Forward", True },
3312 { "menuStep.Backward", True },
3313 { "menuStep.Forward to End", True },
3314 { "menuStep.Back to Start", True },
3315 { "menuStep.Move Now", True },
3316 { "menuStep.Truncate Game", True },
3320 Enables machineThinkingEnables[] = {
3321 { "menuFile.Load Game", False },
3322 { "menuFile.Load Next Game", False },
3323 { "menuFile.Load Previous Game", False },
3324 { "menuFile.Reload Same Game", False },
3325 { "menuFile.Paste Game", False },
3326 { "menuFile.Load Position", False },
3327 { "menuFile.Load Next Position", False },
3328 { "menuFile.Load Previous Position", False },
3329 { "menuFile.Reload Same Position", False },
3330 { "menuFile.Paste Position", False },
3331 { "menuMode.Machine White", False },
3332 { "menuMode.Machine Black", False },
3333 { "menuMode.Two Machines", False },
3334 { "menuStep.Retract Move", False },
3338 Enables userThinkingEnables[] = {
3339 { "menuFile.Load Game", True },
3340 { "menuFile.Load Next Game", True },
3341 { "menuFile.Load Previous Game", True },
3342 { "menuFile.Reload Same Game", True },
3343 { "menuFile.Paste Game", True },
3344 { "menuFile.Load Position", True },
3345 { "menuFile.Load Next Position", True },
3346 { "menuFile.Load Previous Position", True },
3347 { "menuFile.Reload Same Position", True },
3348 { "menuFile.Paste Position", True },
3349 { "menuMode.Machine White", True },
3350 { "menuMode.Machine Black", True },
3351 { "menuMode.Two Machines", True },
3352 { "menuStep.Retract Move", True },
3358 SetMenuEnables(icsEnables);
3361 if (appData.zippyPlay && !appData.noChessProgram) /* [DM] icsEngineAnalyze */
3362 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
3369 SetMenuEnables(ncpEnables);
3375 SetMenuEnables(gnuEnables);
3381 SetMenuEnables(cmailEnables);
3387 SetMenuEnables(trainingOnEnables);
3388 if (appData.showButtonBar) {
3389 XtSetSensitive(buttonBarWidget, False);
3395 SetTrainingModeOff()
3397 SetMenuEnables(trainingOffEnables);
3398 if (appData.showButtonBar) {
3399 XtSetSensitive(buttonBarWidget, True);
3404 SetUserThinkingEnables()
3406 if (appData.noChessProgram) return;
3407 SetMenuEnables(userThinkingEnables);
3411 SetMachineThinkingEnables()
3413 if (appData.noChessProgram) return;
3414 SetMenuEnables(machineThinkingEnables);
3416 case MachinePlaysBlack:
3417 case MachinePlaysWhite:
3418 case TwoMachinesPlay:
3419 XtSetSensitive(XtNameToWidget(menuBarWidget,
3420 ModeToWidgetName(gameMode)), True);
3427 #define Abs(n) ((n)<0 ? -(n) : (n))
3430 * Find a font that matches "pattern" that is as close as
3431 * possible to the targetPxlSize. Prefer fonts that are k
3432 * pixels smaller to fonts that are k pixels larger. The
3433 * pattern must be in the X Consortium standard format,
3434 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
3435 * The return value should be freed with XtFree when no
3438 char *FindFont(pattern, targetPxlSize)
3442 char **fonts, *p, *best, *scalable, *scalableTail;
3443 int i, j, nfonts, minerr, err, pxlSize;
3446 char **missing_list;
3448 char *def_string, *base_fnt_lst, strInt[3];
3450 XFontStruct **fnt_list;
3452 base_fnt_lst = calloc(1, strlen(pattern) + 3);
3453 sprintf(strInt, "%d", targetPxlSize);
3454 p = strstr(pattern, "--");
3455 strncpy(base_fnt_lst, pattern, p - pattern + 2);
3456 strcat(base_fnt_lst, strInt);
3457 strcat(base_fnt_lst, strchr(p + 2, '-'));
3459 if ((fntSet = XCreateFontSet(xDisplay,
3463 &def_string)) == NULL) {
3465 fprintf(stderr, _("Unable to create font set.\n"));
3469 nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
3471 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
3473 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
3474 programName, pattern);
3482 for (i=0; i<nfonts; i++) {
3485 if (*p != '-') continue;
3487 if (*p == NULLCHAR) break;
3488 if (*p++ == '-') j++;
3490 if (j < 7) continue;
3493 scalable = fonts[i];
3496 err = pxlSize - targetPxlSize;
3497 if (Abs(err) < Abs(minerr) ||
3498 (minerr > 0 && err < 0 && -err == minerr)) {
3504 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
3505 /* If the error is too big and there is a scalable font,
3506 use the scalable font. */
3507 int headlen = scalableTail - scalable;
3508 p = (char *) XtMalloc(strlen(scalable) + 10);
3509 while (isdigit(*scalableTail)) scalableTail++;
3510 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
3512 p = (char *) XtMalloc(strlen(best) + 1);
3515 if (appData.debugMode) {
3516 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
3517 pattern, targetPxlSize, p);
3520 if (missing_count > 0)
3521 XFreeStringList(missing_list);
3522 XFreeFontSet(xDisplay, fntSet);
3524 XFreeFontNames(fonts);
3531 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
3532 | GCBackground | GCFunction | GCPlaneMask;
3533 XGCValues gc_values;
3536 gc_values.plane_mask = AllPlanes;
3537 gc_values.line_width = lineGap;
3538 gc_values.line_style = LineSolid;
3539 gc_values.function = GXcopy;
3541 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3542 gc_values.background = XBlackPixel(xDisplay, xScreen);
3543 lineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3545 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3546 gc_values.background = XWhitePixel(xDisplay, xScreen);
3547 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
3548 XSetFont(xDisplay, coordGC, coordFontID);
3550 // [HGM] make font for holdings counts (white on black0
3551 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3552 gc_values.background = XBlackPixel(xDisplay, xScreen);
3553 countGC = XtGetGC(shellWidget, value_mask, &gc_values);
3554 XSetFont(xDisplay, countGC, countFontID);
3556 if (appData.monoMode) {
3557 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3558 gc_values.background = XWhitePixel(xDisplay, xScreen);
3559 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3561 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3562 gc_values.background = XBlackPixel(xDisplay, xScreen);
3563 lightSquareGC = wbPieceGC
3564 = XtGetGC(shellWidget, value_mask, &gc_values);
3566 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3567 gc_values.background = XWhitePixel(xDisplay, xScreen);
3568 darkSquareGC = bwPieceGC
3569 = XtGetGC(shellWidget, value_mask, &gc_values);
3571 if (DefaultDepth(xDisplay, xScreen) == 1) {
3572 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3573 gc_values.function = GXcopyInverted;
3574 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3575 gc_values.function = GXcopy;
3576 if (XBlackPixel(xDisplay, xScreen) == 1) {
3577 bwPieceGC = darkSquareGC;
3578 wbPieceGC = copyInvertedGC;
3580 bwPieceGC = copyInvertedGC;
3581 wbPieceGC = lightSquareGC;
3585 gc_values.foreground = highlightSquareColor;
3586 gc_values.background = highlightSquareColor;
3587 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3589 gc_values.foreground = premoveHighlightColor;
3590 gc_values.background = premoveHighlightColor;
3591 prelineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3593 gc_values.foreground = lightSquareColor;
3594 gc_values.background = darkSquareColor;
3595 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3597 gc_values.foreground = darkSquareColor;
3598 gc_values.background = lightSquareColor;
3599 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3601 gc_values.foreground = jailSquareColor;
3602 gc_values.background = jailSquareColor;
3603 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3605 gc_values.foreground = whitePieceColor;
3606 gc_values.background = darkSquareColor;
3607 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3609 gc_values.foreground = whitePieceColor;
3610 gc_values.background = lightSquareColor;
3611 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3613 gc_values.foreground = whitePieceColor;
3614 gc_values.background = jailSquareColor;
3615 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3617 gc_values.foreground = blackPieceColor;
3618 gc_values.background = darkSquareColor;
3619 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3621 gc_values.foreground = blackPieceColor;
3622 gc_values.background = lightSquareColor;
3623 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3625 gc_values.foreground = blackPieceColor;
3626 gc_values.background = jailSquareColor;
3627 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3634 WhitePawn, WhiteKnight, WhiteBishop, WhiteRook, WhiteQueen, WhiteKing,
3635 BlackPawn, BlackKnight, BlackBishop, BlackRook, BlackQueen, BlackKing,
3638 SVGpieces[WhitePawn] = load_pixbuf("svg/WhitePawn.svg",squareSize);
3639 SVGpieces[WhiteKnight] = load_pixbuf("svg/WhiteKnight.svg",squareSize);
3640 SVGpieces[WhiteBishop] = load_pixbuf("svg/WhiteBishop.svg",squareSize);
3641 SVGpieces[WhiteRook] = load_pixbuf("svg/WhiteRook.svg",squareSize);
3642 SVGpieces[WhiteQueen] = load_pixbuf("svg/WhiteQueen.svg",squareSize);
3643 SVGpieces[WhiteKing] = load_pixbuf("svg/WhiteKing.svg",squareSize);
3645 SVGpieces[BlackPawn] = load_pixbuf("svg/BlackPawn.svg",squareSize);
3646 SVGpieces[BlackKnight] = load_pixbuf("svg/BlackKnight.svg",squareSize);
3647 SVGpieces[BlackBishop] = load_pixbuf("svg/BlackBishop.svg",squareSize);
3648 SVGpieces[BlackRook] = load_pixbuf("svg/BlackRook.svg",squareSize);
3649 SVGpieces[BlackQueen] = load_pixbuf("svg/BlackQueen.svg",squareSize);
3650 SVGpieces[BlackKing] = load_pixbuf("svg/BlackKing.svg",squareSize);
3660 if (lineGap == 0) return;
3662 /* [HR] Split this into 2 loops for non-square boards. */
3664 for (i = 0; i < BOARD_HEIGHT + 1; i++) {
3665 gridSegments[i].x1 = 0;
3666 gridSegments[i].x2 =
3667 lineGap + BOARD_WIDTH * (squareSize + lineGap);
3668 gridSegments[i].y1 = gridSegments[i].y2
3669 = lineGap / 2 + (i * (squareSize + lineGap));
3672 for (j = 0; j < BOARD_WIDTH + 1; j++) {
3673 gridSegments[j + i].y1 = 0;
3674 gridSegments[j + i].y2 =
3675 lineGap + BOARD_HEIGHT * (squareSize + lineGap);
3676 gridSegments[j + i].x1 = gridSegments[j + i].x2
3677 = lineGap / 2 + (j * (squareSize + lineGap));
3681 static void MenuBarSelect(w, addr, index)
3686 XtActionProc proc = (XtActionProc) addr;
3688 (proc)(NULL, NULL, NULL, NULL);
3691 void CreateMenuBarPopup(parent, name, mb)
3701 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3704 XtSetArg(args[j], XtNleftMargin, 20); j++;
3705 XtSetArg(args[j], XtNrightMargin, 20); j++;
3707 while (mi->string != NULL) {
3708 if (strcmp(mi->string, "----") == 0) {
3709 entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
3712 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string)));
3713 entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass,
3715 XtAddCallback(entry, XtNcallback,
3716 (XtCallbackProc) MenuBarSelect,
3717 (caddr_t) mi->proc);
3723 Widget CreateMenuBar(mb)
3727 Widget anchor, menuBar;
3729 char menuName[MSG_SIZ];
3732 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3733 XtSetArg(args[j], XtNvSpace, 0); j++;
3734 XtSetArg(args[j], XtNborderWidth, 0); j++;
3735 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
3736 formWidget, args, j);
3738 while (mb->name != NULL) {
3739 strcpy(menuName, "menu");
3740 strcat(menuName, mb->name);
3742 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
3745 shortName[0] = _(mb->name)[0];
3746 shortName[1] = NULLCHAR;
3747 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
3750 XtSetArg(args[j], XtNlabel, XtNewString(_(mb->name))); j++;
3753 XtSetArg(args[j], XtNborderWidth, 0); j++;
3754 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
3756 CreateMenuBarPopup(menuBar, menuName, mb);
3762 Widget CreateButtonBar(mi)
3766 Widget button, buttonBar;
3770 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3772 XtSetArg(args[j], XtNhSpace, 0); j++;
3774 XtSetArg(args[j], XtNborderWidth, 0); j++;
3775 XtSetArg(args[j], XtNvSpace, 0); j++;
3776 buttonBar = XtCreateWidget("buttonBar", boxWidgetClass,
3777 formWidget, args, j);
3779 while (mi->string != NULL) {
3782 XtSetArg(args[j], XtNinternalWidth, 2); j++;
3783 XtSetArg(args[j], XtNborderWidth, 0); j++;
3785 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string))); j++;
3786 button = XtCreateManagedWidget(mi->string, commandWidgetClass,
3787 buttonBar, args, j);
3788 XtAddCallback(button, XtNcallback,
3789 (XtCallbackProc) MenuBarSelect,
3790 (caddr_t) mi->proc);
3797 CreatePieceMenu(name, color)
3804 ChessSquare selection;
3806 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3807 boardWidget, args, 0);
3809 for (i = 0; i < PIECE_MENU_SIZE; i++) {
3810 String item = pieceMenuStrings[color][i];
3812 if (strcmp(item, "----") == 0) {
3813 entry = XtCreateManagedWidget(item, smeLineObjectClass,
3816 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3817 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3819 selection = pieceMenuTranslation[color][i];
3820 XtAddCallback(entry, XtNcallback,
3821 (XtCallbackProc) PieceMenuSelect,
3822 (caddr_t) selection);
3823 if (selection == WhitePawn || selection == BlackPawn) {
3824 XtSetArg(args[0], XtNpopupOnEntry, entry);
3825 XtSetValues(menu, args, 1);
3838 ChessSquare selection;
3840 // whitePieceMenu = CreatePieceMenu("menuW", 0);
3841 // blackPieceMenu = CreatePieceMenu("menuB", 1);
3843 // XtRegisterGrabAction(PieceMenuPopup, True,
3844 // (unsigned)(ButtonPressMask|ButtonReleaseMask),
3845 // GrabModeAsync, GrabModeAsync);
3847 // XtSetArg(args[0], XtNlabel, _("Drop"));
3848 // dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
3849 // boardWidget, args, 1);
3850 // for (i = 0; i < DROP_MENU_SIZE; i++) {
3851 // String item = dropMenuStrings[i];
3853 // if (strcmp(item, "----") == 0) {
3854 // entry = XtCreateManagedWidget(item, smeLineObjectClass,
3855 // dropMenu, NULL, 0);
3857 // XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3858 // entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3859 // dropMenu, args, 1);
3860 // selection = dropMenuTranslation[i];
3861 // XtAddCallback(entry, XtNcallback,
3862 // (XtCallbackProc) DropMenuSelect,
3863 // (caddr_t) selection);
3868 void SetupDropMenu()
3876 for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
3877 entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
3878 p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
3879 dmEnables[i].piece);
3880 XtSetSensitive(entry, p != NULL || !appData.testLegality
3881 /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
3882 && !appData.icsActive));
3884 while (p && *p++ == dmEnables[i].piece) count++;
3885 snprintf(label, sizeof(label), "%s %d", dmEnables[i].widget, count);
3887 XtSetArg(args[j], XtNlabel, label); j++;
3888 XtSetValues(entry, args, j);
3892 void PieceMenuPopup(w, event, params, num_params)
3896 Cardinal *num_params;
3899 if (event->type != ButtonPress) return;
3900 if (errorUp) ErrorPopDown();
3904 whichMenu = params[0];
3906 case IcsPlayingWhite:
3907 case IcsPlayingBlack:
3909 case MachinePlaysWhite:
3910 case MachinePlaysBlack:
3911 if (appData.testLegality &&
3912 gameInfo.variant != VariantBughouse &&
3913 gameInfo.variant != VariantCrazyhouse) return;
3915 whichMenu = "menuD";
3921 if (((pmFromX = EventToSquare(event->xbutton.x, BOARD_WIDTH)) < 0) ||
3922 ((pmFromY = EventToSquare(event->xbutton.y, BOARD_HEIGHT)) < 0)) {
3923 pmFromX = pmFromY = -1;
3927 pmFromX = BOARD_WIDTH - 1 - pmFromX;
3929 pmFromY = BOARD_HEIGHT - 1 - pmFromY;
3931 XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
3934 static void PieceMenuSelect(w, piece, junk)
3939 if (pmFromX < 0 || pmFromY < 0) return;
3940 EditPositionMenuEvent(piece, pmFromX, pmFromY);
3943 static void DropMenuSelect(w, piece, junk)
3948 if (pmFromX < 0 || pmFromY < 0) return;
3949 DropMenuEvent(piece, pmFromX, pmFromY);
3952 void WhiteClock(w, event, prms, nprms)
3958 if (gameMode == EditPosition || gameMode == IcsExamining) {
3959 SetWhiteToPlayEvent();
3960 } else if (gameMode == IcsPlayingBlack || gameMode == MachinePlaysWhite) {
3965 void BlackClock(w, event, prms, nprms)
3971 if (gameMode == EditPosition || gameMode == IcsExamining) {
3972 SetBlackToPlayEvent();
3973 } else if (gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) {
3980 * If the user selects on a border boundary, return -1; if off the board,
3981 * return -2. Otherwise map the event coordinate to the square.
3983 int EventToSquare(x, limit)
3991 if ((x % (squareSize + lineGap)) >= squareSize)
3993 x /= (squareSize + lineGap);
3999 static void do_flash_delay(msec)
4005 static void drawHighlight(file, rank, gc)
4011 if (lineGap == 0 || appData.blindfold) return;
4014 x = lineGap/2 + ((BOARD_WIDTH-1)-file) *
4015 (squareSize + lineGap);
4016 y = lineGap/2 + rank * (squareSize + lineGap);
4018 x = lineGap/2 + file * (squareSize + lineGap);
4019 y = lineGap/2 + ((BOARD_HEIGHT-1)-rank) *
4020 (squareSize + lineGap);
4023 XDrawRectangle(xDisplay, xBoardWindow, gc, x, y,
4024 squareSize+lineGap, squareSize+lineGap);
4027 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
4028 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
4031 SetHighlights(fromX, fromY, toX, toY)
4032 int fromX, fromY, toX, toY;
4034 if (hi1X != fromX || hi1Y != fromY) {
4035 if (hi1X >= 0 && hi1Y >= 0) {
4036 drawHighlight(hi1X, hi1Y, lineGC);
4038 if (fromX >= 0 && fromY >= 0) {
4039 drawHighlight(fromX, fromY, highlineGC);
4042 if (hi2X != toX || hi2Y != toY) {
4043 if (hi2X >= 0 && hi2Y >= 0) {
4044 drawHighlight(hi2X, hi2Y, lineGC);
4046 if (toX >= 0 && toY >= 0) {
4047 drawHighlight(toX, toY, highlineGC);
4059 SetHighlights(-1, -1, -1, -1);
4064 SetPremoveHighlights(fromX, fromY, toX, toY)
4065 int fromX, fromY, toX, toY;
4067 if (pm1X != fromX || pm1Y != fromY) {
4068 if (pm1X >= 0 && pm1Y >= 0) {
4069 drawHighlight(pm1X, pm1Y, lineGC);
4071 if (fromX >= 0 && fromY >= 0) {
4072 drawHighlight(fromX, fromY, prelineGC);
4075 if (pm2X != toX || pm2Y != toY) {
4076 if (pm2X >= 0 && pm2Y >= 0) {
4077 drawHighlight(pm2X, pm2Y, lineGC);
4079 if (toX >= 0 && toY >= 0) {
4080 drawHighlight(toX, toY, prelineGC);
4090 ClearPremoveHighlights()
4092 SetPremoveHighlights(-1, -1, -1, -1);
4095 static void BlankSquare(x, y, color, piece, dest)
4100 if (useImages && useImageSqs) {
4104 pb = SVGLightSquare;
4109 case 2: /* neutral */
4111 pb = SVGNeutralSquare;
4114 gdk_draw_pixbuf(GDK_WINDOW(GUI_Board->window),NULL,pb,0,0,x,y,-1,-1, GDK_RGB_DITHER_NORMAL, 0, 0);
4119 gc = gdk_gc_new(GDK_WINDOW(GUI_Board->window));
4123 // gc = lightSquareGC;
4127 gdk_gc_set_rgb_fg_color(gc, &tmp);
4130 // gc = darkSquareGC;
4134 gdk_gc_set_rgb_fg_color(gc, &tmp);
4136 case 2: /* neutral */
4138 // gc = jailSquareGC;
4142 gdk_gc_set_rgb_fg_color(gc, &tmp);
4145 gdk_draw_rectangle(GDK_WINDOW(GUI_Board->window),gc,1,x,y,squareSize,squareSize);
4151 I split out the routines to draw a piece so that I could
4152 make a generic flash routine.
4154 static void monoDrawPiece_1bit(piece, square_color, x, y, dest)
4156 int square_color, x, y;
4159 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
4160 switch (square_color) {
4162 case 2: /* neutral */
4164 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4165 ? *pieceToOutline(piece)
4166 : *pieceToSolid(piece),
4167 dest, bwPieceGC, 0, 0,
4168 squareSize, squareSize, x, y);
4171 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4172 ? *pieceToSolid(piece)
4173 : *pieceToOutline(piece),
4174 dest, wbPieceGC, 0, 0,
4175 squareSize, squareSize, x, y);
4180 static void monoDrawPiece(piece, square_color, x, y, dest)
4182 int square_color, x, y;
4185 switch (square_color) {
4187 case 2: /* neutral */
4189 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4190 ? *pieceToOutline(piece)
4191 : *pieceToSolid(piece),
4192 dest, bwPieceGC, 0, 0,
4193 squareSize, squareSize, x, y, 1);
4196 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4197 ? *pieceToSolid(piece)
4198 : *pieceToOutline(piece),
4199 dest, wbPieceGC, 0, 0,
4200 squareSize, squareSize, x, y, 1);
4205 static void colorDrawPiece(piece, square_color, x, y, dest)
4207 int square_color, x, y;
4210 gdk_draw_pixbuf(GDK_WINDOW(GUI_Board->window),NULL,GDK_PIXBUF(SVGpieces[piece]),0,0,x,y,-1,-1, GDK_RGB_DITHER_NORMAL, 0, 0);
4213 // if(pieceToSolid(piece) == NULL) return; // [HGM] bitmaps: make it non-fatal if we have no bitmap;
4214 // switch (square_color) {
4215 // case 1: /* light */
4216 // XCopyPlane(xDisplay, *pieceToSolid(piece),
4217 // dest, (int) piece < (int) BlackPawn
4218 // ? wlPieceGC : blPieceGC, 0, 0,
4219 // squareSize, squareSize, x, y, 1);
4221 // case 0: /* dark */
4222 // XCopyPlane(xDisplay, *pieceToSolid(piece),
4223 // dest, (int) piece < (int) BlackPawn
4224 // ? wdPieceGC : bdPieceGC, 0, 0,
4225 // squareSize, squareSize, x, y, 1);
4227 // case 2: /* neutral */
4229 // XCopyPlane(xDisplay, *pieceToSolid(piece),
4230 // dest, (int) piece < (int) BlackPawn
4231 // ? wjPieceGC : bjPieceGC, 0, 0,
4232 // squareSize, squareSize, x, y, 1);
4237 static void colorDrawPieceImage(piece, square_color, x, y, dest)
4239 int square_color, x, y;
4244 switch (square_color) {
4246 case 2: /* neutral */
4248 if ((int)piece < (int) BlackPawn) {
4256 if ((int)piece < (int) BlackPawn) {
4264 XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
4265 dest, wlPieceGC, 0, 0,
4266 squareSize, squareSize, x, y);
4269 typedef void (*DrawFunc)();
4271 DrawFunc ChooseDrawFunc()
4273 if (appData.monoMode) {
4274 if (DefaultDepth(xDisplay, xScreen) == 1) {
4275 return monoDrawPiece_1bit;
4277 return monoDrawPiece;
4281 return colorDrawPieceImage;
4283 return colorDrawPiece;
4287 /* [HR] determine square color depending on chess variant. */
4288 static int SquareColor(row, column)
4293 if (gameInfo.variant == VariantXiangqi) {
4294 if (column >= 3 && column <= 5 && row >= 0 && row <= 2) {
4296 } else if (column >= 3 && column <= 5 && row >= 7 && row <= 9) {
4298 } else if (row <= 4) {
4304 square_color = ((column + row) % 2) == 1;
4307 /* [hgm] holdings: next line makes all holdings squares light */
4308 if(column < BOARD_LEFT || column >= BOARD_RGHT) square_color = 1;
4310 return square_color;
4313 void DrawSquare(row, column, piece, do_flash)
4314 int row, column, do_flash;
4317 int square_color, x, y, direction, font_ascent, font_descent;
4320 XCharStruct overall;
4324 /* Calculate delay in milliseconds (2-delays per complete flash) */
4325 flash_delay = 500 / appData.flashRate;
4327 /* calculate x and y coordinates from row and column */
4329 x = lineGap + ((BOARD_WIDTH-1)-column) *
4330 (squareSize + lineGap);
4331 y = lineGap + row * (squareSize + lineGap);
4333 x = lineGap + column * (squareSize + lineGap);
4334 y = lineGap + ((BOARD_HEIGHT-1)-row) *
4335 (squareSize + lineGap);
4338 square_color = SquareColor(row, column);
4340 if ( // [HGM] holdings: blank out area between board and holdings
4341 column == BOARD_LEFT-1 || column == BOARD_RGHT
4342 || (column == BOARD_LEFT-2 && row < BOARD_HEIGHT-gameInfo.holdingsSize)
4343 || (column == BOARD_RGHT+1 && row >= gameInfo.holdingsSize) ) {
4344 BlankSquare(x, y, 2, EmptySquare, xBoardWindow);
4346 // [HGM] print piece counts next to holdings
4347 string[1] = NULLCHAR;
4348 if (column == (flipView ? BOARD_LEFT-1 : BOARD_RGHT) && piece > 1 ) {
4349 string[0] = '0' + piece;
4350 XTextExtents(countFontStruct, string, 1, &direction,
4351 &font_ascent, &font_descent, &overall);
4352 if (appData.monoMode) {
4353 XDrawImageString(xDisplay, xBoardWindow, countGC,
4354 x + squareSize - overall.width - 2,
4355 y + font_ascent + 1, string, 1);
4357 XDrawString(xDisplay, xBoardWindow, countGC,
4358 x + squareSize - overall.width - 2,
4359 y + font_ascent + 1, string, 1);
4362 if (column == (flipView ? BOARD_RGHT : BOARD_LEFT-1) && piece > 1) {
4363 string[0] = '0' + piece;
4364 XTextExtents(countFontStruct, string, 1, &direction,
4365 &font_ascent, &font_descent, &overall);
4366 if (appData.monoMode) {
4367 XDrawImageString(xDisplay, xBoardWindow, countGC,
4368 x + 2, y + font_ascent + 1, string, 1);
4370 XDrawString(xDisplay, xBoardWindow, countGC,
4371 x + 2, y + font_ascent + 1, string, 1);
4375 if (piece == EmptySquare || appData.blindfold) {
4376 BlankSquare(x, y, square_color, piece, xBoardWindow);
4378 drawfunc = ChooseDrawFunc();
4379 if (do_flash && appData.flashCount > 0) {
4380 for (i=0; i<appData.flashCount; ++i) {
4382 drawfunc(piece, square_color, x, y, xBoardWindow);
4383 XSync(xDisplay, False);
4384 do_flash_delay(flash_delay);
4386 BlankSquare(x, y, square_color, piece, xBoardWindow);
4387 XSync(xDisplay, False);
4388 do_flash_delay(flash_delay);
4391 drawfunc(piece, square_color, x, y, xBoardWindow);
4395 string[1] = NULLCHAR;
4396 if (appData.showCoords && row == (flipView ? BOARD_HEIGHT-1 : 0)
4397 && column >= BOARD_LEFT && column < BOARD_RGHT) {
4398 string[0] = 'a' + column - BOARD_LEFT;
4399 XTextExtents(coordFontStruct, string, 1, &direction,
4400 &font_ascent, &font_descent, &overall);
4401 if (appData.monoMode) {
4402 XDrawImageString(xDisplay, xBoardWindow, coordGC,
4403 x + squareSize - overall.width - 2,
4404 y + squareSize - font_descent - 1, string, 1);
4406 XDrawString(xDisplay, xBoardWindow, coordGC,
4407 x + squareSize - overall.width - 2,
4408 y + squareSize - font_descent - 1, string, 1);
4411 if (appData.showCoords && column == (flipView ? BOARD_RGHT-1 : BOARD_LEFT)) {
4412 string[0] = ONE + row;
4413 XTextExtents(coordFontStruct, string, 1, &direction,
4414 &font_ascent, &font_descent, &overall);
4415 if (appData.monoMode) {
4416 XDrawImageString(xDisplay, xBoardWindow, coordGC,
4417 x + 2, y + font_ascent + 1, string, 1);
4419 XDrawString(xDisplay, xBoardWindow, coordGC,
4420 x + 2, y + font_ascent + 1, string, 1);
4426 /* Returns 1 if there are "too many" differences between b1 and b2
4427 (i.e. more than 1 move was made) */
4428 static int too_many_diffs(b1, b2)
4434 for (i=0; i<BOARD_HEIGHT; ++i) {
4435 for (j=0; j<BOARD_WIDTH; ++j) {
4436 if (b1[i][j] != b2[i][j]) {
4437 if (++c > 4) /* Castling causes 4 diffs */
4446 /* Matrix describing castling maneuvers */
4447 /* Row, ColRookFrom, ColKingFrom, ColRookTo, ColKingTo */
4448 static int castling_matrix[4][5] = {
4449 { 0, 0, 4, 3, 2 }, /* 0-0-0, white */
4450 { 0, 7, 4, 5, 6 }, /* 0-0, white */
4451 { 7, 0, 4, 3, 2 }, /* 0-0-0, black */
4452 { 7, 7, 4, 5, 6 } /* 0-0, black */
4455 /* Checks whether castling occurred. If it did, *rrow and *rcol
4456 are set to the destination (row,col) of the rook that moved.
4458 Returns 1 if castling occurred, 0 if not.
4460 Note: Only handles a max of 1 castling move, so be sure
4461 to call too_many_diffs() first.
4463 static int check_castle_draw(newb, oldb, rrow, rcol)
4470 /* For each type of castling... */
4471 for (i=0; i<4; ++i) {
4472 r = castling_matrix[i];
4474 /* Check the 4 squares involved in the castling move */
4476 for (j=1; j<=4; ++j) {
4477 if (newb[r[0]][r[j]] == oldb[r[0]][r[j]]) {
4484 /* All 4 changed, so it must be a castling move */
4493 static int damage[BOARD_SIZE][BOARD_SIZE];
4496 * event handler for redrawing the board
4498 void DrawPosition( repaint, board)
4499 /*Boolean*/int repaint;
4503 static int lastFlipView = 0;
4504 static int lastBoardValid = 0;
4505 static Board lastBoard;
4509 if (board == NULL) {
4510 if (!lastBoardValid) return;
4513 if (!lastBoardValid || lastFlipView != flipView) {
4514 XtSetArg(args[0], XtNleftBitmap, (flipView ? xMarkPixmap : None));
4515 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flip View"),
4520 * It would be simpler to clear the window with XClearWindow()
4521 * but this causes a very distracting flicker.
4524 if (!repaint && lastBoardValid && lastFlipView == flipView) {
4525 /* If too much changes (begin observing new game, etc.), don't
4527 do_flash = too_many_diffs(board, lastBoard) ? 0 : 1;
4529 /* Special check for castling so we don't flash both the king
4530 and the rook (just flash the king). */
4532 if (check_castle_draw(board, lastBoard, &rrow, &rcol)) {
4533 /* Draw rook with NO flashing. King will be drawn flashing later */
4534 DrawSquare(rrow, rcol, board[rrow][rcol], 0);
4535 lastBoard[rrow][rcol] = board[rrow][rcol];
4539 /* First pass -- Draw (newly) empty squares and repair damage.
4540 This prevents you from having a piece show up twice while it
4541 is flashing on its new square */
4542 for (i = 0; i < BOARD_HEIGHT; i++)
4543 for (j = 0; j < BOARD_WIDTH; j++)
4544 if ((board[i][j] != lastBoard[i][j] && board[i][j] == EmptySquare)
4546 DrawSquare(i, j, board[i][j], 0);
4547 damage[i][j] = False;
4550 /* Second pass -- Draw piece(s) in new position and flash them */
4551 for (i = 0; i < BOARD_HEIGHT; i++)
4552 for (j = 0; j < BOARD_WIDTH; j++)
4553 if (board[i][j] != lastBoard[i][j]) {
4554 DrawSquare(i, j, board[i][j], do_flash);
4559 /* todo move GC to setupgc */
4560 GdkGC *gtklineGC=NULL;
4563 gtklineGC = gdk_gc_new(GDK_WINDOW(GUI_Board->window));
4568 gdk_gc_set_rgb_fg_color(gtklineGC, &tmp);
4573 gdk_gc_set_rgb_bg_color(gtklineGC, &tmp);
4575 gdk_draw_segments(GUI_Board->window,gtklineGC,
4576 gridSegments, BOARD_HEIGHT + BOARD_WIDTH + 2 );
4580 for (i = 0; i < BOARD_HEIGHT; i++)
4581 for (j = 0; j < BOARD_WIDTH; j++) {
4582 DrawSquare(i, j, board[i][j], 0);
4583 damage[i][j] = False;
4587 CopyBoard(lastBoard, board);
4589 lastFlipView = flipView;
4591 /* Draw highlights */
4592 if (pm1X >= 0 && pm1Y >= 0) {
4593 drawHighlight(pm1X, pm1Y, prelineGC);
4595 if (pm2X >= 0 && pm2Y >= 0) {
4596 drawHighlight(pm2X, pm2Y, prelineGC);
4598 if (hi1X >= 0 && hi1Y >= 0) {
4599 drawHighlight(hi1X, hi1Y, highlineGC);
4601 if (hi2X >= 0 && hi2Y >= 0) {
4602 drawHighlight(hi2X, hi2Y, highlineGC);
4605 /* If piece being dragged around board, must redraw that too */
4608 // XSync(xDisplay, False);
4613 * event handler for redrawing the board
4615 void DrawPositionProc(w, event, prms, nprms)
4621 DrawPosition(True, NULL);
4626 * event handler for parsing user moves
4628 // [HGM] This routine will need quite some reworking. Although the backend still supports the old
4629 // way of doing things, by calling UserMoveEvent() to test the legality of the move and then perform
4630 // it at the end, and doing all kind of preliminary tests here (e.g. to weed out self-captures), it
4631 // should be made to use the new way, of calling UserMoveTest early to determine the legality of the
4632 // move, (which will weed out the illegal selfcaptures and moves into the holdings, and flag promotions),
4633 // and at the end FinishMove() to perform the move after optional promotion popups.
4634 // For now I patched it to allow self-capture with King, and suppress clicks between board and holdings.
4635 void HandleUserMove(w, event, prms, nprms)
4642 Boolean saveAnimate;
4643 static int second = 0;
4645 if (w != boardWidget || errorExitStatus != -1) return;
4647 if (event->type == ButtonPress) ErrorPopDown();
4650 if (event->type == ButtonPress) {
4651 XtPopdown(promotionShell);
4652 XtDestroyWidget(promotionShell);
4653 promotionUp = False;
4661 x = EventToSquare(event->xbutton.x, BOARD_WIDTH);
4662 y = EventToSquare(event->xbutton.y, BOARD_HEIGHT);
4663 if (!flipView && y >= 0) {
4664 y = BOARD_HEIGHT - 1 - y;
4666 if (flipView && x >= 0) {
4667 x = BOARD_WIDTH - 1 - x;
4670 /* [HGM] holdings: next 5 lines: ignore all clicks between board and holdings */
4671 if(event->type == ButtonPress
4672 && ( x == BOARD_LEFT-1 || x == BOARD_RGHT
4673 || x == BOARD_LEFT-2 && y < BOARD_HEIGHT-gameInfo.holdingsSize
4674 || x == BOARD_RGHT+1 && y >= gameInfo.holdingsSize) )
4678 if (event->type == ButtonPress) {
4680 if (OKToStartUserMove(x, y)) {
4684 DragPieceBegin(event->xbutton.x, event->xbutton.y);
4685 if (appData.highlightDragging) {
4686 SetHighlights(x, y, -1, -1);
4694 if (event->type == ButtonPress && gameMode != EditPosition &&
4699 /* Check if clicking again on the same color piece */
4700 fromP = boards[currentMove][fromY][fromX];
4701 toP = boards[currentMove][y][x];
4702 if ((WhitePawn <= fromP && fromP < WhiteKing && // [HGM] this test should go, as UserMoveTest now does it.
4703 WhitePawn <= toP && toP <= WhiteKing) || // For now I made it less critical by exempting King
4704 (BlackPawn <= fromP && fromP < BlackKing && // moves, to not interfere with FRC castlings.
4705 BlackPawn <= toP && toP <= BlackKing)) {
4706 /* Clicked again on same color piece -- changed his mind */
4707 second = (x == fromX && y == fromY);
4708 if (appData.highlightDragging) {
4709 SetHighlights(x, y, -1, -1);
4713 if (OKToStartUserMove(x, y)) {
4716 DragPieceBegin(event->xbutton.x, event->xbutton.y);
4722 if (event->type == ButtonRelease && x == fromX && y == fromY) {
4723 DragPieceEnd(event->xbutton.x, event->xbutton.y);
4724 if (appData.animateDragging) {
4725 /* Undo animation damage if any */
4726 DrawPosition(FALSE, NULL);
4729 /* Second up/down in same square; just abort move */
4734 ClearPremoveHighlights();
4736 /* First upclick in same square; start click-click mode */
4737 SetHighlights(x, y, -1, -1);
4742 /* Completed move */
4745 saveAnimate = appData.animate;
4746 if (event->type == ButtonPress) {
4747 /* Finish clickclick move */
4748 if (appData.animate || appData.highlightLastMove) {
4749 SetHighlights(fromX, fromY, toX, toY);
4754 /* Finish drag move */
4755 if (appData.highlightLastMove) {
4756 SetHighlights(fromX, fromY, toX, toY);
4760 DragPieceEnd(event->xbutton.x, event->xbutton.y);
4761 /* Don't animate move and drag both */
4762 appData.animate = FALSE;
4764 if (IsPromotion(fromX, fromY, toX, toY)) {
4765 if (appData.alwaysPromoteToQueen) {
4766 UserMoveEvent(fromX, fromY, toX, toY, 'q');
4767 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
4768 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
4771 SetHighlights(fromX, fromY, toX, toY);
4775 UserMoveEvent(fromX, fromY, toX, toY, NULLCHAR);
4776 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
4777 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
4780 appData.animate = saveAnimate;
4781 if (appData.animate || appData.animateDragging) {
4782 /* Undo animation damage if needed */
4783 DrawPosition(FALSE, NULL);
4787 void AnimateUserMove (Widget w, XEvent * event,
4788 String * params, Cardinal * nParams)
4790 DragPieceMove(event->xmotion.x, event->xmotion.y);
4793 Widget CommentCreate(name, text, mutable, callback, lines)
4795 int /*Boolean*/ mutable;
4796 XtCallbackProc callback;
4800 Widget shell, layout, form, edit, b_ok, b_cancel, b_clear, b_close, b_edit;
4805 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4806 XtGetValues(boardWidget, args, j);
4809 XtSetArg(args[j], XtNresizable, True); j++;
4812 XtCreatePopupShell(name, topLevelShellWidgetClass,
4813 shellWidget, args, j);
4816 XtCreatePopupShell(name, transientShellWidgetClass,
4817 shellWidget, args, j);
4820 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
4821 layoutArgs, XtNumber(layoutArgs));
4823 XtCreateManagedWidget("form", formWidgetClass, layout,
4824 formArgs, XtNumber(formArgs));
4828 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
4829 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
4831 XtSetArg(args[j], XtNstring, text); j++;
4832 XtSetArg(args[j], XtNtop, XtChainTop); j++;
4833 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4834 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4835 XtSetArg(args[j], XtNright, XtChainRight); j++;
4836 XtSetArg(args[j], XtNresizable, True); j++;
4837 XtSetArg(args[j], XtNwidth, bw_width); j++; /*force wider than buttons*/
4839 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
4841 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
4842 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
4844 XtSetArg(args[j], XtNautoFill, True); j++;
4845 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
4847 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
4851 XtSetArg(args[j], XtNfromVert, edit); j++;
4852 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4853 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4854 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4855 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4857 XtCreateManagedWidget(_("ok"), commandWidgetClass, form, args, j);
4858 XtAddCallback(b_ok, XtNcallback, callback, (XtPointer) 0);
4861 XtSetArg(args[j], XtNfromVert, edit); j++;
4862 XtSetArg(args[j], XtNfromHoriz, b_ok); j++;
4863 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4864 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4865 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4866 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4868 XtCreateManagedWidget(_("cancel"), commandWidgetClass, form, args, j);
4869 XtAddCallback(b_cancel, XtNcallback, callback, (XtPointer) 0);
4872 XtSetArg(args[j], XtNfromVert, edit); j++;
4873 XtSetArg(args[j], XtNfromHoriz, b_cancel); j++;
4874 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4875 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4876 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4877 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4879 XtCreateManagedWidget(_("clear"), commandWidgetClass, form, args, j);
4880 XtAddCallback(b_clear, XtNcallback, callback, (XtPointer) 0);
4883 XtSetArg(args[j], XtNfromVert, edit); j++;
4884 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4885 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4886 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4887 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4889 XtCreateManagedWidget(_("close"), commandWidgetClass, form, args, j);
4890 XtAddCallback(b_close, XtNcallback, callback, (XtPointer) 0);
4893 XtSetArg(args[j], XtNfromVert, edit); j++;
4894 XtSetArg(args[j], XtNfromHoriz, b_close); j++;
4895 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4896 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4897 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4898 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4900 XtCreateManagedWidget(_("edit"), commandWidgetClass, form, args, j);
4901 XtAddCallback(b_edit, XtNcallback, callback, (XtPointer) 0);
4904 XtRealizeWidget(shell);
4906 if (commentX == -1) {
4909 Dimension pw_height;
4910 Dimension ew_height;
4913 XtSetArg(args[j], XtNheight, &ew_height); j++;
4914 XtGetValues(edit, args, j);
4917 XtSetArg(args[j], XtNheight, &pw_height); j++;
4918 XtGetValues(shell, args, j);
4919 commentH = pw_height + (lines - 1) * ew_height;
4920 commentW = bw_width - 16;
4922 XSync(xDisplay, False);
4924 /* This code seems to tickle an X bug if it is executed too soon
4925 after xboard starts up. The coordinates get transformed as if
4926 the main window was positioned at (0, 0).
4928 XtTranslateCoords(shellWidget,
4929 (bw_width - commentW) / 2, 0 - commentH / 2,
4930 &commentX, &commentY);
4932 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
4933 RootWindowOfScreen(XtScreen(shellWidget)),
4934 (bw_width - commentW) / 2, 0 - commentH / 2,
4939 if (commentY < 0) commentY = 0; /*avoid positioning top offscreen*/
4942 XtSetArg(args[j], XtNheight, commentH); j++;
4943 XtSetArg(args[j], XtNwidth, commentW); j++;
4944 XtSetArg(args[j], XtNx, commentX); j++;
4945 XtSetArg(args[j], XtNy, commentY); j++;
4946 XtSetValues(shell, args, j);
4947 XtSetKeyboardFocus(shell, edit);
4952 /* Used for analysis window and ICS input window */
4953 Widget MiscCreate(name, text, mutable, callback, lines)
4955 int /*Boolean*/ mutable;
4956 XtCallbackProc callback;
4960 Widget shell, layout, form, edit;
4962 Dimension bw_width, pw_height, ew_height, w, h;
4968 XtSetArg(args[j], XtNresizable, True); j++;
4971 XtCreatePopupShell(name, topLevelShellWidgetClass,
4972 shellWidget, args, j);
4975 XtCreatePopupShell(name, transientShellWidgetClass,
4976 shellWidget, args, j);
4979 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
4980 layoutArgs, XtNumber(layoutArgs));
4982 XtCreateManagedWidget("form", formWidgetClass, layout,
4983 formArgs, XtNumber(formArgs));
4987 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
4988 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
4990 XtSetArg(args[j], XtNstring, text); j++;
4991 XtSetArg(args[j], XtNtop, XtChainTop); j++;
4992 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4993 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4994 XtSetArg(args[j], XtNright, XtChainRight); j++;
4995 XtSetArg(args[j], XtNresizable, True); j++;
4997 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
4999 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
5000 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
5002 XtSetArg(args[j], XtNautoFill, True); j++;
5003 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
5005 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
5007 XtRealizeWidget(shell);
5010 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5011 XtGetValues(boardWidget, args, j);
5014 XtSetArg(args[j], XtNheight, &ew_height); j++;
5015 XtGetValues(edit, args, j);
5018 XtSetArg(args[j], XtNheight, &pw_height); j++;
5019 XtGetValues(shell, args, j);
5020 h = pw_height + (lines - 1) * ew_height;
5023 XSync(xDisplay, False);
5025 /* This code seems to tickle an X bug if it is executed too soon
5026 after xboard starts up. The coordinates get transformed as if
5027 the main window was positioned at (0, 0).
5029 XtTranslateCoords(shellWidget, (bw_width - w) / 2, 0 - h / 2, &x, &y);
5031 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
5032 RootWindowOfScreen(XtScreen(shellWidget)),
5033 (bw_width - w) / 2, 0 - h / 2, &xx, &yy, &junk);
5037 if (y < 0) y = 0; /*avoid positioning top offscreen*/
5040 XtSetArg(args[j], XtNheight, h); j++;
5041 XtSetArg(args[j], XtNwidth, w); j++;
5042 XtSetArg(args[j], XtNx, x); j++;
5043 XtSetArg(args[j], XtNy, y); j++;
5044 XtSetValues(shell, args, j);
5050 static int savedIndex; /* gross that this is global */
5052 void EditCommentPopUp(index, title, text)
5061 if (text == NULL) text = "";
5063 if (editShell == NULL) {
5065 CommentCreate(title, text, True, EditCommentCallback, 4);
5066 XtRealizeWidget(editShell);
5067 CatchDeleteWindow(editShell, "EditCommentPopDown");
5069 edit = XtNameToWidget(editShell, "*form.text");
5071 XtSetArg(args[j], XtNstring, text); j++;
5072 XtSetValues(edit, args, j);
5074 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5075 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5076 XtSetValues(editShell, args, j);
5079 XtPopup(editShell, XtGrabNone);
5083 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
5084 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
5088 void EditCommentCallback(w, client_data, call_data)
5090 XtPointer client_data, call_data;
5098 XtSetArg(args[j], XtNlabel, &name); j++;
5099 XtGetValues(w, args, j);
5101 if (strcmp(name, _("ok")) == 0) {
5102 edit = XtNameToWidget(editShell, "*form.text");
5104 XtSetArg(args[j], XtNstring, &val); j++;
5105 XtGetValues(edit, args, j);
5106 ReplaceComment(savedIndex, val);
5107 EditCommentPopDown();
5108 } else if (strcmp(name, _("cancel")) == 0) {
5109 EditCommentPopDown();
5110 } else if (strcmp(name, _("clear")) == 0) {
5111 edit = XtNameToWidget(editShell, "*form.text");
5112 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
5113 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
5117 void EditCommentPopDown()
5122 if (!editUp) return;
5124 XtSetArg(args[j], XtNx, &commentX); j++;
5125 XtSetArg(args[j], XtNy, &commentY); j++;
5126 XtSetArg(args[j], XtNheight, &commentH); j++;
5127 XtSetArg(args[j], XtNwidth, &commentW); j++;
5128 XtGetValues(editShell, args, j);
5129 XtPopdown(editShell);
5132 XtSetArg(args[j], XtNleftBitmap, None); j++;
5133 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
5137 void ICSInputBoxPopUp()
5142 char *title = _("ICS Input");
5145 if (ICSInputShell == NULL) {
5146 ICSInputShell = MiscCreate(title, "", True, NULL, 1);
5147 tr = XtParseTranslationTable(ICSInputTranslations);
5148 edit = XtNameToWidget(ICSInputShell, "*form.text");
5149 XtOverrideTranslations(edit, tr);
5150 XtRealizeWidget(ICSInputShell);
5151 CatchDeleteWindow(ICSInputShell, "ICSInputBoxPopDown");
5154 edit = XtNameToWidget(ICSInputShell, "*form.text");
5156 XtSetArg(args[j], XtNstring, ""); j++;
5157 XtSetValues(edit, args, j);
5159 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5160 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5161 XtSetValues(ICSInputShell, args, j);
5164 XtPopup(ICSInputShell, XtGrabNone);
5165 XtSetKeyboardFocus(ICSInputShell, edit);
5167 ICSInputBoxUp = True;
5169 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
5170 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
5174 void ICSInputSendText()
5181 edit = XtNameToWidget(ICSInputShell, "*form.text");
5183 XtSetArg(args[j], XtNstring, &val); j++;
5184 XtGetValues(edit, args, j);
5185 SendMultiLineToICS(val);
5186 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
5187 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
5190 void ICSInputBoxPopDown()
5195 if (!ICSInputBoxUp) return;
5197 XtPopdown(ICSInputShell);
5198 ICSInputBoxUp = False;
5200 XtSetArg(args[j], XtNleftBitmap, None); j++;
5201 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
5205 void CommentPopUp(title, text)
5212 if (commentShell == NULL) {
5214 CommentCreate(title, text, False, CommentCallback, 4);
5215 XtRealizeWidget(commentShell);
5216 CatchDeleteWindow(commentShell, "CommentPopDown");
5218 edit = XtNameToWidget(commentShell, "*form.text");
5220 XtSetArg(args[j], XtNstring, text); j++;
5221 XtSetValues(edit, args, j);
5223 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5224 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5225 XtSetValues(commentShell, args, j);
5228 XtPopup(commentShell, XtGrabNone);
5229 XSync(xDisplay, False);
5234 void AnalysisPopUp(title, text)
5241 if (analysisShell == NULL) {
5242 analysisShell = MiscCreate(title, text, False, NULL, 4);
5243 XtRealizeWidget(analysisShell);
5244 CatchDeleteWindow(analysisShell, "AnalysisPopDown");
5247 edit = XtNameToWidget(analysisShell, "*form.text");
5249 XtSetArg(args[j], XtNstring, text); j++;
5250 XtSetValues(edit, args, j);
5252 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5253 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5254 XtSetValues(analysisShell, args, j);
5258 XtPopup(analysisShell, XtGrabNone);
5260 XSync(xDisplay, False);
5265 void CommentCallback(w, client_data, call_data)
5267 XtPointer client_data, call_data;
5274 XtSetArg(args[j], XtNlabel, &name); j++;
5275 XtGetValues(w, args, j);
5277 if (strcmp(name, _("close")) == 0) {
5279 } else if (strcmp(name, _("edit")) == 0) {
5286 void CommentPopDown()
5291 if (!commentUp) return;
5293 XtSetArg(args[j], XtNx, &commentX); j++;
5294 XtSetArg(args[j], XtNy, &commentY); j++;
5295 XtSetArg(args[j], XtNwidth, &commentW); j++;
5296 XtSetArg(args[j], XtNheight, &commentH); j++;
5297 XtGetValues(commentShell, args, j);
5298 XtPopdown(commentShell);
5299 XSync(xDisplay, False);
5303 void AnalysisPopDown()
5305 if (!analysisUp) return;
5306 XtPopdown(analysisShell);
5307 XSync(xDisplay, False);
5309 if (appData.icsEngineAnalyze) ExitAnalyzeMode(); /* [DM] icsEngineAnalyze */
5313 void FileNamePopUp(label, def, proc, openMode)
5320 Widget popup, layout, dialog, edit;
5326 fileProc = proc; /* I can't see a way not */
5327 fileOpenMode = openMode; /* to use globals here */
5330 XtSetArg(args[i], XtNresizable, True); i++;
5331 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
5332 XtSetArg(args[i], XtNtitle, XtNewString(_("File name prompt"))); i++;
5333 fileNameShell = popup =
5334 XtCreatePopupShell("File name prompt", transientShellWidgetClass,
5335 shellWidget, args, i);
5338 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
5339 layoutArgs, XtNumber(layoutArgs));
5342 XtSetArg(args[i], XtNlabel, label); i++;
5343 XtSetArg(args[i], XtNvalue, def); i++;
5344 XtSetArg(args[i], XtNborderWidth, 0); i++;
5345 dialog = XtCreateManagedWidget("fileName", dialogWidgetClass,
5348 XawDialogAddButton(dialog, _("ok"), FileNameCallback, (XtPointer) dialog);
5349 XawDialogAddButton(dialog, _("cancel"), FileNameCallback,
5350 (XtPointer) dialog);
5352 XtRealizeWidget(popup);
5353 CatchDeleteWindow(popup, "FileNamePopDown");
5355 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
5356 &x, &y, &win_x, &win_y, &mask);
5358 XtSetArg(args[0], XtNx, x - 10);
5359 XtSetArg(args[1], XtNy, y - 30);
5360 XtSetValues(popup, args, 2);
5362 XtPopup(popup, XtGrabExclusive);
5365 edit = XtNameToWidget(dialog, "*value");
5366 XtSetKeyboardFocus(popup, edit);
5369 void FileNamePopDown()
5371 if (!filenameUp) return;
5372 XtPopdown(fileNameShell);
5373 XtDestroyWidget(fileNameShell);
5378 void FileNameCallback(w, client_data, call_data)
5380 XtPointer client_data, call_data;
5385 XtSetArg(args[0], XtNlabel, &name);
5386 XtGetValues(w, args, 1);
5388 if (strcmp(name, _("cancel")) == 0) {
5393 FileNameAction(w, NULL, NULL, NULL);
5396 void FileNameAction(w, event, prms, nprms)
5408 name = XawDialogGetValueString(w = XtParent(w));
5410 if ((name != NULL) && (*name != NULLCHAR)) {
5412 XtPopdown(w = XtParent(XtParent(w)));
5416 p = strrchr(buf, ' ');
5423 fullname = ExpandPathName(buf);
5425 ErrorPopUp(_("Error"), _("Can't open file"), FALSE);
5428 f = fopen(fullname, fileOpenMode);
5430 DisplayError(_("Failed to open file"), errno);
5432 (void) (*fileProc)(f, index, buf);
5439 XtPopdown(w = XtParent(XtParent(w)));
5445 void PromotionPopUp()
5448 Widget dialog, layout;
5450 Dimension bw_width, pw_width;
5454 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5455 XtGetValues(boardWidget, args, j);
5458 XtSetArg(args[j], XtNresizable, True); j++;
5459 XtSetArg(args[j], XtNtitle, XtNewString(_("Promotion"))); j++;
5461 XtCreatePopupShell("Promotion", transientShellWidgetClass,
5462 shellWidget, args, j);
5464 XtCreateManagedWidget(layoutName, formWidgetClass, promotionShell,
5465 layoutArgs, XtNumber(layoutArgs));
5468 XtSetArg(args[j], XtNlabel, _("Promote to what?")); j++;
5469 XtSetArg(args[j], XtNborderWidth, 0); j++;
5470 dialog = XtCreateManagedWidget("promotion", dialogWidgetClass,
5473 if(gameInfo.variant != VariantShogi) {
5474 XawDialogAddButton(dialog, _("Queen"), PromotionCallback,
5475 (XtPointer) dialog);
5476 XawDialogAddButton(dialog, _("Rook"), PromotionCallback,
5477 (XtPointer) dialog);
5478 XawDialogAddButton(dialog, _("Bishop"), PromotionCallback,
5479 (XtPointer) dialog);
5480 XawDialogAddButton(dialog, _("Knight"), PromotionCallback,
5481 (XtPointer) dialog);
5482 if (!appData.testLegality || gameInfo.variant == VariantSuicide ||
5483 gameInfo.variant == VariantGiveaway) {
5484 XawDialogAddButton(dialog, _("King"), PromotionCallback,
5485 (XtPointer) dialog);
5487 if(gameInfo.variant == VariantCapablanca ||
5488 gameInfo.variant == VariantGothic ||
5489 gameInfo.variant == VariantCapaRandom) {
5490 XawDialogAddButton(dialog, _("Archbishop"), PromotionCallback,
5491 (XtPointer) dialog);
5492 XawDialogAddButton(dialog, _("Chancellor"), PromotionCallback,
5493 (XtPointer) dialog);
5495 } else // [HGM] shogi
5497 XawDialogAddButton(dialog, _("Promote"), PromotionCallback,
5498 (XtPointer) dialog);
5499 XawDialogAddButton(dialog, _("Defer"), PromotionCallback,
5500 (XtPointer) dialog);
5502 XawDialogAddButton(dialog, _("cancel"), PromotionCallback,
5503 (XtPointer) dialog);
5505 XtRealizeWidget(promotionShell);
5506 CatchDeleteWindow(promotionShell, "PromotionPopDown");
5509 XtSetArg(args[j], XtNwidth, &pw_width); j++;
5510 XtGetValues(promotionShell, args, j);
5512 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
5513 lineGap + squareSize/3 +
5514 ((toY == BOARD_HEIGHT-1) ^ (flipView) ?
5515 0 : 6*(squareSize + lineGap)), &x, &y);
5518 XtSetArg(args[j], XtNx, x); j++;
5519 XtSetArg(args[j], XtNy, y); j++;
5520 XtSetValues(promotionShell, args, j);
5522 XtPopup(promotionShell, XtGrabNone);
5527 void PromotionPopDown()
5529 if (!promotionUp) return;
5530 XtPopdown(promotionShell);
5531 XtDestroyWidget(promotionShell);
5532 promotionUp = False;
5535 void PromotionCallback(w, client_data, call_data)
5537 XtPointer client_data, call_data;
5543 XtSetArg(args[0], XtNlabel, &name);
5544 XtGetValues(w, args, 1);
5548 if (fromX == -1) return;
5550 if (strcmp(name, _("cancel")) == 0) {
5554 } else if (strcmp(name, _("Knight")) == 0) {
5556 } else if (strcmp(name, _("Promote")) == 0) {
5558 } else if (strcmp(name, _("Defer")) == 0) {
5561 promoChar = ToLower(name[0]);
5564 UserMoveEvent(fromX, fromY, toX, toY, promoChar);
5566 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
5567 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
5572 void ErrorCallback(w, client_data, call_data)
5574 XtPointer client_data, call_data;
5577 XtPopdown(w = XtParent(XtParent(XtParent(w))));
5579 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5585 if (!errorUp) return;
5587 XtPopdown(errorShell);
5588 XtDestroyWidget(errorShell);
5589 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5592 void ErrorPopUp(title, label, modal)
5593 char *title, *label;
5598 dialog = gtk_message_dialog_new(GTK_WINDOW(GUI_Window),
5599 GTK_DIALOG_DESTROY_WITH_PARENT,
5604 gtk_window_set_title(GTK_WINDOW(dialog),(gchar *) title);
5607 gtk_dialog_run(GTK_DIALOG(dialog));
5608 gtk_widget_destroy(GTK_WIDGET(dialog));
5612 g_signal_connect_swapped (dialog, "response",
5613 G_CALLBACK (ErrorPopDownProc),
5616 gtk_widget_show(GTK_WIDGET(dialog));
5620 /* Disable all user input other than deleting the window */
5621 static int frozen = 0;
5625 /* Grab by a widget that doesn't accept input */
5626 // XtAddGrab(messageWidget, TRUE, FALSE);
5630 /* Undo a FreezeUI */
5633 if (!frozen) return;
5634 XtRemoveGrab(messageWidget);
5638 char *ModeToWidgetName(mode)
5642 case BeginningOfGame:
5643 if (appData.icsActive)
5644 return "menuMode.ICS Client";
5645 else if (appData.noChessProgram ||
5646 *appData.cmailGameName != NULLCHAR)
5647 return "menuMode.Edit Game";
5649 return "menuMode.Machine Black";
5650 case MachinePlaysBlack:
5651 return "menuMode.Machine Black";
5652 case MachinePlaysWhite:
5653 return "menuMode.Machine White";
5655 return "menuMode.Analysis Mode";
5657 return "menuMode.Analyze File";
5658 case TwoMachinesPlay:
5659 return "menuMode.Two Machines";
5661 return "menuMode.Edit Game";
5662 case PlayFromGameFile:
5663 return "menuFile.Load Game";
5665 return "menuMode.Edit Position";
5667 return "menuMode.Training";
5668 case IcsPlayingWhite:
5669 case IcsPlayingBlack:
5673 return "menuMode.ICS Client";
5680 void ModeHighlight()
5682 static int oldPausing = FALSE;
5683 static GameMode oldmode = (GameMode) -1;
5686 // todo this toggling of the pause button doesn't seem to work?
5687 // e.g. select pause from buttonbar doesn't activate menumode.pause
5689 // if (!boardWidget || !XtIsRealized(boardWidget)) return;
5691 if (pausing != oldPausing) {
5692 oldPausing = pausing;
5693 gtk_button_set_relief(GTK_BUTTON (gtk_builder_get_object (builder, "menuMode.Pause")),pausing?GTK_RELIEF_NORMAL:GTK_RELIEF_NONE);
5694 /* toggle background color in showbuttonbar */
5695 if (appData.showButtonBar) {
5697 gtk_button_pressed(GTK_BUTTON (gtk_builder_get_object (builder, "buttonbar.Pause")));
5699 gtk_button_released(GTK_BUTTON (gtk_builder_get_object (builder, "buttonbar.Pause")));
5704 wname = ModeToWidgetName(oldmode);
5706 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, wname)),True);
5710 /* Maybe all the enables should be handled here, not just this one */
5711 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuMode.Training")),
5712 gameMode == Training || gameMode == PlayFromGameFile);
5717 * Button/menu procedures
5720 int LoadGamePopUp(f, gameNumber, title)
5725 cmailMsgLoaded = FALSE;
5726 if (gameNumber == 0) {
5727 int error = GameListBuild(f);
5729 DisplayError(_("Cannot build game list"), error);
5730 } else if (!ListEmpty(&gameList) &&
5731 ((ListGame *) gameList.tailPred)->number > 1) {
5732 GameListPopUp(f, title);
5738 return LoadGame(f, gameNumber, title, FALSE);
5742 void LoadNextPositionProc(w, event, prms, nprms)
5751 void LoadPrevPositionProc(w, event, prms, nprms)
5760 void ReloadPositionProc(w, event, prms, nprms)
5769 void LoadPositionProc(w, event, prms, nprms)
5775 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
5778 FileNamePopUp(_("Load position file name?"), "", LoadPosition, "rb");
5781 void SaveGameProc(w, event, prms, nprms)
5787 FileNamePopUp(_("Save game file name?"),
5788 DefaultFileName(appData.oldSaveStyle ? "game" : "pgn"),
5792 void SavePositionProc(w, event, prms, nprms)
5798 FileNamePopUp(_("Save position file name?"),
5799 DefaultFileName(appData.oldSaveStyle ? "pos" : "fen"),
5803 void ReloadCmailMsgProc(w, event, prms, nprms)
5809 ReloadCmailMsgEvent(FALSE);
5812 void MailMoveProc(w, event, prms, nprms)
5821 /* this variable is shared between CopyPositionProc and SendPositionSelection */
5822 static char *selected_fen_position=NULL;
5825 SendPositionSelection(Widget w, Atom *selection, Atom *target,
5826 Atom *type_return, XtPointer *value_return,
5827 unsigned long *length_return, int *format_return)
5829 char *selection_tmp;
5831 if (!selected_fen_position) return False; /* should never happen */
5832 if (*target == XA_STRING){
5833 /* note: since no XtSelectionDoneProc was registered, Xt will
5834 * automatically call XtFree on the value returned. So have to
5835 * make a copy of it allocated with XtMalloc */
5836 selection_tmp= XtMalloc(strlen(selected_fen_position)+16);
5837 strcpy(selection_tmp, selected_fen_position);
5839 *value_return=selection_tmp;
5840 *length_return=strlen(selection_tmp);
5841 *type_return=XA_STRING;
5842 *format_return = 8; /* bits per byte */
5849 /* note: when called from menu all parameters are NULL, so no clue what the
5850 * Widget which was clicked on was, or what the click event was
5852 void CopyPositionProc(w, event, prms, nprms)
5860 if (selected_fen_position) free(selected_fen_position);
5861 selected_fen_position = (char *)PositionToFEN(currentMove, NULL);
5862 if (!selected_fen_position) return;
5863 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
5865 SendPositionSelection,
5866 NULL/* lose_ownership_proc */ ,
5867 NULL/* transfer_done_proc */);
5869 free(selected_fen_position);
5870 selected_fen_position=NULL;
5874 /* function called when the data to Paste is ready */
5876 PastePositionCB(Widget w, XtPointer client_data, Atom *selection,
5877 Atom *type, XtPointer value, unsigned long *len, int *format)
5880 if (value==NULL || *len==0) return; /* nothing had been selected to copy */
5881 fenstr[*len]='\0'; /* normally this string is terminated, but be safe */
5882 EditPositionPasteFEN(fenstr);
5886 /* called when Paste Position button is pressed,
5887 * all parameters will be NULL */
5888 void PastePositionProc(w, event, prms, nprms)
5894 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
5895 /* (XtSelectionCallbackProc) */ PastePositionCB,
5896 NULL, /* client_data passed to PastePositionCB */
5898 /* better to use the time field from the event that triggered the
5899 * call to this function, but that isn't trivial to get
5907 SendGameSelection(Widget w, Atom *selection, Atom *target,
5908 Atom *type_return, XtPointer *value_return,
5909 unsigned long *length_return, int *format_return)
5911 char *selection_tmp;
5913 if (*target == XA_STRING){
5914 FILE* f = fopen(gameCopyFilename, "r");
5917 if (f == NULL) return False;
5921 selection_tmp = XtMalloc(len + 1);
5922 count = fread(selection_tmp, 1, len, f);
5924 XtFree(selection_tmp);
5927 selection_tmp[len] = NULLCHAR;
5928 *value_return = selection_tmp;
5929 *length_return = len;
5930 *type_return = XA_STRING;
5931 *format_return = 8; /* bits per byte */
5938 /* note: when called from menu all parameters are NULL, so no clue what the
5939 * Widget which was clicked on was, or what the click event was
5941 void CopyGameProc(w, event, prms, nprms)
5949 ret = SaveGameToFile(gameCopyFilename, FALSE);
5952 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
5955 NULL/* lose_ownership_proc */ ,
5956 NULL/* transfer_done_proc */);
5959 /* function called when the data to Paste is ready */
5961 PasteGameCB(Widget w, XtPointer client_data, Atom *selection,
5962 Atom *type, XtPointer value, unsigned long *len, int *format)
5965 if (value == NULL || *len == 0) {
5966 return; /* nothing had been selected to copy */
5968 f = fopen(gamePasteFilename, "w");
5970 DisplayError(_("Can't open temp file"), errno);
5973 fwrite(value, 1, *len, f);
5976 LoadGameFromFile(gamePasteFilename, 0, gamePasteFilename, TRUE);
5979 /* called when Paste Game button is pressed,
5980 * all parameters will be NULL */
5981 void PasteGameProc(w, event, prms, nprms)
5987 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
5988 /* (XtSelectionCallbackProc) */ PasteGameCB,
5989 NULL, /* client_data passed to PasteGameCB */
5991 /* better to use the time field from the event that triggered the
5992 * call to this function, but that isn't trivial to get
6002 SaveGameProc(NULL, NULL, NULL, NULL);
6005 void MachineBlackProc(w, event, prms, nprms)
6011 MachineBlackEvent();
6014 void MachineWhiteProc(w, event, prms, nprms)
6020 MachineWhiteEvent();
6023 void AnalyzeModeProc(w, event, prms, nprms)
6031 if (!first.analysisSupport) {
6032 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
6033 DisplayError(buf, 0);
6036 /* [DM] icsEngineAnalyze [HGM] This is horrible code; reverse the gameMode and isEngineAnalyze tests! */
6037 if (appData.icsActive) {
6038 if (gameMode != IcsObserving) {
6039 sprintf(buf,_("You are not observing a game"));
6040 DisplayError(buf, 0);
6042 if (appData.icsEngineAnalyze) {
6043 if (appData.debugMode)
6044 fprintf(debugFP, _("Found unexpected active ICS engine analyze \n"));
6050 /* if enable, use want disable icsEngineAnalyze */
6051 if (appData.icsEngineAnalyze) {
6056 appData.icsEngineAnalyze = TRUE;
6057 if (appData.debugMode)
6058 fprintf(debugFP, _("ICS engine analyze starting... \n"));
6060 if (!appData.showThinking)
6061 ShowThinkingProc(w,event,prms,nprms);
6066 void AnalyzeFileProc(w, event, prms, nprms)
6072 if (!first.analysisSupport) {
6074 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
6075 DisplayError(buf, 0);
6080 if (!appData.showThinking)
6081 ShowThinkingProc(w,event,prms,nprms);
6084 FileNamePopUp(_("File to analyze"), "", LoadGamePopUp, "rb");
6085 AnalysisPeriodicEvent(1);
6088 void TwoMachinesProc(w, event, prms, nprms)
6097 void IcsClientProc(w, event, prms, nprms)
6106 void EditGameProc(w, event, prms, nprms)
6115 void EditPositionProc(w, event, prms, nprms)
6121 EditPositionEvent();
6124 void TrainingProc(w, event, prms, nprms)
6133 void EditCommentProc(w, event, prms, nprms)
6140 EditCommentPopDown();
6146 void IcsInputBoxProc(w, event, prms, nprms)
6152 if (ICSInputBoxUp) {
6153 ICSInputBoxPopDown();
6159 void AcceptProc(w, event, prms, nprms)
6168 void DeclineProc(w, event, prms, nprms)
6177 void RematchProc(w, event, prms, nprms)
6186 void CallFlagProc(w, event, prms, nprms)
6195 void DrawProc(w, event, prms, nprms)
6204 void AbortProc(w, event, prms, nprms)
6213 void AdjournProc(w, event, prms, nprms)
6222 void ResignProc(w, event, prms, nprms)
6231 void AdjuWhiteProc(w, event, prms, nprms)
6237 UserAdjudicationEvent(+1);
6240 void AdjuBlackProc(w, event, prms, nprms)
6246 UserAdjudicationEvent(-1);
6249 void AdjuDrawProc(w, event, prms, nprms)
6255 UserAdjudicationEvent(0);
6258 void EnterKeyProc(w, event, prms, nprms)
6264 if (ICSInputBoxUp == True)
6268 void StopObservingProc(w, event, prms, nprms)
6274 StopObservingEvent();
6277 void StopExaminingProc(w, event, prms, nprms)
6283 StopExaminingEvent();
6287 void ForwardProc(w, event, prms, nprms)
6297 void BackwardProc(w, event, prms, nprms)
6306 void ToStartProc(w, event, prms, nprms)
6315 void ToEndProc(w, event, prms, nprms)
6324 void RevertProc(w, event, prms, nprms)
6333 void TruncateGameProc(w, event, prms, nprms)
6339 TruncateGameEvent();
6341 void RetractMoveProc(w, event, prms, nprms)
6350 void MoveNowProc(w, event, prms, nprms)
6360 void AlwaysQueenProc(w, event, prms, nprms)
6368 appData.alwaysPromoteToQueen = !appData.alwaysPromoteToQueen;
6370 if (appData.alwaysPromoteToQueen) {
6371 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6373 XtSetArg(args[0], XtNleftBitmap, None);
6375 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
6379 void AnimateDraggingProc(w, event, prms, nprms)
6387 appData.animateDragging = !appData.animateDragging;
6389 if (appData.animateDragging) {
6390 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6393 XtSetArg(args[0], XtNleftBitmap, None);
6395 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Dragging"),
6399 void AnimateMovingProc(w, event, prms, nprms)
6407 appData.animate = !appData.animate;
6409 if (appData.animate) {
6410 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6413 XtSetArg(args[0], XtNleftBitmap, None);
6415 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
6419 void AutocommProc(w, event, prms, nprms)
6427 appData.autoComment = !appData.autoComment;
6429 if (appData.autoComment) {
6430 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6432 XtSetArg(args[0], XtNleftBitmap, None);
6434 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
6439 void AutoflagProc(w, event, prms, nprms)
6447 appData.autoCallFlag = !appData.autoCallFlag;
6449 if (appData.autoCallFlag) {
6450 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6452 XtSetArg(args[0], XtNleftBitmap, None);
6454 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
6458 void AutoflipProc(w, event, prms, nprms)
6466 appData.autoFlipView = !appData.autoFlipView;
6468 if (appData.autoFlipView) {
6469 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6471 XtSetArg(args[0], XtNleftBitmap, None);
6473 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flip View"),
6477 void AutobsProc(w, event, prms, nprms)
6485 appData.autoObserve = !appData.autoObserve;
6487 if (appData.autoObserve) {
6488 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6490 XtSetArg(args[0], XtNleftBitmap, None);
6492 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
6496 void AutoraiseProc(w, event, prms, nprms)
6504 appData.autoRaiseBoard = !appData.autoRaiseBoard;
6506 if (appData.autoRaiseBoard) {
6507 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6509 XtSetArg(args[0], XtNleftBitmap, None);
6511 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Raise Board"),
6515 void AutosaveProc(w, event, prms, nprms)
6523 appData.autoSaveGames = !appData.autoSaveGames;
6525 if (appData.autoSaveGames) {
6526 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6528 XtSetArg(args[0], XtNleftBitmap, None);
6530 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
6534 void BlindfoldProc(w, event, prms, nprms)
6542 appData.blindfold = !appData.blindfold;
6544 if (appData.blindfold) {
6545 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6547 XtSetArg(args[0], XtNleftBitmap, None);
6549 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Blindfold"),
6552 DrawPosition(True, NULL);
6555 void TestLegalityProc(w, event, prms, nprms)
6563 appData.testLegality = !appData.testLegality;
6565 if (appData.testLegality) {
6566 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6568 XtSetArg(args[0], XtNleftBitmap, None);
6570 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Test Legality"),
6575 void FlashMovesProc(w, event, prms, nprms)
6583 if (appData.flashCount == 0) {
6584 appData.flashCount = 3;
6586 appData.flashCount = -appData.flashCount;
6589 if (appData.flashCount > 0) {
6590 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6592 XtSetArg(args[0], XtNleftBitmap, None);
6594 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flash Moves"),
6598 void FlipViewProc(w, event, prms, nprms)
6604 flipView = !flipView;
6605 DrawPosition(True, NULL);
6608 void GetMoveListProc(w, event, prms, nprms)
6616 appData.getMoveList = !appData.getMoveList;
6618 if (appData.getMoveList) {
6619 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6622 XtSetArg(args[0], XtNleftBitmap, None);
6624 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
6629 void HighlightDraggingProc(w, event, prms, nprms)
6637 appData.highlightDragging = !appData.highlightDragging;
6639 if (appData.highlightDragging) {
6640 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6642 XtSetArg(args[0], XtNleftBitmap, None);
6644 XtSetValues(XtNameToWidget(menuBarWidget,
6645 "menuOptions.Highlight Dragging"), args, 1);
6649 void HighlightLastMoveProc(w, event, prms, nprms)
6657 appData.highlightLastMove = !appData.highlightLastMove;
6659 if (appData.highlightLastMove) {
6660 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6662 XtSetArg(args[0], XtNleftBitmap, None);
6664 XtSetValues(XtNameToWidget(menuBarWidget,
6665 "menuOptions.Highlight Last Move"), args, 1);
6668 void IcsAlarmProc(w, event, prms, nprms)
6676 appData.icsAlarm = !appData.icsAlarm;
6678 if (appData.icsAlarm) {
6679 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6681 XtSetArg(args[0], XtNleftBitmap, None);
6683 XtSetValues(XtNameToWidget(menuBarWidget,
6684 "menuOptions.ICS Alarm"), args, 1);
6687 void MoveSoundProc(w, event, prms, nprms)
6695 appData.ringBellAfterMoves = !appData.ringBellAfterMoves;
6697 if (appData.ringBellAfterMoves) {
6698 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6700 XtSetArg(args[0], XtNleftBitmap, None);
6702 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
6707 void OldSaveStyleProc(w, event, prms, nprms)
6715 appData.oldSaveStyle = !appData.oldSaveStyle;
6717 if (appData.oldSaveStyle) {
6718 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6720 XtSetArg(args[0], XtNleftBitmap, None);
6722 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Old Save Style"),
6726 void PeriodicUpdatesProc(w, event, prms, nprms)
6734 PeriodicUpdatesEvent(!appData.periodicUpdates);
6736 if (appData.periodicUpdates) {
6737 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6739 XtSetArg(args[0], XtNleftBitmap, None);
6741 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Periodic Updates"),
6745 void PonderNextMoveProc(w, event, prms, nprms)
6753 PonderNextMoveEvent(!appData.ponderNextMove);
6755 if (appData.ponderNextMove) {
6756 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6758 XtSetArg(args[0], XtNleftBitmap, None);
6760 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Ponder Next Move"),
6764 void PopupExitMessageProc(w, event, prms, nprms)
6772 appData.popupExitMessage = !appData.popupExitMessage;
6774 if (appData.popupExitMessage) {
6775 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6777 XtSetArg(args[0], XtNleftBitmap, None);
6779 XtSetValues(XtNameToWidget(menuBarWidget,
6780 "menuOptions.Popup Exit Message"), args, 1);
6783 void PopupMoveErrorsProc(w, event, prms, nprms)
6791 appData.popupMoveErrors = !appData.popupMoveErrors;
6793 if (appData.popupMoveErrors) {
6794 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6796 XtSetArg(args[0], XtNleftBitmap, None);
6798 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Popup Move Errors"),
6802 void PremoveProc(w, event, prms, nprms)
6810 appData.premove = !appData.premove;
6812 if (appData.premove) {
6813 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6815 XtSetArg(args[0], XtNleftBitmap, None);
6817 XtSetValues(XtNameToWidget(menuBarWidget,
6818 "menuOptions.Premove"), args, 1);
6821 void QuietPlayProc(w, event, prms, nprms)
6829 appData.quietPlay = !appData.quietPlay;
6831 if (appData.quietPlay) {
6832 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6834 XtSetArg(args[0], XtNleftBitmap, None);
6836 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Quiet Play"),
6840 void ShowThinkingProc(w, event, prms, nprms)
6848 appData.showThinking = !appData.showThinking; // [HGM] thinking: tken out of ShowThinkingEvent
6849 ShowThinkingEvent();
6851 // [HGM] thinking: currently no suc menu item; replaced by Hide Thinking (From Human)
6852 if (appData.showThinking) {
6853 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6855 XtSetArg(args[0], XtNleftBitmap, None);
6857 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Thinking"),
6862 void HideThinkingProc(w, event, prms, nprms)
6870 appData.hideThinkingFromHuman = !appData.hideThinkingFromHuman; // [HGM] thinking: tken out of ShowThinkingEvent
6871 ShowThinkingEvent();
6873 if (appData.hideThinkingFromHuman) {
6874 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6876 XtSetArg(args[0], XtNleftBitmap, None);
6878 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
6882 void InfoProc(w, event, prms, nprms)
6889 snprintf(buf, sizeof(buf), "xterm -e info --directory %s --directory . -f %s &",
6894 void ManProc(w, event, prms, nprms)
6902 if (nprms && *nprms > 0)
6906 snprintf(buf, sizeof(buf), "xterm -e man %s &", name);
6910 void HintProc(w, event, prms, nprms)
6919 void BookProc(w, event, prms, nprms)
6928 void DebugProc(w, event, prms, nprms)
6934 appData.debugMode = !appData.debugMode;
6937 void AboutGameProc(w, event, prms, nprms)
6946 void NothingProc(w, event, prms, nprms)
6955 void Iconify(w, event, prms, nprms)
6964 XtSetArg(args[0], XtNiconic, True);
6965 XtSetValues(shellWidget, args, 1);
6968 void DisplayMessage(message, extMessage)
6969 gchar *message, *extMessage;
6976 snprintf(buf, sizeof(buf), "%s %s", message, extMessage);
6979 message = extMessage;
6982 gtk_label_set_text( GTK_LABEL(gtk_builder_get_object (builder, "Messages")),message);
6985 void DisplayTitle(text)
6990 char title[MSG_SIZ];
6993 if (text == NULL) text = "";
6995 if (appData.titleInWindow) {
6997 XtSetArg(args[i], XtNlabel, text); i++;
6998 XtSetValues(titleWidget, args, i);
7001 if (*text != NULLCHAR) {
7003 strcpy(title, text);
7004 } else if (appData.icsActive) {
7005 snprintf(icon, sizeof(icon), "%s", appData.icsHost);
7006 snprintf(title, sizeof(title), "%s: %s", programName, appData.icsHost);
7007 } else if (appData.cmailGameName[0] != NULLCHAR) {
7008 snprintf(icon, sizeof(icon), "%s", "CMail");
7009 snprintf(title,sizeof(title), "%s: %s", programName, "CMail");
7011 // [HGM] license: This stuff should really be done in back-end, but WinBoard already had a pop-up for it
7012 } else if (gameInfo.variant == VariantGothic) {
7013 strcpy(icon, programName);
7014 strcpy(title, GOTHIC);
7017 } else if (gameInfo.variant == VariantFalcon) {
7018 strcpy(icon, programName);
7019 strcpy(title, FALCON);
7021 } else if (appData.noChessProgram) {
7022 strcpy(icon, programName);
7023 strcpy(title, programName);
7025 strcpy(icon, first.tidy);
7026 snprintf(title,sizeof(title), "%s: %s", programName, first.tidy);
7029 XtSetArg(args[i], XtNiconName, (XtArgVal) icon); i++;
7030 XtSetArg(args[i], XtNtitle, (XtArgVal) title); i++;
7031 XtSetValues(shellWidget, args, i);
7035 void DisplayError(message, error)
7042 if (appData.debugMode || appData.matchMode) {
7043 fprintf(stderr, "%s: %s\n", programName, message);
7046 if (appData.debugMode || appData.matchMode) {
7047 fprintf(stderr, "%s: %s: %s\n",
7048 programName, message, strerror(error));
7050 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
7053 ErrorPopUp(_("Error"), message, FALSE);
7057 void DisplayMoveError(message)
7062 DrawPosition(FALSE, NULL);
7063 if (appData.debugMode || appData.matchMode) {
7064 fprintf(stderr, "%s: %s\n", programName, message);
7066 if (appData.popupMoveErrors) {
7067 ErrorPopUp(_("Error"), message, FALSE);
7069 DisplayMessage(message, "");
7074 void DisplayFatalError(message, error, status)
7080 errorExitStatus = status;
7082 fprintf(stderr, "%s: %s\n", programName, message);
7084 fprintf(stderr, "%s: %s: %s\n",
7085 programName, message, strerror(error));
7086 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
7089 if (appData.popupExitMessage && boardWidget && XtIsRealized(boardWidget)) {
7090 ErrorPopUp(status ? _("Fatal Error") : _("Exiting"), message, TRUE);
7096 void DisplayInformation(message)
7100 ErrorPopUp(_("Information"), message, TRUE);
7103 void DisplayNote(message)
7107 ErrorPopUp(_("Note"), message, FALSE);
7111 NullXErrorCheck(dpy, error_event)
7113 XErrorEvent *error_event;
7118 void DisplayIcsInteractionTitle(message)
7121 if (oldICSInteractionTitle == NULL) {
7122 /* Magic to find the old window title, adapted from vim */
7123 char *wina = getenv("WINDOWID");
7125 Window win = (Window) atoi(wina);
7126 Window root, parent, *children;
7127 unsigned int nchildren;
7128 int (*oldHandler)() = XSetErrorHandler(NullXErrorCheck);
7130 if (XFetchName(xDisplay, win, &oldICSInteractionTitle)) break;
7131 if (!XQueryTree(xDisplay, win, &root, &parent,
7132 &children, &nchildren)) break;
7133 if (children) XFree((void *)children);
7134 if (parent == root || parent == 0) break;
7137 XSetErrorHandler(oldHandler);
7139 if (oldICSInteractionTitle == NULL) {
7140 oldICSInteractionTitle = "xterm";
7143 printf("\033]0;%s\007", message);
7147 char pendingReplyPrefix[MSG_SIZ];
7148 ProcRef pendingReplyPR;
7150 void AskQuestionProc(w, event, prms, nprms)
7157 fprintf(stderr, _("AskQuestionProc needed 4 parameters, got %d\n"),
7161 AskQuestionEvent(prms[0], prms[1], prms[2], prms[3]);
7164 void AskQuestionPopDown()
7166 if (!askQuestionUp) return;
7167 XtPopdown(askQuestionShell);
7168 XtDestroyWidget(askQuestionShell);
7169 askQuestionUp = False;
7172 void AskQuestionReplyAction(w, event, prms, nprms)
7182 reply = XawDialogGetValueString(w = XtParent(w));
7183 strcpy(buf, pendingReplyPrefix);
7184 if (*buf) strcat(buf, " ");
7187 OutputToProcess(pendingReplyPR, buf, strlen(buf), &err);
7188 AskQuestionPopDown();
7190 if (err) DisplayFatalError(_("Error writing to chess program"), err, 0);
7193 void AskQuestionCallback(w, client_data, call_data)
7195 XtPointer client_data, call_data;
7200 XtSetArg(args[0], XtNlabel, &name);
7201 XtGetValues(w, args, 1);
7203 if (strcmp(name, _("cancel")) == 0) {
7204 AskQuestionPopDown();
7206 AskQuestionReplyAction(w, NULL, NULL, NULL);
7210 void AskQuestion(title, question, replyPrefix, pr)
7211 char *title, *question, *replyPrefix;
7215 Widget popup, layout, dialog, edit;
7221 strcpy(pendingReplyPrefix, replyPrefix);
7222 pendingReplyPR = pr;
7225 XtSetArg(args[i], XtNresizable, True); i++;
7226 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
7227 askQuestionShell = popup =
7228 XtCreatePopupShell(title, transientShellWidgetClass,
7229 shellWidget, args, i);
7232 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
7233 layoutArgs, XtNumber(layoutArgs));
7236 XtSetArg(args[i], XtNlabel, question); i++;
7237 XtSetArg(args[i], XtNvalue, ""); i++;
7238 XtSetArg(args[i], XtNborderWidth, 0); i++;
7239 dialog = XtCreateManagedWidget("question", dialogWidgetClass,
7242 XawDialogAddButton(dialog, _("enter"), AskQuestionCallback,
7243 (XtPointer) dialog);
7244 XawDialogAddButton(dialog, _("cancel"), AskQuestionCallback,
7245 (XtPointer) dialog);
7247 XtRealizeWidget(popup);
7248 CatchDeleteWindow(popup, "AskQuestionPopDown");
7250 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
7251 &x, &y, &win_x, &win_y, &mask);
7253 XtSetArg(args[0], XtNx, x - 10);
7254 XtSetArg(args[1], XtNy, y - 30);
7255 XtSetValues(popup, args, 2);
7257 XtPopup(popup, XtGrabExclusive);
7258 askQuestionUp = True;
7260 edit = XtNameToWidget(dialog, "*value");
7261 XtSetKeyboardFocus(popup, edit);
7269 if (*name == NULLCHAR) {
7271 } else if (strcmp(name, "$") == 0) {
7272 putc(BELLCHAR, stderr);
7275 snprintf(buf, sizeof(buf), "%s '%s' &", appData.soundProgram, name);
7283 PlaySound(appData.soundMove);
7289 PlaySound(appData.soundIcsWin);
7295 PlaySound(appData.soundIcsLoss);
7301 PlaySound(appData.soundIcsDraw);
7305 PlayIcsUnfinishedSound()
7307 PlaySound(appData.soundIcsUnfinished);
7313 PlaySound(appData.soundIcsAlarm);
7319 system("stty echo");
7325 system("stty -echo");
7329 Colorize(cc, continuation)
7334 int count, outCount, error;
7336 if (textColors[(int)cc].bg > 0) {
7337 if (textColors[(int)cc].fg > 0) {
7338 sprintf(buf, "\033[0;%d;%d;%dm", textColors[(int)cc].attr,
7339 textColors[(int)cc].fg, textColors[(int)cc].bg);
7341 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
7342 textColors[(int)cc].bg);
7345 if (textColors[(int)cc].fg > 0) {
7346 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
7347 textColors[(int)cc].fg);
7349 sprintf(buf, "\033[0;%dm", textColors[(int)cc].attr);
7352 count = strlen(buf);
7353 outCount = OutputToProcess(NoProc, buf, count, &error);
7354 if (outCount < count) {
7355 DisplayFatalError(_("Error writing to display"), error, 1);
7358 if (continuation) return;
7361 PlaySound(appData.soundShout);
7364 PlaySound(appData.soundSShout);
7367 PlaySound(appData.soundChannel1);
7370 PlaySound(appData.soundChannel);
7373 PlaySound(appData.soundKibitz);
7376 PlaySound(appData.soundTell);
7378 case ColorChallenge:
7379 PlaySound(appData.soundChallenge);
7382 PlaySound(appData.soundRequest);
7385 PlaySound(appData.soundSeek);
7396 return getpwuid(getuid())->pw_name;
7399 static char *ExpandPathName(path)
7402 static char static_buf[2000];
7403 char *d, *s, buf[2000];
7409 while (*s && isspace(*s))
7418 if (*(s+1) == '/') {
7419 strcpy(d, getpwuid(getuid())->pw_dir);
7424 *strchr(buf, '/') = 0;
7425 pwd = getpwnam(buf);
7428 fprintf(stderr, _("ERROR: Unknown user %s (in path %s)\n"),
7432 strcpy(d, pwd->pw_dir);
7433 strcat(d, strchr(s+1, '/'));
7444 static char host_name[MSG_SIZ];
7446 #if HAVE_GETHOSTNAME
7447 gethostname(host_name, MSG_SIZ);
7449 #else /* not HAVE_GETHOSTNAME */
7450 # if HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H
7451 sysinfo(SI_HOSTNAME, host_name, MSG_SIZ);
7453 # else /* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
7455 # endif/* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
7456 #endif /* not HAVE_GETHOSTNAME */
7459 XtIntervalId delayedEventTimerXID = 0;
7460 DelayedEventCallback delayedEventCallback = 0;
7465 delayedEventTimerXID = 0;
7466 delayedEventCallback();
7470 ScheduleDelayedEvent(cb, millisec)
7471 DelayedEventCallback cb; long millisec;
7473 delayedEventCallback = cb;
7474 delayedEventTimerXID =
7475 XtAppAddTimeOut(appContext, millisec,
7476 (XtTimerCallbackProc) FireDelayedEvent, (XtPointer) 0);
7479 DelayedEventCallback
7482 if (delayedEventTimerXID) {
7483 return delayedEventCallback;
7490 CancelDelayedEvent()
7492 if (delayedEventTimerXID) {
7493 XtRemoveTimeOut(delayedEventTimerXID);
7494 delayedEventTimerXID = 0;
7498 XtIntervalId loadGameTimerXID = 0;
7500 int LoadGameTimerRunning()
7502 return loadGameTimerXID != 0;
7505 int StopLoadGameTimer()
7507 if (loadGameTimerXID != 0) {
7508 XtRemoveTimeOut(loadGameTimerXID);
7509 loadGameTimerXID = 0;
7517 LoadGameTimerCallback(arg, id)
7521 loadGameTimerXID = 0;
7526 StartLoadGameTimer(millisec)
7530 XtAppAddTimeOut(appContext, millisec,
7531 (XtTimerCallbackProc) LoadGameTimerCallback,
7535 XtIntervalId analysisClockXID = 0;
7538 AnalysisClockCallback(arg, id)
7542 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile
7543 || appData.icsEngineAnalyze) { // [DM]
7544 AnalysisPeriodicEvent(0);
7545 StartAnalysisClock();
7550 StartAnalysisClock()
7553 XtAppAddTimeOut(appContext, 2000,
7554 (XtTimerCallbackProc) AnalysisClockCallback,
7558 gint clockTimerTag = 0;
7560 int ClockTimerRunning()
7562 return clockTimerTag != 0;
7565 int StopClockTimer()
7567 if (clockTimerTag != 0) {
7568 gtk_timeout_remove(clockTimerTag);
7577 ClockTimerCallback(data)
7586 StartClockTimer(millisec)
7589 clockTimerTag = gtk_timeout_add(millisec,(GtkFunction) ClockTimerCallback,NULL);
7594 DisplayTimerLabel(w, color, timer, highlight)
7603 if (appData.clockMode) {
7604 sprintf(buf, "%s: %s", color, TimeString(timer));
7606 sprintf(buf, "%s ", color);
7608 gtk_label_set_text(GTK_LABEL(w),buf);
7610 /* check for low time warning */
7611 // Pixel foregroundOrWarningColor = timerForegroundPixel;
7614 // appData.lowTimeWarning &&
7615 // (timer / 1000) < appData.icsAlarmTime)
7616 // foregroundOrWarningColor = lowTimeWarningColor;
7618 // if (appData.clockMode) {
7619 // sprintf(buf, "%s: %s", color, TimeString(timer));
7620 // XtSetArg(args[0], XtNlabel, buf);
7622 // sprintf(buf, "%s ", color);
7623 // XtSetArg(args[0], XtNlabel, buf);
7628 // XtSetArg(args[1], XtNbackground, foregroundOrWarningColor);
7629 // XtSetArg(args[2], XtNforeground, timerBackgroundPixel);
7631 // XtSetArg(args[1], XtNbackground, timerBackgroundPixel);
7632 // XtSetArg(args[2], XtNforeground, foregroundOrWarningColor);
7635 // XtSetValues(w, args, 3);
7640 DisplayWhiteClock(timeRemaining, highlight)
7644 if(appData.noGUI) return;
7646 DisplayTimerLabel(GUI_Whiteclock, _("White"), timeRemaining, highlight);
7647 if (highlight && WindowIcon == BlackIcon) {
7648 WindowIcon = WhiteIcon;
7649 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
7654 DisplayBlackClock(timeRemaining, highlight)
7658 if(appData.noGUI) return;
7659 DisplayTimerLabel(GUI_Blackclock, _("Black"), timeRemaining, highlight);
7660 if (highlight && WindowIcon == WhiteIcon) {
7661 WindowIcon = BlackIcon;
7662 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
7680 int StartChildProcess(cmdLine, dir, pr)
7687 int to_prog[2], from_prog[2];
7691 if (appData.debugMode) {
7692 fprintf(stderr, "StartChildProcess (dir=\"%s\") %s\n",dir, cmdLine);
7695 /* We do NOT feed the cmdLine to the shell; we just
7696 parse it into blank-separated arguments in the
7697 most simple-minded way possible.
7700 strcpy(buf, cmdLine);
7705 if (p == NULL) break;
7710 SetUpChildIO(to_prog, from_prog);
7712 if ((pid = fork()) == 0) {
7714 // [HGM] PSWBTM: made order resistant against case where fd of created pipe was 0 or 1
7715 close(to_prog[1]); // first close the unused pipe ends
7716 close(from_prog[0]);
7717 dup2(to_prog[0], 0); // to_prog was created first, nd is the only one to use 0 or 1
7718 dup2(from_prog[1], 1);
7719 if(to_prog[0] >= 2) close(to_prog[0]); // if 0 or 1, the dup2 already cosed the original
7720 close(from_prog[1]); // and closing again loses one of the pipes!
7721 if(fileno(stderr) >= 2) // better safe than sorry...
7722 dup2(1, fileno(stderr)); /* force stderr to the pipe */
7724 if (dir[0] != NULLCHAR && chdir(dir) != 0) {
7729 nice(appData.niceEngines); // [HGM] nice: adjust priority of engine proc
7731 execvp(argv[0], argv);
7733 /* If we get here, exec failed */
7738 /* Parent process */
7740 close(from_prog[1]);
7742 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7745 cp->fdFrom = from_prog[0];
7746 cp->fdTo = to_prog[1];
7751 // [HGM] kill: implement the 'hard killing' of AS's Winboard_x
7752 static RETSIGTYPE AlarmCallBack(int n)
7758 DestroyChildProcess(pr, signalType)
7762 ChildProc *cp = (ChildProc *) pr;
7764 if (cp->kind != CPReal) return;
7766 if (signalType == 10) { // [HGM] kill: if it does not terminate in 3 sec, kill
7767 signal(SIGALRM, AlarmCallBack);
7769 if(wait((int *) 0) == -1) { // process does not terminate on its own accord
7770 kill(cp->pid, SIGKILL); // kill it forcefully
7771 wait((int *) 0); // and wait again
7775 kill(cp->pid, signalType == 9 ? SIGKILL : SIGTERM); // [HGM] kill: use hard kill if so requested
7777 /* Process is exiting either because of the kill or because of
7778 a quit command sent by the backend; either way, wait for it to die.
7787 InterruptChildProcess(pr)
7790 ChildProc *cp = (ChildProc *) pr;
7792 if (cp->kind != CPReal) return;
7793 (void) kill(cp->pid, SIGINT); /* stop it thinking */
7796 int OpenTelnet(host, port, pr)
7801 char cmdLine[MSG_SIZ];
7803 if (port[0] == NULLCHAR) {
7804 snprintf(cmdLine, sizeof(cmdLine), "%s %s", appData.telnetProgram, host);
7806 snprintf(cmdLine, sizeof(cmdLine), "%s %s %s", appData.telnetProgram, host, port);
7808 return StartChildProcess(cmdLine, "", pr);
7811 int OpenTCP(host, port, pr)
7817 DisplayFatalError(_("Socket support is not configured in"), 0, 2);
7818 #else /* !OMIT_SOCKETS */
7820 struct sockaddr_in sa;
7822 unsigned short uport;
7825 if ((s = socket(AF_INET, SOCK_STREAM, 6)) < 0) {
7829 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
7830 sa.sin_family = AF_INET;
7831 sa.sin_addr.s_addr = INADDR_ANY;
7832 uport = (unsigned short) 0;
7833 sa.sin_port = htons(uport);
7834 if (bind(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)) < 0) {
7838 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
7839 if (!(hp = gethostbyname(host))) {
7841 if (sscanf(host, "%d.%d.%d.%d", &b0, &b1, &b2, &b3) == 4) {
7842 hp = (struct hostent *) calloc(1, sizeof(struct hostent));
7843 hp->h_addrtype = AF_INET;
7845 hp->h_addr_list = (char **) calloc(2, sizeof(char *));
7846 hp->h_addr_list[0] = (char *) malloc(4);
7847 hp->h_addr_list[0][0] = b0;
7848 hp->h_addr_list[0][1] = b1;
7849 hp->h_addr_list[0][2] = b2;
7850 hp->h_addr_list[0][3] = b3;
7855 sa.sin_family = hp->h_addrtype;
7856 uport = (unsigned short) atoi(port);
7857 sa.sin_port = htons(uport);
7858 memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);
7860 if (connect(s, (struct sockaddr *) &sa,
7861 sizeof(struct sockaddr_in)) < 0) {
7865 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7872 #endif /* !OMIT_SOCKETS */
7877 int OpenCommPort(name, pr)
7884 fd = open(name, 2, 0);
7885 if (fd < 0) return errno;
7887 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7897 int OpenLoopback(pr)
7903 SetUpChildIO(to, from);
7905 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7908 cp->fdFrom = to[0]; /* note not from[0]; we are doing a loopback */
7915 int OpenRcmd(host, user, cmd, pr)
7916 char *host, *user, *cmd;
7919 DisplayFatalError(_("internal rcmd not implemented for Unix"), 0, 1);
7923 #define INPUT_SOURCE_BUF_SIZE 8192
7932 char buf[INPUT_SOURCE_BUF_SIZE];
7937 DoInputCallback(closure, source, xid)
7942 InputSource *is = (InputSource *) closure;
7947 if (is->lineByLine) {
7948 count = read(is->fd, is->unused,
7949 INPUT_SOURCE_BUF_SIZE - (is->unused - is->buf));
7951 (is->func)(is, is->closure, is->buf, count, count ? errno : 0);
7954 is->unused += count;
7956 while (p < is->unused) {
7957 q = memchr(p, '\n', is->unused - p);
7958 if (q == NULL) break;
7960 (is->func)(is, is->closure, p, q - p, 0);
7964 while (p < is->unused) {
7969 count = read(is->fd, is->buf, INPUT_SOURCE_BUF_SIZE);
7974 (is->func)(is, is->closure, is->buf, count, error);
7978 InputSourceRef AddInputSource(pr, lineByLine, func, closure)
7985 ChildProc *cp = (ChildProc *) pr;
7987 is = (InputSource *) calloc(1, sizeof(InputSource));
7988 is->lineByLine = lineByLine;
7992 is->fd = fileno(stdin);
7994 is->kind = cp->kind;
7995 is->fd = cp->fdFrom;
7998 is->unused = is->buf;
8001 is->xid = XtAppAddInput(appContext, is->fd,
8002 (XtPointer) (XtInputReadMask),
8003 (XtInputCallbackProc) DoInputCallback,
8005 is->closure = closure;
8006 return (InputSourceRef) is;
8010 RemoveInputSource(isr)
8013 InputSource *is = (InputSource *) isr;
8015 if (is->xid == 0) return;
8016 XtRemoveInput(is->xid);
8020 int OutputToProcess(pr, message, count, outError)
8026 ChildProc *cp = (ChildProc *) pr;
8030 outCount = fwrite(message, 1, count, stdout);
8032 outCount = write(cp->fdTo, message, count);
8042 /* Output message to process, with "ms" milliseconds of delay
8043 between each character. This is needed when sending the logon
8044 script to ICC, which for some reason doesn't like the
8045 instantaneous send. */
8046 int OutputToProcessDelayed(pr, message, count, outError, msdelay)
8053 ChildProc *cp = (ChildProc *) pr;
8058 r = write(cp->fdTo, message++, 1);
8071 /**** Animation code by Hugh Fisher, DCS, ANU.
8073 Known problem: if a window overlapping the board is
8074 moved away while a piece is being animated underneath,
8075 the newly exposed area won't be updated properly.
8076 I can live with this.
8078 Known problem: if you look carefully at the animation
8079 of pieces in mono mode, they are being drawn as solid
8080 shapes without interior detail while moving. Fixing
8081 this would be a major complication for minimal return.
8084 /* Masks for XPM pieces. Black and white pieces can have
8085 different shapes, but in the interest of retaining my
8086 sanity pieces must have the same outline on both light
8087 and dark squares, and all pieces must use the same
8088 background square colors/images. */
8090 static int xpmDone = 0;
8093 CreateAnimMasks (pieceDepth)
8100 unsigned long plane;
8103 /* Need a bitmap just to get a GC with right depth */
8104 buf = XCreatePixmap(xDisplay, xBoardWindow,
8106 values.foreground = 1;
8107 values.background = 0;
8108 /* Don't use XtGetGC, not read only */
8109 maskGC = XCreateGC(xDisplay, buf,
8110 GCForeground | GCBackground, &values);
8111 XFreePixmap(xDisplay, buf);
8113 buf = XCreatePixmap(xDisplay, xBoardWindow,
8114 squareSize, squareSize, pieceDepth);
8115 values.foreground = XBlackPixel(xDisplay, xScreen);
8116 values.background = XWhitePixel(xDisplay, xScreen);
8117 bufGC = XCreateGC(xDisplay, buf,
8118 GCForeground | GCBackground, &values);
8120 for (piece = WhitePawn; piece <= BlackKing; piece++) {
8121 /* Begin with empty mask */
8122 if(!xpmDone) // [HGM] pieces: keep using existing
8123 xpmMask[piece] = XCreatePixmap(xDisplay, xBoardWindow,
8124 squareSize, squareSize, 1);
8125 XSetFunction(xDisplay, maskGC, GXclear);
8126 XFillRectangle(xDisplay, xpmMask[piece], maskGC,
8127 0, 0, squareSize, squareSize);
8129 /* Take a copy of the piece */
8134 XSetFunction(xDisplay, bufGC, GXcopy);
8135 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn],
8137 0, 0, squareSize, squareSize, 0, 0);
8139 /* XOR the background (light) over the piece */
8140 XSetFunction(xDisplay, bufGC, GXxor);
8142 XCopyArea(xDisplay, xpmLightSquare, buf, bufGC,
8143 0, 0, squareSize, squareSize, 0, 0);
8145 XSetForeground(xDisplay, bufGC, lightSquareColor);
8146 XFillRectangle(xDisplay, buf, bufGC, 0, 0, squareSize, squareSize);
8149 /* We now have an inverted piece image with the background
8150 erased. Construct mask by just selecting all the non-zero
8151 pixels - no need to reconstruct the original image. */
8152 XSetFunction(xDisplay, maskGC, GXor);
8154 /* Might be quicker to download an XImage and create bitmap
8155 data from it rather than this N copies per piece, but it
8156 only takes a fraction of a second and there is a much
8157 longer delay for loading the pieces. */
8158 for (n = 0; n < pieceDepth; n ++) {
8159 XCopyPlane(xDisplay, buf, xpmMask[piece], maskGC,
8160 0, 0, squareSize, squareSize,
8166 XFreePixmap(xDisplay, buf);
8167 XFreeGC(xDisplay, bufGC);
8168 XFreeGC(xDisplay, maskGC);
8172 InitAnimState (anim, info)
8174 XWindowAttributes * info;
8179 /* Each buffer is square size, same depth as window */
8180 anim->saveBuf = XCreatePixmap(xDisplay, xBoardWindow,
8181 squareSize, squareSize, info->depth);
8182 anim->newBuf = XCreatePixmap(xDisplay, xBoardWindow,
8183 squareSize, squareSize, info->depth);
8185 /* Create a plain GC for blitting */
8186 mask = GCForeground | GCBackground | GCFunction |
8187 GCPlaneMask | GCGraphicsExposures;
8188 values.foreground = XBlackPixel(xDisplay, xScreen);
8189 values.background = XWhitePixel(xDisplay, xScreen);
8190 values.function = GXcopy;
8191 values.plane_mask = AllPlanes;
8192 values.graphics_exposures = False;
8193 anim->blitGC = XCreateGC(xDisplay, xBoardWindow, mask, &values);
8195 /* Piece will be copied from an existing context at
8196 the start of each new animation/drag. */
8197 anim->pieceGC = XCreateGC(xDisplay, xBoardWindow, 0, &values);
8199 /* Outline will be a read-only copy of an existing */
8200 anim->outlineGC = None;
8206 static VariantClass old = (VariantClass) -1; // [HGM] pieces: redo every time variant changes
8207 XWindowAttributes info;
8209 if (xpmDone && gameInfo.variant == old) return;
8210 if(xpmDone) old = gameInfo.variant; // first time pieces might not be created yet
8211 // XGetWindowAttributes(xDisplay, xBoardWindow, &info);
8213 InitAnimState(&game, &info);
8214 InitAnimState(&player, &info);
8216 /* For XPM pieces, we need bitmaps to use as masks. */
8218 CreateAnimMasks(info.depth);
8224 static Boolean frameWaiting;
8226 static RETSIGTYPE FrameAlarm (sig)
8229 frameWaiting = False;
8230 /* In case System-V style signals. Needed?? */
8231 signal(SIGALRM, FrameAlarm);
8238 struct itimerval delay;
8240 XSync(xDisplay, False);
8243 frameWaiting = True;
8244 signal(SIGALRM, FrameAlarm);
8245 delay.it_interval.tv_sec =
8246 delay.it_value.tv_sec = time / 1000;
8247 delay.it_interval.tv_usec =
8248 delay.it_value.tv_usec = (time % 1000) * 1000;
8249 setitimer(ITIMER_REAL, &delay, NULL);
8251 /* Ugh -- busy-wait! --tpm */
8252 while (frameWaiting);
8254 while (frameWaiting) pause();
8256 delay.it_interval.tv_sec = delay.it_value.tv_sec = 0;
8257 delay.it_interval.tv_usec = delay.it_value.tv_usec = 0;
8258 setitimer(ITIMER_REAL, &delay, NULL);
8268 XSync(xDisplay, False);
8270 usleep(time * 1000);
8275 /* Convert board position to corner of screen rect and color */
8278 ScreenSquare(column, row, pt, color)
8279 int column; int row; XPoint * pt; int * color;
8282 pt->x = lineGap + ((BOARD_WIDTH-1)-column) * (squareSize + lineGap);
8283 pt->y = lineGap + row * (squareSize + lineGap);
8285 pt->x = lineGap + column * (squareSize + lineGap);
8286 pt->y = lineGap + ((BOARD_HEIGHT-1)-row) * (squareSize + lineGap);
8288 *color = SquareColor(row, column);
8291 /* Convert window coords to square */
8294 BoardSquare(x, y, column, row)
8295 int x; int y; int * column; int * row;
8297 *column = EventToSquare(x, BOARD_WIDTH);
8298 if (flipView && *column >= 0)
8299 *column = BOARD_WIDTH - 1 - *column;
8300 *row = EventToSquare(y, BOARD_HEIGHT);
8301 if (!flipView && *row >= 0)
8302 *row = BOARD_HEIGHT - 1 - *row;
8307 #undef Max /* just in case */
8309 #define Max(a, b) ((a) > (b) ? (a) : (b))
8310 #define Min(a, b) ((a) < (b) ? (a) : (b))
8313 SetRect(rect, x, y, width, height)
8314 XRectangle * rect; int x; int y; int width; int height;
8318 rect->width = width;
8319 rect->height = height;
8322 /* Test if two frames overlap. If they do, return
8323 intersection rect within old and location of
8324 that rect within new. */
8327 Intersect(old, new, size, area, pt)
8328 XPoint * old; XPoint * new;
8329 int size; XRectangle * area; XPoint * pt;
8331 if (old->x > new->x + size || new->x > old->x + size ||
8332 old->y > new->y + size || new->y > old->y + size) {
8335 SetRect(area, Max(new->x - old->x, 0), Max(new->y - old->y, 0),
8336 size - abs(old->x - new->x), size - abs(old->y - new->y));
8337 pt->x = Max(old->x - new->x, 0);
8338 pt->y = Max(old->y - new->y, 0);
8343 /* For two overlapping frames, return the rect(s)
8344 in the old that do not intersect with the new. */
8347 CalcUpdateRects(old, new, size, update, nUpdates)
8348 XPoint * old; XPoint * new; int size;
8349 XRectangle update[]; int * nUpdates;
8353 /* If old = new (shouldn't happen) then nothing to draw */
8354 if (old->x == new->x && old->y == new->y) {
8358 /* Work out what bits overlap. Since we know the rects
8359 are the same size we don't need a full intersect calc. */
8361 /* Top or bottom edge? */
8362 if (new->y > old->y) {
8363 SetRect(&(update[count]), old->x, old->y, size, new->y - old->y);
8365 } else if (old->y > new->y) {
8366 SetRect(&(update[count]), old->x, old->y + size - (old->y - new->y),
8367 size, old->y - new->y);
8370 /* Left or right edge - don't overlap any update calculated above. */
8371 if (new->x > old->x) {
8372 SetRect(&(update[count]), old->x, Max(new->y, old->y),
8373 new->x - old->x, size - abs(new->y - old->y));
8375 } else if (old->x > new->x) {
8376 SetRect(&(update[count]), new->x + size, Max(new->y, old->y),
8377 old->x - new->x, size - abs(new->y - old->y));
8384 /* Generate a series of frame coords from start->mid->finish.
8385 The movement rate doubles until the half way point is
8386 reached, then halves back down to the final destination,
8387 which gives a nice slow in/out effect. The algorithmn
8388 may seem to generate too many intermediates for short
8389 moves, but remember that the purpose is to attract the
8390 viewers attention to the piece about to be moved and
8391 then to where it ends up. Too few frames would be less
8395 Tween(start, mid, finish, factor, frames, nFrames)
8396 XPoint * start; XPoint * mid;
8397 XPoint * finish; int factor;
8398 XPoint frames[]; int * nFrames;
8400 int fraction, n, count;
8404 /* Slow in, stepping 1/16th, then 1/8th, ... */
8406 for (n = 0; n < factor; n++)
8408 for (n = 0; n < factor; n++) {
8409 frames[count].x = start->x + (mid->x - start->x) / fraction;
8410 frames[count].y = start->y + (mid->y - start->y) / fraction;
8412 fraction = fraction / 2;
8416 frames[count] = *mid;
8419 /* Slow out, stepping 1/2, then 1/4, ... */
8421 for (n = 0; n < factor; n++) {
8422 frames[count].x = finish->x - (finish->x - mid->x) / fraction;
8423 frames[count].y = finish->y - (finish->y - mid->y) / fraction;
8425 fraction = fraction * 2;
8430 /* Draw a piece on the screen without disturbing what's there */
8433 SelectGCMask(piece, clip, outline, mask)
8434 ChessSquare piece; GC * clip; GC * outline; Pixmap * mask;
8438 /* Bitmap for piece being moved. */
8439 if (appData.monoMode) {
8440 *mask = *pieceToSolid(piece);
8441 } else if (useImages) {
8443 *mask = xpmMask[piece];
8445 *mask = ximMaskPm[piece];
8448 *mask = *pieceToSolid(piece);
8451 /* GC for piece being moved. Square color doesn't matter, but
8452 since it gets modified we make a copy of the original. */
8454 if (appData.monoMode)
8459 if (appData.monoMode)
8464 XCopyGC(xDisplay, source, 0xFFFFFFFF, *clip);
8466 /* Outline only used in mono mode and is not modified */
8468 *outline = bwPieceGC;
8470 *outline = wbPieceGC;
8474 OverlayPiece(piece, clip, outline, dest)
8475 ChessSquare piece; GC clip; GC outline; Drawable dest;
8480 /* Draw solid rectangle which will be clipped to shape of piece */
8481 XFillRectangle(xDisplay, dest, clip,
8482 0, 0, squareSize, squareSize);
8483 if (appData.monoMode)
8484 /* Also draw outline in contrasting color for black
8485 on black / white on white cases */
8486 XCopyPlane(xDisplay, *pieceToOutline(piece), dest, outline,
8487 0, 0, squareSize, squareSize, 0, 0, 1);
8489 /* Copy the piece */
8494 XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
8496 0, 0, squareSize, squareSize,
8501 /* Animate the movement of a single piece */
8504 BeginAnimation(anim, piece, startColor, start)
8512 /* The old buffer is initialised with the start square (empty) */
8513 BlankSquare(0, 0, startColor, EmptySquare, anim->saveBuf);
8514 anim->prevFrame = *start;
8516 /* The piece will be drawn using its own bitmap as a matte */
8517 SelectGCMask(piece, &anim->pieceGC, &anim->outlineGC, &mask);
8518 XSetClipMask(xDisplay, anim->pieceGC, mask);
8522 AnimationFrame(anim, frame, piece)
8527 XRectangle updates[4];
8532 /* Save what we are about to draw into the new buffer */
8533 XCopyArea(xDisplay, xBoardWindow, anim->newBuf, anim->blitGC,
8534 frame->x, frame->y, squareSize, squareSize,
8537 /* Erase bits of the previous frame */
8538 if (Intersect(&anim->prevFrame, frame, squareSize, &overlap, &pt)) {
8539 /* Where the new frame overlapped the previous,
8540 the contents in newBuf are wrong. */
8541 XCopyArea(xDisplay, anim->saveBuf, anim->newBuf, anim->blitGC,
8542 overlap.x, overlap.y,
8543 overlap.width, overlap.height,
8545 /* Repaint the areas in the old that don't overlap new */
8546 CalcUpdateRects(&anim->prevFrame, frame, squareSize, updates, &count);
8547 for (i = 0; i < count; i++)
8548 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
8549 updates[i].x - anim->prevFrame.x,
8550 updates[i].y - anim->prevFrame.y,
8551 updates[i].width, updates[i].height,
8552 updates[i].x, updates[i].y);
8554 /* Easy when no overlap */
8555 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
8556 0, 0, squareSize, squareSize,
8557 anim->prevFrame.x, anim->prevFrame.y);
8560 /* Save this frame for next time round */
8561 XCopyArea(xDisplay, anim->newBuf, anim->saveBuf, anim->blitGC,
8562 0, 0, squareSize, squareSize,
8564 anim->prevFrame = *frame;
8566 /* Draw piece over original screen contents, not current,
8567 and copy entire rect. Wipes out overlapping piece images. */
8568 OverlayPiece(piece, anim->pieceGC, anim->outlineGC, anim->newBuf);
8569 XCopyArea(xDisplay, anim->newBuf, xBoardWindow, anim->blitGC,
8570 0, 0, squareSize, squareSize,
8571 frame->x, frame->y);
8575 EndAnimation (anim, finish)
8579 XRectangle updates[4];
8584 /* The main code will redraw the final square, so we
8585 only need to erase the bits that don't overlap. */
8586 if (Intersect(&anim->prevFrame, finish, squareSize, &overlap, &pt)) {
8587 CalcUpdateRects(&anim->prevFrame, finish, squareSize, updates, &count);
8588 for (i = 0; i < count; i++)
8589 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
8590 updates[i].x - anim->prevFrame.x,
8591 updates[i].y - anim->prevFrame.y,
8592 updates[i].width, updates[i].height,
8593 updates[i].x, updates[i].y);
8595 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
8596 0, 0, squareSize, squareSize,
8597 anim->prevFrame.x, anim->prevFrame.y);
8602 FrameSequence(anim, piece, startColor, start, finish, frames, nFrames)
8604 ChessSquare piece; int startColor;
8605 XPoint * start; XPoint * finish;
8606 XPoint frames[]; int nFrames;
8610 BeginAnimation(anim, piece, startColor, start);
8611 for (n = 0; n < nFrames; n++) {
8612 AnimationFrame(anim, &(frames[n]), piece);
8613 FrameDelay(appData.animSpeed);
8615 EndAnimation(anim, finish);
8618 /* Main control logic for deciding what to animate and how */
8621 AnimateMove(board, fromX, fromY, toX, toY)
8630 XPoint start, finish, mid;
8631 XPoint frames[kFactor * 2 + 1];
8632 int nFrames, startColor, endColor;
8634 /* Are we animating? */
8635 if (!appData.animate || appData.blindfold)
8638 if(board[toY][toX] == WhiteRook && board[fromY][fromX] == WhiteKing ||
8639 board[toY][toX] == BlackRook && board[fromY][fromX] == BlackKing)
8640 return; // [HGM] FRC: no animtion of FRC castlings, as to-square is not true to-square
8642 if (fromY < 0 || fromX < 0 || toX < 0 || toY < 0) return;
8643 piece = board[fromY][fromX];
8644 if (piece >= EmptySquare) return;
8649 hop = (piece == WhiteKnight || piece == BlackKnight);
8652 if (appData.debugMode) {
8653 fprintf(debugFP, hop ? _("AnimateMove: piece %d hops from %d,%d to %d,%d \n") :
8654 _("AnimateMove: piece %d slides from %d,%d to %d,%d \n"),
8655 piece, fromX, fromY, toX, toY); }
8657 ScreenSquare(fromX, fromY, &start, &startColor);
8658 ScreenSquare(toX, toY, &finish, &endColor);
8661 /* Knight: make diagonal movement then straight */
8662 if (abs(toY - fromY) < abs(toX - fromX)) {
8663 mid.x = start.x + (finish.x - start.x) / 2;
8667 mid.y = start.y + (finish.y - start.y) / 2;
8670 mid.x = start.x + (finish.x - start.x) / 2;
8671 mid.y = start.y + (finish.y - start.y) / 2;
8674 /* Don't use as many frames for very short moves */
8675 if (abs(toY - fromY) + abs(toX - fromX) <= 2)
8676 Tween(&start, &mid, &finish, kFactor - 1, frames, &nFrames);
8678 Tween(&start, &mid, &finish, kFactor, frames, &nFrames);
8679 FrameSequence(&game, piece, startColor, &start, &finish, frames, nFrames);
8681 /* Be sure end square is redrawn */
8682 damage[toY][toX] = True;
8686 DragPieceBegin(x, y)
8689 int boardX, boardY, color;
8692 /* Are we animating? */
8693 if (!appData.animateDragging || appData.blindfold)
8696 /* Figure out which square we start in and the
8697 mouse position relative to top left corner. */
8698 BoardSquare(x, y, &boardX, &boardY);
8699 player.startBoardX = boardX;
8700 player.startBoardY = boardY;
8701 ScreenSquare(boardX, boardY, &corner, &color);
8702 player.startSquare = corner;
8703 player.startColor = color;
8705 /* Start from exactly where the piece is. This can be confusing
8706 if you start dragging far from the center of the square; most
8707 or all of the piece can be over a different square from the one
8708 the mouse pointer is in. */
8709 player.mouseDelta.x = x - corner.x;
8710 player.mouseDelta.y = y - corner.y;
8712 /* As soon as we start dragging, the piece will jump slightly to
8713 be centered over the mouse pointer. */
8714 player.mouseDelta.x = squareSize/2;
8715 player.mouseDelta.y = squareSize/2;
8717 /* Initialise animation */
8718 player.dragPiece = PieceForSquare(boardX, boardY);
8720 if (player.dragPiece >= 0 && player.dragPiece < EmptySquare) {
8721 player.dragActive = True;
8722 BeginAnimation(&player, player.dragPiece, color, &corner);
8723 /* Mark this square as needing to be redrawn. Note that
8724 we don't remove the piece though, since logically (ie
8725 as seen by opponent) the move hasn't been made yet. */
8726 if(boardX == BOARD_RGHT+1 && PieceForSquare(boardX-1, boardY) > 1 ||
8727 boardX == BOARD_LEFT-2 && PieceForSquare(boardX+1, boardY) > 1)
8728 XCopyArea(xDisplay, xBoardWindow, player.saveBuf, player.blitGC,
8729 corner.x, corner.y, squareSize, squareSize,
8730 0, 0); // [HGM] zh: unstack in stead of grab
8731 damage[boardY][boardX] = True;
8733 player.dragActive = False;
8743 /* Are we animating? */
8744 if (!appData.animateDragging || appData.blindfold)
8748 if (! player.dragActive)
8750 /* Move piece, maintaining same relative position
8751 of mouse within square */
8752 corner.x = x - player.mouseDelta.x;
8753 corner.y = y - player.mouseDelta.y;
8754 AnimationFrame(&player, &corner, player.dragPiece);
8756 if (appData.highlightDragging) {
8758 BoardSquare(x, y, &boardX, &boardY);
8759 SetHighlights(fromX, fromY, boardX, boardY);
8768 int boardX, boardY, color;
8771 /* Are we animating? */
8772 if (!appData.animateDragging || appData.blindfold)
8776 if (! player.dragActive)
8778 /* Last frame in sequence is square piece is
8779 placed on, which may not match mouse exactly. */
8780 BoardSquare(x, y, &boardX, &boardY);
8781 ScreenSquare(boardX, boardY, &corner, &color);
8782 EndAnimation(&player, &corner);
8784 /* Be sure end square is redrawn */
8785 damage[boardY][boardX] = True;
8787 /* This prevents weird things happening with fast successive
8788 clicks which on my Sun at least can cause motion events
8789 without corresponding press/release. */
8790 player.dragActive = False;
8793 /* Handle expose event while piece being dragged */
8798 if (!player.dragActive || appData.blindfold)
8801 /* What we're doing: logically, the move hasn't been made yet,
8802 so the piece is still in it's original square. But visually
8803 it's being dragged around the board. So we erase the square
8804 that the piece is on and draw it at the last known drag point. */
8805 BlankSquare(player.startSquare.x, player.startSquare.y,
8806 player.startColor, EmptySquare, xBoardWindow);
8807 AnimationFrame(&player, &player.prevFrame, player.dragPiece);
8808 damage[player.startBoardY][player.startBoardX] = TRUE;
8812 SetProgramStats( FrontEndProgramStats * stats )
8815 // [HGM] done, but perhaps backend should call this directly?
8816 EngineOutputUpdate( stats );