2 * xboard.c -- X front end for XBoard
4 * Copyright 1991 by Digital Equipment Corporation, Maynard,
7 * Enhancements Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006,
8 * 2007, 2008, 2009 Free Software Foundation, Inc.
10 * The following terms apply to Digital Equipment Corporation's copyright
12 * ------------------------------------------------------------------------
15 * Permission to use, copy, modify, and distribute this software and its
16 * documentation for any purpose and without fee is hereby granted,
17 * provided that the above copyright notice appear in all copies and that
18 * both that copyright notice and this permission notice appear in
19 * supporting documentation, and that the name of Digital not be
20 * used in advertising or publicity pertaining to distribution of the
21 * software without specific, written prior permission.
23 * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
24 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
25 * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
26 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
27 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
28 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
30 * ------------------------------------------------------------------------
32 * The following terms apply to the enhanced version of XBoard
33 * distributed by the Free Software Foundation:
34 * ------------------------------------------------------------------------
36 * GNU XBoard is free software: you can redistribute it and/or modify
37 * it under the terms of the GNU General Public License as published by
38 * the Free Software Foundation, either version 3 of the License, or (at
39 * your option) any later version.
41 * GNU XBoard is distributed in the hope that it will be useful, but
42 * WITHOUT ANY WARRANTY; without even the implied warranty of
43 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
44 * General Public License for more details.
46 * You should have received a copy of the GNU General Public License
47 * along with this program. If not, see http://www.gnu.org/licenses/. *
49 *------------------------------------------------------------------------
50 ** See the file ChangeLog for a revision history. */
58 #include <sys/types.h>
63 # if HAVE_SYS_SOCKET_H
64 # include <sys/socket.h>
65 # include <netinet/in.h>
67 # else /* not HAVE_SYS_SOCKET_H */
68 # if HAVE_LAN_SOCKET_H
69 # include <lan/socket.h>
71 # include <lan/netdb.h>
72 # else /* not HAVE_LAN_SOCKET_H */
73 # define OMIT_SOCKETS 1
74 # endif /* not HAVE_LAN_SOCKET_H */
75 # endif /* not HAVE_SYS_SOCKET_H */
76 #endif /* !OMIT_SOCKETS */
81 #else /* not STDC_HEADERS */
82 extern char *getenv();
85 # else /* not HAVE_STRING_H */
87 # endif /* not HAVE_STRING_H */
88 #endif /* not STDC_HEADERS */
91 # include <sys/fcntl.h>
92 #else /* not HAVE_SYS_FCNTL_H */
95 # endif /* HAVE_FCNTL_H */
96 #endif /* not HAVE_SYS_FCNTL_H */
98 #if HAVE_SYS_SYSTEMINFO_H
99 # include <sys/systeminfo.h>
100 #endif /* HAVE_SYS_SYSTEMINFO_H */
102 #if TIME_WITH_SYS_TIME
103 # include <sys/time.h>
107 # include <sys/time.h>
118 # include <sys/wait.h>
123 # define NAMLEN(dirent) strlen((dirent)->d_name)
124 # define HAVE_DIR_STRUCT
126 # define dirent direct
127 # define NAMLEN(dirent) (dirent)->d_namlen
129 # include <sys/ndir.h>
130 # define HAVE_DIR_STRUCT
133 # include <sys/dir.h>
134 # define HAVE_DIR_STRUCT
138 # define HAVE_DIR_STRUCT
142 #include <X11/Intrinsic.h>
143 #include <X11/StringDefs.h>
144 #include <X11/Shell.h>
145 #include <X11/cursorfont.h>
146 #include <X11/Xatom.h>
148 #include <X11/Xaw3d/Dialog.h>
149 #include <X11/Xaw3d/Form.h>
150 #include <X11/Xaw3d/List.h>
151 #include <X11/Xaw3d/Label.h>
152 #include <X11/Xaw3d/SimpleMenu.h>
153 #include <X11/Xaw3d/SmeBSB.h>
154 #include <X11/Xaw3d/SmeLine.h>
155 #include <X11/Xaw3d/Box.h>
156 #include <X11/Xaw3d/MenuButton.h>
157 #include <X11/Xaw3d/Text.h>
158 #include <X11/Xaw3d/AsciiText.h>
160 #include <X11/Xaw/Dialog.h>
161 #include <X11/Xaw/Form.h>
162 #include <X11/Xaw/List.h>
163 #include <X11/Xaw/Label.h>
164 #include <X11/Xaw/SimpleMenu.h>
165 #include <X11/Xaw/SmeBSB.h>
166 #include <X11/Xaw/SmeLine.h>
167 #include <X11/Xaw/Box.h>
168 #include <X11/Xaw/MenuButton.h>
169 #include <X11/Xaw/Text.h>
170 #include <X11/Xaw/AsciiText.h>
173 // [HGM] bitmaps: put before incuding the bitmaps / pixmaps, to know how many piece types there are.
178 #include "pixmaps/pixmaps.h"
179 #define IMAGE_EXT "xpm"
181 #define IMAGE_EXT "xim"
182 #include "bitmaps/bitmaps.h"
187 #include <gdk-pixbuf/gdk-pixbuf.h>
189 #include "bitmaps/icon_white.bm"
190 #include "bitmaps/icon_black.bm"
191 #include "bitmaps/checkmark.bm"
193 #include "frontend.h"
198 #include "xgamelist.h"
199 #include "xhistory.h"
200 #include "xedittags.h"
202 #include "callback.h"
203 #include "interface.h"
205 // must be moved to xengineoutput.h
207 void EngineOutputProc P((Widget w, XEvent *event,
208 String *prms, Cardinal *nprms));
210 void EngineOutputPopDown();
217 #define usleep(t) _sleep2(((t)+500)/1000)
221 # define _(s) gettext (s)
222 # define N_(s) gettext_noop (s)
245 int main P((int argc, char **argv));
246 RETSIGTYPE CmailSigHandler P((int sig));
247 RETSIGTYPE IntSigHandler P((int sig));
248 void CreateGCs P((void));
249 void CreateXIMPieces P((void));
250 void CreateXPMPieces P((void));
251 void CreatePieces P((void));
252 void CreatePieceMenus P((void));
253 Widget CreateMenuBar P((Menu *mb));
254 Widget CreateButtonBar P ((MenuItem *mi));
255 char *FindFont P((char *pattern, int targetPxlSize));
256 void PieceMenuPopup P((Widget w, XEvent *event,
257 String *params, Cardinal *num_params));
258 static void PieceMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
259 static void DropMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
260 int EventToSquare P((int x, int limit));
261 void DrawSquare P((int row, int column, ChessSquare piece, int do_flash));
262 void HandleUserMove P((Widget w, XEvent *event,
263 String *prms, Cardinal *nprms));
264 void AnimateUserMove P((Widget w, XEvent * event,
265 String * params, Cardinal * nParams));
266 void WhiteClock P((Widget w, XEvent *event,
267 String *prms, Cardinal *nprms));
268 void BlackClock P((Widget w, XEvent *event,
269 String *prms, Cardinal *nprms));
270 void CommentPopUp P((char *title, char *label));
271 void CommentPopDown P((void));
272 void CommentCallback P((Widget w, XtPointer client_data,
273 XtPointer call_data));
274 void ICSInputBoxPopUp P((void));
275 void ICSInputBoxPopDown P((void));
276 void FileNamePopUp P((char *label, char *def,
277 FileProc proc, char *openMode));
278 void FileNamePopDown P((void));
279 void FileNameCallback P((Widget w, XtPointer client_data,
280 XtPointer call_data));
281 void FileNameAction P((Widget w, XEvent *event,
282 String *prms, Cardinal *nprms));
283 void AskQuestionReplyAction P((Widget w, XEvent *event,
284 String *prms, Cardinal *nprms));
285 void AskQuestionProc P((Widget w, XEvent *event,
286 String *prms, Cardinal *nprms));
287 void AskQuestionPopDown P((void));
288 void PromotionPopUp P((void));
289 void PromotionPopDown P((void));
290 void PromotionCallback P((Widget w, XtPointer client_data,
291 XtPointer call_data));
292 void EditCommentPopDown P((void));
293 void EditCommentCallback P((Widget w, XtPointer client_data,
294 XtPointer call_data));
295 void SelectCommand P((Widget w, XtPointer client_data, XtPointer call_data));
296 void LoadPositionProc P((Widget w, XEvent *event,
297 String *prms, Cardinal *nprms));
298 void LoadNextPositionProc P((Widget w, XEvent *event, String *prms,
300 void LoadPrevPositionProc P((Widget w, XEvent *event, String *prms,
302 void ReloadPositionProc P((Widget w, XEvent *event, String *prms,
304 void CopyPositionProc P((Widget w, XEvent *event, String *prms,
306 void PastePositionProc P((Widget w, XEvent *event, String *prms,
308 void CopyGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
309 void PasteGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
310 void SaveGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
311 void SavePositionProc P((Widget w, XEvent *event,
312 String *prms, Cardinal *nprms));
313 void MailMoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
314 void ReloadCmailMsgProc P((Widget w, XEvent *event, String *prms,
316 void MachineBlackProc P((Widget w, XEvent *event, String *prms,
318 void MachineWhiteProc P((Widget w, XEvent *event,
319 String *prms, Cardinal *nprms));
320 void AnalyzeModeProc P((Widget w, XEvent *event,
321 String *prms, Cardinal *nprms));
322 void AnalyzeFileProc P((Widget w, XEvent *event,
323 String *prms, Cardinal *nprms));
324 void TwoMachinesProc P((Widget w, XEvent *event, String *prms,
326 void IcsClientProc P((Widget w, XEvent *event, String *prms,
328 void EditGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
329 void EditPositionProc P((Widget w, XEvent *event,
330 String *prms, Cardinal *nprms));
331 void TrainingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
332 void EditCommentProc P((Widget w, XEvent *event,
333 String *prms, Cardinal *nprms));
334 void IcsInputBoxProc P((Widget w, XEvent *event,
335 String *prms, Cardinal *nprms));
336 void AcceptProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
337 void DeclineProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
338 void RematchProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
339 void CallFlagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
340 void DrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
341 void AbortProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
342 void AdjournProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
343 void ResignProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
344 void AdjuWhiteProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
345 void AdjuBlackProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
346 void AdjuDrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
347 void EnterKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
348 void StopObservingProc P((Widget w, XEvent *event, String *prms,
350 void StopExaminingProc P((Widget w, XEvent *event, String *prms,
352 void BackwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
353 void ForwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
354 void ToStartProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
355 void ToEndProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
356 void RevertProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
357 void TruncateGameProc P((Widget w, XEvent *event, String *prms,
359 void RetractMoveProc P((Widget w, XEvent *event, String *prms,
361 void MoveNowProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
362 void AlwaysQueenProc P((Widget w, XEvent *event, String *prms,
364 void AnimateDraggingProc P((Widget w, XEvent *event, String *prms,
366 void AnimateMovingProc P((Widget w, XEvent *event, String *prms,
368 void AutocommProc P((Widget w, XEvent *event, String *prms,
370 void AutoflagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
371 void AutoflipProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
372 void AutobsProc P((Widget w, XEvent *event, String *prms,
374 void AutoraiseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
375 void AutosaveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
376 void BlindfoldProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
377 void FlashMovesProc P((Widget w, XEvent *event, String *prms,
379 void FlipViewProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
380 void GetMoveListProc P((Widget w, XEvent *event, String *prms,
382 void HighlightDraggingProc P((Widget w, XEvent *event, String *prms,
384 void HighlightLastMoveProc P((Widget w, XEvent *event, String *prms,
386 void MoveSoundProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
387 void IcsAlarmProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
388 void OldSaveStyleProc P((Widget w, XEvent *event, String *prms,
390 void PeriodicUpdatesProc P((Widget w, XEvent *event, String *prms,
392 void PonderNextMoveProc P((Widget w, XEvent *event, String *prms,
394 void PopupMoveErrorsProc P((Widget w, XEvent *event, String *prms,
396 void PopupExitMessageProc P((Widget w, XEvent *event, String *prms,
398 void PremoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
399 void QuietPlayProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
400 void ShowThinkingProc P((Widget w, XEvent *event, String *prms,
402 void HideThinkingProc P((Widget w, XEvent *event, String *prms,
404 void TestLegalityProc P((Widget w, XEvent *event, String *prms,
406 void InfoProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
407 void ManProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
408 void HintProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
409 void BookProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
410 void AboutGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
411 void DebugProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
412 void NothingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
413 void Iconify P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
414 void DisplayMove P((int moveNumber));
415 void DisplayTitle P((char *title));
416 void ICSInitScript P((void));
417 int LoadGamePopUp P((FILE *f, int gameNumber, char *title));
418 void ErrorPopUp P((char *title, char *text, int modal));
419 void ErrorPopDown P((void));
420 static char *ExpandPathName P((char *path));
421 static void CreateAnimVars P((void));
422 void DragPieceBegin P((int x, int y));
423 static void DragPieceMove P((int x, int y));
424 void DragPieceEnd P((int x, int y));
425 static void DrawDragPiece P((void));
426 char *ModeToWidgetName P((GameMode mode));
427 void EngineOutputUpdate( FrontEndProgramStats * stats );
428 void ShuffleMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
429 void EngineMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
430 void UciMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
431 void TimeControlProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
432 void NewVariantProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
433 void FirstSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
434 void SecondSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
435 void ShufflePopDown P(());
436 void EnginePopDown P(());
437 void UciPopDown P(());
438 void TimeControlPopDown P(());
439 void NewVariantPopDown P(());
440 void SettingsPopDown P(());
441 void SetMenuEnables P((Enables *enab));
444 * XBoard depends on Xt R4 or higher
446 int xtVersion = XtSpecificationRelease;
451 Pixel lightSquareColor, darkSquareColor, whitePieceColor, blackPieceColor,
452 jailSquareColor, highlightSquareColor, premoveHighlightColor;
453 Pixel lowTimeWarningColor;
455 #define LINE_TYPE_NORMAL 0
456 #define LINE_TYPE_HIGHLIGHT 1
457 #define LINE_TYPE_PRE 2
460 GC lightSquareGC, darkSquareGC, jailSquareGC, wdPieceGC, wlPieceGC,
461 bdPieceGC, blPieceGC, wbPieceGC, bwPieceGC, coordGC,
462 wjPieceGC, bjPieceGC;
463 Pixmap iconPixmap, wIconPixmap, bIconPixmap, xMarkPixmap;
464 Widget shellWidget, layoutWidget, formWidget, boardWidget, messageWidget,
465 whiteTimerWidget, blackTimerWidget, titleWidget, widgetList[16],
466 commentShell, promotionShell, whitePieceMenu, blackPieceMenu, dropMenu,
467 menuBarWidget, buttonBarWidget, editShell, errorShell, analysisShell,
468 ICSInputShell, fileNameShell, askQuestionShell;
469 Font clockFontID, coordFontID, countFontID;
470 XFontStruct *clockFontStruct, *coordFontStruct, *countFontStruct;
471 XtAppContext appContext;
473 char *oldICSInteractionTitle;
477 char installDir[] = "."; // [HGM] UCI: needed for UCI; probably needs run-time initializtion
479 Position commentX = -1, commentY = -1;
480 Dimension commentW, commentH;
482 int squareSize, smallLayout = 0, tinyLayout = 0,
483 marginW, marginH, // [HGM] for run-time resizing
484 fromX = -1, fromY = -1, toX, toY, commentUp = False, analysisUp = False,
485 ICSInputBoxUp = False, askQuestionUp = False,
486 filenameUp = False, promotionUp = False, pmFromX = -1, pmFromY = -1,
487 editUp = False, errorUp = False, errorExitStatus = -1, lineGap;
488 Pixel timerForegroundPixel, timerBackgroundPixel;
489 Pixel buttonForegroundPixel, buttonBackgroundPixel;
490 char *chessDir, *programName, *programVersion,
491 *gameCopyFilename, *gamePasteFilename;
495 Pixmap pieceBitmap[2][(int)BlackPawn];
496 Pixmap pieceBitmap2[2][(int)BlackPawn+4]; /* [HGM] pieces */
497 Pixmap xpmPieceBitmap[4][(int)BlackPawn]; /* LL, LD, DL, DD actually used*/
498 Pixmap xpmPieceBitmap2[4][(int)BlackPawn+4]; /* LL, LD, DL, DD set to select from */
499 Pixmap xpmLightSquare, xpmDarkSquare, xpmJailSquare;
500 int useImages=0, useImageSqs;
501 XImage *ximPieceBitmap[4][(int)BlackPawn+4]; /* LL, LD, DL, DD */
502 Pixmap ximMaskPm[(int)BlackPawn]; /* clipmasks, used for XIM pieces */
503 Pixmap ximMaskPm2[(int)BlackPawn+4]; /* clipmasks, used for XIM pieces */
504 XImage *ximLightSquare, *ximDarkSquare;
507 #define pieceToSolid(piece) &pieceBitmap[SOLID][(piece) % (int)BlackPawn]
508 #define pieceToOutline(piece) &pieceBitmap[OUTLINE][(piece) % (int)BlackPawn]
510 #define White(piece) ((int)(piece) < (int)BlackPawn)
512 /* Variables for doing smooth animation. This whole thing
513 would be much easier if the board was double-buffered,
514 but that would require a fairly major rewrite. */
519 GC blitGC, pieceGC, outlineGC;
520 XPoint startSquare, prevFrame, mouseDelta;
524 int startBoardX, startBoardY;
527 /* There can be two pieces being animated at once: a player
528 can begin dragging a piece before the remote opponent has moved. */
530 static AnimState game, player;
532 /* Bitmaps for use as masks when drawing XPM pieces.
533 Need one for each black and white piece. */
534 static Pixmap xpmMask[BlackKing + 1];
536 /* This magic number is the number of intermediate frames used
537 in each half of the animation. For short moves it's reduced
538 by 1. The total number of frames will be factor * 2 + 1. */
541 SizeDefaults sizeDefaults[] = SIZE_DEFAULTS;
543 Enables icsEnables[] = {
544 { "menuFile.Mail Move", False },
545 { "menuFile.Reload CMail Message", False },
546 { "menuMode.Machine Black", False },
547 { "menuMode.Machine White", False },
548 { "menuMode.Analysis Mode", False },
549 { "menuMode.Analyze File", False },
550 { "menuMode.Two Machines", False },
552 { "menuHelp.Hint", False },
553 { "menuHelp.Book", False },
554 { "menuStep.Move Now", False },
555 { "menuOptions.Periodic Updates", False },
556 { "menuOptions.Hide Thinking", False },
557 { "menuOptions.Ponder Next Move", False },
562 Enables ncpEnables[] = {
563 { "menuFile.Mail Move", False },
564 { "menuFile.Reload CMail Message", False },
565 { "menuMode.Machine White", False },
566 { "menuMode.Machine Black", False },
567 { "menuMode.Analysis Mode", False },
568 { "menuMode.Analyze File", False },
569 { "menuMode.Two Machines", False },
570 { "menuMode.ICS Client", False },
571 { "menuMode.ICS Input Box", False },
573 { "menuStep.Revert", False },
574 { "menuStep.Move Now", False },
575 { "menuStep.Retract Move", False },
576 { "menuOptions.Auto Comment", False },
577 { "menuOptions.Auto Flag", False },
578 { "menuOptions.Auto Flip View", False },
579 { "menuOptions.Auto Observe", False },
580 { "menuOptions.Auto Raise Board", False },
581 { "menuOptions.Get Move List", False },
582 { "menuOptions.ICS Alarm", False },
583 { "menuOptions.Move Sound", False },
584 { "menuOptions.Quiet Play", False },
585 { "menuOptions.Hide Thinking", False },
586 { "menuOptions.Periodic Updates", False },
587 { "menuOptions.Ponder Next Move", False },
588 { "menuHelp.Hint", False },
589 { "menuHelp.Book", False },
593 Enables gnuEnables[] = {
594 { "menuMode.ICS Client", False },
595 { "menuMode.ICS Input Box", False },
596 { "menuAction.Accept", False },
597 { "menuAction.Decline", False },
598 { "menuAction.Rematch", False },
599 { "menuAction.Adjourn", False },
600 { "menuAction.Stop Examining", False },
601 { "menuAction.Stop Observing", False },
602 { "menuStep.Revert", False },
603 { "menuOptions.Auto Comment", False },
604 { "menuOptions.Auto Observe", False },
605 { "menuOptions.Auto Raise Board", False },
606 { "menuOptions.Get Move List", False },
607 { "menuOptions.Premove", False },
608 { "menuOptions.Quiet Play", False },
610 /* The next two options rely on SetCmailMode being called *after* */
611 /* SetGNUMode so that when GNU is being used to give hints these */
612 /* menu options are still available */
614 { "menuFile.Mail Move", False },
615 { "menuFile.Reload CMail Message", False },
619 Enables cmailEnables[] = {
621 { "menuAction.Call Flag", False },
622 { "menuAction.Draw", True },
623 { "menuAction.Adjourn", False },
624 { "menuAction.Abort", False },
625 { "menuAction.Stop Observing", False },
626 { "menuAction.Stop Examining", False },
627 { "menuFile.Mail Move", True },
628 { "menuFile.Reload CMail Message", True },
632 Enables trainingOnEnables[] = {
633 { "menuMode.Edit Comment", False },
634 { "menuMode.Pause", False },
635 { "menuStep.Forward", False },
636 { "menuStep.Backward", False },
637 { "menuStep.Forward to End", False },
638 { "menuStep.Back to Start", False },
639 { "menuStep.Move Now", False },
640 { "menuStep.Truncate Game", False },
644 Enables trainingOffEnables[] = {
645 { "menuMode.Edit Comment", True },
646 { "menuMode.Pause", True },
647 { "menuStep.Forward", True },
648 { "menuStep.Backward", True },
649 { "menuStep.Forward to End", True },
650 { "menuStep.Back to Start", True },
651 { "menuStep.Move Now", True },
652 { "menuStep.Truncate Game", True },
656 Enables machineThinkingEnables[] = {
657 { "menuFile.Load Game", False },
658 { "menuFile.Load Next Game", False },
659 { "menuFile.Load Previous Game", False },
660 { "menuFile.Reload Same Game", False },
661 { "menuFile.Paste Game", False },
662 { "menuFile.Load Position", False },
663 { "menuFile.Load Next Position", False },
664 { "menuFile.Load Previous Position", False },
665 { "menuFile.Reload Same Position", False },
666 { "menuFile.Paste Position", False },
667 { "menuMode.Machine White", False },
668 { "menuMode.Machine Black", False },
669 { "menuMode.Two Machines", False },
670 { "menuStep.Retract Move", False },
674 Enables userThinkingEnables[] = {
675 { "menuFile.Load Game", True },
676 { "menuFile.Load Next Game", True },
677 { "menuFile.Load Previous Game", True },
678 { "menuFile.Reload Same Game", True },
679 { "menuFile.Paste Game", True },
680 { "menuFile.Load Position", True },
681 { "menuFile.Load Next Position", True },
682 { "menuFile.Load Previous Position", True },
683 { "menuFile.Reload Same Position", True },
684 { "menuFile.Paste Position", True },
685 { "menuMode.Machine White", True },
686 { "menuMode.Machine Black", True },
687 { "menuMode.Two Machines", True },
688 { "menuStep.Retract Move", True },
694 MenuItem fileMenu[] = {
695 {N_("New Shuffle Game ..."), ShuffleMenuProc},
696 {N_("New Variant ..."), NewVariantProc}, // [HGM] variant: not functional yet
697 {"----", NothingProc},
698 {N_("Save Game"), SaveGameProc},
699 {"----", NothingProc},
700 {N_("Copy Game"), CopyGameProc},
701 {N_("Paste Game"), PasteGameProc},
702 {"----", NothingProc},
703 {N_("Load Position"), LoadPositionProc},
704 {N_("Load Next Position"), LoadNextPositionProc},
705 {N_("Load Previous Position"), LoadPrevPositionProc},
706 {N_("Reload Same Position"), ReloadPositionProc},
707 {N_("Save Position"), SavePositionProc},
708 {"----", NothingProc},
709 {N_("Copy Position"), CopyPositionProc},
710 {N_("Paste Position"), PastePositionProc},
711 {"----", NothingProc},
712 {N_("Mail Move"), MailMoveProc},
713 {N_("Reload CMail Message"), ReloadCmailMsgProc},
714 {"----", NothingProc},
718 MenuItem modeMenu[] = {
719 {N_("Machine White"), MachineWhiteProc},
720 {N_("Machine Black"), MachineBlackProc},
721 {N_("Two Machines"), TwoMachinesProc},
722 {N_("Analysis Mode"), AnalyzeModeProc},
723 {N_("Analyze File"), AnalyzeFileProc },
724 {N_("ICS Client"), IcsClientProc},
725 {N_("Edit Game"), EditGameProc},
726 {N_("Edit Position"), EditPositionProc},
727 {N_("Training"), TrainingProc},
728 {"----", NothingProc},
729 {N_("Show Engine Output"), EngineOutputProc},
730 {N_("Show Evaluation Graph"), NothingProc}, // [HGM] evalgr: not functional yet
731 {N_("Show Game List"), ShowGameListProc},
732 {"Show Move History", HistoryShowProc}, // [HGM] hist: activate 4.2.7 code
733 {"----", NothingProc},
734 {N_("Edit Tags"), EditTagsProc},
735 {N_("Edit Comment"), EditCommentProc},
736 {N_("ICS Input Box"), IcsInputBoxProc},
740 MenuItem actionMenu[] = {
741 {N_("Accept"), AcceptProc},
742 {N_("Decline"), DeclineProc},
743 {N_("Rematch"), RematchProc},
744 {"----", NothingProc},
745 {N_("Call Flag"), CallFlagProc},
746 {N_("Draw"), DrawProc},
747 {N_("Adjourn"), AdjournProc},
748 {N_("Abort"), AbortProc},
749 {N_("Resign"), ResignProc},
750 {"----", NothingProc},
751 {N_("Stop Observing"), StopObservingProc},
752 {N_("Stop Examining"), StopExaminingProc},
753 {"----", NothingProc},
754 {N_("Adjudicate to White"), AdjuWhiteProc},
755 {N_("Adjudicate to Black"), AdjuBlackProc},
756 {N_("Adjudicate Draw"), AdjuDrawProc},
760 MenuItem stepMenu[] = {
761 {N_("Backward"), BackwardProc},
762 {N_("Forward"), ForwardProc},
763 {N_("Back to Start"), ToStartProc},
764 {N_("Forward to End"), ToEndProc},
765 {N_("Revert"), RevertProc},
766 {N_("Truncate Game"), TruncateGameProc},
767 {"----", NothingProc},
768 {N_("Move Now"), MoveNowProc},
769 {N_("Retract Move"), RetractMoveProc},
773 MenuItem optionsMenu[] = {
774 {N_("Flip View"), FlipViewProc},
775 {"----", NothingProc},
776 {N_("Adjudications ..."), EngineMenuProc},
777 {N_("General Settings ..."), UciMenuProc},
778 {N_("Engine #1 Settings ..."), FirstSettingsProc},
779 {N_("Engine #2 Settings ..."), SecondSettingsProc},
780 {N_("Time Control ..."), TimeControlProc},
781 {"----", NothingProc},
782 {N_("Always Queen"), AlwaysQueenProc},
783 {N_("Animate Dragging"), AnimateDraggingProc},
784 {N_("Animate Moving"), AnimateMovingProc},
785 {N_("Auto Comment"), AutocommProc},
786 {N_("Auto Flag"), AutoflagProc},
787 {N_("Auto Flip View"), AutoflipProc},
788 {N_("Auto Observe"), AutobsProc},
789 {N_("Auto Raise Board"), AutoraiseProc},
790 {N_("Auto Save"), AutosaveProc},
791 {N_("Blindfold"), BlindfoldProc},
792 {N_("Flash Moves"), FlashMovesProc},
793 {N_("Get Move List"), GetMoveListProc},
795 {N_("Highlight Dragging"), HighlightDraggingProc},
797 {N_("Highlight Last Move"), HighlightLastMoveProc},
798 {N_("Move Sound"), MoveSoundProc},
799 {N_("ICS Alarm"), IcsAlarmProc},
800 {N_("Old Save Style"), OldSaveStyleProc},
801 {N_("Periodic Updates"), PeriodicUpdatesProc},
802 {N_("Ponder Next Move"), PonderNextMoveProc},
803 {N_("Popup Exit Message"), PopupExitMessageProc},
804 {N_("Popup Move Errors"), PopupMoveErrorsProc},
805 {N_("Premove"), PremoveProc},
806 {N_("Quiet Play"), QuietPlayProc},
807 {N_("Hide Thinking"), HideThinkingProc},
808 {N_("Test Legality"), TestLegalityProc},
812 MenuItem helpMenu[] = {
813 {N_("Info XBoard"), InfoProc},
814 {N_("Man XBoard"), ManProc},
815 {"----", NothingProc},
816 {N_("Hint"), HintProc},
817 {N_("Book"), BookProc},
818 {"----", NothingProc},
823 {N_("File"), fileMenu},
824 {N_("Mode"), modeMenu},
825 {N_("Action"), actionMenu},
826 {N_("Step"), stepMenu},
827 {N_("Options"), optionsMenu},
828 {N_("Help"), helpMenu},
832 #define PAUSE_BUTTON N_("P")
833 MenuItem buttonBar[] = {
836 // {PAUSE_BUTTON, PauseProc},
842 #define PIECE_MENU_SIZE 18
843 String pieceMenuStrings[2][PIECE_MENU_SIZE] = {
844 { N_("White"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
845 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
846 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
847 N_("Empty square"), N_("Clear board") },
848 { N_("Black"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
849 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
850 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
851 N_("Empty square"), N_("Clear board") }
853 /* must be in same order as PieceMenuStrings! */
854 ChessSquare pieceMenuTranslation[2][PIECE_MENU_SIZE] = {
855 { WhitePlay, (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
856 WhiteRook, WhiteQueen, WhiteKing, (ChessSquare) 0, WhiteAlfil,
857 WhiteCannon, WhiteAngel, WhiteMarshall, (ChessSquare) 0,
858 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
859 { BlackPlay, (ChessSquare) 0, BlackPawn, BlackKnight, BlackBishop,
860 BlackRook, BlackQueen, BlackKing, (ChessSquare) 0, BlackAlfil,
861 BlackCannon, BlackAngel, BlackMarshall, (ChessSquare) 0,
862 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
865 #define DROP_MENU_SIZE 6
866 String dropMenuStrings[DROP_MENU_SIZE] = {
867 "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"), N_("Queen")
869 /* must be in same order as PieceMenuStrings! */
870 ChessSquare dropMenuTranslation[DROP_MENU_SIZE] = {
871 (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
872 WhiteRook, WhiteQueen
880 DropMenuEnables dmEnables[] = {
898 { XtNborderWidth, 0 },
899 { XtNdefaultDistance, 0 },
903 { XtNborderWidth, 0 },
904 { XtNresizable, (XtArgVal) True },
908 { XtNborderWidth, 0 },
914 { XtNjustify, (XtArgVal) XtJustifyRight },
915 { XtNlabel, (XtArgVal) "..." },
916 { XtNresizable, (XtArgVal) True },
917 { XtNresize, (XtArgVal) False }
920 Arg messageArgs[] = {
921 { XtNjustify, (XtArgVal) XtJustifyLeft },
922 { XtNlabel, (XtArgVal) "..." },
923 { XtNresizable, (XtArgVal) True },
924 { XtNresize, (XtArgVal) False }
928 { XtNborderWidth, 0 },
929 { XtNjustify, (XtArgVal) XtJustifyLeft }
932 XtResource clientResources[] = {
933 { "whitePieceColor", "whitePieceColor", XtRString, sizeof(String),
934 XtOffset(AppDataPtr, whitePieceColor), XtRString,
936 { "blackPieceColor", "blackPieceColor", XtRString, sizeof(String),
937 XtOffset(AppDataPtr, blackPieceColor), XtRString,
939 { "lightSquareColor", "lightSquareColor", XtRString,
940 sizeof(String), XtOffset(AppDataPtr, lightSquareColor),
941 XtRString, LIGHT_SQUARE_COLOR },
942 { "darkSquareColor", "darkSquareColor", XtRString, sizeof(String),
943 XtOffset(AppDataPtr, darkSquareColor), XtRString,
945 { "highlightSquareColor", "highlightSquareColor", XtRString,
946 sizeof(String), XtOffset(AppDataPtr, highlightSquareColor),
947 XtRString, HIGHLIGHT_SQUARE_COLOR },
948 { "premoveHighlightColor", "premoveHighlightColor", XtRString,
949 sizeof(String), XtOffset(AppDataPtr, premoveHighlightColor),
950 XtRString, PREMOVE_HIGHLIGHT_COLOR },
951 { "movesPerSession", "movesPerSession", XtRInt, sizeof(int),
952 XtOffset(AppDataPtr, movesPerSession), XtRImmediate,
953 (XtPointer) MOVES_PER_SESSION },
954 { "timeIncrement", "timeIncrement", XtRInt, sizeof(int),
955 XtOffset(AppDataPtr, timeIncrement), XtRImmediate,
956 (XtPointer) TIME_INCREMENT },
957 { "initString", "initString", XtRString, sizeof(String),
958 XtOffset(AppDataPtr, initString), XtRString, INIT_STRING },
959 { "secondInitString", "secondInitString", XtRString, sizeof(String),
960 XtOffset(AppDataPtr, secondInitString), XtRString, INIT_STRING },
961 { "firstComputerString", "firstComputerString", XtRString,
962 sizeof(String), XtOffset(AppDataPtr, firstComputerString), XtRString,
964 { "secondComputerString", "secondComputerString", XtRString,
965 sizeof(String), XtOffset(AppDataPtr, secondComputerString), XtRString,
967 { "firstChessProgram", "firstChessProgram", XtRString,
968 sizeof(String), XtOffset(AppDataPtr, firstChessProgram),
969 XtRString, FIRST_CHESS_PROGRAM },
970 { "secondChessProgram", "secondChessProgram", XtRString,
971 sizeof(String), XtOffset(AppDataPtr, secondChessProgram),
972 XtRString, SECOND_CHESS_PROGRAM },
973 { "firstPlaysBlack", "firstPlaysBlack", XtRBoolean,
974 sizeof(Boolean), XtOffset(AppDataPtr, firstPlaysBlack),
975 XtRImmediate, (XtPointer) False },
976 { "noChessProgram", "noChessProgram", XtRBoolean,
977 sizeof(Boolean), XtOffset(AppDataPtr, noChessProgram),
978 XtRImmediate, (XtPointer) False },
979 { "firstHost", "firstHost", XtRString, sizeof(String),
980 XtOffset(AppDataPtr, firstHost), XtRString, FIRST_HOST },
981 { "secondHost", "secondHost", XtRString, sizeof(String),
982 XtOffset(AppDataPtr, secondHost), XtRString, SECOND_HOST },
983 { "firstDirectory", "firstDirectory", XtRString, sizeof(String),
984 XtOffset(AppDataPtr, firstDirectory), XtRString, "." },
985 { "secondDirectory", "secondDirectory", XtRString, sizeof(String),
986 XtOffset(AppDataPtr, secondDirectory), XtRString, "." },
987 { "bitmapDirectory", "bitmapDirectory", XtRString,
988 sizeof(String), XtOffset(AppDataPtr, bitmapDirectory),
990 { "remoteShell", "remoteShell", XtRString, sizeof(String),
991 XtOffset(AppDataPtr, remoteShell), XtRString, REMOTE_SHELL },
992 { "remoteUser", "remoteUser", XtRString, sizeof(String),
993 XtOffset(AppDataPtr, remoteUser), XtRString, "" },
994 { "timeDelay", "timeDelay", XtRFloat, sizeof(float),
995 XtOffset(AppDataPtr, timeDelay), XtRString,
996 (XtPointer) TIME_DELAY_QUOTE },
997 { "timeControl", "timeControl", XtRString, sizeof(String),
998 XtOffset(AppDataPtr, timeControl), XtRString,
999 (XtPointer) TIME_CONTROL },
1000 { "internetChessServerMode", "internetChessServerMode",
1001 XtRBoolean, sizeof(Boolean),
1002 XtOffset(AppDataPtr, icsActive), XtRImmediate,
1003 (XtPointer) False },
1004 { "internetChessServerHost", "internetChessServerHost",
1005 XtRString, sizeof(String),
1006 XtOffset(AppDataPtr, icsHost),
1007 XtRString, (XtPointer) ICS_HOST },
1008 { "internetChessServerPort", "internetChessServerPort",
1009 XtRString, sizeof(String),
1010 XtOffset(AppDataPtr, icsPort), XtRString,
1011 (XtPointer) ICS_PORT },
1012 { "internetChessServerCommPort", "internetChessServerCommPort",
1013 XtRString, sizeof(String),
1014 XtOffset(AppDataPtr, icsCommPort), XtRString,
1016 { "internetChessServerLogonScript", "internetChessServerLogonScript",
1017 XtRString, sizeof(String),
1018 XtOffset(AppDataPtr, icsLogon), XtRString,
1020 { "internetChessServerHelper", "internetChessServerHelper",
1021 XtRString, sizeof(String),
1022 XtOffset(AppDataPtr, icsHelper), XtRString, "" },
1023 { "internetChessServerInputBox", "internetChessServerInputBox",
1024 XtRBoolean, sizeof(Boolean),
1025 XtOffset(AppDataPtr, icsInputBox), XtRImmediate,
1026 (XtPointer) False },
1027 { "icsAlarm", "icsAlarm",
1028 XtRBoolean, sizeof(Boolean),
1029 XtOffset(AppDataPtr, icsAlarm), XtRImmediate,
1031 { "icsAlarmTime", "icsAlarmTime",
1032 XtRInt, sizeof(int),
1033 XtOffset(AppDataPtr, icsAlarmTime), XtRImmediate,
1035 { "useTelnet", "useTelnet", XtRBoolean, sizeof(Boolean),
1036 XtOffset(AppDataPtr, useTelnet), XtRImmediate,
1037 (XtPointer) False },
1038 { "telnetProgram", "telnetProgram", XtRString, sizeof(String),
1039 XtOffset(AppDataPtr, telnetProgram), XtRString, TELNET_PROGRAM },
1040 { "gateway", "gateway", XtRString, sizeof(String),
1041 XtOffset(AppDataPtr, gateway), XtRString, "" },
1042 { "loadGameFile", "loadGameFile", XtRString, sizeof(String),
1043 XtOffset(AppDataPtr, loadGameFile), XtRString, "" },
1044 { "loadGameIndex", "loadGameIndex",
1045 XtRInt, sizeof(int),
1046 XtOffset(AppDataPtr, loadGameIndex), XtRImmediate,
1048 { "saveGameFile", "saveGameFile", XtRString, sizeof(String),
1049 XtOffset(AppDataPtr, saveGameFile), XtRString, "" },
1050 { "autoRaiseBoard", "autoRaiseBoard", XtRBoolean,
1051 sizeof(Boolean), XtOffset(AppDataPtr, autoRaiseBoard),
1052 XtRImmediate, (XtPointer) True },
1053 { "autoSaveGames", "autoSaveGames", XtRBoolean,
1054 sizeof(Boolean), XtOffset(AppDataPtr, autoSaveGames),
1055 XtRImmediate, (XtPointer) False },
1056 { "blindfold", "blindfold", XtRBoolean,
1057 sizeof(Boolean), XtOffset(AppDataPtr, blindfold),
1058 XtRImmediate, (XtPointer) False },
1059 { "loadPositionFile", "loadPositionFile", XtRString,
1060 sizeof(String), XtOffset(AppDataPtr, loadPositionFile),
1062 { "loadPositionIndex", "loadPositionIndex",
1063 XtRInt, sizeof(int),
1064 XtOffset(AppDataPtr, loadPositionIndex), XtRImmediate,
1066 { "savePositionFile", "savePositionFile", XtRString,
1067 sizeof(String), XtOffset(AppDataPtr, savePositionFile),
1069 { "matchMode", "matchMode", XtRBoolean, sizeof(Boolean),
1070 XtOffset(AppDataPtr, matchMode), XtRImmediate, (XtPointer) False },
1071 { "matchGames", "matchGames", XtRInt, sizeof(int),
1072 XtOffset(AppDataPtr, matchGames), XtRImmediate,
1074 { "monoMode", "monoMode", XtRBoolean, sizeof(Boolean),
1075 XtOffset(AppDataPtr, monoMode), XtRImmediate,
1076 (XtPointer) False },
1077 { "debugMode", "debugMode", XtRBoolean, sizeof(Boolean),
1078 XtOffset(AppDataPtr, debugMode), XtRImmediate,
1079 (XtPointer) False },
1080 { "clockMode", "clockMode", XtRBoolean, sizeof(Boolean),
1081 XtOffset(AppDataPtr, clockMode), XtRImmediate,
1083 { "boardSize", "boardSize", XtRString, sizeof(String),
1084 XtOffset(AppDataPtr, boardSize), XtRString, "" },
1085 { "searchTime", "searchTime", XtRString, sizeof(String),
1086 XtOffset(AppDataPtr, searchTime), XtRString,
1088 { "searchDepth", "searchDepth", XtRInt, sizeof(int),
1089 XtOffset(AppDataPtr, searchDepth), XtRImmediate,
1091 { "showCoords", "showCoords", XtRBoolean, sizeof(Boolean),
1092 XtOffset(AppDataPtr, showCoords), XtRImmediate,
1093 (XtPointer) False },
1094 { "showJail", "showJail", XtRInt, sizeof(int),
1095 XtOffset(AppDataPtr, showJail), XtRImmediate,
1097 { "showThinking", "showThinking", XtRBoolean, sizeof(Boolean),
1098 XtOffset(AppDataPtr, showThinking), XtRImmediate,
1100 { "ponderNextMove", "ponderNextMove", XtRBoolean, sizeof(Boolean),
1101 XtOffset(AppDataPtr, ponderNextMove), XtRImmediate,
1103 { "periodicUpdates", "periodicUpdates", XtRBoolean, sizeof(Boolean),
1104 XtOffset(AppDataPtr, periodicUpdates), XtRImmediate,
1106 { "clockFont", "clockFont", XtRString, sizeof(String),
1107 XtOffset(AppDataPtr, clockFont), XtRString, CLOCK_FONT },
1108 { "coordFont", "coordFont", XtRString, sizeof(String),
1109 XtOffset(AppDataPtr, coordFont), XtRString, COORD_FONT },
1110 { "font", "font", XtRString, sizeof(String),
1111 XtOffset(AppDataPtr, font), XtRString, DEFAULT_FONT },
1112 { "ringBellAfterMoves", "ringBellAfterMoves",
1113 XtRBoolean, sizeof(Boolean),
1114 XtOffset(AppDataPtr, ringBellAfterMoves),
1115 XtRImmediate, (XtPointer) False },
1116 { "autoCallFlag", "autoCallFlag", XtRBoolean,
1117 sizeof(Boolean), XtOffset(AppDataPtr, autoCallFlag),
1118 XtRImmediate, (XtPointer) False },
1119 { "autoFlipView", "autoFlipView", XtRBoolean,
1120 sizeof(Boolean), XtOffset(AppDataPtr, autoFlipView),
1121 XtRImmediate, (XtPointer) True },
1122 { "autoObserve", "autoObserve", XtRBoolean,
1123 sizeof(Boolean), XtOffset(AppDataPtr, autoObserve),
1124 XtRImmediate, (XtPointer) False },
1125 { "autoComment", "autoComment", XtRBoolean,
1126 sizeof(Boolean), XtOffset(AppDataPtr, autoComment),
1127 XtRImmediate, (XtPointer) False },
1128 { "getMoveList", "getMoveList", XtRBoolean,
1129 sizeof(Boolean), XtOffset(AppDataPtr, getMoveList),
1130 XtRImmediate, (XtPointer) True },
1132 { "highlightDragging", "highlightDragging", XtRBoolean,
1133 sizeof(Boolean), XtOffset(AppDataPtr, highlightDragging),
1134 XtRImmediate, (XtPointer) False },
1136 { "highlightLastMove", "highlightLastMove", XtRBoolean,
1137 sizeof(Boolean), XtOffset(AppDataPtr, highlightLastMove),
1138 XtRImmediate, (XtPointer) False },
1139 { "premove", "premove", XtRBoolean,
1140 sizeof(Boolean), XtOffset(AppDataPtr, premove),
1141 XtRImmediate, (XtPointer) True },
1142 { "testLegality", "testLegality", XtRBoolean,
1143 sizeof(Boolean), XtOffset(AppDataPtr, testLegality),
1144 XtRImmediate, (XtPointer) True },
1145 { "flipView", "flipView", XtRBoolean,
1146 sizeof(Boolean), XtOffset(AppDataPtr, flipView),
1147 XtRImmediate, (XtPointer) False },
1148 { "cmail", "cmailGameName", XtRString, sizeof(String),
1149 XtOffset(AppDataPtr, cmailGameName), XtRString, "" },
1150 { "alwaysPromoteToQueen", "alwaysPromoteToQueen", XtRBoolean,
1151 sizeof(Boolean), XtOffset(AppDataPtr, alwaysPromoteToQueen),
1152 XtRImmediate, (XtPointer) False },
1153 { "oldSaveStyle", "oldSaveStyle", XtRBoolean,
1154 sizeof(Boolean), XtOffset(AppDataPtr, oldSaveStyle),
1155 XtRImmediate, (XtPointer) False },
1156 { "quietPlay", "quietPlay", XtRBoolean,
1157 sizeof(Boolean), XtOffset(AppDataPtr, quietPlay),
1158 XtRImmediate, (XtPointer) False },
1159 { "titleInWindow", "titleInWindow", XtRBoolean,
1160 sizeof(Boolean), XtOffset(AppDataPtr, titleInWindow),
1161 XtRImmediate, (XtPointer) False },
1162 { "localLineEditing", "localLineEditing", XtRBoolean,
1163 sizeof(Boolean), XtOffset(AppDataPtr, localLineEditing),
1164 XtRImmediate, (XtPointer) True }, /* not implemented, must be True */
1166 { "zippyTalk", "zippyTalk", XtRBoolean,
1167 sizeof(Boolean), XtOffset(AppDataPtr, zippyTalk),
1168 XtRImmediate, (XtPointer) ZIPPY_TALK },
1169 { "zippyPlay", "zippyPlay", XtRBoolean,
1170 sizeof(Boolean), XtOffset(AppDataPtr, zippyPlay),
1171 XtRImmediate, (XtPointer) ZIPPY_PLAY },
1172 { "zippyLines", "zippyLines", XtRString, sizeof(String),
1173 XtOffset(AppDataPtr, zippyLines), XtRString, ZIPPY_LINES },
1174 { "zippyPinhead", "zippyPinhead", XtRString, sizeof(String),
1175 XtOffset(AppDataPtr, zippyPinhead), XtRString, ZIPPY_PINHEAD },
1176 { "zippyPassword", "zippyPassword", XtRString, sizeof(String),
1177 XtOffset(AppDataPtr, zippyPassword), XtRString, ZIPPY_PASSWORD },
1178 { "zippyPassword2", "zippyPassword2", XtRString, sizeof(String),
1179 XtOffset(AppDataPtr, zippyPassword2), XtRString, ZIPPY_PASSWORD2 },
1180 { "zippyWrongPassword", "zippyWrongPassword", XtRString, sizeof(String),
1181 XtOffset(AppDataPtr, zippyWrongPassword), XtRString,
1182 ZIPPY_WRONG_PASSWORD },
1183 { "zippyAcceptOnly", "zippyAcceptOnly", XtRString, sizeof(String),
1184 XtOffset(AppDataPtr, zippyAcceptOnly), XtRString, ZIPPY_ACCEPT_ONLY },
1185 { "zippyUseI", "zippyUseI", XtRBoolean,
1186 sizeof(Boolean), XtOffset(AppDataPtr, zippyUseI),
1187 XtRImmediate, (XtPointer) ZIPPY_USE_I },
1188 { "zippyBughouse", "zippyBughouse", XtRInt,
1189 sizeof(int), XtOffset(AppDataPtr, zippyBughouse),
1190 XtRImmediate, (XtPointer) ZIPPY_BUGHOUSE },
1191 { "zippyNoplayCrafty", "zippyNoplayCrafty", XtRBoolean,
1192 sizeof(Boolean), XtOffset(AppDataPtr, zippyNoplayCrafty),
1193 XtRImmediate, (XtPointer) ZIPPY_NOPLAY_CRAFTY },
1194 { "zippyGameEnd", "zippyGameEnd", XtRString, sizeof(String),
1195 XtOffset(AppDataPtr, zippyGameEnd), XtRString, ZIPPY_GAME_END },
1196 { "zippyGameStart", "zippyGameStart", XtRString, sizeof(String),
1197 XtOffset(AppDataPtr, zippyGameStart), XtRString, ZIPPY_GAME_START },
1198 { "zippyAdjourn", "zippyAdjourn", XtRBoolean,
1199 sizeof(Boolean), XtOffset(AppDataPtr, zippyAdjourn),
1200 XtRImmediate, (XtPointer) ZIPPY_ADJOURN },
1201 { "zippyAbort", "zippyAbort", XtRBoolean,
1202 sizeof(Boolean), XtOffset(AppDataPtr, zippyAbort),
1203 XtRImmediate, (XtPointer) ZIPPY_ABORT },
1204 { "zippyVariants", "zippyVariants", XtRString, sizeof(String),
1205 XtOffset(AppDataPtr, zippyVariants), XtRString, ZIPPY_VARIANTS },
1206 { "zippyMaxGames", "zippyMaxGames", XtRInt, sizeof(int),
1207 XtOffset(AppDataPtr, zippyMaxGames), XtRImmediate,
1208 (XtPointer) ZIPPY_MAX_GAMES },
1209 { "zippyReplayTimeout", "zippyReplayTimeout", XtRInt, sizeof(int),
1210 XtOffset(AppDataPtr, zippyReplayTimeout), XtRImmediate,
1211 (XtPointer) ZIPPY_REPLAY_TIMEOUT },
1212 { "zippyShortGame", "zippyShortGame", XtRInt, sizeof(int),
1213 XtOffset(AppDataPtr, zippyShortGame), XtRImmediate,
1216 { "flashCount", "flashCount", XtRInt, sizeof(int),
1217 XtOffset(AppDataPtr, flashCount), XtRImmediate,
1218 (XtPointer) FLASH_COUNT },
1219 { "flashRate", "flashRate", XtRInt, sizeof(int),
1220 XtOffset(AppDataPtr, flashRate), XtRImmediate,
1221 (XtPointer) FLASH_RATE },
1222 { "pixmapDirectory", "pixmapDirectory", XtRString,
1223 sizeof(String), XtOffset(AppDataPtr, pixmapDirectory),
1225 { "msLoginDelay", "msLoginDelay", XtRInt, sizeof(int),
1226 XtOffset(AppDataPtr, msLoginDelay), XtRImmediate,
1227 (XtPointer) MS_LOGIN_DELAY },
1228 { "colorizeMessages", "colorizeMessages", XtRBoolean,
1229 sizeof(Boolean), XtOffset(AppDataPtr, colorize),
1230 XtRImmediate, (XtPointer) False },
1231 { "colorShout", "colorShout", XtRString,
1232 sizeof(String), XtOffset(AppDataPtr, colorShout),
1233 XtRString, COLOR_SHOUT },
1234 { "colorSShout", "colorSShout", XtRString,
1235 sizeof(String), XtOffset(AppDataPtr, colorSShout),
1236 XtRString, COLOR_SSHOUT },
1237 { "colorChannel1", "colorChannel1", XtRString,
1238 sizeof(String), XtOffset(AppDataPtr, colorChannel1),
1239 XtRString, COLOR_CHANNEL1 },
1240 { "colorChannel", "colorChannel", XtRString,
1241 sizeof(String), XtOffset(AppDataPtr, colorChannel),
1242 XtRString, COLOR_CHANNEL },
1243 { "colorKibitz", "colorKibitz", XtRString,
1244 sizeof(String), XtOffset(AppDataPtr, colorKibitz),
1245 XtRString, COLOR_KIBITZ },
1246 { "colorTell", "colorTell", XtRString,
1247 sizeof(String), XtOffset(AppDataPtr, colorTell),
1248 XtRString, COLOR_TELL },
1249 { "colorChallenge", "colorChallenge", XtRString,
1250 sizeof(String), XtOffset(AppDataPtr, colorChallenge),
1251 XtRString, COLOR_CHALLENGE },
1252 { "colorRequest", "colorRequest", XtRString,
1253 sizeof(String), XtOffset(AppDataPtr, colorRequest),
1254 XtRString, COLOR_REQUEST },
1255 { "colorSeek", "colorSeek", XtRString,
1256 sizeof(String), XtOffset(AppDataPtr, colorSeek),
1257 XtRString, COLOR_SEEK },
1258 { "colorNormal", "colorNormal", XtRString,
1259 sizeof(String), XtOffset(AppDataPtr, colorNormal),
1260 XtRString, COLOR_NORMAL },
1261 { "soundProgram", "soundProgram", XtRString,
1262 sizeof(String), XtOffset(AppDataPtr, soundProgram),
1263 XtRString, "play" },
1264 { "soundShout", "soundShout", XtRString,
1265 sizeof(String), XtOffset(AppDataPtr, soundShout),
1267 { "soundSShout", "soundSShout", XtRString,
1268 sizeof(String), XtOffset(AppDataPtr, soundSShout),
1270 { "soundChannel1", "soundChannel1", XtRString,
1271 sizeof(String), XtOffset(AppDataPtr, soundChannel1),
1273 { "soundChannel", "soundChannel", XtRString,
1274 sizeof(String), XtOffset(AppDataPtr, soundChannel),
1276 { "soundKibitz", "soundKibitz", XtRString,
1277 sizeof(String), XtOffset(AppDataPtr, soundKibitz),
1279 { "soundTell", "soundTell", XtRString,
1280 sizeof(String), XtOffset(AppDataPtr, soundTell),
1282 { "soundChallenge", "soundChallenge", XtRString,
1283 sizeof(String), XtOffset(AppDataPtr, soundChallenge),
1285 { "soundRequest", "soundRequest", XtRString,
1286 sizeof(String), XtOffset(AppDataPtr, soundRequest),
1288 { "soundSeek", "soundSeek", XtRString,
1289 sizeof(String), XtOffset(AppDataPtr, soundSeek),
1291 { "soundMove", "soundMove", XtRString,
1292 sizeof(String), XtOffset(AppDataPtr, soundMove),
1294 { "soundIcsWin", "soundIcsWin", XtRString,
1295 sizeof(String), XtOffset(AppDataPtr, soundIcsWin),
1297 { "soundIcsLoss", "soundIcsLoss", XtRString,
1298 sizeof(String), XtOffset(AppDataPtr, soundIcsLoss),
1300 { "soundIcsDraw", "soundIcsDraw", XtRString,
1301 sizeof(String), XtOffset(AppDataPtr, soundIcsDraw),
1303 { "soundIcsUnfinished", "soundIcsUnfinished", XtRString,
1304 sizeof(String), XtOffset(AppDataPtr, soundIcsUnfinished),
1306 { "soundIcsAlarm", "soundIcsAlarm", XtRString,
1307 sizeof(String), XtOffset(AppDataPtr, soundIcsAlarm),
1309 { "reuseFirst", "reuseFirst", XtRBoolean,
1310 sizeof(Boolean), XtOffset(AppDataPtr, reuseFirst),
1311 XtRImmediate, (XtPointer) True },
1312 { "reuseSecond", "reuseSecond", XtRBoolean,
1313 sizeof(Boolean), XtOffset(AppDataPtr, reuseSecond),
1314 XtRImmediate, (XtPointer) True },
1315 { "animateDragging", "animateDragging", XtRBoolean,
1316 sizeof(Boolean), XtOffset(AppDataPtr, animateDragging),
1317 XtRImmediate, (XtPointer) True },
1318 { "animateMoving", "animateMoving", XtRBoolean,
1319 sizeof(Boolean), XtOffset(AppDataPtr, animate),
1320 XtRImmediate, (XtPointer) True },
1321 { "animateSpeed", "animateSpeed", XtRInt,
1322 sizeof(int), XtOffset(AppDataPtr, animSpeed),
1323 XtRImmediate, (XtPointer)10 },
1324 { "popupExitMessage", "popupExitMessage", XtRBoolean,
1325 sizeof(Boolean), XtOffset(AppDataPtr, popupExitMessage),
1326 XtRImmediate, (XtPointer) True },
1327 { "popupMoveErrors", "popupMoveErrors", XtRBoolean,
1328 sizeof(Boolean), XtOffset(AppDataPtr, popupMoveErrors),
1329 XtRImmediate, (XtPointer) False },
1330 { "fontSizeTolerance", "fontSizeTolerance", XtRInt,
1331 sizeof(int), XtOffset(AppDataPtr, fontSizeTolerance),
1332 XtRImmediate, (XtPointer)4 },
1333 { "initialMode", "initialMode", XtRString,
1334 sizeof(String), XtOffset(AppDataPtr, initialMode),
1335 XtRImmediate, (XtPointer) "" },
1336 { "variant", "variant", XtRString,
1337 sizeof(String), XtOffset(AppDataPtr, variant),
1338 XtRImmediate, (XtPointer) "normal" },
1339 { "firstProtocolVersion", "firstProtocolVersion", XtRInt,
1340 sizeof(int), XtOffset(AppDataPtr, firstProtocolVersion),
1341 XtRImmediate, (XtPointer)PROTOVER },
1342 { "secondProtocolVersion", "secondProtocolVersion", XtRInt,
1343 sizeof(int), XtOffset(AppDataPtr, secondProtocolVersion),
1344 XtRImmediate, (XtPointer)PROTOVER },
1345 { "showButtonBar", "showButtonBar", XtRBoolean,
1346 sizeof(Boolean), XtOffset(AppDataPtr, showButtonBar),
1347 XtRImmediate, (XtPointer) True },
1348 { "lowTimeWarningColor", "lowTimeWarningColor", XtRString,
1349 sizeof(String), XtOffset(AppDataPtr, lowTimeWarningColor),
1350 XtRString, COLOR_LOWTIMEWARNING },
1351 { "lowTimeWarning", "lowTimeWarning", XtRBoolean,
1352 sizeof(Boolean), XtOffset(AppDataPtr, lowTimeWarning),
1353 XtRImmediate, (XtPointer) False },
1354 {"icsEngineAnalyze", "icsEngineAnalyze", XtRBoolean, /* [DM] icsEngineAnalyze */
1355 sizeof(Boolean), XtOffset(AppDataPtr, icsEngineAnalyze),
1356 XtRImmediate, (XtPointer) False },
1357 { "firstScoreAbs", "firstScoreAbs", XtRBoolean,
1358 sizeof(Boolean), XtOffset(AppDataPtr, firstScoreIsAbsolute),
1359 XtRImmediate, (XtPointer) False },
1360 { "secondScoreAbs", "secondScoreAbs", XtRBoolean,
1361 sizeof(Boolean), XtOffset(AppDataPtr, secondScoreIsAbsolute),
1362 XtRImmediate, (XtPointer) False },
1363 { "pgnExtendedInfo", "pgnExtendedInfo", XtRBoolean,
1364 sizeof(Boolean), XtOffset(AppDataPtr, saveExtendedInfoInPGN),
1365 XtRImmediate, (XtPointer) False },
1366 { "hideThinkingFromHuman", "hideThinkingFromHuman", XtRBoolean,
1367 sizeof(Boolean), XtOffset(AppDataPtr, hideThinkingFromHuman),
1368 XtRImmediate, (XtPointer) True },
1369 { "adjudicateLossThreshold", "adjudicateLossThreshold", XtRInt,
1370 sizeof(int), XtOffset(AppDataPtr, adjudicateLossThreshold),
1371 XtRImmediate, (XtPointer) 0},
1372 { "pgnEventHeader", "pgnEventHeader", XtRString,
1373 sizeof(String), XtOffset(AppDataPtr, pgnEventHeader),
1374 XtRImmediate, (XtPointer) "Computer Chess Game" },
1375 { "defaultFrcPosition", "defaultFrcPositon", XtRInt,
1376 sizeof(int), XtOffset(AppDataPtr, defaultFrcPosition),
1377 XtRImmediate, (XtPointer) -1},
1378 { "gameListTags", "gameListTags", XtRString,
1379 sizeof(String), XtOffset(AppDataPtr, gameListTags),
1380 XtRImmediate, (XtPointer) GLT_DEFAULT_TAGS },
1382 // [HGM] 4.3.xx options
1383 { "boardWidth", "boardWidth", XtRInt,
1384 sizeof(int), XtOffset(AppDataPtr, NrFiles),
1385 XtRImmediate, (XtPointer) -1},
1386 { "boardHeight", "boardHeight", XtRInt,
1387 sizeof(int), XtOffset(AppDataPtr, NrRanks),
1388 XtRImmediate, (XtPointer) -1},
1389 { "matchPause", "matchPause", XtRInt,
1390 sizeof(int), XtOffset(AppDataPtr, matchPause),
1391 XtRImmediate, (XtPointer) 10000},
1392 { "holdingsSize", "holdingsSize", XtRInt,
1393 sizeof(int), XtOffset(AppDataPtr, holdingsSize),
1394 XtRImmediate, (XtPointer) -1},
1395 { "flipBlack", "flipBlack", XtRBoolean,
1396 sizeof(Boolean), XtOffset(AppDataPtr, upsideDown),
1397 XtRImmediate, (XtPointer) False},
1398 { "allWhite", "allWhite", XtRBoolean,
1399 sizeof(Boolean), XtOffset(AppDataPtr, allWhite),
1400 XtRImmediate, (XtPointer) False},
1401 { "pieceToCharTable", "pieceToCharTable", XtRString,
1402 sizeof(String), XtOffset(AppDataPtr, pieceToCharTable),
1403 XtRImmediate, (XtPointer) 0},
1404 { "alphaRank", "alphaRank", XtRBoolean,
1405 sizeof(Boolean), XtOffset(AppDataPtr, alphaRank),
1406 XtRImmediate, (XtPointer) False},
1407 { "testClaims", "testClaims", XtRBoolean,
1408 sizeof(Boolean), XtOffset(AppDataPtr, testClaims),
1409 XtRImmediate, (XtPointer) True},
1410 { "checkMates", "checkMates", XtRBoolean,
1411 sizeof(Boolean), XtOffset(AppDataPtr, checkMates),
1412 XtRImmediate, (XtPointer) True},
1413 { "materialDraws", "materialDraws", XtRBoolean,
1414 sizeof(Boolean), XtOffset(AppDataPtr, materialDraws),
1415 XtRImmediate, (XtPointer) True},
1416 { "trivialDraws", "trivialDraws", XtRBoolean,
1417 sizeof(Boolean), XtOffset(AppDataPtr, trivialDraws),
1418 XtRImmediate, (XtPointer) False},
1419 { "ruleMoves", "ruleMoves", XtRInt,
1420 sizeof(int), XtOffset(AppDataPtr, ruleMoves),
1421 XtRImmediate, (XtPointer) 51},
1422 { "repeatsToDraw", "repeatsToDraw", XtRInt,
1423 sizeof(int), XtOffset(AppDataPtr, drawRepeats),
1424 XtRImmediate, (XtPointer) 6},
1425 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1426 sizeof(int), XtOffset(AppDataPtr, engineComments),
1427 XtRImmediate, (XtPointer) 1},
1428 { "userName", "userName", XtRString,
1429 sizeof(int), XtOffset(AppDataPtr, userName),
1430 XtRImmediate, (XtPointer) 0},
1431 { "autoKibitz", "autoKibitz", XtRBoolean,
1432 sizeof(Boolean), XtOffset(AppDataPtr, autoKibitz),
1433 XtRImmediate, (XtPointer) False},
1434 { "firstTimeOdds", "firstTimeOdds", XtRInt,
1435 sizeof(int), XtOffset(AppDataPtr, firstTimeOdds),
1436 XtRImmediate, (XtPointer) 1},
1437 { "secondTimeOdds", "secondTimeOdds", XtRInt,
1438 sizeof(int), XtOffset(AppDataPtr, secondTimeOdds),
1439 XtRImmediate, (XtPointer) 1},
1440 { "timeOddsMode", "timeOddsMode", XtRInt,
1441 sizeof(int), XtOffset(AppDataPtr, timeOddsMode),
1442 XtRImmediate, (XtPointer) 0},
1443 { "firstAccumulateTC", "firstAccumulateTC", XtRInt,
1444 sizeof(int), XtOffset(AppDataPtr, firstAccumulateTC),
1445 XtRImmediate, (XtPointer) 1},
1446 { "secondAccumulateTC", "secondAccumulateTC", XtRInt,
1447 sizeof(int), XtOffset(AppDataPtr, secondAccumulateTC),
1448 XtRImmediate, (XtPointer) 1},
1449 { "firstNPS", "firstNPS", XtRInt,
1450 sizeof(int), XtOffset(AppDataPtr, firstNPS),
1451 XtRImmediate, (XtPointer) -1},
1452 { "secondNPS", "secondNPS", XtRInt,
1453 sizeof(int), XtOffset(AppDataPtr, secondNPS),
1454 XtRImmediate, (XtPointer) -1},
1455 { "serverMoves", "serverMoves", XtRString,
1456 sizeof(String), XtOffset(AppDataPtr, serverMovesName),
1457 XtRImmediate, (XtPointer) 0},
1458 { "serverPause", "serverPause", XtRInt,
1459 sizeof(int), XtOffset(AppDataPtr, serverPause),
1460 XtRImmediate, (XtPointer) 0},
1461 { "suppressLoadMoves", "suppressLoadMoves", XtRBoolean,
1462 sizeof(Boolean), XtOffset(AppDataPtr, suppressLoadMoves),
1463 XtRImmediate, (XtPointer) False},
1464 { "userName", "userName", XtRString,
1465 sizeof(String), XtOffset(AppDataPtr, userName),
1466 XtRImmediate, (XtPointer) 0},
1467 { "egtFormats", "egtFormats", XtRString,
1468 sizeof(String), XtOffset(AppDataPtr, egtFormats),
1469 XtRImmediate, (XtPointer) 0},
1470 { "rewindIndex", "rewindIndex", XtRInt,
1471 sizeof(int), XtOffset(AppDataPtr, rewindIndex),
1472 XtRImmediate, (XtPointer) 0},
1473 { "sameColorGames", "sameColorGames", XtRInt,
1474 sizeof(int), XtOffset(AppDataPtr, sameColorGames),
1475 XtRImmediate, (XtPointer) 0},
1476 { "smpCores", "smpCores", XtRInt,
1477 sizeof(int), XtOffset(AppDataPtr, smpCores),
1478 XtRImmediate, (XtPointer) 1},
1479 { "niceEngines", "niceEngines", XtRInt,
1480 sizeof(int), XtOffset(AppDataPtr, niceEngines),
1481 XtRImmediate, (XtPointer) 0},
1482 { "nameOfDebugFile", "nameOfDebugFile", XtRString,
1483 sizeof(String), XtOffset(AppDataPtr, nameOfDebugFile),
1484 XtRImmediate, (XtPointer) "xboard.debug"},
1485 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1486 sizeof(int), XtOffset(AppDataPtr, engineComments),
1487 XtRImmediate, (XtPointer) 0},
1488 { "noGUI", "noGUI", XtRBoolean,
1489 sizeof(Boolean), XtOffset(AppDataPtr, noGUI),
1490 XtRImmediate, (XtPointer) 0},
1491 { "firstOptions", "firstOptions", XtRString,
1492 sizeof(String), XtOffset(AppDataPtr, firstOptions),
1493 XtRImmediate, (XtPointer) "" },
1494 { "secondOptions", "secondOptions", XtRString,
1495 sizeof(String), XtOffset(AppDataPtr, secondOptions),
1496 XtRImmediate, (XtPointer) "" },
1497 { "firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XtRString,
1498 sizeof(String), XtOffset(AppDataPtr, fenOverride1),
1499 XtRImmediate, (XtPointer) 0 },
1500 { "secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XtRString,
1501 sizeof(String), XtOffset(AppDataPtr, fenOverride2),
1502 XtRImmediate, (XtPointer) 0 },
1504 // [HGM] Winboard_x UCI options
1505 { "firstIsUCI", "firstIsUCI", XtRBoolean,
1506 sizeof(Boolean), XtOffset(AppDataPtr, firstIsUCI),
1507 XtRImmediate, (XtPointer) False},
1508 { "secondIsUCI", "secondIsUCI", XtRBoolean,
1509 sizeof(Boolean), XtOffset(AppDataPtr, secondIsUCI),
1510 XtRImmediate, (XtPointer) False},
1511 { "firstHasOwnBookUCI", "firstHasOwnBookUCI", XtRBoolean,
1512 sizeof(Boolean), XtOffset(AppDataPtr, firstHasOwnBookUCI),
1513 XtRImmediate, (XtPointer) True},
1514 { "secondHasOwnBookUCI", "secondHasOwnBookUCI", XtRBoolean,
1515 sizeof(Boolean), XtOffset(AppDataPtr, secondHasOwnBookUCI),
1516 XtRImmediate, (XtPointer) True},
1517 { "usePolyglotBook", "usePolyglotBook", XtRBoolean,
1518 sizeof(Boolean), XtOffset(AppDataPtr, usePolyglotBook),
1519 XtRImmediate, (XtPointer) False},
1520 { "defaultHashSize", "defaultHashSize", XtRInt,
1521 sizeof(int), XtOffset(AppDataPtr, defaultHashSize),
1522 XtRImmediate, (XtPointer) 64},
1523 { "defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XtRInt,
1524 sizeof(int), XtOffset(AppDataPtr, defaultCacheSizeEGTB),
1525 XtRImmediate, (XtPointer) 4},
1526 { "polyglotDir", "polyglotDir", XtRString,
1527 sizeof(String), XtOffset(AppDataPtr, polyglotDir),
1528 XtRImmediate, (XtPointer) "." },
1529 { "polyglotBook", "polyglotBook", XtRString,
1530 sizeof(String), XtOffset(AppDataPtr, polyglotBook),
1531 XtRImmediate, (XtPointer) "" },
1532 { "defaultPathEGTB", "defaultPathEGTB", XtRString,
1533 sizeof(String), XtOffset(AppDataPtr, defaultPathEGTB),
1534 XtRImmediate, (XtPointer) "/usr/local/share/egtb"},
1535 { "delayBeforeQuit", "delayBeforeQuit", XtRInt,
1536 sizeof(int), XtOffset(AppDataPtr, delayBeforeQuit),
1537 XtRImmediate, (XtPointer) 0},
1538 { "delayAfterQuit", "delayAfterQuit", XtRInt,
1539 sizeof(int), XtOffset(AppDataPtr, delayAfterQuit),
1540 XtRImmediate, (XtPointer) 0},
1543 XrmOptionDescRec shellOptions[] = {
1544 { "-whitePieceColor", "whitePieceColor", XrmoptionSepArg, NULL },
1545 { "-blackPieceColor", "blackPieceColor", XrmoptionSepArg, NULL },
1546 { "-lightSquareColor", "lightSquareColor", XrmoptionSepArg, NULL },
1547 { "-darkSquareColor", "darkSquareColor", XrmoptionSepArg, NULL },
1548 { "-highlightSquareColor", "highlightSquareColor", XrmoptionSepArg, NULL },
1549 { "-premoveHighlightColor", "premoveHighlightColor", XrmoptionSepArg,NULL},
1550 { "-movesPerSession", "movesPerSession", XrmoptionSepArg, NULL },
1551 { "-mps", "movesPerSession", XrmoptionSepArg, NULL },
1552 { "-timeIncrement", "timeIncrement", XrmoptionSepArg, NULL },
1553 { "-inc", "timeIncrement", XrmoptionSepArg, NULL },
1554 { "-initString", "initString", XrmoptionSepArg, NULL },
1555 { "-firstInitString", "initString", XrmoptionSepArg, NULL },
1556 { "-secondInitString", "secondInitString", XrmoptionSepArg, NULL },
1557 { "-firstComputerString", "firstComputerString", XrmoptionSepArg, NULL },
1558 { "-secondComputerString", "secondComputerString", XrmoptionSepArg, NULL },
1559 { "-firstChessProgram", "firstChessProgram", XrmoptionSepArg, NULL },
1560 { "-fcp", "firstChessProgram", XrmoptionSepArg, NULL },
1561 { "-secondChessProgram", "secondChessProgram", XrmoptionSepArg, NULL },
1562 { "-scp", "secondChessProgram", XrmoptionSepArg, NULL },
1563 { "-firstPlaysBlack", "firstPlaysBlack", XrmoptionSepArg, NULL },
1564 { "-fb", "firstPlaysBlack", XrmoptionNoArg, "True" },
1565 { "-xfb", "firstPlaysBlack", XrmoptionNoArg, "False" },
1566 { "-noChessProgram", "noChessProgram", XrmoptionSepArg, NULL },
1567 { "-ncp", "noChessProgram", XrmoptionNoArg, "True" },
1568 { "-xncp", "noChessProgram", XrmoptionNoArg, "False" },
1569 { "-firstHost", "firstHost", XrmoptionSepArg, NULL },
1570 { "-fh", "firstHost", XrmoptionSepArg, NULL },
1571 { "-secondHost", "secondHost", XrmoptionSepArg, NULL },
1572 { "-sh", "secondHost", XrmoptionSepArg, NULL },
1573 { "-firstDirectory", "firstDirectory", XrmoptionSepArg, NULL },
1574 { "-fd", "firstDirectory", XrmoptionSepArg, NULL },
1575 { "-secondDirectory", "secondDirectory", XrmoptionSepArg, NULL },
1576 { "-sd", "secondDirectory", XrmoptionSepArg, NULL },
1577 { "-bitmapDirectory", "bitmapDirectory", XrmoptionSepArg, NULL },
1578 { "-bm", "bitmapDirectory", XrmoptionSepArg, NULL },
1579 { "-remoteShell", "remoteShell", XrmoptionSepArg, NULL },
1580 { "-rsh", "remoteShell", XrmoptionSepArg, NULL },
1581 { "-remoteUser", "remoteUser", XrmoptionSepArg, NULL },
1582 { "-ruser", "remoteUser", XrmoptionSepArg, NULL },
1583 { "-timeDelay", "timeDelay", XrmoptionSepArg, NULL },
1584 { "-td", "timeDelay", XrmoptionSepArg, NULL },
1585 { "-timeControl", "timeControl", XrmoptionSepArg, NULL },
1586 { "-tc", "timeControl", XrmoptionSepArg, NULL },
1587 { "-internetChessServerMode", "internetChessServerMode",
1588 XrmoptionSepArg, NULL },
1589 { "-ics", "internetChessServerMode", XrmoptionNoArg, "True" },
1590 { "-xics", "internetChessServerMode", XrmoptionNoArg, "False" },
1591 { "-internetChessServerHost", "internetChessServerHost",
1592 XrmoptionSepArg, NULL },
1593 { "-icshost", "internetChessServerHost", XrmoptionSepArg, NULL },
1594 { "-internetChessServerPort", "internetChessServerPort",
1595 XrmoptionSepArg, NULL },
1596 { "-icsport", "internetChessServerPort", XrmoptionSepArg, NULL },
1597 { "-internetChessServerCommPort", "internetChessServerCommPort",
1598 XrmoptionSepArg, NULL },
1599 { "-icscomm", "internetChessServerCommPort", XrmoptionSepArg, NULL },
1600 { "-internetChessServerLogonScript", "internetChessServerLogonScript",
1601 XrmoptionSepArg, NULL },
1602 { "-icslogon", "internetChessServerLogonScript", XrmoptionSepArg, NULL },
1603 { "-internetChessServerHelper", "internetChessServerHelper",
1604 XrmoptionSepArg, NULL },
1605 { "-icshelper", "internetChessServerHelper", XrmoptionSepArg, NULL },
1606 { "-internetChessServerInputBox", "internetChessServerInputBox",
1607 XrmoptionSepArg, NULL },
1608 { "-icsinput", "internetChessServerInputBox", XrmoptionNoArg, "True" },
1609 { "-xicsinput", "internetChessServerInputBox", XrmoptionNoArg, "False" },
1610 { "-icsAlarm", "icsAlarm", XrmoptionSepArg, NULL },
1611 { "-alarm", "icsAlarm", XrmoptionNoArg, "True" },
1612 { "-xalarm", "icsAlarm", XrmoptionNoArg, "False" },
1613 { "-icsAlarmTime", "icsAlarmTime", XrmoptionSepArg, NULL },
1614 { "-useTelnet", "useTelnet", XrmoptionSepArg, NULL },
1615 { "-telnet", "useTelnet", XrmoptionNoArg, "True" },
1616 { "-xtelnet", "useTelnet", XrmoptionNoArg, "False" },
1617 { "-telnetProgram", "telnetProgram", XrmoptionSepArg, NULL },
1618 { "-gateway", "gateway", XrmoptionSepArg, NULL },
1619 { "-loadGameFile", "loadGameFile", XrmoptionSepArg, NULL },
1620 { "-lgf", "loadGameFile", XrmoptionSepArg, NULL },
1621 { "-loadGameIndex", "loadGameIndex", XrmoptionSepArg, NULL },
1622 { "-lgi", "loadGameIndex", XrmoptionSepArg, NULL },
1623 { "-saveGameFile", "saveGameFile", XrmoptionSepArg, NULL },
1624 { "-sgf", "saveGameFile", XrmoptionSepArg, NULL },
1625 { "-autoSaveGames", "autoSaveGames", XrmoptionSepArg, NULL },
1626 { "-autosave", "autoSaveGames", XrmoptionNoArg, "True" },
1627 { "-xautosave", "autoSaveGames", XrmoptionNoArg, "False" },
1628 { "-autoRaiseBoard", "autoRaiseBoard", XrmoptionSepArg, NULL },
1629 { "-autoraise", "autoRaiseBoard", XrmoptionNoArg, "True" },
1630 { "-xautoraise", "autoRaiseBoard", XrmoptionNoArg, "False" },
1631 { "-blindfold", "blindfold", XrmoptionSepArg, NULL },
1632 { "-blind", "blindfold", XrmoptionNoArg, "True" },
1633 { "-xblind", "blindfold", XrmoptionNoArg, "False" },
1634 { "-loadPositionFile", "loadPositionFile", XrmoptionSepArg, NULL },
1635 { "-lpf", "loadPositionFile", XrmoptionSepArg, NULL },
1636 { "-loadPositionIndex", "loadPositionIndex", XrmoptionSepArg, NULL },
1637 { "-lpi", "loadPositionIndex", XrmoptionSepArg, NULL },
1638 { "-savePositionFile", "savePositionFile", XrmoptionSepArg, NULL },
1639 { "-spf", "savePositionFile", XrmoptionSepArg, NULL },
1640 { "-matchMode", "matchMode", XrmoptionSepArg, NULL },
1641 { "-mm", "matchMode", XrmoptionNoArg, "True" },
1642 { "-xmm", "matchMode", XrmoptionNoArg, "False" },
1643 { "-matchGames", "matchGames", XrmoptionSepArg, NULL },
1644 { "-mg", "matchGames", XrmoptionSepArg, NULL },
1645 { "-monoMode", "monoMode", XrmoptionSepArg, NULL },
1646 { "-mono", "monoMode", XrmoptionNoArg, "True" },
1647 { "-xmono", "monoMode", XrmoptionNoArg, "False" },
1648 { "-debugMode", "debugMode", XrmoptionSepArg, NULL },
1649 { "-debug", "debugMode", XrmoptionNoArg, "True" },
1650 { "-xdebug", "debugMode", XrmoptionNoArg, "False" },
1651 { "-clockMode", "clockMode", XrmoptionSepArg, NULL },
1652 { "-clock", "clockMode", XrmoptionNoArg, "True" },
1653 { "-xclock", "clockMode", XrmoptionNoArg, "False" },
1654 { "-boardSize", "boardSize", XrmoptionSepArg, NULL },
1655 { "-size", "boardSize", XrmoptionSepArg, NULL },
1656 { "-searchTime", "searchTime", XrmoptionSepArg, NULL },
1657 { "-st", "searchTime", XrmoptionSepArg, NULL },
1658 { "-searchDepth", "searchDepth", XrmoptionSepArg, NULL },
1659 { "-depth", "searchDepth", XrmoptionSepArg, NULL },
1660 { "-showCoords", "showCoords", XrmoptionSepArg, NULL },
1661 { "-coords", "showCoords", XrmoptionNoArg, "True" },
1662 { "-xcoords", "showCoords", XrmoptionNoArg, "False" },
1664 { "-showJail", "showJail", XrmoptionSepArg, NULL },
1665 { "-jail", "showJail", XrmoptionNoArg, "1" },
1666 { "-sidejail", "showJail", XrmoptionNoArg, "2" },
1667 { "-xjail", "showJail", XrmoptionNoArg, "0" },
1669 { "-showThinking", "showThinking", XrmoptionSepArg, NULL },
1670 { "-thinking", "showThinking", XrmoptionNoArg, "True" },
1671 { "-xthinking", "showThinking", XrmoptionNoArg, "False" },
1672 { "-ponderNextMove", "ponderNextMove", XrmoptionSepArg, NULL },
1673 { "-ponder", "ponderNextMove", XrmoptionNoArg, "True" },
1674 { "-xponder", "ponderNextMove", XrmoptionNoArg, "False" },
1675 { "-periodicUpdates", "periodicUpdates", XrmoptionSepArg, NULL },
1676 { "-periodic", "periodicUpdates", XrmoptionNoArg, "True" },
1677 { "-xperiodic", "periodicUpdates", XrmoptionNoArg, "False" },
1678 { "-clockFont", "clockFont", XrmoptionSepArg, NULL },
1679 { "-coordFont", "coordFont", XrmoptionSepArg, NULL },
1680 { "-font", "font", XrmoptionSepArg, NULL },
1681 { "-ringBellAfterMoves", "ringBellAfterMoves", XrmoptionSepArg, NULL },
1682 { "-bell", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1683 { "-xbell", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1684 { "-movesound", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1685 { "-xmovesound", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1686 { "-autoCallFlag", "autoCallFlag", XrmoptionSepArg, NULL },
1687 { "-autoflag", "autoCallFlag", XrmoptionNoArg, "True" },
1688 { "-xautoflag", "autoCallFlag", XrmoptionNoArg, "False" },
1689 { "-autoFlipView", "autoFlipView", XrmoptionSepArg, NULL },
1690 { "-autoflip", "autoFlipView", XrmoptionNoArg, "True" },
1691 { "-xautoflip", "autoFlipView", XrmoptionNoArg, "False" },
1692 { "-autoObserve", "autoObserve", XrmoptionSepArg, NULL },
1693 { "-autobs", "autoObserve", XrmoptionNoArg, "True" },
1694 { "-xautobs", "autoObserve", XrmoptionNoArg, "False" },
1695 { "-autoComment", "autoComment", XrmoptionSepArg, NULL },
1696 { "-autocomm", "autoComment", XrmoptionNoArg, "True" },
1697 { "-xautocomm", "autoComment", XrmoptionNoArg, "False" },
1698 { "-getMoveList", "getMoveList", XrmoptionSepArg, NULL },
1699 { "-moves", "getMoveList", XrmoptionNoArg, "True" },
1700 { "-xmoves", "getMoveList", XrmoptionNoArg, "False" },
1702 { "-highlightDragging", "highlightDragging", XrmoptionSepArg, NULL },
1703 { "-highdrag", "highlightDragging", XrmoptionNoArg, "True" },
1704 { "-xhighdrag", "highlightDragging", XrmoptionNoArg, "False" },
1706 { "-highlightLastMove", "highlightLastMove", XrmoptionSepArg, NULL },
1707 { "-highlight", "highlightLastMove", XrmoptionNoArg, "True" },
1708 { "-xhighlight", "highlightLastMove", XrmoptionNoArg, "False" },
1709 { "-premove", "premove", XrmoptionSepArg, NULL },
1710 { "-pre", "premove", XrmoptionNoArg, "True" },
1711 { "-xpre", "premove", XrmoptionNoArg, "False" },
1712 { "-testLegality", "testLegality", XrmoptionSepArg, NULL },
1713 { "-legal", "testLegality", XrmoptionNoArg, "True" },
1714 { "-xlegal", "testLegality", XrmoptionNoArg, "False" },
1715 { "-flipView", "flipView", XrmoptionSepArg, NULL },
1716 { "-flip", "flipView", XrmoptionNoArg, "True" },
1717 { "-xflip", "flipView", XrmoptionNoArg, "False" },
1718 { "-cmail", "cmailGameName", XrmoptionSepArg, NULL },
1719 { "-alwaysPromoteToQueen", "alwaysPromoteToQueen",
1720 XrmoptionSepArg, NULL },
1721 { "-queen", "alwaysPromoteToQueen", XrmoptionNoArg, "True" },
1722 { "-xqueen", "alwaysPromoteToQueen", XrmoptionNoArg, "False" },
1723 { "-oldSaveStyle", "oldSaveStyle", XrmoptionSepArg, NULL },
1724 { "-oldsave", "oldSaveStyle", XrmoptionNoArg, "True" },
1725 { "-xoldsave", "oldSaveStyle", XrmoptionNoArg, "False" },
1726 { "-quietPlay", "quietPlay", XrmoptionSepArg, NULL },
1727 { "-quiet", "quietPlay", XrmoptionNoArg, "True" },
1728 { "-xquiet", "quietPlay", XrmoptionNoArg, "False" },
1729 { "-titleInWindow", "titleInWindow", XrmoptionSepArg, NULL },
1730 { "-title", "titleInWindow", XrmoptionNoArg, "True" },
1731 { "-xtitle", "titleInWindow", XrmoptionNoArg, "False" },
1733 { "-zippyTalk", "zippyTalk", XrmoptionSepArg, NULL },
1734 { "-zt", "zippyTalk", XrmoptionNoArg, "True" },
1735 { "-xzt", "zippyTalk", XrmoptionNoArg, "False" },
1736 { "-zippyPlay", "zippyPlay", XrmoptionSepArg, NULL },
1737 { "-zp", "zippyPlay", XrmoptionNoArg, "True" },
1738 { "-xzp", "zippyPlay", XrmoptionNoArg, "False" },
1739 { "-zippyLines", "zippyLines", XrmoptionSepArg, NULL },
1740 { "-zippyPinhead", "zippyPinhead", XrmoptionSepArg, NULL },
1741 { "-zippyPassword", "zippyPassword", XrmoptionSepArg, NULL },
1742 { "-zippyPassword2", "zippyPassword2", XrmoptionSepArg, NULL },
1743 { "-zippyWrongPassword", "zippyWrongPassword", XrmoptionSepArg, NULL },
1744 { "-zippyAcceptOnly", "zippyAcceptOnly", XrmoptionSepArg, NULL },
1745 { "-zippyUseI", "zippyUseI", XrmoptionSepArg, NULL },
1746 { "-zui", "zippyUseI", XrmoptionNoArg, "True" },
1747 { "-xzui", "zippyUseI", XrmoptionNoArg, "False" },
1748 { "-zippyBughouse", "zippyBughouse", XrmoptionSepArg, NULL },
1749 { "-zippyNoplayCrafty", "zippyNoplayCrafty", XrmoptionSepArg, NULL },
1750 { "-znc", "zippyNoplayCrafty", XrmoptionNoArg, "True" },
1751 { "-xznc", "zippyNoplayCrafty", XrmoptionNoArg, "False" },
1752 { "-zippyGameEnd", "zippyGameEnd", XrmoptionSepArg, NULL },
1753 { "-zippyGameStart", "zippyGameStart", XrmoptionSepArg, NULL },
1754 { "-zippyAdjourn", "zippyAdjourn", XrmoptionSepArg, NULL },
1755 { "-zadj", "zippyAdjourn", XrmoptionNoArg, "True" },
1756 { "-xzadj", "zippyAdjourn", XrmoptionNoArg, "False" },
1757 { "-zippyAbort", "zippyAbort", XrmoptionSepArg, NULL },
1758 { "-zab", "zippyAbort", XrmoptionNoArg, "True" },
1759 { "-xzab", "zippyAbort", XrmoptionNoArg, "False" },
1760 { "-zippyVariants", "zippyVariants", XrmoptionSepArg, NULL },
1761 { "-zippyMaxGames", "zippyMaxGames", XrmoptionSepArg, NULL },
1762 { "-zippyReplayTimeout", "zippyReplayTimeout", XrmoptionSepArg, NULL },
1763 { "-zippyShortGame", "zippyShortGame", XrmoptionSepArg, NULL },
1765 { "-flashCount", "flashCount", XrmoptionSepArg, NULL },
1766 { "-flash", "flashCount", XrmoptionNoArg, "3" },
1767 { "-xflash", "flashCount", XrmoptionNoArg, "0" },
1768 { "-flashRate", "flashRate", XrmoptionSepArg, NULL },
1769 { "-pixmapDirectory", "pixmapDirectory", XrmoptionSepArg, NULL },
1770 { "-msLoginDelay", "msLoginDelay", XrmoptionSepArg, NULL },
1771 { "-pixmap", "pixmapDirectory", XrmoptionSepArg, NULL },
1772 { "-colorizeMessages", "colorizeMessages", XrmoptionSepArg, NULL },
1773 { "-colorize", "colorizeMessages", XrmoptionNoArg, "True" },
1774 { "-xcolorize", "colorizeMessages", XrmoptionNoArg, "False" },
1775 { "-colorShout", "colorShout", XrmoptionSepArg, NULL },
1776 { "-colorSShout", "colorSShout", XrmoptionSepArg, NULL },
1777 { "-colorCShout", "colorSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1778 { "-colorChannel1", "colorChannel1", XrmoptionSepArg, NULL },
1779 { "-colorChannel", "colorChannel", XrmoptionSepArg, NULL },
1780 { "-colorKibitz", "colorKibitz", XrmoptionSepArg, NULL },
1781 { "-colorTell", "colorTell", XrmoptionSepArg, NULL },
1782 { "-colorChallenge", "colorChallenge", XrmoptionSepArg, NULL },
1783 { "-colorRequest", "colorRequest", XrmoptionSepArg, NULL },
1784 { "-colorSeek", "colorSeek", XrmoptionSepArg, NULL },
1785 { "-colorNormal", "colorNormal", XrmoptionSepArg, NULL },
1786 { "-soundProgram", "soundProgram", XrmoptionSepArg, NULL },
1787 { "-soundShout", "soundShout", XrmoptionSepArg, NULL },
1788 { "-soundSShout", "soundSShout", XrmoptionSepArg, NULL },
1789 { "-soundCShout", "soundSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1790 { "-soundChannel1", "soundChannel1", XrmoptionSepArg, NULL },
1791 { "-soundChannel", "soundChannel", XrmoptionSepArg, NULL },
1792 { "-soundKibitz", "soundKibitz", XrmoptionSepArg, NULL },
1793 { "-soundTell", "soundTell", XrmoptionSepArg, NULL },
1794 { "-soundChallenge", "soundChallenge", XrmoptionSepArg, NULL },
1795 { "-soundRequest", "soundRequest", XrmoptionSepArg, NULL },
1796 { "-soundSeek", "soundSeek", XrmoptionSepArg, NULL },
1797 { "-soundMove", "soundMove", XrmoptionSepArg, NULL },
1798 { "-soundIcsWin", "soundIcsWin", XrmoptionSepArg, NULL },
1799 { "-soundIcsLoss", "soundIcsLoss", XrmoptionSepArg, NULL },
1800 { "-soundIcsDraw", "soundIcsDraw", XrmoptionSepArg, NULL },
1801 { "-soundIcsUnfinished", "soundIcsUnfinished", XrmoptionSepArg, NULL },
1802 { "-soundIcsAlarm", "soundIcsAlarm", XrmoptionSepArg, NULL },
1803 { "-reuseFirst", "reuseFirst", XrmoptionSepArg, NULL },
1804 { "-reuseChessPrograms", "reuseFirst", XrmoptionSepArg, NULL }, /*compat*/
1805 { "-reuse", "reuseFirst", XrmoptionNoArg, "True" },
1806 { "-xreuse", "reuseFirst", XrmoptionNoArg, "False" },
1807 { "-reuseSecond", "reuseSecond", XrmoptionSepArg, NULL },
1808 { "-reuse2", "reuseSecond", XrmoptionNoArg, "True" },
1809 { "-xreuse2", "reuseSecond", XrmoptionNoArg, "False" },
1810 { "-animateMoving", "animateMoving", XrmoptionSepArg, NULL },
1811 { "-animate", "animateMoving", XrmoptionNoArg, "True" },
1812 { "-xanimate", "animateMoving", XrmoptionNoArg, "False" },
1813 { "-animateDragging", "animateDragging", XrmoptionSepArg, NULL },
1814 { "-drag", "animateDragging", XrmoptionNoArg, "True" },
1815 { "-xdrag", "animateDragging", XrmoptionNoArg, "False" },
1816 { "-animateSpeed", "animateSpeed", XrmoptionSepArg, NULL },
1817 { "-popupExitMessage", "popupExitMessage", XrmoptionSepArg, NULL },
1818 { "-exit", "popupExitMessage", XrmoptionNoArg, "True" },
1819 { "-xexit", "popupExitMessage", XrmoptionNoArg, "False" },
1820 { "-popupMoveErrors", "popupMoveErrors", XrmoptionSepArg, NULL },
1821 { "-popup", "popupMoveErrors", XrmoptionNoArg, "True" },
1822 { "-xpopup", "popupMoveErrors", XrmoptionNoArg, "False" },
1823 { "-fontSizeTolerance", "fontSizeTolerance", XrmoptionSepArg, NULL },
1824 { "-initialMode", "initialMode", XrmoptionSepArg, NULL },
1825 { "-mode", "initialMode", XrmoptionSepArg, NULL },
1826 { "-variant", "variant", XrmoptionSepArg, NULL },
1827 { "-firstProtocolVersion", "firstProtocolVersion", XrmoptionSepArg, NULL },
1828 { "-secondProtocolVersion","secondProtocolVersion",XrmoptionSepArg, NULL },
1829 { "-showButtonBar", "showButtonBar", XrmoptionSepArg, NULL },
1830 { "-buttons", "showButtonBar", XrmoptionNoArg, "True" },
1831 { "-xbuttons", "showButtonBar", XrmoptionNoArg, "False" },
1832 { "-lowTimeWarningColor", "lowTimeWarningColor", XrmoptionSepArg, NULL },
1833 { "-lowTimeWarning", "lowTimeWarning", XrmoptionSepArg, NULL },
1834 /* [AS,HR] New features */
1835 { "-firstScoreAbs", "firstScoreAbs", XrmoptionSepArg, NULL },
1836 { "-secondScoreAbs", "secondScoreAbs", XrmoptionSepArg, NULL },
1837 { "-pgnExtendedInfo", "pgnExtendedInfo", XrmoptionSepArg, NULL },
1838 { "-hideThinkingFromHuman", "hideThinkingFromHuman", XrmoptionSepArg, NULL },
1839 { "-adjudicateLossThreshold", "adjudicateLossThreshold", XrmoptionSepArg, NULL },
1840 { "-pgnEventHeader", "pgnEventHeader", XrmoptionSepArg, NULL },
1841 { "-firstIsUCI", "firstIsUCI", XrmoptionSepArg, NULL },
1842 { "-secondIsUCI", "secondIsUCI", XrmoptionSepArg, NULL },
1843 { "-fUCI", "firstIsUCI", XrmoptionNoArg, "True" },
1844 { "-sUCI", "secondIsUCI", XrmoptionNoArg, "True" },
1845 { "-firstHasOwnBookUCI", "firstHasOwnBookUCI", XrmoptionSepArg, NULL },
1846 { "-secondHasOwnBookUCI", "secondHasOwnBookUCI", XrmoptionSepArg, NULL },
1847 { "-fNoOwnBookUCI", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1848 { "-sNoOwnBookUCI", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1849 { "-firstXBook", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1850 { "-secondXBook", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1851 { "-polyglotDir", "polyglotDir", XrmoptionSepArg, NULL },
1852 { "-usePolyglotBook", "usePolyglotBook", XrmoptionSepArg, NULL },
1853 { "-polyglotBook", "polyglotBook", XrmoptionSepArg, NULL },
1854 { "-defaultHashSize", "defaultHashSize", XrmoptionSepArg, NULL },
1855 { "-defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XrmoptionSepArg, NULL },
1856 { "-defaultPathEGTB", "defaultPathEGTB", XrmoptionSepArg, NULL },
1857 { "-defaultFrcPosition", "defaultFrcPosition", XrmoptionSepArg, NULL },
1858 { "-gameListTags", "gameListTags", XrmoptionSepArg, NULL },
1859 // [HGM] I am sure AS added many more options, but we have to fish them out, from the list in winboard.c
1861 /* [HGM,HR] User-selectable board size */
1862 { "-boardWidth", "boardWidth", XrmoptionSepArg, NULL },
1863 { "-boardHeight", "boardHeight", XrmoptionSepArg, NULL },
1864 { "-matchPause", "matchPause", XrmoptionSepArg, NULL },
1866 /* [HGM] new arguments of 4.3.xx. All except first three are back-end options, which should work immediately */
1867 { "-holdingsSize", "holdingsSize", XrmoptionSepArg, NULL }, // requires extensive front-end changes to work
1868 { "-flipBlack", "flipBlack", XrmoptionSepArg, NULL }, // requires front-end changes to work
1869 { "-allWhite", "allWhite", XrmoptionSepArg, NULL }, // requires front-end changes to work
1870 { "-pieceToCharTable", "pieceToCharTable", XrmoptionSepArg, NULL },
1871 { "-alphaRank", "alphaRank", XrmoptionSepArg, NULL },
1872 { "-testClaims", "testClaims", XrmoptionSepArg, NULL },
1873 { "-checkMates", "checkMates", XrmoptionSepArg, NULL },
1874 { "-materialDraws", "materialDraws", XrmoptionSepArg, NULL },
1875 { "-trivialDraws", "trivialDraws", XrmoptionSepArg, NULL },
1876 { "-ruleMoves", "ruleMoves", XrmoptionSepArg, NULL },
1877 { "-repeatsToDraw", "repeatsToDraw", XrmoptionSepArg, NULL },
1878 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1879 { "-userName", "userName", XrmoptionSepArg, NULL },
1880 { "-autoKibitz", "autoKibitz", XrmoptionNoArg, "True" },
1881 { "-firstTimeOdds", "firstTimeOdds", XrmoptionSepArg, NULL },
1882 { "-secondTimeOdds", "secondTimeOdds", XrmoptionSepArg, NULL },
1883 { "-timeOddsMode", "timeOddsMode", XrmoptionSepArg, NULL },
1884 { "-firstAccumulateTC", "firstAccumulateTC", XrmoptionSepArg, NULL },
1885 { "-secondAccumulateTC", "secondAccumulateTC", XrmoptionSepArg, NULL },
1886 { "-firstNPS", "firstNPS", XrmoptionSepArg, NULL },
1887 { "-secondNPS", "secondNPS", XrmoptionSepArg, NULL },
1888 { "-serverMoves", "serverMoves", XrmoptionSepArg, NULL },
1889 { "-serverPause", "serverPause", XrmoptionSepArg, NULL },
1890 { "-suppressLoadMoves", "suppressLoadMoves", XrmoptionSepArg, NULL },
1891 { "-egtFormats", "egtFormats", XrmoptionSepArg, NULL },
1892 { "-userName", "userName", XrmoptionSepArg, NULL },
1893 { "-smpCores", "smpCores", XrmoptionSepArg, NULL },
1894 { "-sameColorGames", "sameColorGames", XrmoptionSepArg, NULL },
1895 { "-rewindIndex", "rewindIndex", XrmoptionSepArg, NULL },
1896 { "-niceEngines", "niceEngines", XrmoptionSepArg, NULL },
1897 { "-delayBeforeQuit", "delayBeforeQuit", XrmoptionSepArg, NULL },
1898 { "-delayAfterQuit", "delayAfterQuit", XrmoptionSepArg, NULL },
1899 { "-nameOfDebugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1900 { "-debugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1901 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1902 { "-noGUI", "noGUI", XrmoptionNoArg, "True" },
1903 { "-firstOptions", "firstOptions", XrmoptionSepArg, NULL },
1904 { "-secondOptions", "secondOptions", XrmoptionSepArg, NULL },
1905 { "-firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1906 { "-secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1910 XtActionsRec boardActions[] = {
1911 { "HandleUserMove", HandleUserMove },
1912 { "AnimateUserMove", AnimateUserMove },
1913 { "FileNameAction", FileNameAction },
1914 { "AskQuestionProc", AskQuestionProc },
1915 { "AskQuestionReplyAction", AskQuestionReplyAction },
1916 { "PieceMenuPopup", PieceMenuPopup },
1917 { "WhiteClock", WhiteClock },
1918 { "BlackClock", BlackClock },
1919 { "Iconify", Iconify },
1920 { "LoadSelectedProc", LoadSelectedProc },
1921 { "LoadPositionProc", LoadPositionProc },
1922 { "LoadNextPositionProc", LoadNextPositionProc },
1923 { "LoadPrevPositionProc", LoadPrevPositionProc },
1924 { "ReloadPositionProc", ReloadPositionProc },
1925 { "CopyPositionProc", CopyPositionProc },
1926 { "PastePositionProc", PastePositionProc },
1927 { "CopyGameProc", CopyGameProc },
1928 { "PasteGameProc", PasteGameProc },
1929 { "SaveGameProc", SaveGameProc },
1930 { "SavePositionProc", SavePositionProc },
1931 { "MailMoveProc", MailMoveProc },
1932 { "ReloadCmailMsgProc", ReloadCmailMsgProc },
1933 { "MachineWhiteProc", MachineWhiteProc },
1934 { "MachineBlackProc", MachineBlackProc },
1935 { "AnalysisModeProc", AnalyzeModeProc },
1936 { "AnalyzeFileProc", AnalyzeFileProc },
1937 { "TwoMachinesProc", TwoMachinesProc },
1938 { "IcsClientProc", IcsClientProc },
1939 { "EditGameProc", EditGameProc },
1940 { "EditPositionProc", EditPositionProc },
1941 { "TrainingProc", EditPositionProc },
1942 { "EngineOutputProc", EngineOutputProc}, // [HGM] Winboard_x engine-output window
1943 { "ShowGameListProc", ShowGameListProc },
1944 { "ShowMoveListProc", HistoryShowProc},
1945 { "EditTagsProc", EditCommentProc },
1946 { "EditCommentProc", EditCommentProc },
1947 { "IcsAlarmProc", IcsAlarmProc },
1948 { "IcsInputBoxProc", IcsInputBoxProc },
1949 { "AcceptProc", AcceptProc },
1950 { "DeclineProc", DeclineProc },
1951 { "RematchProc", RematchProc },
1952 { "CallFlagProc", CallFlagProc },
1953 { "DrawProc", DrawProc },
1954 { "AdjournProc", AdjournProc },
1955 { "AbortProc", AbortProc },
1956 { "ResignProc", ResignProc },
1957 { "AdjuWhiteProc", AdjuWhiteProc },
1958 { "AdjuBlackProc", AdjuBlackProc },
1959 { "AdjuDrawProc", AdjuDrawProc },
1960 { "EnterKeyProc", EnterKeyProc },
1961 { "StopObservingProc", StopObservingProc },
1962 { "StopExaminingProc", StopExaminingProc },
1963 { "BackwardProc", BackwardProc },
1964 { "ForwardProc", ForwardProc },
1965 { "ToStartProc", ToStartProc },
1966 { "ToEndProc", ToEndProc },
1967 { "RevertProc", RevertProc },
1968 { "TruncateGameProc", TruncateGameProc },
1969 { "MoveNowProc", MoveNowProc },
1970 { "RetractMoveProc", RetractMoveProc },
1971 { "AlwaysQueenProc", AlwaysQueenProc },
1972 { "AnimateDraggingProc", AnimateDraggingProc },
1973 { "AnimateMovingProc", AnimateMovingProc },
1974 { "AutoflagProc", AutoflagProc },
1975 { "AutoflipProc", AutoflipProc },
1976 { "AutobsProc", AutobsProc },
1977 { "AutoraiseProc", AutoraiseProc },
1978 { "AutosaveProc", AutosaveProc },
1979 { "BlindfoldProc", BlindfoldProc },
1980 { "FlashMovesProc", FlashMovesProc },
1981 { "FlipViewProc", FlipViewProc },
1982 { "GetMoveListProc", GetMoveListProc },
1984 { "HighlightDraggingProc", HighlightDraggingProc },
1986 { "HighlightLastMoveProc", HighlightLastMoveProc },
1987 { "IcsAlarmProc", IcsAlarmProc },
1988 { "MoveSoundProc", MoveSoundProc },
1989 { "OldSaveStyleProc", OldSaveStyleProc },
1990 { "PeriodicUpdatesProc", PeriodicUpdatesProc },
1991 { "PonderNextMoveProc", PonderNextMoveProc },
1992 { "PopupExitMessageProc", PopupExitMessageProc },
1993 { "PopupMoveErrorsProc", PopupMoveErrorsProc },
1994 { "PremoveProc", PremoveProc },
1995 { "QuietPlayProc", QuietPlayProc },
1996 { "ShowThinkingProc", ShowThinkingProc },
1997 { "HideThinkingProc", HideThinkingProc },
1998 { "TestLegalityProc", TestLegalityProc },
1999 { "InfoProc", InfoProc },
2000 { "ManProc", ManProc },
2001 { "HintProc", HintProc },
2002 { "BookProc", BookProc },
2003 { "AboutGameProc", AboutGameProc },
2004 { "DebugProc", DebugProc },
2005 { "NothingProc", NothingProc },
2006 { "CommentPopDown", (XtActionProc) CommentPopDown },
2007 { "EditCommentPopDown", (XtActionProc) EditCommentPopDown },
2008 { "TagsPopDown", (XtActionProc) TagsPopDown },
2009 { "ErrorPopDown", (XtActionProc) ErrorPopDown },
2010 { "ICSInputBoxPopDown", (XtActionProc) ICSInputBoxPopDown },
2011 { "AnalysisPopDown", (XtActionProc) AnalysisPopDown },
2012 { "FileNamePopDown", (XtActionProc) FileNamePopDown },
2013 { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown },
2014 { "GameListPopDown", (XtActionProc) GameListPopDown },
2015 { "PromotionPopDown", (XtActionProc) PromotionPopDown },
2016 { "HistoryPopDown", (XtActionProc) HistoryPopDown },
2017 { "EngineOutputPopDown", (XtActionProc) EngineOutputPopDown },
2018 { "ShufflePopDown", (XtActionProc) ShufflePopDown },
2019 { "EnginePopDown", (XtActionProc) EnginePopDown },
2020 { "UciPopDown", (XtActionProc) UciPopDown },
2021 { "TimeControlPopDown", (XtActionProc) TimeControlPopDown },
2022 { "NewVariantPopDown", (XtActionProc) NewVariantPopDown },
2023 { "SettingsPopDown", (XtActionProc) SettingsPopDown },
2027 char ICSInputTranslations[] =
2028 "<Key>Return: EnterKeyProc() \n";
2030 String xboardResources[] = {
2031 "*fileName*value.translations: #override\\n <Key>Return: FileNameAction()",
2032 "*question*value.translations: #override\\n <Key>Return: AskQuestionReplyAction()",
2033 "*errorpopup*translations: #override\\n <Key>Return: ErrorPopDown()",
2037 static char *cnames[9] = { "black", "red", "green", "yellow", "blue",
2038 "magenta", "cyan", "white" };
2042 TextColors textColors[(int)NColorClasses];
2044 /* String is: "fg, bg, attr". Which is 0, 1, 2 */
2046 parse_color(str, which)
2050 char *p, buf[100], *d;
2053 if (strlen(str) > 99) /* watch bounds on buf */
2058 for (i=0; i<which; ++i) {
2065 /* Could be looking at something like:
2067 .. in which case we want to stop on a comma also */
2068 while (*p && *p != ',' && !isalpha(*p) && !isdigit(*p))
2072 return -1; /* Use default for empty field */
2075 if (which == 2 || isdigit(*p))
2078 while (*p && isalpha(*p))
2083 for (i=0; i<8; ++i) {
2084 if (!StrCaseCmp(buf, cnames[i]))
2085 return which? (i+40) : (i+30);
2087 if (!StrCaseCmp(buf, "default")) return -1;
2089 fprintf(stderr, _("%s: unrecognized color %s\n"), programName, buf);
2094 parse_cpair(cc, str)
2098 if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {
2099 fprintf(stderr, _("%s: can't parse foreground color in `%s'\n"),
2104 /* bg and attr are optional */
2105 textColors[(int)cc].bg = parse_color(str, 1);
2106 if ((textColors[(int)cc].attr = parse_color(str, 2)) < 0) {
2107 textColors[(int)cc].attr = 0;
2113 /* Arrange to catch delete-window events */
2114 Atom wm_delete_window;
2116 CatchDeleteWindow(Widget w, String procname)
2119 XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
2120 snprintf(buf, sizeof(buf), "<Message>WM_PROTOCOLS: %s() \n", procname);
2121 XtAugmentTranslations(w, XtParseTranslationTable(buf));
2127 /* this should raise the board to the top */
2128 gtk_window_present(GTK_WINDOW(GUI_Window));
2133 // eventually, all layout determining code should go into a subroutine, but until then IDSIZE remains undefined
2135 #define BoardSize int
2136 void InitDrawingSizes(BoardSize boardSize, int flags)
2137 { // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
2138 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2140 XtGeometryResult gres;
2143 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2144 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2146 timerWidth = (boardWidth - sep) / 2;
2148 if (appData.titleInWindow)
2153 w = boardWidth - 2*bor;
2157 w = boardWidth - w - sep - 2*bor - 2; // WIDTH_FUDGE
2161 if(!formWidget) return;
2164 * Inhibit shell resizing.
2167 // [HGM] pieces: tailor piece bitmaps to needs of specific variant
2170 for(i=0; i<4; i++) {
2172 for(p=0; p<=(int)WhiteKing; p++)
2173 xpmPieceBitmap[i][p] = xpmPieceBitmap2[i][p]; // defaults
2174 if(gameInfo.variant == VariantShogi) {
2175 xpmPieceBitmap[i][(int)WhiteCannon] = xpmPieceBitmap2[i][(int)WhiteKing+1];
2176 xpmPieceBitmap[i][(int)WhiteNightrider] = xpmPieceBitmap2[i][(int)WhiteKing+2];
2177 xpmPieceBitmap[i][(int)WhiteSilver] = xpmPieceBitmap2[i][(int)WhiteKing+3];
2178 xpmPieceBitmap[i][(int)WhiteGrasshopper] = xpmPieceBitmap2[i][(int)WhiteKing+4];
2179 xpmPieceBitmap[i][(int)WhiteQueen] = xpmPieceBitmap2[i][(int)WhiteLance];
2182 if(gameInfo.variant == VariantGothic) {
2183 xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteSilver];
2187 // [HGM] why are thee ximMasks used at all? the ximPieceBitmaps seem to be never used!
2188 for(p=0; p<=(int)WhiteKing; p++)
2189 ximMaskPm[p] = ximMaskPm2[p]; // defaults
2190 if(gameInfo.variant == VariantShogi) {
2191 ximMaskPm[(int)WhiteCannon] = ximMaskPm2[(int)WhiteKing+1];
2192 ximMaskPm[(int)WhiteNightrider] = ximMaskPm2[(int)WhiteKing+2];
2193 ximMaskPm[(int)WhiteSilver] = ximMaskPm2[(int)WhiteKing+3];
2194 ximMaskPm[(int)WhiteGrasshopper] = ximMaskPm2[(int)WhiteKing+4];
2195 ximMaskPm[(int)WhiteQueen] = ximMaskPm2[(int)WhiteLance];
2198 if(gameInfo.variant == VariantGothic) {
2199 ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[i][(int)WhiteSilver];
2205 for(i=0; i<2; i++) {
2207 for(p=0; p<=(int)WhiteKing; p++)
2208 pieceBitmap[i][p] = pieceBitmap2[i][p]; // defaults
2209 if(gameInfo.variant == VariantShogi) {
2210 pieceBitmap[i][(int)WhiteCannon] = pieceBitmap2[i][(int)WhiteKing+1];
2211 pieceBitmap[i][(int)WhiteNightrider] = pieceBitmap2[i][(int)WhiteKing+2];
2212 pieceBitmap[i][(int)WhiteSilver] = pieceBitmap2[i][(int)WhiteKing+3];
2213 pieceBitmap[i][(int)WhiteGrasshopper] = pieceBitmap2[i][(int)WhiteKing+4];
2214 pieceBitmap[i][(int)WhiteQueen] = pieceBitmap2[i][(int)WhiteLance];
2217 if(gameInfo.variant == VariantGothic) {
2218 pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteSilver];
2234 int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
2235 XSetWindowAttributes window_attributes;
2237 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2238 XrmValue vFrom, vTo;
2239 XtGeometryResult gres;
2242 int forceMono = False;
2246 // [HGM] before anything else, expand any indirection files amongst options
2247 char *argvCopy[1000]; // 1000 seems enough
2248 char newArgs[10000]; // holds actual characters
2251 srandom(time(0)); // [HGM] book: make random truly random
2254 for(i=0; i<argc; i++) {
2255 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2256 //fprintf(stderr, "arg %s\n", argv[i]);
2257 if(argv[i][0] != '@') argvCopy[j++] = argv[i]; else {
2259 FILE *f = fopen(argv[i]+1, "rb");
2260 if(f == NULL) { fprintf(stderr, _("ignore %s\n"), argv[i]); continue; } // do not expand non-existing
2261 argvCopy[j++] = newArgs + k; // get ready for first argument from file
2262 while((c = fgetc(f)) != EOF) { // each line of file inserts 1 argument in the list
2264 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2265 newArgs[k++] = 0; // terminate current arg
2266 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2267 argvCopy[j++] = newArgs + k; // get ready for next
2269 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2282 if(appData.debugMode,1) { // OK, appData is not initialized here yet...
2283 for(i=0; i<argc; i++) fprintf(stderr, "argv[%2d] = '%s'\n", i, argv[i]);
2289 setbuf(stdout, NULL);
2290 setbuf(stderr, NULL);
2293 programName = strrchr(argv[0], '/');
2294 if (programName == NULL)
2295 programName = argv[0];
2300 XtSetLanguageProc(NULL, NULL, NULL);
2301 bindtextdomain(PACKAGE, LOCALEDIR);
2302 textdomain(PACKAGE);
2306 XtAppInitialize(&appContext, "XBoard", shellOptions,
2307 XtNumber(shellOptions),
2308 &argc, argv, xboardResources, NULL, 0);
2312 gtk_init (&argc, &argv);
2314 /* parse glade file to build widgets */
2316 builder = gtk_builder_new ();
2317 gtk_builder_add_from_file (builder, "gtk-interface.xml", NULL);
2319 /* test if everything worked ok */
2321 GUI_Window = GTK_WIDGET (gtk_builder_get_object (builder, "MainWindow"));
2322 if(!GUI_Window) printf("Error: gtk_builder didn't work!\n");
2323 GUI_Board = GTK_WIDGET (gtk_builder_get_object (builder, "Board"));
2324 if(!GUI_Board) printf("Error: gtk_builder didn't work!\n");
2325 GUI_Whiteclock = GTK_WIDGET (gtk_builder_get_object (builder, "WhiteClock"));
2326 if(!GUI_Whiteclock) printf("Error: gtk_builder didn't work!\n");
2327 GUI_Blackclock = GTK_WIDGET (gtk_builder_get_object (builder, "BlackClock"));
2328 if(!GUI_Blackclock) printf("Error: gtk_builder didn't work!\n");
2330 gtk_builder_connect_signals (builder, NULL);
2332 // don't unref the builder, since we use it to get references to widgets
2333 // g_object_unref (G_OBJECT (builder));
2335 /* end parse glade file */
2339 fprintf(stderr, _("%s: unrecognized argument %s\n"),
2340 programName, argv[1]);
2341 fprintf(stderr, "Recognized options:\n");
2342 for(i = 0; i < XtNumber(shellOptions); i++)
2344 j = fprintf(stderr, " %s%s", shellOptions[i].option,
2345 (shellOptions[i].argKind == XrmoptionSepArg
2347 if (i++ < XtNumber(shellOptions))
2349 fprintf(stderr, "%*c%s%s\n", 40 - j, ' ',
2350 shellOptions[i].option,
2351 (shellOptions[i].argKind == XrmoptionSepArg
2356 fprintf(stderr, "\n");
2362 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL)
2368 if (chdir(chessDir) != 0)
2370 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
2377 if (p == NULL) p = "/tmp";
2378 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
2379 gameCopyFilename = (char*) malloc(i);
2380 gamePasteFilename = (char*) malloc(i);
2381 snprintf(gameCopyFilename,i, "%s/.xboard%05uc.pgn", p, getpid());
2382 snprintf(gamePasteFilename,i, "%s/.xboard%05up.pgn", p, getpid());
2384 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
2385 clientResources, XtNumber(clientResources),
2388 if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) {
2389 /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */
2390 if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL) {
2391 printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile);
2394 setbuf(debugFP, NULL);
2397 /* [HGM,HR] make sure board size is acceptable */
2398 if(appData.NrFiles > BOARD_SIZE ||
2399 appData.NrRanks > BOARD_SIZE )
2400 DisplayFatalError(_("Recompile with BOARD_SIZE > 12, to support this size"), 0, 2);
2403 /* This feature does not work; animation needs a rewrite */
2404 appData.highlightDragging = FALSE;
2408 xDisplay = XtDisplay(shellWidget);
2409 xScreen = DefaultScreen(xDisplay);
2410 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
2412 gameInfo.variant = StringToVariant(appData.variant);
2413 InitPosition(FALSE);
2417 * Determine boardSize
2419 gameInfo.boardWidth = gameInfo.boardHeight = 8; // [HGM] boardsize: make sure we start as 8x8
2422 // [HGM] as long as we have not created the possibility to change size while running, start with requested size
2423 gameInfo.boardWidth = appData.NrFiles > 0 ? appData.NrFiles : 8;
2424 gameInfo.boardHeight = appData.NrRanks > 0 ? appData.NrRanks : 8;
2425 gameInfo.holdingsWidth = appData.holdingsSize > 0 ? 2 : 0;
2430 InitDrawingSizes(-1, 0); // [HGM] initsize: make this into a subroutine
2432 if (isdigit(appData.boardSize[0])) {
2433 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
2434 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
2435 &fontPxlSize, &smallLayout, &tinyLayout);
2437 fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
2438 programName, appData.boardSize);
2442 /* Find some defaults; use the nearest known size */
2443 SizeDefaults *szd, *nearest;
2444 int distance = 99999;
2445 nearest = szd = sizeDefaults;
2446 while (szd->name != NULL) {
2447 if (abs(szd->squareSize - squareSize) < distance) {
2449 distance = abs(szd->squareSize - squareSize);
2450 if (distance == 0) break;
2454 if (i < 2) lineGap = nearest->lineGap;
2455 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
2456 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
2457 if (i < 5) fontPxlSize = nearest->fontPxlSize;
2458 if (i < 6) smallLayout = nearest->smallLayout;
2459 if (i < 7) tinyLayout = nearest->tinyLayout;
2462 SizeDefaults *szd = sizeDefaults;
2463 if (*appData.boardSize == NULLCHAR) {
2464 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize ||
2465 DisplayHeight(xDisplay, xScreen) < szd->minScreenSize) {
2468 if (szd->name == NULL) szd--;
2470 while (szd->name != NULL &&
2471 StrCaseCmp(szd->name, appData.boardSize) != 0) szd++;
2472 if (szd->name == NULL) {
2473 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
2474 programName, appData.boardSize);
2478 squareSize = szd->squareSize;
2479 lineGap = szd->lineGap;
2480 clockFontPxlSize = szd->clockFontPxlSize;
2481 coordFontPxlSize = szd->coordFontPxlSize;
2482 fontPxlSize = szd->fontPxlSize;
2483 smallLayout = szd->smallLayout;
2484 tinyLayout = szd->tinyLayout;
2487 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2488 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2489 if (appData.showJail == 1) {
2490 /* Jail on top and bottom */
2491 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2492 XtSetArg(boardArgs[2], XtNheight,
2493 boardHeight + 2*(lineGap + squareSize));
2494 } else if (appData.showJail == 2) {
2496 XtSetArg(boardArgs[1], XtNwidth,
2497 boardWidth + 2*(lineGap + squareSize));
2498 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2501 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2502 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2506 * Determine what fonts to use.
2508 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
2509 clockFontID = XLoadFont(xDisplay, appData.clockFont);
2510 clockFontStruct = XQueryFont(xDisplay, clockFontID);
2511 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
2512 coordFontID = XLoadFont(xDisplay, appData.coordFont);
2513 coordFontStruct = XQueryFont(xDisplay, coordFontID);
2514 appData.font = FindFont(appData.font, fontPxlSize);
2515 countFontID = XLoadFont(xDisplay, appData.coordFont); // [HGM] holdings
2516 countFontStruct = XQueryFont(xDisplay, countFontID);
2517 // appData.font = FindFont(appData.font, fontPxlSize);
2519 xdb = XtDatabase(xDisplay);
2520 XrmPutStringResource(&xdb, "*font", appData.font);
2523 * Detect if there are not enough colors available and adapt.
2525 if (DefaultDepth(xDisplay, xScreen) <= 2) {
2526 appData.monoMode = True;
2529 if (!appData.monoMode) {
2530 vFrom.addr = (caddr_t) appData.lightSquareColor;
2531 vFrom.size = strlen(appData.lightSquareColor);
2532 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2533 if (vTo.addr == NULL) {
2534 appData.monoMode = True;
2537 lightSquareColor = *(Pixel *) vTo.addr;
2540 if (!appData.monoMode) {
2541 vFrom.addr = (caddr_t) appData.darkSquareColor;
2542 vFrom.size = strlen(appData.darkSquareColor);
2543 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2544 if (vTo.addr == NULL) {
2545 appData.monoMode = True;
2548 darkSquareColor = *(Pixel *) vTo.addr;
2551 if (!appData.monoMode) {
2552 vFrom.addr = (caddr_t) appData.whitePieceColor;
2553 vFrom.size = strlen(appData.whitePieceColor);
2554 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2555 if (vTo.addr == NULL) {
2556 appData.monoMode = True;
2559 whitePieceColor = *(Pixel *) vTo.addr;
2562 if (!appData.monoMode) {
2563 vFrom.addr = (caddr_t) appData.blackPieceColor;
2564 vFrom.size = strlen(appData.blackPieceColor);
2565 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2566 if (vTo.addr == NULL) {
2567 appData.monoMode = True;
2570 blackPieceColor = *(Pixel *) vTo.addr;
2574 if (!appData.monoMode) {
2575 vFrom.addr = (caddr_t) appData.highlightSquareColor;
2576 vFrom.size = strlen(appData.highlightSquareColor);
2577 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2578 if (vTo.addr == NULL) {
2579 appData.monoMode = True;
2582 highlightSquareColor = *(Pixel *) vTo.addr;
2586 if (!appData.monoMode) {
2587 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
2588 vFrom.size = strlen(appData.premoveHighlightColor);
2589 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2590 if (vTo.addr == NULL) {
2591 appData.monoMode = True;
2594 premoveHighlightColor = *(Pixel *) vTo.addr;
2599 fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2602 if (appData.bitmapDirectory == NULL ||
2603 appData.bitmapDirectory[0] == NULLCHAR)
2604 appData.bitmapDirectory = DEF_BITMAP_DIR;
2607 if (appData.lowTimeWarning && !appData.monoMode) {
2608 vFrom.addr = (caddr_t) appData.lowTimeWarningColor;
2609 vFrom.size = strlen(appData.lowTimeWarningColor);
2610 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2611 if (vTo.addr == NULL)
2612 appData.monoMode = True;
2614 lowTimeWarningColor = *(Pixel *) vTo.addr;
2617 if (appData.monoMode && appData.debugMode) {
2618 fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2619 (unsigned long) XWhitePixel(xDisplay, xScreen),
2620 (unsigned long) XBlackPixel(xDisplay, xScreen));
2623 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
2624 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
2625 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
2626 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
2627 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
2628 parse_cpair(ColorTell, appData.colorTell) < 0 ||
2629 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
2630 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
2631 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
2632 parse_cpair(ColorNormal, appData.colorNormal) < 0)
2634 if (appData.colorize) {
2636 _("%s: can't parse color names; disabling colorization\n"),
2639 appData.colorize = FALSE;
2641 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2642 textColors[ColorNone].attr = 0;
2644 // XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2650 layoutName = "tinyLayout";
2651 } else if (smallLayout) {
2652 layoutName = "smallLayout";
2654 layoutName = "normalLayout";
2657 if (appData.titleInWindow) {
2658 /* todo check what this appdata does */
2661 if (appData.showButtonBar) {
2662 /* TODO hide button bar if requested */
2666 * gtk set properties of widgets
2669 /* set board size */
2670 gtk_widget_set_size_request(GTK_WIDGET(GUI_Board),
2671 boardWidth,boardHeight);
2673 /* end gtk set properties of widgets */
2675 if (appData.titleInWindow)
2680 if (appData.showButtonBar)
2687 if (appData.showButtonBar)
2696 // [HGM] it seems the layout code ends here, but perhaps the color stuff is size independent and would
2697 // not need to go into InitDrawingSizes().
2700 /* set some checkboxes in the menu according to appData */
2702 if (appData.alwaysPromoteToQueen)
2703 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Always Queen")),TRUE);
2705 if (appData.animateDragging)
2706 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Animate Dragging")),TRUE);
2708 if (appData.animate)
2709 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Animate Moving")),TRUE);
2711 if (appData.autoComment)
2712 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Comment")),TRUE);
2714 if (appData.autoCallFlag)
2715 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Flag")),TRUE);
2717 if (appData.autoFlipView)
2718 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Flip View")),TRUE);
2720 if (appData.autoObserve)
2721 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Observe")),TRUE);
2723 if (appData.autoRaiseBoard)
2724 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Raise Board")),TRUE);
2726 if (appData.autoSaveGames)
2727 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Save")),TRUE);
2729 if (appData.saveGameFile[0] != NULLCHAR)
2731 /* Can't turn this off from menu */
2732 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Save")),TRUE);
2733 gtk_action_set_sensitive(GTK_ACTION (gtk_builder_get_object (builder, "menuOptions.Auto Save")),FALSE);
2736 if (appData.blindfold)
2737 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Blindfold")),TRUE);
2739 if (appData.flashCount > 0)
2740 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Flash Moves")),TRUE);
2742 if (appData.getMoveList)
2743 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Get Move List")),TRUE);
2746 if (appData.highlightDragging)
2747 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Highlight Dragging")),TRUE);
2750 if (appData.highlightLastMove)
2751 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Highlight Last Move")),TRUE);
2753 if (appData.icsAlarm)
2754 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.ICS Alarm")),TRUE);
2756 if (appData.ringBellAfterMoves)
2757 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Move Sound")),TRUE);
2759 if (appData.oldSaveStyle)
2760 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Old Save Style")),TRUE);
2762 if (appData.periodicUpdates)
2763 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Periodic Updates")),TRUE);
2765 if (appData.ponderNextMove)
2766 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Ponder Next Move")),TRUE);
2768 if (appData.popupExitMessage)
2769 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Popup Exit Message")),TRUE);
2771 if (appData.popupMoveErrors)
2772 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Popup Move Errors")),TRUE);
2774 if (appData.premove)
2775 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Premove")),TRUE);
2777 if (appData.quietPlay)
2778 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Quit Play")),TRUE);
2780 if (appData.showCoords)
2781 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Show Coords")),TRUE);
2783 if (appData.showThinking)
2784 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Show Thinking")),TRUE);
2786 if (appData.testLegality)
2787 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Test Legality")),TRUE);
2789 /* end setting check boxes */
2792 /* load square colors */
2793 SVGLightSquare = load_pixbuf("svg/LightSquare.svg",squareSize);
2794 SVGDarkSquare = load_pixbuf("svg/DarkSquare.svg",squareSize);
2795 SVGNeutralSquare = load_pixbuf("svg/NeutralSquare.svg",squareSize);
2797 /* use two icons to indicate if it is white's or black's turn */
2798 WhiteIcon = load_pixbuf("svg/icon_white.svg",0);
2799 BlackIcon = load_pixbuf("svg/icon_black.svg",0);
2800 WindowIcon = WhiteIcon;
2801 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
2803 /* do resizing to a fixed aspect ratio */
2808 GUI_SetAspectRatio(0.7);
2810 /* realize window */
2811 gtk_widget_show (GUI_Window);
2817 if (appData.animate || appData.animateDragging)
2822 if (errorExitStatus == -1) {
2823 if (appData.icsActive) {
2824 /* We now wait until we see "login:" from the ICS before
2825 sending the logon script (problems with timestamp otherwise) */
2826 /*ICSInitScript();*/
2827 if (appData.icsInputBox) ICSInputBoxPopUp();
2830 signal(SIGINT, IntSigHandler);
2831 signal(SIGTERM, IntSigHandler);
2832 if (*appData.cmailGameName != NULLCHAR) {
2833 signal(SIGUSR1, CmailSigHandler);
2836 gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes()
2840 * Create a cursor for the board widget.
2841 * (This needs to be called after the window has been created to have access to board-window)
2844 BoardCursor = gdk_cursor_new(GDK_HAND2);
2845 gdk_window_set_cursor(GUI_Board->window, BoardCursor);
2846 gdk_cursor_destroy(BoardCursor);
2851 if (appData.debugMode) fclose(debugFP); // [DM] debug
2858 if (appData.icsActive && oldICSInteractionTitle != NULL) {
2859 DisplayIcsInteractionTitle(oldICSInteractionTitle);
2861 unlink(gameCopyFilename);
2862 unlink(gamePasteFilename);
2873 CmailSigHandler(sig)
2879 signal(SIGUSR1, SIG_IGN); /* suspend handler */
2881 /* Activate call-back function CmailSigHandlerCallBack() */
2882 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
2884 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
2888 CmailSigHandlerCallBack(isr, closure, message, count, error)
2896 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
2898 /**** end signal code ****/
2908 f = fopen(appData.icsLogon, "r");
2914 strcat(buf, appData.icsLogon);
2915 f = fopen(buf, "r");
2919 ProcessICSInitScript(f);
2926 EditCommentPopDown();
2932 SetMenuEnables(enab)
2937 if (!builder) return;
2938 while (enab->name != NULL) {
2939 o = gtk_builder_get_object(builder, enab->name);
2940 if(GTK_IS_WIDGET(o))
2941 gtk_widget_set_sensitive(GTK_WIDGET (o),enab->value);
2944 if(GTK_IS_ACTION(o))
2945 gtk_action_set_sensitive(GTK_ACTION (o),enab->value);
2947 DisplayError(enab->name, 0);
2955 SetMenuEnables(icsEnables);
2958 if (appData.zippyPlay && !appData.noChessProgram) /* [DM] icsEngineAnalyze */
2959 {}; // XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
2966 SetMenuEnables(ncpEnables);
2972 SetMenuEnables(gnuEnables);
2978 SetMenuEnables(cmailEnables);
2984 SetMenuEnables(trainingOnEnables);
2985 if (appData.showButtonBar) {
2986 // XtSetSensitive(buttonBarWidget, False);
2992 SetTrainingModeOff()
2994 SetMenuEnables(trainingOffEnables);
2995 if (appData.showButtonBar) {
2996 // XtSetSensitive(buttonBarWidget, True);
3001 SetUserThinkingEnables()
3003 if (appData.noChessProgram) return;
3004 SetMenuEnables(userThinkingEnables);
3008 SetMachineThinkingEnables()
3010 if (appData.noChessProgram) return;
3011 SetMenuEnables(machineThinkingEnables);
3013 case MachinePlaysBlack:
3014 case MachinePlaysWhite:
3015 case TwoMachinesPlay:
3016 XtSetSensitive(XtNameToWidget(menuBarWidget,
3017 ModeToWidgetName(gameMode)), True);
3024 #define Abs(n) ((n)<0 ? -(n) : (n))
3027 * Find a font that matches "pattern" that is as close as
3028 * possible to the targetPxlSize. Prefer fonts that are k
3029 * pixels smaller to fonts that are k pixels larger. The
3030 * pattern must be in the X Consortium standard format,
3031 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
3032 * The return value should be freed with XtFree when no
3035 char *FindFont(pattern, targetPxlSize)
3039 char **fonts, *p, *best, *scalable, *scalableTail;
3040 int i, j, nfonts, minerr, err, pxlSize;
3043 char **missing_list;
3045 char *def_string, *base_fnt_lst, strInt[3];
3047 XFontStruct **fnt_list;
3049 base_fnt_lst = calloc(1, strlen(pattern) + 3);
3050 sprintf(strInt, "%d", targetPxlSize);
3051 p = strstr(pattern, "--");
3052 strncpy(base_fnt_lst, pattern, p - pattern + 2);
3053 strcat(base_fnt_lst, strInt);
3054 strcat(base_fnt_lst, strchr(p + 2, '-'));
3056 if ((fntSet = XCreateFontSet(xDisplay,
3060 &def_string)) == NULL) {
3062 fprintf(stderr, _("Unable to create font set.\n"));
3066 nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
3068 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
3070 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
3071 programName, pattern);
3079 for (i=0; i<nfonts; i++) {
3082 if (*p != '-') continue;
3084 if (*p == NULLCHAR) break;
3085 if (*p++ == '-') j++;
3087 if (j < 7) continue;
3090 scalable = fonts[i];
3093 err = pxlSize - targetPxlSize;
3094 if (Abs(err) < Abs(minerr) ||
3095 (minerr > 0 && err < 0 && -err == minerr)) {
3101 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
3102 /* If the error is too big and there is a scalable font,
3103 use the scalable font. */
3104 int headlen = scalableTail - scalable;
3105 p = (char *) XtMalloc(strlen(scalable) + 10);
3106 while (isdigit(*scalableTail)) scalableTail++;
3107 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
3109 p = (char *) XtMalloc(strlen(best) + 1);
3112 if (appData.debugMode) {
3113 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
3114 pattern, targetPxlSize, p);
3117 if (missing_count > 0)
3118 XFreeStringList(missing_list);
3119 XFreeFontSet(xDisplay, fntSet);
3121 XFreeFontNames(fonts);
3128 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
3129 | GCBackground | GCFunction | GCPlaneMask;
3130 XGCValues gc_values;
3133 gc_values.plane_mask = AllPlanes;
3134 gc_values.line_width = lineGap;
3135 gc_values.line_style = LineSolid;
3136 gc_values.function = GXcopy;
3138 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3139 gc_values.background = XWhitePixel(xDisplay, xScreen);
3140 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
3141 XSetFont(xDisplay, coordGC, coordFontID);
3143 if (appData.monoMode) {
3144 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3145 gc_values.background = XBlackPixel(xDisplay, xScreen);
3146 lightSquareGC = wbPieceGC
3147 = XtGetGC(shellWidget, value_mask, &gc_values);
3149 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3150 gc_values.background = XWhitePixel(xDisplay, xScreen);
3151 darkSquareGC = bwPieceGC
3152 = XtGetGC(shellWidget, value_mask, &gc_values);
3154 if (DefaultDepth(xDisplay, xScreen) == 1) {
3155 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3156 gc_values.function = GXcopyInverted;
3157 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3158 gc_values.function = GXcopy;
3159 if (XBlackPixel(xDisplay, xScreen) == 1) {
3160 bwPieceGC = darkSquareGC;
3161 wbPieceGC = copyInvertedGC;
3163 bwPieceGC = copyInvertedGC;
3164 wbPieceGC = lightSquareGC;
3168 gc_values.foreground = lightSquareColor;
3169 gc_values.background = darkSquareColor;
3170 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3172 gc_values.foreground = darkSquareColor;
3173 gc_values.background = lightSquareColor;
3174 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3176 gc_values.foreground = jailSquareColor;
3177 gc_values.background = jailSquareColor;
3178 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3180 gc_values.foreground = whitePieceColor;
3181 gc_values.background = darkSquareColor;
3182 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3184 gc_values.foreground = whitePieceColor;
3185 gc_values.background = lightSquareColor;
3186 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3188 gc_values.foreground = whitePieceColor;
3189 gc_values.background = jailSquareColor;
3190 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3192 gc_values.foreground = blackPieceColor;
3193 gc_values.background = darkSquareColor;
3194 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3196 gc_values.foreground = blackPieceColor;
3197 gc_values.background = lightSquareColor;
3198 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3200 gc_values.foreground = blackPieceColor;
3201 gc_values.background = jailSquareColor;
3202 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3209 WhitePawn, WhiteKnight, WhiteBishop, WhiteRook, WhiteQueen, WhiteKing,
3210 BlackPawn, BlackKnight, BlackBishop, BlackRook, BlackQueen, BlackKing,
3213 SVGpieces[WhitePawn] = load_pixbuf("svg/WhitePawn.svg",squareSize);
3214 SVGpieces[WhiteKnight] = load_pixbuf("svg/WhiteKnight.svg",squareSize);
3215 SVGpieces[WhiteBishop] = load_pixbuf("svg/WhiteBishop.svg",squareSize);
3216 SVGpieces[WhiteRook] = load_pixbuf("svg/WhiteRook.svg",squareSize);
3217 SVGpieces[WhiteQueen] = load_pixbuf("svg/WhiteQueen.svg",squareSize);
3218 SVGpieces[WhiteKing] = load_pixbuf("svg/WhiteKing.svg",squareSize);
3220 SVGpieces[BlackPawn] = load_pixbuf("svg/BlackPawn.svg",squareSize);
3221 SVGpieces[BlackKnight] = load_pixbuf("svg/BlackKnight.svg",squareSize);
3222 SVGpieces[BlackBishop] = load_pixbuf("svg/BlackBishop.svg",squareSize);
3223 SVGpieces[BlackRook] = load_pixbuf("svg/BlackRook.svg",squareSize);
3224 SVGpieces[BlackQueen] = load_pixbuf("svg/BlackQueen.svg",squareSize);
3225 SVGpieces[BlackKing] = load_pixbuf("svg/BlackKing.svg",squareSize);
3231 static void MenuBarSelect(w, addr, index)
3236 XtActionProc proc = (XtActionProc) addr;
3238 (proc)(NULL, NULL, NULL, NULL);
3241 void CreateMenuBarPopup(parent, name, mb)
3251 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3254 XtSetArg(args[j], XtNleftMargin, 20); j++;
3255 XtSetArg(args[j], XtNrightMargin, 20); j++;
3257 while (mi->string != NULL) {
3258 if (strcmp(mi->string, "----") == 0) {
3259 entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
3262 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string)));
3263 entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass,
3265 XtAddCallback(entry, XtNcallback,
3266 (XtCallbackProc) MenuBarSelect,
3267 (caddr_t) mi->proc);
3273 Widget CreateMenuBar(mb)
3277 Widget anchor, menuBar;
3279 char menuName[MSG_SIZ];
3282 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3283 XtSetArg(args[j], XtNvSpace, 0); j++;
3284 XtSetArg(args[j], XtNborderWidth, 0); j++;
3285 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
3286 formWidget, args, j);
3288 while (mb->name != NULL) {
3289 strcpy(menuName, "menu");
3290 strcat(menuName, mb->name);
3292 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
3295 shortName[0] = _(mb->name)[0];
3296 shortName[1] = NULLCHAR;
3297 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
3300 XtSetArg(args[j], XtNlabel, XtNewString(_(mb->name))); j++;
3303 XtSetArg(args[j], XtNborderWidth, 0); j++;
3304 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
3306 CreateMenuBarPopup(menuBar, menuName, mb);
3312 Widget CreateButtonBar(mi)
3316 Widget button, buttonBar;
3320 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3322 XtSetArg(args[j], XtNhSpace, 0); j++;
3324 XtSetArg(args[j], XtNborderWidth, 0); j++;
3325 XtSetArg(args[j], XtNvSpace, 0); j++;
3326 buttonBar = XtCreateWidget("buttonBar", boxWidgetClass,
3327 formWidget, args, j);
3329 while (mi->string != NULL) {
3332 XtSetArg(args[j], XtNinternalWidth, 2); j++;
3333 XtSetArg(args[j], XtNborderWidth, 0); j++;
3335 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string))); j++;
3336 button = XtCreateManagedWidget(mi->string, commandWidgetClass,
3337 buttonBar, args, j);
3338 XtAddCallback(button, XtNcallback,
3339 (XtCallbackProc) MenuBarSelect,
3340 (caddr_t) mi->proc);
3347 CreatePieceMenu(name, color)
3354 ChessSquare selection;
3356 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3357 boardWidget, args, 0);
3359 for (i = 0; i < PIECE_MENU_SIZE; i++) {
3360 String item = pieceMenuStrings[color][i];
3362 if (strcmp(item, "----") == 0) {
3363 entry = XtCreateManagedWidget(item, smeLineObjectClass,
3366 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3367 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3369 selection = pieceMenuTranslation[color][i];
3370 XtAddCallback(entry, XtNcallback,
3371 (XtCallbackProc) PieceMenuSelect,
3372 (caddr_t) selection);
3373 if (selection == WhitePawn || selection == BlackPawn) {
3374 XtSetArg(args[0], XtNpopupOnEntry, entry);
3375 XtSetValues(menu, args, 1);
3388 ChessSquare selection;
3390 // whitePieceMenu = CreatePieceMenu("menuW", 0);
3391 // blackPieceMenu = CreatePieceMenu("menuB", 1);
3393 // XtRegisterGrabAction(PieceMenuPopup, True,
3394 // (unsigned)(ButtonPressMask|ButtonReleaseMask),
3395 // GrabModeAsync, GrabModeAsync);
3397 // XtSetArg(args[0], XtNlabel, _("Drop"));
3398 // dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
3399 // boardWidget, args, 1);
3400 // for (i = 0; i < DROP_MENU_SIZE; i++) {
3401 // String item = dropMenuStrings[i];
3403 // if (strcmp(item, "----") == 0) {
3404 // entry = XtCreateManagedWidget(item, smeLineObjectClass,
3405 // dropMenu, NULL, 0);
3407 // XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3408 // entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3409 // dropMenu, args, 1);
3410 // selection = dropMenuTranslation[i];
3411 // XtAddCallback(entry, XtNcallback,
3412 // (XtCallbackProc) DropMenuSelect,
3413 // (caddr_t) selection);
3418 void SetupDropMenu()
3426 for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
3427 entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
3428 p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
3429 dmEnables[i].piece);
3430 XtSetSensitive(entry, p != NULL || !appData.testLegality
3431 /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
3432 && !appData.icsActive));
3434 while (p && *p++ == dmEnables[i].piece) count++;
3435 snprintf(label, sizeof(label), "%s %d", dmEnables[i].widget, count);
3437 XtSetArg(args[j], XtNlabel, label); j++;
3438 XtSetValues(entry, args, j);
3442 void PieceMenuPopup(w, event, params, num_params)
3446 Cardinal *num_params;
3449 if (event->type != ButtonPress) return;
3450 if (errorUp) ErrorPopDown();
3454 whichMenu = params[0];
3456 case IcsPlayingWhite:
3457 case IcsPlayingBlack:
3459 case MachinePlaysWhite:
3460 case MachinePlaysBlack:
3461 if (appData.testLegality &&
3462 gameInfo.variant != VariantBughouse &&
3463 gameInfo.variant != VariantCrazyhouse) return;
3465 whichMenu = "menuD";
3471 if (((pmFromX = EventToSquare(event->xbutton.x, BOARD_WIDTH)) < 0) ||
3472 ((pmFromY = EventToSquare(event->xbutton.y, BOARD_HEIGHT)) < 0)) {
3473 pmFromX = pmFromY = -1;
3477 pmFromX = BOARD_WIDTH - 1 - pmFromX;
3479 pmFromY = BOARD_HEIGHT - 1 - pmFromY;
3481 XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
3484 static void PieceMenuSelect(w, piece, junk)
3489 if (pmFromX < 0 || pmFromY < 0) return;
3490 EditPositionMenuEvent(piece, pmFromX, pmFromY);
3493 static void DropMenuSelect(w, piece, junk)
3498 if (pmFromX < 0 || pmFromY < 0) return;
3499 DropMenuEvent(piece, pmFromX, pmFromY);
3502 void WhiteClock(w, event, prms, nprms)
3508 if (gameMode == EditPosition || gameMode == IcsExamining) {
3509 SetWhiteToPlayEvent();
3510 } else if (gameMode == IcsPlayingBlack || gameMode == MachinePlaysWhite) {
3515 void BlackClock(w, event, prms, nprms)
3521 if (gameMode == EditPosition || gameMode == IcsExamining) {
3522 SetBlackToPlayEvent();
3523 } else if (gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) {
3530 * If the user selects on a border boundary, return -1; if off the board,
3531 * return -2. Otherwise map the event coordinate to the square.
3533 int EventToSquare(x, limit)
3541 if ((x % (squareSize + lineGap)) >= squareSize)
3543 x /= (squareSize + lineGap);
3549 static void do_flash_delay(msec)
3555 static void drawHighlight(file, rank, line_type)
3556 int file, rank, line_type;
3561 if (lineGap == 0 || appData.blindfold) return;
3565 x = lineGap/2 + ((BOARD_WIDTH-1)-file) *
3566 (squareSize + lineGap);
3567 y = lineGap/2 + rank * (squareSize + lineGap);
3571 x = lineGap/2 + file * (squareSize + lineGap);
3572 y = lineGap/2 + ((BOARD_HEIGHT-1)-rank) *
3573 (squareSize + lineGap);
3577 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3579 /* draw the highlight */
3580 cairo_move_to (cr, x, y);
3581 cairo_rel_line_to (cr, 0,squareSize+lineGap);
3582 cairo_rel_line_to (cr, squareSize+lineGap,0);
3583 cairo_rel_line_to (cr, 0,-squareSize-lineGap);
3584 cairo_close_path (cr);
3586 cairo_set_line_width (cr, lineGap);
3589 /* TODO: use appdata colors */
3590 case LINE_TYPE_HIGHLIGHT:
3591 cairo_set_source_rgba (cr, 1, 1, 0, 1.0);
3594 cairo_set_source_rgba (cr, 1, 0, 0, 1.0);
3596 case LINE_TYPE_NORMAL:
3598 cairo_set_source_rgba (cr, 0, 1, 0, 1.0);
3609 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
3610 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
3613 SetHighlights(fromX, fromY, toX, toY)
3614 int fromX, fromY, toX, toY;
3616 if (hi1X != fromX || hi1Y != fromY)
3618 if (hi1X >= 0 && hi1Y >= 0)
3620 drawHighlight(hi1X, hi1Y, LINE_TYPE_NORMAL);
3622 if (fromX >= 0 && fromY >= 0)
3624 drawHighlight(fromX, fromY, LINE_TYPE_HIGHLIGHT);
3627 if (hi2X != toX || hi2Y != toY)
3629 if (hi2X >= 0 && hi2Y >= 0)
3631 drawHighlight(hi2X, hi2Y, LINE_TYPE_NORMAL);
3633 if (toX >= 0 && toY >= 0)
3635 drawHighlight(toX, toY, LINE_TYPE_HIGHLIGHT);
3649 SetHighlights(-1, -1, -1, -1);
3654 SetPremoveHighlights(fromX, fromY, toX, toY)
3655 int fromX, fromY, toX, toY;
3657 if (pm1X != fromX || pm1Y != fromY)
3659 if (pm1X >= 0 && pm1Y >= 0)
3661 drawHighlight(pm1X, pm1Y, LINE_TYPE_NORMAL);
3663 if (fromX >= 0 && fromY >= 0)
3665 drawHighlight(fromX, fromY, LINE_TYPE_PRE);
3668 if (pm2X != toX || pm2Y != toY)
3670 if (pm2X >= 0 && pm2Y >= 0)
3672 drawHighlight(pm2X, pm2Y, LINE_TYPE_NORMAL);
3674 if (toX >= 0 && toY >= 0)
3676 drawHighlight(toX, toY, LINE_TYPE_PRE);
3689 ClearPremoveHighlights()
3691 SetPremoveHighlights(-1, -1, -1, -1);
3694 static void BlankSquare(x, y, color, piece, dest)
3702 pb = SVGLightSquare;
3707 case 2: /* neutral */
3709 pb = SVGNeutralSquare;
3712 gdk_draw_pixbuf(GDK_WINDOW(GUI_Board->window),NULL,pb,0,0,x,y,-1,-1, GDK_RGB_DITHER_NORMAL, 0, 0);
3715 static void DrawPiece(piece, square_color, x, y, dest)
3717 int square_color, x, y;
3720 gdk_draw_pixbuf(GDK_WINDOW(GUI_Board->window),NULL,
3721 GDK_PIXBUF(SVGpieces[piece]),0,0,x,y,-1,-1,
3722 GDK_RGB_DITHER_NORMAL, 0, 0);
3726 /* [HR] determine square color depending on chess variant. */
3727 static int SquareColor(row, column)
3732 if (gameInfo.variant == VariantXiangqi) {
3733 if (column >= 3 && column <= 5 && row >= 0 && row <= 2) {
3735 } else if (column >= 3 && column <= 5 && row >= 7 && row <= 9) {
3737 } else if (row <= 4) {
3743 square_color = ((column + row) % 2) == 1;
3746 /* [hgm] holdings: next line makes all holdings squares light */
3747 if(column < BOARD_LEFT || column >= BOARD_RGHT) square_color = 1;
3749 return square_color;
3752 void DrawSquare(row, column, piece, do_flash)
3753 int row, column, do_flash;
3756 int square_color, x, y;
3761 /* Calculate delay in milliseconds (2-delays per complete flash) */
3762 flash_delay = 500 / appData.flashRate;
3764 /* calculate x and y coordinates from row and column */
3767 x = lineGap + ((BOARD_WIDTH-1)-column) *
3768 (squareSize + lineGap);
3769 y = lineGap + row * (squareSize + lineGap);
3773 x = lineGap + column * (squareSize + lineGap);
3774 y = lineGap + ((BOARD_HEIGHT-1)-row) *
3775 (squareSize + lineGap);
3778 square_color = SquareColor(row, column);
3780 // [HGM] holdings: blank out area between board and holdings
3781 if ( column == BOARD_LEFT-1 || column == BOARD_RGHT
3782 || (column == BOARD_LEFT-2 && row < BOARD_HEIGHT-gameInfo.holdingsSize)
3783 || (column == BOARD_RGHT+1 && row >= gameInfo.holdingsSize) )
3785 BlankSquare(x, y, 2, EmptySquare, xBoardWindow);
3787 // [HGM] print piece counts next to holdings
3788 string[1] = NULLCHAR;
3791 cairo_text_extents_t extents;
3796 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3798 string[0] = '0' + piece;
3800 /* TODO this has to go into the font-selection */
3801 cairo_select_font_face (cr, "Sans",
3802 CAIRO_FONT_SLANT_NORMAL,
3803 CAIRO_FONT_WEIGHT_NORMAL);
3805 cairo_set_font_size (cr, 12.0);
3806 cairo_text_extents (cr, string, &extents);
3809 if (column == (flipView ? BOARD_LEFT-1 : BOARD_RGHT) )
3811 xpos= x + squareSize - extents.width - 2;
3812 ypos= y + extents.y_bearing + 1;
3814 if (column == (flipView ? BOARD_RGHT : BOARD_LEFT-1) && piece > 1)
3817 ypos = y + extents.y_bearing + 1;
3820 /* TODO mono mode? */
3821 cairo_move_to (cr, xpos, ypos);
3822 cairo_text_path (cr, string);
3823 cairo_set_source_rgb (cr, 1.0, 1.0, 1);
3824 cairo_fill_preserve (cr);
3825 cairo_set_source_rgb (cr, 0, 0, 0);
3826 cairo_set_line_width (cr, 0.1);
3836 /* square on the board */
3837 if (piece == EmptySquare || appData.blindfold)
3839 BlankSquare(x, y, square_color, piece, xBoardWindow);
3843 if (do_flash && appData.flashCount > 0)
3845 for (i=0; i<appData.flashCount; ++i)
3848 DrawPiece(piece, square_color, x, y, xBoardWindow);
3849 do_flash_delay(flash_delay);
3851 BlankSquare(x, y, square_color, piece, xBoardWindow);
3852 do_flash_delay(flash_delay);
3855 DrawPiece(piece, square_color, x, y, xBoardWindow);
3859 /* show coordinates if necessary */
3860 if(appData.showCoords)
3862 cairo_text_extents_t extents;
3866 /* TODO this has to go into the font-selection */
3867 cairo_select_font_face (cr, "Sans",
3868 CAIRO_FONT_SLANT_NORMAL,
3869 CAIRO_FONT_WEIGHT_NORMAL);
3870 cairo_set_font_size (cr, 12.0);
3872 string[1] = NULLCHAR;
3875 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3877 if (row == (flipView ? BOARD_HEIGHT-1 : 0) &&
3878 column >= BOARD_LEFT && column < BOARD_RGHT)
3880 string[0] = 'a' + column - BOARD_LEFT;
3881 cairo_text_extents (cr, string, &extents);
3883 xpos = x + squareSize - extents.width - 2;
3884 ypos = y + squareSize - extents.height - extents.y_bearing - 1;
3886 if (appData.monoMode)
3893 cairo_move_to (cr, xpos, ypos);
3894 cairo_text_path (cr, string);
3895 cairo_set_source_rgb (cr, 0.0, 0.0, 0);
3896 cairo_fill_preserve (cr);
3897 cairo_set_source_rgb (cr, 0, 1.0, 0);
3898 cairo_set_line_width (cr, 0.1);
3901 if ( column == (flipView ? BOARD_RGHT-1 : BOARD_LEFT))
3904 string[0] = ONE + row;
3905 cairo_text_extents (cr, string, &extents);
3908 ypos = y + extents.height + 1;
3910 if (appData.monoMode)
3917 cairo_move_to (cr, xpos, ypos);
3918 cairo_text_path (cr, string);
3919 cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
3920 cairo_fill_preserve (cr);
3921 cairo_set_source_rgb (cr, 0, 0, 1.0);
3922 cairo_set_line_width (cr, 0.1);
3934 /* Returns 1 if there are "too many" differences between b1 and b2
3935 (i.e. more than 1 move was made) */
3936 static int too_many_diffs(b1, b2)
3942 for (i=0; i<BOARD_HEIGHT; ++i) {
3943 for (j=0; j<BOARD_WIDTH; ++j) {
3944 if (b1[i][j] != b2[i][j]) {
3945 if (++c > 4) /* Castling causes 4 diffs */
3954 /* Matrix describing castling maneuvers */
3955 /* Row, ColRookFrom, ColKingFrom, ColRookTo, ColKingTo */
3956 static int castling_matrix[4][5] = {
3957 { 0, 0, 4, 3, 2 }, /* 0-0-0, white */
3958 { 0, 7, 4, 5, 6 }, /* 0-0, white */
3959 { 7, 0, 4, 3, 2 }, /* 0-0-0, black */
3960 { 7, 7, 4, 5, 6 } /* 0-0, black */
3963 /* Checks whether castling occurred. If it did, *rrow and *rcol
3964 are set to the destination (row,col) of the rook that moved.
3966 Returns 1 if castling occurred, 0 if not.
3968 Note: Only handles a max of 1 castling move, so be sure
3969 to call too_many_diffs() first.
3971 static int check_castle_draw(newb, oldb, rrow, rcol)
3978 /* For each type of castling... */
3979 for (i=0; i<4; ++i) {
3980 r = castling_matrix[i];
3982 /* Check the 4 squares involved in the castling move */
3984 for (j=1; j<=4; ++j) {
3985 if (newb[r[0]][r[j]] == oldb[r[0]][r[j]]) {
3992 /* All 4 changed, so it must be a castling move */
4001 static int damage[BOARD_SIZE][BOARD_SIZE];
4004 * event handler for redrawing the board
4006 void DrawPosition( repaint, board)
4007 /*Boolean*/int repaint;
4011 static int lastFlipView = 0;
4012 static int lastBoardValid = 0;
4013 static Board lastBoard;
4016 if (board == NULL) {
4017 if (!lastBoardValid) return;
4020 if (!lastBoardValid || lastFlipView != flipView) {
4021 // XtSetArg(args[0], XtNleftBitmap, (flipView ? xMarkPixmap : None));
4022 // XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flip View"),
4027 * It would be simpler to clear the window with XClearWindow()
4028 * but this causes a very distracting flicker.
4031 if (!repaint && lastBoardValid && lastFlipView == flipView)
4033 /* If too much changes (begin observing new game, etc.), don't
4035 do_flash = too_many_diffs(board, lastBoard) ? 0 : 1;
4037 /* Special check for castling so we don't flash both the king
4038 and the rook (just flash the king). */
4041 if (check_castle_draw(board, lastBoard, &rrow, &rcol))
4043 /* Draw rook with NO flashing. King will be drawn flashing later */
4044 DrawSquare(rrow, rcol, board[rrow][rcol], 0);
4045 lastBoard[rrow][rcol] = board[rrow][rcol];
4049 /* First pass -- Draw (newly) empty squares and repair damage.
4050 This prevents you from having a piece show up twice while it
4051 is flashing on its new square */
4052 for (i = 0; i < BOARD_HEIGHT; i++)
4053 for (j = 0; j < BOARD_WIDTH; j++)
4054 if ((board[i][j] != lastBoard[i][j] && board[i][j] == EmptySquare)
4057 DrawSquare(i, j, board[i][j], 0);
4058 damage[i][j] = False;
4061 /* Second pass -- Draw piece(s) in new position and flash them */
4062 for (i = 0; i < BOARD_HEIGHT; i++)
4063 for (j = 0; j < BOARD_WIDTH; j++)
4064 if (board[i][j] != lastBoard[i][j])
4066 DrawSquare(i, j, board[i][j], do_flash);
4078 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
4080 cairo_set_line_width (cr, lineGap);
4082 /* TODO: use appdata colors */
4083 cairo_set_source_rgba (cr, 0, 1, 0, 1.0);
4087 for (i = 0; i < BOARD_HEIGHT + 1; i++)
4090 x2 = lineGap + BOARD_WIDTH * (squareSize + lineGap);
4091 y1 = y2 = lineGap / 2 + (i * (squareSize + lineGap));
4093 cairo_move_to (cr, x1, y1);
4094 cairo_rel_line_to (cr, x2,0);
4098 for (j = 0; j < BOARD_WIDTH + 1; j++)
4101 y2 = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
4102 x1 = x2 = lineGap / 2 + (j * (squareSize + lineGap));
4104 cairo_move_to (cr, x1, y1);
4105 cairo_rel_line_to (cr, 0, y2);
4114 for (i = 0; i < BOARD_HEIGHT; i++)
4115 for (j = 0; j < BOARD_WIDTH; j++)
4117 DrawSquare(i, j, board[i][j], 0);
4118 damage[i][j] = False;
4122 CopyBoard(lastBoard, board);
4124 lastFlipView = flipView;
4126 /* Draw highlights */
4127 if (pm1X >= 0 && pm1Y >= 0)
4129 drawHighlight(pm1X, pm1Y, LINE_TYPE_PRE);
4131 if (pm2X >= 0 && pm2Y >= 0)
4133 drawHighlight(pm2X, pm2Y, LINE_TYPE_PRE);
4135 if (hi1X >= 0 && hi1Y >= 0)
4137 drawHighlight(hi1X, hi1Y, LINE_TYPE_HIGHLIGHT);
4139 if (hi2X >= 0 && hi2Y >= 0)
4141 drawHighlight(hi2X, hi2Y, LINE_TYPE_HIGHLIGHT);
4144 /* If piece being dragged around board, must redraw that too */
4151 * event handler for parsing user moves
4153 // [HGM] This routine will need quite some reworking. Although the backend still supports the old
4154 // way of doing things, by calling UserMoveEvent() to test the legality of the move and then perform
4155 // it at the end, and doing all kind of preliminary tests here (e.g. to weed out self-captures), it
4156 // should be made to use the new way, of calling UserMoveTest early to determine the legality of the
4157 // move, (which will weed out the illegal selfcaptures and moves into the holdings, and flag promotions),
4158 // and at the end FinishMove() to perform the move after optional promotion popups.
4159 // For now I patched it to allow self-capture with King, and suppress clicks between board and holdings.
4160 void HandleUserMove(w, event, prms, nprms)
4167 Boolean saveAnimate;
4168 static int second = 0;
4170 if (w != boardWidget || errorExitStatus != -1) return;
4172 if (event->type == ButtonPress) ErrorPopDown();
4175 if (event->type == ButtonPress) {
4176 XtPopdown(promotionShell);
4177 XtDestroyWidget(promotionShell);
4178 promotionUp = False;
4186 x = EventToSquare(event->xbutton.x, BOARD_WIDTH);
4187 y = EventToSquare(event->xbutton.y, BOARD_HEIGHT);
4188 if (!flipView && y >= 0) {
4189 y = BOARD_HEIGHT - 1 - y;
4191 if (flipView && x >= 0) {
4192 x = BOARD_WIDTH - 1 - x;
4195 /* [HGM] holdings: next 5 lines: ignore all clicks between board and holdings */
4196 if(event->type == ButtonPress
4197 && ( x == BOARD_LEFT-1 || x == BOARD_RGHT
4198 || x == BOARD_LEFT-2 && y < BOARD_HEIGHT-gameInfo.holdingsSize
4199 || x == BOARD_RGHT+1 && y >= gameInfo.holdingsSize) )
4203 if (event->type == ButtonPress) {
4205 if (OKToStartUserMove(x, y)) {
4209 DragPieceBegin(event->xbutton.x, event->xbutton.y);
4210 if (appData.highlightDragging) {
4211 SetHighlights(x, y, -1, -1);
4219 if (event->type == ButtonPress && gameMode != EditPosition &&
4224 /* Check if clicking again on the same color piece */
4225 fromP = boards[currentMove][fromY][fromX];
4226 toP = boards[currentMove][y][x];
4227 if ((WhitePawn <= fromP && fromP < WhiteKing && // [HGM] this test should go, as UserMoveTest now does it.
4228 WhitePawn <= toP && toP <= WhiteKing) || // For now I made it less critical by exempting King
4229 (BlackPawn <= fromP && fromP < BlackKing && // moves, to not interfere with FRC castlings.
4230 BlackPawn <= toP && toP <= BlackKing)) {
4231 /* Clicked again on same color piece -- changed his mind */
4232 second = (x == fromX && y == fromY);
4233 if (appData.highlightDragging) {
4234 SetHighlights(x, y, -1, -1);
4238 if (OKToStartUserMove(x, y)) {
4241 DragPieceBegin(event->xbutton.x, event->xbutton.y);
4247 if (event->type == ButtonRelease && x == fromX && y == fromY) {
4248 DragPieceEnd(event->xbutton.x, event->xbutton.y);
4249 if (appData.animateDragging) {
4250 /* Undo animation damage if any */
4251 DrawPosition(FALSE, NULL);
4254 /* Second up/down in same square; just abort move */
4259 ClearPremoveHighlights();
4261 /* First upclick in same square; start click-click mode */
4262 SetHighlights(x, y, -1, -1);
4267 /* Completed move */
4270 saveAnimate = appData.animate;
4271 if (event->type == ButtonPress) {
4272 /* Finish clickclick move */
4273 if (appData.animate || appData.highlightLastMove) {
4274 SetHighlights(fromX, fromY, toX, toY);
4279 /* Finish drag move */
4280 if (appData.highlightLastMove) {
4281 SetHighlights(fromX, fromY, toX, toY);
4285 DragPieceEnd(event->xbutton.x, event->xbutton.y);
4286 /* Don't animate move and drag both */
4287 appData.animate = FALSE;
4289 if (IsPromotion(fromX, fromY, toX, toY)) {
4290 if (appData.alwaysPromoteToQueen) {
4291 UserMoveEvent(fromX, fromY, toX, toY, 'q');
4292 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
4293 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
4296 SetHighlights(fromX, fromY, toX, toY);
4300 UserMoveEvent(fromX, fromY, toX, toY, NULLCHAR);
4301 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
4302 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
4305 appData.animate = saveAnimate;
4306 if (appData.animate || appData.animateDragging) {
4307 /* Undo animation damage if needed */
4308 DrawPosition(FALSE, NULL);
4312 void AnimateUserMove (Widget w, XEvent * event,
4313 String * params, Cardinal * nParams)
4315 DragPieceMove(event->xmotion.x, event->xmotion.y);
4318 Widget CommentCreate(name, text, mutable, callback, lines)
4320 int /*Boolean*/ mutable;
4321 XtCallbackProc callback;
4325 Widget shell, layout, form, edit, b_ok, b_cancel, b_clear, b_close, b_edit;
4330 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4331 XtGetValues(boardWidget, args, j);
4334 XtSetArg(args[j], XtNresizable, True); j++;
4337 XtCreatePopupShell(name, topLevelShellWidgetClass,
4338 shellWidget, args, j);
4341 XtCreatePopupShell(name, transientShellWidgetClass,
4342 shellWidget, args, j);
4345 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
4346 layoutArgs, XtNumber(layoutArgs));
4348 XtCreateManagedWidget("form", formWidgetClass, layout,
4349 formArgs, XtNumber(formArgs));
4353 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
4354 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
4356 XtSetArg(args[j], XtNstring, text); j++;
4357 XtSetArg(args[j], XtNtop, XtChainTop); j++;
4358 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4359 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4360 XtSetArg(args[j], XtNright, XtChainRight); j++;
4361 XtSetArg(args[j], XtNresizable, True); j++;
4362 XtSetArg(args[j], XtNwidth, bw_width); j++; /*force wider than buttons*/
4364 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
4366 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
4367 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
4369 XtSetArg(args[j], XtNautoFill, True); j++;
4370 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
4372 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
4376 XtSetArg(args[j], XtNfromVert, edit); j++;
4377 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4378 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4379 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4380 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4382 XtCreateManagedWidget(_("ok"), commandWidgetClass, form, args, j);
4383 XtAddCallback(b_ok, XtNcallback, callback, (XtPointer) 0);
4386 XtSetArg(args[j], XtNfromVert, edit); j++;
4387 XtSetArg(args[j], XtNfromHoriz, b_ok); j++;
4388 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4389 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4390 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4391 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4393 XtCreateManagedWidget(_("cancel"), commandWidgetClass, form, args, j);
4394 XtAddCallback(b_cancel, XtNcallback, callback, (XtPointer) 0);
4397 XtSetArg(args[j], XtNfromVert, edit); j++;
4398 XtSetArg(args[j], XtNfromHoriz, b_cancel); j++;
4399 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4400 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4401 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4402 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4404 XtCreateManagedWidget(_("clear"), commandWidgetClass, form, args, j);
4405 XtAddCallback(b_clear, XtNcallback, callback, (XtPointer) 0);
4408 XtSetArg(args[j], XtNfromVert, edit); j++;
4409 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4410 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4411 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4412 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4414 XtCreateManagedWidget(_("close"), commandWidgetClass, form, args, j);
4415 XtAddCallback(b_close, XtNcallback, callback, (XtPointer) 0);
4418 XtSetArg(args[j], XtNfromVert, edit); j++;
4419 XtSetArg(args[j], XtNfromHoriz, b_close); j++;
4420 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4421 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4422 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4423 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4425 XtCreateManagedWidget(_("edit"), commandWidgetClass, form, args, j);
4426 XtAddCallback(b_edit, XtNcallback, callback, (XtPointer) 0);
4429 XtRealizeWidget(shell);
4431 if (commentX == -1) {
4434 Dimension pw_height;
4435 Dimension ew_height;
4438 XtSetArg(args[j], XtNheight, &ew_height); j++;
4439 XtGetValues(edit, args, j);
4442 XtSetArg(args[j], XtNheight, &pw_height); j++;
4443 XtGetValues(shell, args, j);
4444 commentH = pw_height + (lines - 1) * ew_height;
4445 commentW = bw_width - 16;
4447 XSync(xDisplay, False);
4449 /* This code seems to tickle an X bug if it is executed too soon
4450 after xboard starts up. The coordinates get transformed as if
4451 the main window was positioned at (0, 0).
4453 XtTranslateCoords(shellWidget,
4454 (bw_width - commentW) / 2, 0 - commentH / 2,
4455 &commentX, &commentY);
4457 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
4458 RootWindowOfScreen(XtScreen(shellWidget)),
4459 (bw_width - commentW) / 2, 0 - commentH / 2,
4464 if (commentY < 0) commentY = 0; /*avoid positioning top offscreen*/
4467 XtSetArg(args[j], XtNheight, commentH); j++;
4468 XtSetArg(args[j], XtNwidth, commentW); j++;
4469 XtSetArg(args[j], XtNx, commentX); j++;
4470 XtSetArg(args[j], XtNy, commentY); j++;
4471 XtSetValues(shell, args, j);
4472 XtSetKeyboardFocus(shell, edit);
4477 /* Used for analysis window and ICS input window */
4478 Widget MiscCreate(name, text, mutable, callback, lines)
4480 int /*Boolean*/ mutable;
4481 XtCallbackProc callback;
4485 Widget shell, layout, form, edit;
4487 Dimension bw_width, pw_height, ew_height, w, h;
4493 XtSetArg(args[j], XtNresizable, True); j++;
4496 XtCreatePopupShell(name, topLevelShellWidgetClass,
4497 shellWidget, args, j);
4500 XtCreatePopupShell(name, transientShellWidgetClass,
4501 shellWidget, args, j);
4504 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
4505 layoutArgs, XtNumber(layoutArgs));
4507 XtCreateManagedWidget("form", formWidgetClass, layout,
4508 formArgs, XtNumber(formArgs));
4512 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
4513 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
4515 XtSetArg(args[j], XtNstring, text); j++;
4516 XtSetArg(args[j], XtNtop, XtChainTop); j++;
4517 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4518 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4519 XtSetArg(args[j], XtNright, XtChainRight); j++;
4520 XtSetArg(args[j], XtNresizable, True); j++;
4522 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
4524 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
4525 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
4527 XtSetArg(args[j], XtNautoFill, True); j++;
4528 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
4530 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
4532 XtRealizeWidget(shell);
4535 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4536 XtGetValues(boardWidget, args, j);
4539 XtSetArg(args[j], XtNheight, &ew_height); j++;
4540 XtGetValues(edit, args, j);
4543 XtSetArg(args[j], XtNheight, &pw_height); j++;
4544 XtGetValues(shell, args, j);
4545 h = pw_height + (lines - 1) * ew_height;
4548 XSync(xDisplay, False);
4550 /* This code seems to tickle an X bug if it is executed too soon
4551 after xboard starts up. The coordinates get transformed as if
4552 the main window was positioned at (0, 0).
4554 XtTranslateCoords(shellWidget, (bw_width - w) / 2, 0 - h / 2, &x, &y);
4556 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
4557 RootWindowOfScreen(XtScreen(shellWidget)),
4558 (bw_width - w) / 2, 0 - h / 2, &xx, &yy, &junk);
4562 if (y < 0) y = 0; /*avoid positioning top offscreen*/
4565 XtSetArg(args[j], XtNheight, h); j++;
4566 XtSetArg(args[j], XtNwidth, w); j++;
4567 XtSetArg(args[j], XtNx, x); j++;
4568 XtSetArg(args[j], XtNy, y); j++;
4569 XtSetValues(shell, args, j);
4575 static int savedIndex; /* gross that this is global */
4577 void EditCommentPopUp(index, title, text)
4586 if (text == NULL) text = "";
4588 if (editShell == NULL) {
4590 CommentCreate(title, text, True, EditCommentCallback, 4);
4591 XtRealizeWidget(editShell);
4592 CatchDeleteWindow(editShell, "EditCommentPopDown");
4594 edit = XtNameToWidget(editShell, "*form.text");
4596 XtSetArg(args[j], XtNstring, text); j++;
4597 XtSetValues(edit, args, j);
4599 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4600 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4601 XtSetValues(editShell, args, j);
4604 XtPopup(editShell, XtGrabNone);
4608 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
4609 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
4613 void EditCommentCallback(w, client_data, call_data)
4615 XtPointer client_data, call_data;
4623 XtSetArg(args[j], XtNlabel, &name); j++;
4624 XtGetValues(w, args, j);
4626 if (strcmp(name, _("ok")) == 0) {
4627 edit = XtNameToWidget(editShell, "*form.text");
4629 XtSetArg(args[j], XtNstring, &val); j++;
4630 XtGetValues(edit, args, j);
4631 ReplaceComment(savedIndex, val);
4632 EditCommentPopDown();
4633 } else if (strcmp(name, _("cancel")) == 0) {
4634 EditCommentPopDown();
4635 } else if (strcmp(name, _("clear")) == 0) {
4636 edit = XtNameToWidget(editShell, "*form.text");
4637 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
4638 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
4642 void EditCommentPopDown()
4647 if (!editUp) return;
4649 XtSetArg(args[j], XtNx, &commentX); j++;
4650 XtSetArg(args[j], XtNy, &commentY); j++;
4651 XtSetArg(args[j], XtNheight, &commentH); j++;
4652 XtSetArg(args[j], XtNwidth, &commentW); j++;
4653 XtGetValues(editShell, args, j);
4654 XtPopdown(editShell);
4657 XtSetArg(args[j], XtNleftBitmap, None); j++;
4658 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
4662 void ICSInputBoxPopUp()
4667 char *title = _("ICS Input");
4670 if (ICSInputShell == NULL) {
4671 ICSInputShell = MiscCreate(title, "", True, NULL, 1);
4672 tr = XtParseTranslationTable(ICSInputTranslations);
4673 edit = XtNameToWidget(ICSInputShell, "*form.text");
4674 XtOverrideTranslations(edit, tr);
4675 XtRealizeWidget(ICSInputShell);
4676 CatchDeleteWindow(ICSInputShell, "ICSInputBoxPopDown");
4679 edit = XtNameToWidget(ICSInputShell, "*form.text");
4681 XtSetArg(args[j], XtNstring, ""); j++;
4682 XtSetValues(edit, args, j);
4684 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4685 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4686 XtSetValues(ICSInputShell, args, j);
4689 XtPopup(ICSInputShell, XtGrabNone);
4690 XtSetKeyboardFocus(ICSInputShell, edit);
4692 ICSInputBoxUp = True;
4694 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
4695 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
4699 void ICSInputSendText()
4706 edit = XtNameToWidget(ICSInputShell, "*form.text");
4708 XtSetArg(args[j], XtNstring, &val); j++;
4709 XtGetValues(edit, args, j);
4710 SendMultiLineToICS(val);
4711 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
4712 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
4715 void ICSInputBoxPopDown()
4720 if (!ICSInputBoxUp) return;
4722 XtPopdown(ICSInputShell);
4723 ICSInputBoxUp = False;
4725 XtSetArg(args[j], XtNleftBitmap, None); j++;
4726 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
4730 void CommentPopUp(title, text)
4737 if (commentShell == NULL) {
4739 CommentCreate(title, text, False, CommentCallback, 4);
4740 XtRealizeWidget(commentShell);
4741 CatchDeleteWindow(commentShell, "CommentPopDown");
4743 edit = XtNameToWidget(commentShell, "*form.text");
4745 XtSetArg(args[j], XtNstring, text); j++;
4746 XtSetValues(edit, args, j);
4748 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4749 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4750 XtSetValues(commentShell, args, j);
4753 XtPopup(commentShell, XtGrabNone);
4754 XSync(xDisplay, False);
4759 void AnalysisPopUp(title, text)
4766 if (analysisShell == NULL) {
4767 analysisShell = MiscCreate(title, text, False, NULL, 4);
4768 XtRealizeWidget(analysisShell);
4769 CatchDeleteWindow(analysisShell, "AnalysisPopDown");
4772 edit = XtNameToWidget(analysisShell, "*form.text");
4774 XtSetArg(args[j], XtNstring, text); j++;
4775 XtSetValues(edit, args, j);
4777 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4778 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4779 XtSetValues(analysisShell, args, j);
4783 XtPopup(analysisShell, XtGrabNone);
4785 XSync(xDisplay, False);
4790 void CommentCallback(w, client_data, call_data)
4792 XtPointer client_data, call_data;
4799 XtSetArg(args[j], XtNlabel, &name); j++;
4800 XtGetValues(w, args, j);
4802 if (strcmp(name, _("close")) == 0) {
4804 } else if (strcmp(name, _("edit")) == 0) {
4811 void CommentPopDown()
4816 if (!commentUp) return;
4818 XtSetArg(args[j], XtNx, &commentX); j++;
4819 XtSetArg(args[j], XtNy, &commentY); j++;
4820 XtSetArg(args[j], XtNwidth, &commentW); j++;
4821 XtSetArg(args[j], XtNheight, &commentH); j++;
4822 XtGetValues(commentShell, args, j);
4823 XtPopdown(commentShell);
4824 XSync(xDisplay, False);
4828 void AnalysisPopDown()
4830 if (!analysisUp) return;
4831 XtPopdown(analysisShell);
4832 XSync(xDisplay, False);
4834 if (appData.icsEngineAnalyze) ExitAnalyzeMode(); /* [DM] icsEngineAnalyze */
4838 void FileNamePopUp(label, def, proc, openMode)
4845 Widget popup, layout, dialog, edit;
4851 fileProc = proc; /* I can't see a way not */
4852 fileOpenMode = openMode; /* to use globals here */
4855 XtSetArg(args[i], XtNresizable, True); i++;
4856 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
4857 XtSetArg(args[i], XtNtitle, XtNewString(_("File name prompt"))); i++;
4858 fileNameShell = popup =
4859 XtCreatePopupShell("File name prompt", transientShellWidgetClass,
4860 shellWidget, args, i);
4863 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
4864 layoutArgs, XtNumber(layoutArgs));
4867 XtSetArg(args[i], XtNlabel, label); i++;
4868 XtSetArg(args[i], XtNvalue, def); i++;
4869 XtSetArg(args[i], XtNborderWidth, 0); i++;
4870 dialog = XtCreateManagedWidget("fileName", dialogWidgetClass,
4873 XawDialogAddButton(dialog, _("ok"), FileNameCallback, (XtPointer) dialog);
4874 XawDialogAddButton(dialog, _("cancel"), FileNameCallback,
4875 (XtPointer) dialog);
4877 XtRealizeWidget(popup);
4878 CatchDeleteWindow(popup, "FileNamePopDown");
4880 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
4881 &x, &y, &win_x, &win_y, &mask);
4883 XtSetArg(args[0], XtNx, x - 10);
4884 XtSetArg(args[1], XtNy, y - 30);
4885 XtSetValues(popup, args, 2);
4887 XtPopup(popup, XtGrabExclusive);
4890 edit = XtNameToWidget(dialog, "*value");
4891 XtSetKeyboardFocus(popup, edit);
4894 void FileNamePopDown()
4896 if (!filenameUp) return;
4897 XtPopdown(fileNameShell);
4898 XtDestroyWidget(fileNameShell);
4903 void FileNameCallback(w, client_data, call_data)
4905 XtPointer client_data, call_data;
4910 XtSetArg(args[0], XtNlabel, &name);
4911 XtGetValues(w, args, 1);
4913 if (strcmp(name, _("cancel")) == 0) {
4918 FileNameAction(w, NULL, NULL, NULL);
4921 void FileNameAction(w, event, prms, nprms)
4933 name = XawDialogGetValueString(w = XtParent(w));
4935 if ((name != NULL) && (*name != NULLCHAR)) {
4937 XtPopdown(w = XtParent(XtParent(w)));
4941 p = strrchr(buf, ' ');
4948 fullname = ExpandPathName(buf);
4950 ErrorPopUp(_("Error"), _("Can't open file"), FALSE);
4953 f = fopen(fullname, fileOpenMode);
4955 DisplayError(_("Failed to open file"), errno);
4957 (void) (*fileProc)(f, index, buf);
4964 XtPopdown(w = XtParent(XtParent(w)));
4970 void PromotionPopUp()
4973 Widget dialog, layout;
4975 Dimension bw_width, pw_width;
4979 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4980 XtGetValues(boardWidget, args, j);
4983 XtSetArg(args[j], XtNresizable, True); j++;
4984 XtSetArg(args[j], XtNtitle, XtNewString(_("Promotion"))); j++;
4986 XtCreatePopupShell("Promotion", transientShellWidgetClass,
4987 shellWidget, args, j);
4989 XtCreateManagedWidget(layoutName, formWidgetClass, promotionShell,
4990 layoutArgs, XtNumber(layoutArgs));
4993 XtSetArg(args[j], XtNlabel, _("Promote to what?")); j++;
4994 XtSetArg(args[j], XtNborderWidth, 0); j++;
4995 dialog = XtCreateManagedWidget("promotion", dialogWidgetClass,
4998 if(gameInfo.variant != VariantShogi) {
4999 XawDialogAddButton(dialog, _("Queen"), PromotionCallback,
5000 (XtPointer) dialog);
5001 XawDialogAddButton(dialog, _("Rook"), PromotionCallback,
5002 (XtPointer) dialog);
5003 XawDialogAddButton(dialog, _("Bishop"), PromotionCallback,
5004 (XtPointer) dialog);
5005 XawDialogAddButton(dialog, _("Knight"), PromotionCallback,
5006 (XtPointer) dialog);
5007 if (!appData.testLegality || gameInfo.variant == VariantSuicide ||
5008 gameInfo.variant == VariantGiveaway) {
5009 XawDialogAddButton(dialog, _("King"), PromotionCallback,
5010 (XtPointer) dialog);
5012 if(gameInfo.variant == VariantCapablanca ||
5013 gameInfo.variant == VariantGothic ||
5014 gameInfo.variant == VariantCapaRandom) {
5015 XawDialogAddButton(dialog, _("Archbishop"), PromotionCallback,
5016 (XtPointer) dialog);
5017 XawDialogAddButton(dialog, _("Chancellor"), PromotionCallback,
5018 (XtPointer) dialog);
5020 } else // [HGM] shogi
5022 XawDialogAddButton(dialog, _("Promote"), PromotionCallback,
5023 (XtPointer) dialog);
5024 XawDialogAddButton(dialog, _("Defer"), PromotionCallback,
5025 (XtPointer) dialog);
5027 XawDialogAddButton(dialog, _("cancel"), PromotionCallback,
5028 (XtPointer) dialog);
5030 XtRealizeWidget(promotionShell);
5031 CatchDeleteWindow(promotionShell, "PromotionPopDown");
5034 XtSetArg(args[j], XtNwidth, &pw_width); j++;
5035 XtGetValues(promotionShell, args, j);
5037 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
5038 lineGap + squareSize/3 +
5039 ((toY == BOARD_HEIGHT-1) ^ (flipView) ?
5040 0 : 6*(squareSize + lineGap)), &x, &y);
5043 XtSetArg(args[j], XtNx, x); j++;
5044 XtSetArg(args[j], XtNy, y); j++;
5045 XtSetValues(promotionShell, args, j);
5047 XtPopup(promotionShell, XtGrabNone);
5052 void PromotionPopDown()
5054 if (!promotionUp) return;
5055 XtPopdown(promotionShell);
5056 XtDestroyWidget(promotionShell);
5057 promotionUp = False;
5060 void PromotionCallback(w, client_data, call_data)
5062 XtPointer client_data, call_data;
5068 XtSetArg(args[0], XtNlabel, &name);
5069 XtGetValues(w, args, 1);
5073 if (fromX == -1) return;
5075 if (strcmp(name, _("cancel")) == 0) {
5079 } else if (strcmp(name, _("Knight")) == 0) {
5081 } else if (strcmp(name, _("Promote")) == 0) {
5083 } else if (strcmp(name, _("Defer")) == 0) {
5086 promoChar = ToLower(name[0]);
5089 UserMoveEvent(fromX, fromY, toX, toY, promoChar);
5091 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
5092 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
5097 void ErrorCallback(w, client_data, call_data)
5099 XtPointer client_data, call_data;
5102 XtPopdown(w = XtParent(XtParent(XtParent(w))));
5104 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5110 if (!errorUp) return;
5114 gtk_widget_destroy(GTK_WIDGET(GUI_Error));
5116 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5121 void ErrorPopUp(title, label, modal)
5122 char *title, *label;
5125 GUI_Error = gtk_message_dialog_new(GTK_WINDOW(GUI_Window),
5126 GTK_DIALOG_DESTROY_WITH_PARENT,
5131 gtk_window_set_title(GTK_WINDOW(GUI_Error),(gchar *) title);
5134 gtk_dialog_run(GTK_DIALOG(GUI_Error));
5135 gtk_widget_destroy(GTK_WIDGET(GUI_Error));
5139 g_signal_connect_swapped (GUI_Error, "response",
5140 G_CALLBACK (ErrorPopDownProc),
5143 gtk_widget_show(GTK_WIDGET(GUI_Error));
5149 /* Disable all user input other than deleting the window */
5150 static int frozen = 0;
5154 /* Grab by a widget that doesn't accept input */
5155 // XtAddGrab(messageWidget, TRUE, FALSE);
5159 /* Undo a FreezeUI */
5162 if (!frozen) return;
5163 // XtRemoveGrab(messageWidget);
5167 char *ModeToWidgetName(mode)
5171 case BeginningOfGame:
5172 if (appData.icsActive)
5173 return "menuMode.ICS Client";
5174 else if (appData.noChessProgram ||
5175 *appData.cmailGameName != NULLCHAR)
5176 return "menuMode.Edit Game";
5178 return "menuMode.Machine Black";
5179 case MachinePlaysBlack:
5180 return "menuMode.Machine Black";
5181 case MachinePlaysWhite:
5182 return "menuMode.Machine White";
5184 return "menuMode.Analysis Mode";
5186 return "menuMode.Analyze File";
5187 case TwoMachinesPlay:
5188 return "menuMode.Two Machines";
5190 return "menuMode.Edit Game";
5191 case PlayFromGameFile:
5192 return "menuFile.Load Game";
5194 return "menuMode.Edit Position";
5196 return "menuMode.Training";
5197 case IcsPlayingWhite:
5198 case IcsPlayingBlack:
5202 return "menuMode.ICS Client";
5209 void ModeHighlight()
5211 static int oldPausing = FALSE;
5212 static GameMode oldmode = (GameMode) -1;
5215 // todo this toggling of the pause button doesn't seem to work?
5216 // e.g. select pause from buttonbar doesn't activate menumode.pause
5218 // if (!boardWidget || !XtIsRealized(boardWidget)) return;
5220 if (pausing != oldPausing) {
5221 oldPausing = pausing;
5222 gtk_button_set_relief(GTK_BUTTON (gtk_builder_get_object (builder, "menuMode.Pause")),pausing?GTK_RELIEF_NORMAL:GTK_RELIEF_NONE);
5223 /* toggle background color in showbuttonbar */
5224 if (appData.showButtonBar) {
5226 gtk_button_pressed(GTK_BUTTON (gtk_builder_get_object (builder, "buttonbar.Pause")));
5228 gtk_button_released(GTK_BUTTON (gtk_builder_get_object (builder, "buttonbar.Pause")));
5233 wname = ModeToWidgetName(oldmode);
5235 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, wname)),True);
5239 /* Maybe all the enables should be handled here, not just this one */
5240 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuMode.Training")),
5241 gameMode == Training || gameMode == PlayFromGameFile);
5246 * Button/menu procedures
5249 int LoadGamePopUp(f, gameNumber, title)
5254 cmailMsgLoaded = FALSE;
5255 if (gameNumber == 0) {
5256 int error = GameListBuild(f);
5258 DisplayError(_("Cannot build game list"), error);
5259 } else if (!ListEmpty(&gameList) &&
5260 ((ListGame *) gameList.tailPred)->number > 1) {
5261 GameListPopUp(f, title);
5267 return LoadGame(f, gameNumber, title, FALSE);
5271 void LoadNextPositionProc(w, event, prms, nprms)
5280 void LoadPrevPositionProc(w, event, prms, nprms)
5289 void ReloadPositionProc(w, event, prms, nprms)
5298 void LoadPositionProc(w, event, prms, nprms)
5304 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
5307 FileNamePopUp(_("Load position file name?"), "", LoadPosition, "rb");
5310 void SaveGameProc(w, event, prms, nprms)
5316 FileNamePopUp(_("Save game file name?"),
5317 DefaultFileName(appData.oldSaveStyle ? "game" : "pgn"),
5321 void SavePositionProc(w, event, prms, nprms)
5327 FileNamePopUp(_("Save position file name?"),
5328 DefaultFileName(appData.oldSaveStyle ? "pos" : "fen"),
5332 void ReloadCmailMsgProc(w, event, prms, nprms)
5338 ReloadCmailMsgEvent(FALSE);
5341 void MailMoveProc(w, event, prms, nprms)
5350 /* this variable is shared between CopyPositionProc and SendPositionSelection */
5351 static char *selected_fen_position=NULL;
5354 SendPositionSelection(Widget w, Atom *selection, Atom *target,
5355 Atom *type_return, XtPointer *value_return,
5356 unsigned long *length_return, int *format_return)
5358 char *selection_tmp;
5360 if (!selected_fen_position) return False; /* should never happen */
5361 if (*target == XA_STRING){
5362 /* note: since no XtSelectionDoneProc was registered, Xt will
5363 * automatically call XtFree on the value returned. So have to
5364 * make a copy of it allocated with XtMalloc */
5365 selection_tmp= XtMalloc(strlen(selected_fen_position)+16);
5366 strcpy(selection_tmp, selected_fen_position);
5368 *value_return=selection_tmp;
5369 *length_return=strlen(selection_tmp);
5370 *type_return=XA_STRING;
5371 *format_return = 8; /* bits per byte */
5378 /* note: when called from menu all parameters are NULL, so no clue what the
5379 * Widget which was clicked on was, or what the click event was
5381 void CopyPositionProc(w, event, prms, nprms)
5389 if (selected_fen_position) free(selected_fen_position);
5390 selected_fen_position = (char *)PositionToFEN(currentMove, NULL);
5391 if (!selected_fen_position) return;
5392 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
5394 SendPositionSelection,
5395 NULL/* lose_ownership_proc */ ,
5396 NULL/* transfer_done_proc */);
5398 free(selected_fen_position);
5399 selected_fen_position=NULL;
5403 /* function called when the data to Paste is ready */
5405 PastePositionCB(Widget w, XtPointer client_data, Atom *selection,
5406 Atom *type, XtPointer value, unsigned long *len, int *format)
5409 if (value==NULL || *len==0) return; /* nothing had been selected to copy */
5410 fenstr[*len]='\0'; /* normally this string is terminated, but be safe */
5411 EditPositionPasteFEN(fenstr);
5415 /* called when Paste Position button is pressed,
5416 * all parameters will be NULL */
5417 void PastePositionProc(w, event, prms, nprms)
5423 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
5424 /* (XtSelectionCallbackProc) */ PastePositionCB,
5425 NULL, /* client_data passed to PastePositionCB */
5427 /* better to use the time field from the event that triggered the
5428 * call to this function, but that isn't trivial to get
5436 SendGameSelection(Widget w, Atom *selection, Atom *target,
5437 Atom *type_return, XtPointer *value_return,
5438 unsigned long *length_return, int *format_return)
5440 char *selection_tmp;
5442 if (*target == XA_STRING){
5443 FILE* f = fopen(gameCopyFilename, "r");
5446 if (f == NULL) return False;
5450 selection_tmp = XtMalloc(len + 1);
5451 count = fread(selection_tmp, 1, len, f);
5453 XtFree(selection_tmp);
5456 selection_tmp[len] = NULLCHAR;
5457 *value_return = selection_tmp;
5458 *length_return = len;
5459 *type_return = XA_STRING;
5460 *format_return = 8; /* bits per byte */
5467 /* note: when called from menu all parameters are NULL, so no clue what the
5468 * Widget which was clicked on was, or what the click event was
5470 void CopyGameProc(w, event, prms, nprms)
5478 ret = SaveGameToFile(gameCopyFilename, FALSE);
5481 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
5484 NULL/* lose_ownership_proc */ ,
5485 NULL/* transfer_done_proc */);
5488 /* function called when the data to Paste is ready */
5490 PasteGameCB(Widget w, XtPointer client_data, Atom *selection,
5491 Atom *type, XtPointer value, unsigned long *len, int *format)
5494 if (value == NULL || *len == 0) {
5495 return; /* nothing had been selected to copy */
5497 f = fopen(gamePasteFilename, "w");
5499 DisplayError(_("Can't open temp file"), errno);
5502 fwrite(value, 1, *len, f);
5505 LoadGameFromFile(gamePasteFilename, 0, gamePasteFilename, TRUE);
5508 /* called when Paste Game button is pressed,
5509 * all parameters will be NULL */
5510 void PasteGameProc(w, event, prms, nprms)
5516 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
5517 /* (XtSelectionCallbackProc) */ PasteGameCB,
5518 NULL, /* client_data passed to PasteGameCB */
5520 /* better to use the time field from the event that triggered the
5521 * call to this function, but that isn't trivial to get
5531 SaveGameProc(NULL, NULL, NULL, NULL);
5534 void MachineBlackProc(w, event, prms, nprms)
5540 MachineBlackEvent();
5543 void MachineWhiteProc(w, event, prms, nprms)
5549 MachineWhiteEvent();
5552 void AnalyzeModeProc(w, event, prms, nprms)
5560 if (!first.analysisSupport) {
5561 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
5562 DisplayError(buf, 0);
5565 /* [DM] icsEngineAnalyze [HGM] This is horrible code; reverse the gameMode and isEngineAnalyze tests! */
5566 if (appData.icsActive) {
5567 if (gameMode != IcsObserving) {
5568 sprintf(buf,_("You are not observing a game"));
5569 DisplayError(buf, 0);
5571 if (appData.icsEngineAnalyze) {
5572 if (appData.debugMode)
5573 fprintf(debugFP, _("Found unexpected active ICS engine analyze \n"));
5579 /* if enable, use want disable icsEngineAnalyze */
5580 if (appData.icsEngineAnalyze) {
5585 appData.icsEngineAnalyze = TRUE;
5586 if (appData.debugMode)
5587 fprintf(debugFP, _("ICS engine analyze starting... \n"));
5589 if (!appData.showThinking)
5590 ShowThinkingProc(w,event,prms,nprms);
5595 void AnalyzeFileProc(w, event, prms, nprms)
5601 if (!first.analysisSupport) {
5603 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
5604 DisplayError(buf, 0);
5609 if (!appData.showThinking)
5610 ShowThinkingProc(w,event,prms,nprms);
5613 FileNamePopUp(_("File to analyze"), "", LoadGamePopUp, "rb");
5614 AnalysisPeriodicEvent(1);
5617 void TwoMachinesProc(w, event, prms, nprms)
5626 void IcsClientProc(w, event, prms, nprms)
5635 void EditGameProc(w, event, prms, nprms)
5644 void EditPositionProc(w, event, prms, nprms)
5650 EditPositionEvent();
5653 void TrainingProc(w, event, prms, nprms)
5662 void EditCommentProc(w, event, prms, nprms)
5669 EditCommentPopDown();
5675 void IcsInputBoxProc(w, event, prms, nprms)
5681 if (ICSInputBoxUp) {
5682 ICSInputBoxPopDown();
5688 void AcceptProc(w, event, prms, nprms)
5697 void DeclineProc(w, event, prms, nprms)
5706 void RematchProc(w, event, prms, nprms)
5715 void CallFlagProc(w, event, prms, nprms)
5724 void DrawProc(w, event, prms, nprms)
5733 void AbortProc(w, event, prms, nprms)
5742 void AdjournProc(w, event, prms, nprms)
5751 void ResignProc(w, event, prms, nprms)
5760 void AdjuWhiteProc(w, event, prms, nprms)
5766 UserAdjudicationEvent(+1);
5769 void AdjuBlackProc(w, event, prms, nprms)
5775 UserAdjudicationEvent(-1);
5778 void AdjuDrawProc(w, event, prms, nprms)
5784 UserAdjudicationEvent(0);
5787 void EnterKeyProc(w, event, prms, nprms)
5793 if (ICSInputBoxUp == True)
5797 void StopObservingProc(w, event, prms, nprms)
5803 StopObservingEvent();
5806 void StopExaminingProc(w, event, prms, nprms)
5812 StopExaminingEvent();
5816 void ForwardProc(w, event, prms, nprms)
5826 void BackwardProc(w, event, prms, nprms)
5835 void ToStartProc(w, event, prms, nprms)
5844 void ToEndProc(w, event, prms, nprms)
5853 void RevertProc(w, event, prms, nprms)
5862 void TruncateGameProc(w, event, prms, nprms)
5868 TruncateGameEvent();
5870 void RetractMoveProc(w, event, prms, nprms)
5879 void MoveNowProc(w, event, prms, nprms)
5889 void AlwaysQueenProc(w, event, prms, nprms)
5897 appData.alwaysPromoteToQueen = !appData.alwaysPromoteToQueen;
5899 if (appData.alwaysPromoteToQueen) {
5900 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5902 XtSetArg(args[0], XtNleftBitmap, None);
5904 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
5908 void AnimateDraggingProc(w, event, prms, nprms)
5916 appData.animateDragging = !appData.animateDragging;
5918 if (appData.animateDragging) {
5919 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5922 XtSetArg(args[0], XtNleftBitmap, None);
5924 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Dragging"),
5928 void AnimateMovingProc(w, event, prms, nprms)
5936 appData.animate = !appData.animate;
5938 if (appData.animate) {
5939 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5942 XtSetArg(args[0], XtNleftBitmap, None);
5944 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
5948 void AutocommProc(w, event, prms, nprms)
5956 appData.autoComment = !appData.autoComment;
5958 if (appData.autoComment) {
5959 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5961 XtSetArg(args[0], XtNleftBitmap, None);
5963 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
5968 void AutoflagProc(w, event, prms, nprms)
5976 appData.autoCallFlag = !appData.autoCallFlag;
5978 if (appData.autoCallFlag) {
5979 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5981 XtSetArg(args[0], XtNleftBitmap, None);
5983 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
5987 void AutoflipProc(w, event, prms, nprms)
5995 appData.autoFlipView = !appData.autoFlipView;
5997 if (appData.autoFlipView) {
5998 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6000 XtSetArg(args[0], XtNleftBitmap, None);
6002 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flip View"),
6006 void AutobsProc(w, event, prms, nprms)
6014 appData.autoObserve = !appData.autoObserve;
6016 if (appData.autoObserve) {
6017 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6019 XtSetArg(args[0], XtNleftBitmap, None);
6021 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
6025 void AutoraiseProc(w, event, prms, nprms)
6033 appData.autoRaiseBoard = !appData.autoRaiseBoard;
6035 if (appData.autoRaiseBoard) {
6036 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6038 XtSetArg(args[0], XtNleftBitmap, None);
6040 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Raise Board"),
6044 void AutosaveProc(w, event, prms, nprms)
6052 appData.autoSaveGames = !appData.autoSaveGames;
6054 if (appData.autoSaveGames) {
6055 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6057 XtSetArg(args[0], XtNleftBitmap, None);
6059 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
6063 void BlindfoldProc(w, event, prms, nprms)
6071 appData.blindfold = !appData.blindfold;
6073 if (appData.blindfold) {
6074 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6076 XtSetArg(args[0], XtNleftBitmap, None);
6078 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Blindfold"),
6081 DrawPosition(True, NULL);
6084 void TestLegalityProc(w, event, prms, nprms)
6092 appData.testLegality = !appData.testLegality;
6094 if (appData.testLegality) {
6095 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6097 XtSetArg(args[0], XtNleftBitmap, None);
6099 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Test Legality"),
6104 void FlashMovesProc(w, event, prms, nprms)
6112 if (appData.flashCount == 0) {
6113 appData.flashCount = 3;
6115 appData.flashCount = -appData.flashCount;
6118 if (appData.flashCount > 0) {
6119 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6121 XtSetArg(args[0], XtNleftBitmap, None);
6123 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flash Moves"),
6127 void FlipViewProc(w, event, prms, nprms)
6133 flipView = !flipView;
6134 DrawPosition(True, NULL);
6137 void GetMoveListProc(w, event, prms, nprms)
6145 appData.getMoveList = !appData.getMoveList;
6147 if (appData.getMoveList) {
6148 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6151 XtSetArg(args[0], XtNleftBitmap, None);
6153 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
6158 void HighlightDraggingProc(w, event, prms, nprms)
6166 appData.highlightDragging = !appData.highlightDragging;
6168 if (appData.highlightDragging) {
6169 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6171 XtSetArg(args[0], XtNleftBitmap, None);
6173 XtSetValues(XtNameToWidget(menuBarWidget,
6174 "menuOptions.Highlight Dragging"), args, 1);
6178 void HighlightLastMoveProc(w, event, prms, nprms)
6186 appData.highlightLastMove = !appData.highlightLastMove;
6188 if (appData.highlightLastMove) {
6189 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6191 XtSetArg(args[0], XtNleftBitmap, None);
6193 XtSetValues(XtNameToWidget(menuBarWidget,
6194 "menuOptions.Highlight Last Move"), args, 1);
6197 void IcsAlarmProc(w, event, prms, nprms)
6205 appData.icsAlarm = !appData.icsAlarm;
6207 if (appData.icsAlarm) {
6208 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6210 XtSetArg(args[0], XtNleftBitmap, None);
6212 XtSetValues(XtNameToWidget(menuBarWidget,
6213 "menuOptions.ICS Alarm"), args, 1);
6216 void MoveSoundProc(w, event, prms, nprms)
6224 appData.ringBellAfterMoves = !appData.ringBellAfterMoves;
6226 if (appData.ringBellAfterMoves) {
6227 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6229 XtSetArg(args[0], XtNleftBitmap, None);
6231 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
6236 void OldSaveStyleProc(w, event, prms, nprms)
6244 appData.oldSaveStyle = !appData.oldSaveStyle;
6246 if (appData.oldSaveStyle) {
6247 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6249 XtSetArg(args[0], XtNleftBitmap, None);
6251 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Old Save Style"),
6255 void PeriodicUpdatesProc(w, event, prms, nprms)
6263 PeriodicUpdatesEvent(!appData.periodicUpdates);
6265 if (appData.periodicUpdates) {
6266 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6268 XtSetArg(args[0], XtNleftBitmap, None);
6270 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Periodic Updates"),
6274 void PonderNextMoveProc(w, event, prms, nprms)
6282 PonderNextMoveEvent(!appData.ponderNextMove);
6284 if (appData.ponderNextMove) {
6285 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6287 XtSetArg(args[0], XtNleftBitmap, None);
6289 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Ponder Next Move"),
6293 void PopupExitMessageProc(w, event, prms, nprms)
6301 appData.popupExitMessage = !appData.popupExitMessage;
6303 if (appData.popupExitMessage) {
6304 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6306 XtSetArg(args[0], XtNleftBitmap, None);
6308 XtSetValues(XtNameToWidget(menuBarWidget,
6309 "menuOptions.Popup Exit Message"), args, 1);
6312 void PopupMoveErrorsProc(w, event, prms, nprms)
6320 appData.popupMoveErrors = !appData.popupMoveErrors;
6322 if (appData.popupMoveErrors) {
6323 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6325 XtSetArg(args[0], XtNleftBitmap, None);
6327 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Popup Move Errors"),
6331 void PremoveProc(w, event, prms, nprms)
6339 appData.premove = !appData.premove;
6341 if (appData.premove) {
6342 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6344 XtSetArg(args[0], XtNleftBitmap, None);
6346 XtSetValues(XtNameToWidget(menuBarWidget,
6347 "menuOptions.Premove"), args, 1);
6350 void QuietPlayProc(w, event, prms, nprms)
6358 appData.quietPlay = !appData.quietPlay;
6360 if (appData.quietPlay) {
6361 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6363 XtSetArg(args[0], XtNleftBitmap, None);
6365 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Quiet Play"),
6369 void ShowThinkingProc(w, event, prms, nprms)
6377 appData.showThinking = !appData.showThinking; // [HGM] thinking: tken out of ShowThinkingEvent
6378 ShowThinkingEvent();
6380 // [HGM] thinking: currently no suc menu item; replaced by Hide Thinking (From Human)
6381 if (appData.showThinking) {
6382 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6384 XtSetArg(args[0], XtNleftBitmap, None);
6386 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Thinking"),
6391 void HideThinkingProc(w, event, prms, nprms)
6399 appData.hideThinkingFromHuman = !appData.hideThinkingFromHuman; // [HGM] thinking: tken out of ShowThinkingEvent
6400 ShowThinkingEvent();
6402 if (appData.hideThinkingFromHuman) {
6403 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6405 XtSetArg(args[0], XtNleftBitmap, None);
6407 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
6411 void InfoProc(w, event, prms, nprms)
6418 snprintf(buf, sizeof(buf), "xterm -e info --directory %s --directory . -f %s &",
6423 void ManProc(w, event, prms, nprms)
6431 if (nprms && *nprms > 0)
6435 snprintf(buf, sizeof(buf), "xterm -e man %s &", name);
6439 void HintProc(w, event, prms, nprms)
6448 void BookProc(w, event, prms, nprms)
6457 void DebugProc(w, event, prms, nprms)
6463 appData.debugMode = !appData.debugMode;
6466 void AboutGameProc(w, event, prms, nprms)
6475 void NothingProc(w, event, prms, nprms)
6484 void Iconify(w, event, prms, nprms)
6493 XtSetArg(args[0], XtNiconic, True);
6494 XtSetValues(shellWidget, args, 1);
6497 void DisplayMessage(message, extMessage)
6498 gchar *message, *extMessage;
6505 snprintf(buf, sizeof(buf), "%s %s", message, extMessage);
6508 message = extMessage;
6511 gtk_label_set_text( GTK_LABEL(gtk_builder_get_object (builder, "Messages")),message);
6516 void DisplayTitle(text)
6519 gchar title[MSG_SIZ];
6521 if (text == NULL) text = "";
6523 if (appData.titleInWindow)
6528 if (*text != NULLCHAR)
6530 strcpy(title, text);
6532 else if (appData.icsActive)
6534 snprintf(title, sizeof(title), "%s: %s", programName, appData.icsHost);
6536 else if (appData.cmailGameName[0] != NULLCHAR)
6538 snprintf(title,sizeof(title), "%s: %s", programName, "CMail");
6540 // [HGM] license: This stuff should really be done in back-end, but WinBoard already had a pop-up for it
6542 else if (gameInfo.variant == VariantGothic)
6544 strcpy(title, GOTHIC);
6548 else if (gameInfo.variant == VariantFalcon)
6550 strcpy(title, FALCON);
6553 else if (appData.noChessProgram)
6555 strcpy(title, programName);
6559 snprintf(title,sizeof(title), "%s: %s", programName, first.tidy);
6561 gtk_window_set_title(GTK_WINDOW(GUI_Window),title);
6567 void DisplayError(message, error)
6574 if (appData.debugMode || appData.matchMode) {
6575 fprintf(stderr, "%s: %s\n", programName, message);
6578 if (appData.debugMode || appData.matchMode) {
6579 fprintf(stderr, "%s: %s: %s\n",
6580 programName, message, strerror(error));
6582 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
6585 ErrorPopUp(_("Error"), message, FALSE);
6589 void DisplayMoveError(message)
6594 DrawPosition(FALSE, NULL);
6595 if (appData.debugMode || appData.matchMode) {
6596 fprintf(stderr, "%s: %s\n", programName, message);
6598 if (appData.popupMoveErrors) {
6599 ErrorPopUp(_("Error"), message, FALSE);
6601 DisplayMessage(message, "");
6606 void DisplayFatalError(message, error, status)
6612 errorExitStatus = status;
6614 fprintf(stderr, "%s: %s\n", programName, message);
6616 fprintf(stderr, "%s: %s: %s\n",
6617 programName, message, strerror(error));
6618 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
6621 if (appData.popupExitMessage && boardWidget && XtIsRealized(boardWidget)) {
6622 ErrorPopUp(status ? _("Fatal Error") : _("Exiting"), message, TRUE);
6628 void DisplayInformation(message)
6632 ErrorPopUp(_("Information"), message, TRUE);
6635 void DisplayNote(message)
6639 ErrorPopUp(_("Note"), message, FALSE);
6643 NullXErrorCheck(dpy, error_event)
6645 XErrorEvent *error_event;
6650 void DisplayIcsInteractionTitle(message)
6653 if (oldICSInteractionTitle == NULL) {
6654 /* Magic to find the old window title, adapted from vim */
6655 char *wina = getenv("WINDOWID");
6657 Window win = (Window) atoi(wina);
6658 Window root, parent, *children;
6659 unsigned int nchildren;
6660 int (*oldHandler)() = XSetErrorHandler(NullXErrorCheck);
6662 if (XFetchName(xDisplay, win, &oldICSInteractionTitle)) break;
6663 if (!XQueryTree(xDisplay, win, &root, &parent,
6664 &children, &nchildren)) break;
6665 if (children) XFree((void *)children);
6666 if (parent == root || parent == 0) break;
6669 XSetErrorHandler(oldHandler);
6671 if (oldICSInteractionTitle == NULL) {
6672 oldICSInteractionTitle = "xterm";
6675 printf("\033]0;%s\007", message);
6679 char pendingReplyPrefix[MSG_SIZ];
6680 ProcRef pendingReplyPR;
6682 void AskQuestionProc(w, event, prms, nprms)
6689 fprintf(stderr, _("AskQuestionProc needed 4 parameters, got %d\n"),
6693 AskQuestionEvent(prms[0], prms[1], prms[2], prms[3]);
6696 void AskQuestionPopDown()
6698 if (!askQuestionUp) return;
6699 XtPopdown(askQuestionShell);
6700 XtDestroyWidget(askQuestionShell);
6701 askQuestionUp = False;
6704 void AskQuestionReplyAction(w, event, prms, nprms)
6714 reply = XawDialogGetValueString(w = XtParent(w));
6715 strcpy(buf, pendingReplyPrefix);
6716 if (*buf) strcat(buf, " ");
6719 OutputToProcess(pendingReplyPR, buf, strlen(buf), &err);
6720 AskQuestionPopDown();
6722 if (err) DisplayFatalError(_("Error writing to chess program"), err, 0);
6725 void AskQuestionCallback(w, client_data, call_data)
6727 XtPointer client_data, call_data;
6732 XtSetArg(args[0], XtNlabel, &name);
6733 XtGetValues(w, args, 1);
6735 if (strcmp(name, _("cancel")) == 0) {
6736 AskQuestionPopDown();
6738 AskQuestionReplyAction(w, NULL, NULL, NULL);
6742 void AskQuestion(title, question, replyPrefix, pr)
6743 char *title, *question, *replyPrefix;
6747 Widget popup, layout, dialog, edit;
6753 strcpy(pendingReplyPrefix, replyPrefix);
6754 pendingReplyPR = pr;
6757 XtSetArg(args[i], XtNresizable, True); i++;
6758 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
6759 askQuestionShell = popup =
6760 XtCreatePopupShell(title, transientShellWidgetClass,
6761 shellWidget, args, i);
6764 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
6765 layoutArgs, XtNumber(layoutArgs));
6768 XtSetArg(args[i], XtNlabel, question); i++;
6769 XtSetArg(args[i], XtNvalue, ""); i++;
6770 XtSetArg(args[i], XtNborderWidth, 0); i++;
6771 dialog = XtCreateManagedWidget("question", dialogWidgetClass,
6774 XawDialogAddButton(dialog, _("enter"), AskQuestionCallback,
6775 (XtPointer) dialog);
6776 XawDialogAddButton(dialog, _("cancel"), AskQuestionCallback,
6777 (XtPointer) dialog);
6779 XtRealizeWidget(popup);
6780 CatchDeleteWindow(popup, "AskQuestionPopDown");
6782 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
6783 &x, &y, &win_x, &win_y, &mask);
6785 XtSetArg(args[0], XtNx, x - 10);
6786 XtSetArg(args[1], XtNy, y - 30);
6787 XtSetValues(popup, args, 2);
6789 XtPopup(popup, XtGrabExclusive);
6790 askQuestionUp = True;
6792 edit = XtNameToWidget(dialog, "*value");
6793 XtSetKeyboardFocus(popup, edit);
6801 if (*name == NULLCHAR) {
6803 } else if (strcmp(name, "$") == 0) {
6804 putc(BELLCHAR, stderr);
6807 snprintf(buf, sizeof(buf), "%s '%s' &", appData.soundProgram, name);
6815 PlaySound(appData.soundMove);
6821 PlaySound(appData.soundIcsWin);
6827 PlaySound(appData.soundIcsLoss);
6833 PlaySound(appData.soundIcsDraw);
6837 PlayIcsUnfinishedSound()
6839 PlaySound(appData.soundIcsUnfinished);
6845 PlaySound(appData.soundIcsAlarm);
6851 system("stty echo");
6857 system("stty -echo");
6861 Colorize(cc, continuation)
6866 int count, outCount, error;
6868 if (textColors[(int)cc].bg > 0) {
6869 if (textColors[(int)cc].fg > 0) {
6870 sprintf(buf, "\033[0;%d;%d;%dm", textColors[(int)cc].attr,
6871 textColors[(int)cc].fg, textColors[(int)cc].bg);
6873 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
6874 textColors[(int)cc].bg);
6877 if (textColors[(int)cc].fg > 0) {
6878 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
6879 textColors[(int)cc].fg);
6881 sprintf(buf, "\033[0;%dm", textColors[(int)cc].attr);
6884 count = strlen(buf);
6885 outCount = OutputToProcess(NoProc, buf, count, &error);
6886 if (outCount < count) {
6887 DisplayFatalError(_("Error writing to display"), error, 1);
6890 if (continuation) return;
6893 PlaySound(appData.soundShout);
6896 PlaySound(appData.soundSShout);
6899 PlaySound(appData.soundChannel1);
6902 PlaySound(appData.soundChannel);
6905 PlaySound(appData.soundKibitz);
6908 PlaySound(appData.soundTell);
6910 case ColorChallenge:
6911 PlaySound(appData.soundChallenge);
6914 PlaySound(appData.soundRequest);
6917 PlaySound(appData.soundSeek);
6928 return getpwuid(getuid())->pw_name;
6931 static char *ExpandPathName(path)
6934 static char static_buf[2000];
6935 char *d, *s, buf[2000];
6941 while (*s && isspace(*s))
6950 if (*(s+1) == '/') {
6951 strcpy(d, getpwuid(getuid())->pw_dir);
6956 *strchr(buf, '/') = 0;
6957 pwd = getpwnam(buf);
6960 fprintf(stderr, _("ERROR: Unknown user %s (in path %s)\n"),
6964 strcpy(d, pwd->pw_dir);
6965 strcat(d, strchr(s+1, '/'));
6976 static char host_name[MSG_SIZ];
6978 #if HAVE_GETHOSTNAME
6979 gethostname(host_name, MSG_SIZ);
6981 #else /* not HAVE_GETHOSTNAME */
6982 # if HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H
6983 sysinfo(SI_HOSTNAME, host_name, MSG_SIZ);
6985 # else /* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
6987 # endif/* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
6988 #endif /* not HAVE_GETHOSTNAME */
6991 gint delayedEventTimerTag = 0;
6992 DelayedEventCallback delayedEventCallback = 0;
6995 FireDelayedEvent(data)
6998 delayedEventTimerTag = 0;
6999 delayedEventCallback();
7003 ScheduleDelayedEvent(cb, millisec)
7004 DelayedEventCallback cb; long millisec;
7006 delayedEventCallback = cb;
7007 delayedEventTimerTag =
7008 gtk_timeout_add(millisec,(GtkFunction) FireDelayedEvent, NULL);
7011 DelayedEventCallback
7014 if (delayedEventTimerTag)
7016 return delayedEventCallback;
7025 CancelDelayedEvent()
7027 if (delayedEventTimerTag)
7029 gtk_timeout_remove(delayedEventTimerTag);
7030 delayedEventTimerTag = 0;
7035 gint loadGameTimerTag = 0;
7037 int LoadGameTimerRunning()
7039 return loadGameTimerTag != 0;
7042 int StopLoadGameTimer()
7044 if (loadGameTimerTag != 0) {
7045 gtk_timeout_remove(loadGameTimerTag);
7046 loadGameTimerTag = 0;
7054 LoadGameTimerCallback(data)
7057 loadGameTimerTag = 0;
7062 StartLoadGameTimer(millisec)
7066 gtk_timeout_add( millisec, (GtkFunction) LoadGameTimerCallback, NULL);
7069 gint analysisClockTag = 0;
7072 AnalysisClockCallback(data)
7075 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile
7076 || appData.icsEngineAnalyze)
7078 AnalysisPeriodicEvent(0);
7079 StartAnalysisClock();
7084 StartAnalysisClock()
7087 gtk_timeout_add( 2000,(GtkFunction) AnalysisClockCallback, NULL);
7090 gint clockTimerTag = 0;
7092 int ClockTimerRunning()
7094 return clockTimerTag != 0;
7097 int StopClockTimer()
7099 if (clockTimerTag != 0)
7101 gtk_timeout_remove(clockTimerTag);
7112 ClockTimerCallback(data)
7121 StartClockTimer(millisec)
7124 clockTimerTag = gtk_timeout_add(millisec,(GtkFunction) ClockTimerCallback,NULL);
7129 DisplayTimerLabel(w, color, timer, highlight)
7138 if (appData.clockMode) {
7139 sprintf(buf, "%s: %s", color, TimeString(timer));
7141 sprintf(buf, "%s ", color);
7143 gtk_label_set_text(GTK_LABEL(w),buf);
7145 /* check for low time warning */
7146 // Pixel foregroundOrWarningColor = timerForegroundPixel;
7149 // appData.lowTimeWarning &&
7150 // (timer / 1000) < appData.icsAlarmTime)
7151 // foregroundOrWarningColor = lowTimeWarningColor;
7153 // if (appData.clockMode) {
7154 // sprintf(buf, "%s: %s", color, TimeString(timer));
7155 // XtSetArg(args[0], XtNlabel, buf);
7157 // sprintf(buf, "%s ", color);
7158 // XtSetArg(args[0], XtNlabel, buf);
7163 // XtSetArg(args[1], XtNbackground, foregroundOrWarningColor);
7164 // XtSetArg(args[2], XtNforeground, timerBackgroundPixel);
7166 // XtSetArg(args[1], XtNbackground, timerBackgroundPixel);
7167 // XtSetArg(args[2], XtNforeground, foregroundOrWarningColor);
7170 // XtSetValues(w, args, 3);
7175 DisplayWhiteClock(timeRemaining, highlight)
7179 if(appData.noGUI) return;
7181 DisplayTimerLabel(GUI_Whiteclock, _("White"), timeRemaining, highlight);
7182 if (highlight && WindowIcon == BlackIcon)
7184 WindowIcon = WhiteIcon;
7185 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
7190 DisplayBlackClock(timeRemaining, highlight)
7194 if(appData.noGUI) return;
7196 DisplayTimerLabel(GUI_Blackclock, _("Black"), timeRemaining, highlight);
7197 if (highlight && WindowIcon == WhiteIcon)
7199 WindowIcon = BlackIcon;
7200 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
7218 int StartChildProcess(cmdLine, dir, pr)
7225 int to_prog[2], from_prog[2];
7229 if (appData.debugMode) {
7230 fprintf(stderr, "StartChildProcess (dir=\"%s\") %s\n",dir, cmdLine);
7233 /* We do NOT feed the cmdLine to the shell; we just
7234 parse it into blank-separated arguments in the
7235 most simple-minded way possible.
7238 strcpy(buf, cmdLine);
7243 if (p == NULL) break;
7248 SetUpChildIO(to_prog, from_prog);
7250 if ((pid = fork()) == 0) {
7252 // [HGM] PSWBTM: made order resistant against case where fd of created pipe was 0 or 1
7253 close(to_prog[1]); // first close the unused pipe ends
7254 close(from_prog[0]);
7255 dup2(to_prog[0], 0); // to_prog was created first, nd is the only one to use 0 or 1
7256 dup2(from_prog[1], 1);
7257 if(to_prog[0] >= 2) close(to_prog[0]); // if 0 or 1, the dup2 already cosed the original
7258 close(from_prog[1]); // and closing again loses one of the pipes!
7259 if(fileno(stderr) >= 2) // better safe than sorry...
7260 dup2(1, fileno(stderr)); /* force stderr to the pipe */
7262 if (dir[0] != NULLCHAR && chdir(dir) != 0) {
7267 nice(appData.niceEngines); // [HGM] nice: adjust priority of engine proc
7269 execvp(argv[0], argv);
7271 /* If we get here, exec failed */
7276 /* Parent process */
7278 close(from_prog[1]);
7280 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7283 cp->fdFrom = from_prog[0];
7284 cp->fdTo = to_prog[1];
7289 // [HGM] kill: implement the 'hard killing' of AS's Winboard_x
7290 static RETSIGTYPE AlarmCallBack(int n)
7296 DestroyChildProcess(pr, signalType)
7300 ChildProc *cp = (ChildProc *) pr;
7302 if (cp->kind != CPReal) return;
7304 if (signalType == 10) { // [HGM] kill: if it does not terminate in 3 sec, kill
7305 signal(SIGALRM, AlarmCallBack);
7307 if(wait((int *) 0) == -1) { // process does not terminate on its own accord
7308 kill(cp->pid, SIGKILL); // kill it forcefully
7309 wait((int *) 0); // and wait again
7313 kill(cp->pid, signalType == 9 ? SIGKILL : SIGTERM); // [HGM] kill: use hard kill if so requested
7315 /* Process is exiting either because of the kill or because of
7316 a quit command sent by the backend; either way, wait for it to die.
7325 InterruptChildProcess(pr)
7328 ChildProc *cp = (ChildProc *) pr;
7330 if (cp->kind != CPReal) return;
7331 (void) kill(cp->pid, SIGINT); /* stop it thinking */
7334 int OpenTelnet(host, port, pr)
7339 char cmdLine[MSG_SIZ];
7341 if (port[0] == NULLCHAR) {
7342 snprintf(cmdLine, sizeof(cmdLine), "%s %s", appData.telnetProgram, host);
7344 snprintf(cmdLine, sizeof(cmdLine), "%s %s %s", appData.telnetProgram, host, port);
7346 return StartChildProcess(cmdLine, "", pr);
7349 int OpenTCP(host, port, pr)
7355 DisplayFatalError(_("Socket support is not configured in"), 0, 2);
7356 #else /* !OMIT_SOCKETS */
7358 struct sockaddr_in sa;
7360 unsigned short uport;
7363 if ((s = socket(AF_INET, SOCK_STREAM, 6)) < 0) {
7367 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
7368 sa.sin_family = AF_INET;
7369 sa.sin_addr.s_addr = INADDR_ANY;
7370 uport = (unsigned short) 0;
7371 sa.sin_port = htons(uport);
7372 if (bind(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)) < 0) {
7376 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
7377 if (!(hp = gethostbyname(host))) {
7379 if (sscanf(host, "%d.%d.%d.%d", &b0, &b1, &b2, &b3) == 4) {
7380 hp = (struct hostent *) calloc(1, sizeof(struct hostent));
7381 hp->h_addrtype = AF_INET;
7383 hp->h_addr_list = (char **) calloc(2, sizeof(char *));
7384 hp->h_addr_list[0] = (char *) malloc(4);
7385 hp->h_addr_list[0][0] = b0;
7386 hp->h_addr_list[0][1] = b1;
7387 hp->h_addr_list[0][2] = b2;
7388 hp->h_addr_list[0][3] = b3;
7393 sa.sin_family = hp->h_addrtype;
7394 uport = (unsigned short) atoi(port);
7395 sa.sin_port = htons(uport);
7396 memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);
7398 if (connect(s, (struct sockaddr *) &sa,
7399 sizeof(struct sockaddr_in)) < 0) {
7403 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7410 #endif /* !OMIT_SOCKETS */
7415 int OpenCommPort(name, pr)
7422 fd = open(name, 2, 0);
7423 if (fd < 0) return errno;
7425 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7435 int OpenLoopback(pr)
7441 SetUpChildIO(to, from);
7443 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7446 cp->fdFrom = to[0]; /* note not from[0]; we are doing a loopback */
7453 int OpenRcmd(host, user, cmd, pr)
7454 char *host, *user, *cmd;
7457 DisplayFatalError(_("internal rcmd not implemented for Unix"), 0, 1);
7461 #define INPUT_SOURCE_BUF_SIZE 8192
7470 char buf[INPUT_SOURCE_BUF_SIZE];
7475 DoInputCallback(closure, source, xid)
7480 InputSource *is = (InputSource *) closure;
7485 if (is->lineByLine) {
7486 count = read(is->fd, is->unused,
7487 INPUT_SOURCE_BUF_SIZE - (is->unused - is->buf));
7489 (is->func)(is, is->closure, is->buf, count, count ? errno : 0);
7492 is->unused += count;
7494 while (p < is->unused) {
7495 q = memchr(p, '\n', is->unused - p);
7496 if (q == NULL) break;
7498 (is->func)(is, is->closure, p, q - p, 0);
7502 while (p < is->unused) {
7507 count = read(is->fd, is->buf, INPUT_SOURCE_BUF_SIZE);
7512 (is->func)(is, is->closure, is->buf, count, error);
7516 InputSourceRef AddInputSource(pr, lineByLine, func, closure)
7523 ChildProc *cp = (ChildProc *) pr;
7525 is = (InputSource *) calloc(1, sizeof(InputSource));
7526 is->lineByLine = lineByLine;
7530 is->fd = fileno(stdin);
7532 is->kind = cp->kind;
7533 is->fd = cp->fdFrom;
7536 is->unused = is->buf;
7539 is->xid = XtAppAddInput(appContext, is->fd,
7540 (XtPointer) (XtInputReadMask),
7541 (XtInputCallbackProc) DoInputCallback,
7543 is->closure = closure;
7544 return (InputSourceRef) is;
7548 RemoveInputSource(isr)
7551 InputSource *is = (InputSource *) isr;
7553 if (is->xid == 0) return;
7554 XtRemoveInput(is->xid);
7558 int OutputToProcess(pr, message, count, outError)
7564 ChildProc *cp = (ChildProc *) pr;
7568 outCount = fwrite(message, 1, count, stdout);
7570 outCount = write(cp->fdTo, message, count);
7580 /* Output message to process, with "ms" milliseconds of delay
7581 between each character. This is needed when sending the logon
7582 script to ICC, which for some reason doesn't like the
7583 instantaneous send. */
7584 int OutputToProcessDelayed(pr, message, count, outError, msdelay)
7591 ChildProc *cp = (ChildProc *) pr;
7596 r = write(cp->fdTo, message++, 1);
7609 /**** Animation code by Hugh Fisher, DCS, ANU.
7611 Known problem: if a window overlapping the board is
7612 moved away while a piece is being animated underneath,
7613 the newly exposed area won't be updated properly.
7614 I can live with this.
7616 Known problem: if you look carefully at the animation
7617 of pieces in mono mode, they are being drawn as solid
7618 shapes without interior detail while moving. Fixing
7619 this would be a major complication for minimal return.
7622 /* Masks for XPM pieces. Black and white pieces can have
7623 different shapes, but in the interest of retaining my
7624 sanity pieces must have the same outline on both light
7625 and dark squares, and all pieces must use the same
7626 background square colors/images. */
7628 static int xpmDone = 0;
7631 CreateAnimMasks (pieceDepth)
7638 unsigned long plane;
7641 /* just return for gtk at the moment */
7644 /* Need a bitmap just to get a GC with right depth */
7645 buf = XCreatePixmap(xDisplay, xBoardWindow,
7647 values.foreground = 1;
7648 values.background = 0;
7649 /* Don't use XtGetGC, not read only */
7650 maskGC = XCreateGC(xDisplay, buf,
7651 GCForeground | GCBackground, &values);
7652 XFreePixmap(xDisplay, buf);
7654 buf = XCreatePixmap(xDisplay, xBoardWindow,
7655 squareSize, squareSize, pieceDepth);
7656 values.foreground = XBlackPixel(xDisplay, xScreen);
7657 values.background = XWhitePixel(xDisplay, xScreen);
7658 bufGC = XCreateGC(xDisplay, buf,
7659 GCForeground | GCBackground, &values);
7661 for (piece = WhitePawn; piece <= BlackKing; piece++) {
7662 /* Begin with empty mask */
7663 if(!xpmDone) // [HGM] pieces: keep using existing
7664 xpmMask[piece] = XCreatePixmap(xDisplay, xBoardWindow,
7665 squareSize, squareSize, 1);
7666 XSetFunction(xDisplay, maskGC, GXclear);
7667 XFillRectangle(xDisplay, xpmMask[piece], maskGC,
7668 0, 0, squareSize, squareSize);
7670 /* Take a copy of the piece */
7675 XSetFunction(xDisplay, bufGC, GXcopy);
7676 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn],
7678 0, 0, squareSize, squareSize, 0, 0);
7680 /* XOR the background (light) over the piece */
7681 XSetFunction(xDisplay, bufGC, GXxor);
7683 XCopyArea(xDisplay, xpmLightSquare, buf, bufGC,
7684 0, 0, squareSize, squareSize, 0, 0);
7686 XSetForeground(xDisplay, bufGC, lightSquareColor);
7687 XFillRectangle(xDisplay, buf, bufGC, 0, 0, squareSize, squareSize);
7690 /* We now have an inverted piece image with the background
7691 erased. Construct mask by just selecting all the non-zero
7692 pixels - no need to reconstruct the original image. */
7693 XSetFunction(xDisplay, maskGC, GXor);
7695 /* Might be quicker to download an XImage and create bitmap
7696 data from it rather than this N copies per piece, but it
7697 only takes a fraction of a second and there is a much
7698 longer delay for loading the pieces. */
7699 for (n = 0; n < pieceDepth; n ++) {
7700 XCopyPlane(xDisplay, buf, xpmMask[piece], maskGC,
7701 0, 0, squareSize, squareSize,
7707 XFreePixmap(xDisplay, buf);
7708 XFreeGC(xDisplay, bufGC);
7709 XFreeGC(xDisplay, maskGC);
7713 InitAnimState (anim, info)
7715 XWindowAttributes * info;
7720 /* Each buffer is square size, same depth as window */
7721 // anim->saveBuf = XCreatePixmap(xDisplay, xBoardWindow,
7722 // squareSize, squareSize, info->depth);
7723 // anim->newBuf = XCreatePixmap(xDisplay, xBoardWindow,
7724 // squareSize, squareSize, info->depth);
7726 // /* Create a plain GC for blitting */
7727 // mask = GCForeground | GCBackground | GCFunction |
7728 // GCPlaneMask | GCGraphicsExposures;
7729 // values.foreground = XBlackPixel(xDisplay, xScreen);
7730 // values.background = XWhitePixel(xDisplay, xScreen);
7731 // values.function = GXcopy;
7732 // values.plane_mask = AllPlanes;
7733 // values.graphics_exposures = False;
7734 // anim->blitGC = XCreateGC(xDisplay, xBoardWindow, mask, &values);
7736 // /* Piece will be copied from an existing context at
7737 // the start of each new animation/drag. */
7738 // anim->pieceGC = XCreateGC(xDisplay, xBoardWindow, 0, &values);
7740 // /* Outline will be a read-only copy of an existing */
7741 // anim->outlineGC = None;
7747 static VariantClass old = (VariantClass) -1; // [HGM] pieces: redo every time variant changes
7748 XWindowAttributes info;
7750 /* for gtk at the moment just ... */
7753 if (xpmDone && gameInfo.variant == old) return;
7754 if(xpmDone) old = gameInfo.variant; // first time pieces might not be created yet
7755 // XGetWindowAttributes(xDisplay, xBoardWindow, &info);
7757 // InitAnimState(&game, &info);
7758 // InitAnimState(&player, &info);
7760 /* For XPM pieces, we need bitmaps to use as masks. */
7762 // CreateAnimMasks(info.depth);
7768 static Boolean frameWaiting;
7770 static RETSIGTYPE FrameAlarm (sig)
7773 frameWaiting = False;
7774 /* In case System-V style signals. Needed?? */
7775 signal(SIGALRM, FrameAlarm);
7782 struct itimerval delay;
7784 XSync(xDisplay, False);
7787 frameWaiting = True;
7788 signal(SIGALRM, FrameAlarm);
7789 delay.it_interval.tv_sec =
7790 delay.it_value.tv_sec = time / 1000;
7791 delay.it_interval.tv_usec =
7792 delay.it_value.tv_usec = (time % 1000) * 1000;
7793 setitimer(ITIMER_REAL, &delay, NULL);
7795 /* Ugh -- busy-wait! --tpm */
7796 while (frameWaiting);
7798 while (frameWaiting) pause();
7800 delay.it_interval.tv_sec = delay.it_value.tv_sec = 0;
7801 delay.it_interval.tv_usec = delay.it_value.tv_usec = 0;
7802 setitimer(ITIMER_REAL, &delay, NULL);
7812 XSync(xDisplay, False);
7814 usleep(time * 1000);
7819 /* Convert board position to corner of screen rect and color */
7822 ScreenSquare(column, row, pt, color)
7823 int column; int row; XPoint * pt; int * color;
7826 pt->x = lineGap + ((BOARD_WIDTH-1)-column) * (squareSize + lineGap);
7827 pt->y = lineGap + row * (squareSize + lineGap);
7829 pt->x = lineGap + column * (squareSize + lineGap);
7830 pt->y = lineGap + ((BOARD_HEIGHT-1)-row) * (squareSize + lineGap);
7832 *color = SquareColor(row, column);
7835 /* Convert window coords to square */
7838 BoardSquare(x, y, column, row)
7839 int x; int y; int * column; int * row;
7841 *column = EventToSquare(x, BOARD_WIDTH);
7842 if (flipView && *column >= 0)
7843 *column = BOARD_WIDTH - 1 - *column;
7844 *row = EventToSquare(y, BOARD_HEIGHT);
7845 if (!flipView && *row >= 0)
7846 *row = BOARD_HEIGHT - 1 - *row;
7851 #undef Max /* just in case */
7853 #define Max(a, b) ((a) > (b) ? (a) : (b))
7854 #define Min(a, b) ((a) < (b) ? (a) : (b))
7857 SetRect(rect, x, y, width, height)
7858 XRectangle * rect; int x; int y; int width; int height;
7862 rect->width = width;
7863 rect->height = height;
7866 /* Test if two frames overlap. If they do, return
7867 intersection rect within old and location of
7868 that rect within new. */
7871 Intersect(old, new, size, area, pt)
7872 XPoint * old; XPoint * new;
7873 int size; XRectangle * area; XPoint * pt;
7875 if (old->x > new->x + size || new->x > old->x + size ||
7876 old->y > new->y + size || new->y > old->y + size) {
7879 SetRect(area, Max(new->x - old->x, 0), Max(new->y - old->y, 0),
7880 size - abs(old->x - new->x), size - abs(old->y - new->y));
7881 pt->x = Max(old->x - new->x, 0);
7882 pt->y = Max(old->y - new->y, 0);
7887 /* For two overlapping frames, return the rect(s)
7888 in the old that do not intersect with the new. */
7891 CalcUpdateRects(old, new, size, update, nUpdates)
7892 XPoint * old; XPoint * new; int size;
7893 XRectangle update[]; int * nUpdates;
7897 /* If old = new (shouldn't happen) then nothing to draw */
7898 if (old->x == new->x && old->y == new->y) {
7902 /* Work out what bits overlap. Since we know the rects
7903 are the same size we don't need a full intersect calc. */
7905 /* Top or bottom edge? */
7906 if (new->y > old->y) {
7907 SetRect(&(update[count]), old->x, old->y, size, new->y - old->y);
7909 } else if (old->y > new->y) {
7910 SetRect(&(update[count]), old->x, old->y + size - (old->y - new->y),
7911 size, old->y - new->y);
7914 /* Left or right edge - don't overlap any update calculated above. */
7915 if (new->x > old->x) {
7916 SetRect(&(update[count]), old->x, Max(new->y, old->y),
7917 new->x - old->x, size - abs(new->y - old->y));
7919 } else if (old->x > new->x) {
7920 SetRect(&(update[count]), new->x + size, Max(new->y, old->y),
7921 old->x - new->x, size - abs(new->y - old->y));
7928 /* Generate a series of frame coords from start->mid->finish.
7929 The movement rate doubles until the half way point is
7930 reached, then halves back down to the final destination,
7931 which gives a nice slow in/out effect. The algorithmn
7932 may seem to generate too many intermediates for short
7933 moves, but remember that the purpose is to attract the
7934 viewers attention to the piece about to be moved and
7935 then to where it ends up. Too few frames would be less
7939 Tween(start, mid, finish, factor, frames, nFrames)
7940 XPoint * start; XPoint * mid;
7941 XPoint * finish; int factor;
7942 XPoint frames[]; int * nFrames;
7944 int fraction, n, count;
7948 /* Slow in, stepping 1/16th, then 1/8th, ... */
7950 for (n = 0; n < factor; n++)
7952 for (n = 0; n < factor; n++) {
7953 frames[count].x = start->x + (mid->x - start->x) / fraction;
7954 frames[count].y = start->y + (mid->y - start->y) / fraction;
7956 fraction = fraction / 2;
7960 frames[count] = *mid;
7963 /* Slow out, stepping 1/2, then 1/4, ... */
7965 for (n = 0; n < factor; n++) {
7966 frames[count].x = finish->x - (finish->x - mid->x) / fraction;
7967 frames[count].y = finish->y - (finish->y - mid->y) / fraction;
7969 fraction = fraction * 2;
7974 /* Draw a piece on the screen without disturbing what's there */
7977 SelectGCMask(piece, clip, outline, mask)
7978 ChessSquare piece; GC * clip; GC * outline; Pixmap * mask;
7982 /* Bitmap for piece being moved. */
7983 if (appData.monoMode) {
7984 *mask = *pieceToSolid(piece);
7985 } else if (useImages) {
7987 *mask = xpmMask[piece];
7989 *mask = ximMaskPm[piece];
7992 *mask = *pieceToSolid(piece);
7995 /* GC for piece being moved. Square color doesn't matter, but
7996 since it gets modified we make a copy of the original. */
7998 if (appData.monoMode)
8003 if (appData.monoMode)
8008 XCopyGC(xDisplay, source, 0xFFFFFFFF, *clip);
8010 /* Outline only used in mono mode and is not modified */
8012 *outline = bwPieceGC;
8014 *outline = wbPieceGC;
8018 OverlayPiece(piece, clip, outline, dest)
8019 ChessSquare piece; GC clip; GC outline; Drawable dest;
8024 /* Draw solid rectangle which will be clipped to shape of piece */
8025 XFillRectangle(xDisplay, dest, clip,
8026 0, 0, squareSize, squareSize);
8027 if (appData.monoMode)
8028 /* Also draw outline in contrasting color for black
8029 on black / white on white cases */
8030 XCopyPlane(xDisplay, *pieceToOutline(piece), dest, outline,
8031 0, 0, squareSize, squareSize, 0, 0, 1);
8033 /* Copy the piece */
8038 XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
8040 0, 0, squareSize, squareSize,
8045 /* Animate the movement of a single piece */
8048 BeginAnimation(anim, piece, startColor, start)
8056 /* The old buffer is initialised with the start square (empty) */
8057 BlankSquare(0, 0, startColor, EmptySquare, anim->saveBuf);
8058 anim->prevFrame = *start;
8060 /* The piece will be drawn using its own bitmap as a matte */
8061 SelectGCMask(piece, &anim->pieceGC, &anim->outlineGC, &mask);
8062 XSetClipMask(xDisplay, anim->pieceGC, mask);
8066 AnimationFrame(anim, frame, piece)
8071 XRectangle updates[4];
8076 /* Save what we are about to draw into the new buffer */
8077 XCopyArea(xDisplay, xBoardWindow, anim->newBuf, anim->blitGC,
8078 frame->x, frame->y, squareSize, squareSize,
8081 /* Erase bits of the previous frame */
8082 if (Intersect(&anim->prevFrame, frame, squareSize, &overlap, &pt)) {
8083 /* Where the new frame overlapped the previous,
8084 the contents in newBuf are wrong. */
8085 XCopyArea(xDisplay, anim->saveBuf, anim->newBuf, anim->blitGC,
8086 overlap.x, overlap.y,
8087 overlap.width, overlap.height,
8089 /* Repaint the areas in the old that don't overlap new */
8090 CalcUpdateRects(&anim->prevFrame, frame, squareSize, updates, &count);
8091 for (i = 0; i < count; i++)
8092 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
8093 updates[i].x - anim->prevFrame.x,
8094 updates[i].y - anim->prevFrame.y,
8095 updates[i].width, updates[i].height,
8096 updates[i].x, updates[i].y);
8098 /* Easy when no overlap */
8099 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
8100 0, 0, squareSize, squareSize,
8101 anim->prevFrame.x, anim->prevFrame.y);
8104 /* Save this frame for next time round */
8105 XCopyArea(xDisplay, anim->newBuf, anim->saveBuf, anim->blitGC,
8106 0, 0, squareSize, squareSize,
8108 anim->prevFrame = *frame;
8110 /* Draw piece over original screen contents, not current,
8111 and copy entire rect. Wipes out overlapping piece images. */
8112 OverlayPiece(piece, anim->pieceGC, anim->outlineGC, anim->newBuf);
8113 XCopyArea(xDisplay, anim->newBuf, xBoardWindow, anim->blitGC,
8114 0, 0, squareSize, squareSize,
8115 frame->x, frame->y);
8119 EndAnimation (anim, finish)
8123 XRectangle updates[4];
8128 /* The main code will redraw the final square, so we
8129 only need to erase the bits that don't overlap. */
8130 if (Intersect(&anim->prevFrame, finish, squareSize, &overlap, &pt)) {
8131 CalcUpdateRects(&anim->prevFrame, finish, squareSize, updates, &count);
8132 for (i = 0; i < count; i++)
8133 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
8134 updates[i].x - anim->prevFrame.x,
8135 updates[i].y - anim->prevFrame.y,
8136 updates[i].width, updates[i].height,
8137 updates[i].x, updates[i].y);
8139 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
8140 0, 0, squareSize, squareSize,
8141 anim->prevFrame.x, anim->prevFrame.y);
8146 FrameSequence(anim, piece, startColor, start, finish, frames, nFrames)
8148 ChessSquare piece; int startColor;
8149 XPoint * start; XPoint * finish;
8150 XPoint frames[]; int nFrames;
8154 BeginAnimation(anim, piece, startColor, start);
8155 for (n = 0; n < nFrames; n++) {
8156 AnimationFrame(anim, &(frames[n]), piece);
8157 FrameDelay(appData.animSpeed);
8159 EndAnimation(anim, finish);
8162 /* Main control logic for deciding what to animate and how */
8165 AnimateMove(board, fromX, fromY, toX, toY)
8174 XPoint start, finish, mid;
8175 XPoint frames[kFactor * 2 + 1];
8176 int nFrames, startColor, endColor;
8178 /* Are we animating? */
8179 if (!appData.animate || appData.blindfold)
8182 if(board[toY][toX] == WhiteRook && board[fromY][fromX] == WhiteKing ||
8183 board[toY][toX] == BlackRook && board[fromY][fromX] == BlackKing)
8184 return; // [HGM] FRC: no animtion of FRC castlings, as to-square is not true to-square
8186 if (fromY < 0 || fromX < 0 || toX < 0 || toY < 0) return;
8187 piece = board[fromY][fromX];
8188 if (piece >= EmptySquare) return;
8193 hop = (piece == WhiteKnight || piece == BlackKnight);
8196 if (appData.debugMode) {
8197 fprintf(debugFP, hop ? _("AnimateMove: piece %d hops from %d,%d to %d,%d \n") :
8198 _("AnimateMove: piece %d slides from %d,%d to %d,%d \n"),
8199 piece, fromX, fromY, toX, toY); }
8201 ScreenSquare(fromX, fromY, &start, &startColor);
8202 ScreenSquare(toX, toY, &finish, &endColor);
8205 /* Knight: make diagonal movement then straight */
8206 if (abs(toY - fromY) < abs(toX - fromX)) {
8207 mid.x = start.x + (finish.x - start.x) / 2;
8211 mid.y = start.y + (finish.y - start.y) / 2;
8214 mid.x = start.x + (finish.x - start.x) / 2;
8215 mid.y = start.y + (finish.y - start.y) / 2;
8218 /* Don't use as many frames for very short moves */
8219 if (abs(toY - fromY) + abs(toX - fromX) <= 2)
8220 Tween(&start, &mid, &finish, kFactor - 1, frames, &nFrames);
8222 Tween(&start, &mid, &finish, kFactor, frames, &nFrames);
8223 FrameSequence(&game, piece, startColor, &start, &finish, frames, nFrames);
8225 /* Be sure end square is redrawn */
8226 damage[toY][toX] = True;
8230 DragPieceBegin(x, y)
8233 int boardX, boardY, color;
8236 /* Are we animating? */
8237 if (!appData.animateDragging || appData.blindfold)
8240 /* Figure out which square we start in and the
8241 mouse position relative to top left corner. */
8242 BoardSquare(x, y, &boardX, &boardY);
8243 player.startBoardX = boardX;
8244 player.startBoardY = boardY;
8245 ScreenSquare(boardX, boardY, &corner, &color);
8246 player.startSquare = corner;
8247 player.startColor = color;
8249 /* Start from exactly where the piece is. This can be confusing
8250 if you start dragging far from the center of the square; most
8251 or all of the piece can be over a different square from the one
8252 the mouse pointer is in. */
8253 player.mouseDelta.x = x - corner.x;
8254 player.mouseDelta.y = y - corner.y;
8256 /* As soon as we start dragging, the piece will jump slightly to
8257 be centered over the mouse pointer. */
8258 player.mouseDelta.x = squareSize/2;
8259 player.mouseDelta.y = squareSize/2;
8261 /* Initialise animation */
8262 player.dragPiece = PieceForSquare(boardX, boardY);
8264 if (player.dragPiece >= 0 && player.dragPiece < EmptySquare) {
8265 player.dragActive = True;
8266 BeginAnimation(&player, player.dragPiece, color, &corner);
8267 /* Mark this square as needing to be redrawn. Note that
8268 we don't remove the piece though, since logically (ie
8269 as seen by opponent) the move hasn't been made yet. */
8270 if(boardX == BOARD_RGHT+1 && PieceForSquare(boardX-1, boardY) > 1 ||
8271 boardX == BOARD_LEFT-2 && PieceForSquare(boardX+1, boardY) > 1)
8272 XCopyArea(xDisplay, xBoardWindow, player.saveBuf, player.blitGC,
8273 corner.x, corner.y, squareSize, squareSize,
8274 0, 0); // [HGM] zh: unstack in stead of grab
8275 damage[boardY][boardX] = True;
8277 player.dragActive = False;
8287 /* Are we animating? */
8288 if (!appData.animateDragging || appData.blindfold)
8292 if (! player.dragActive)
8294 /* Move piece, maintaining same relative position
8295 of mouse within square */
8296 corner.x = x - player.mouseDelta.x;
8297 corner.y = y - player.mouseDelta.y;
8298 AnimationFrame(&player, &corner, player.dragPiece);
8300 if (appData.highlightDragging) {
8302 BoardSquare(x, y, &boardX, &boardY);
8303 SetHighlights(fromX, fromY, boardX, boardY);
8312 int boardX, boardY, color;
8315 /* Are we animating? */
8316 if (!appData.animateDragging || appData.blindfold)
8320 if (! player.dragActive)
8322 /* Last frame in sequence is square piece is
8323 placed on, which may not match mouse exactly. */
8324 BoardSquare(x, y, &boardX, &boardY);
8325 ScreenSquare(boardX, boardY, &corner, &color);
8326 EndAnimation(&player, &corner);
8328 /* Be sure end square is redrawn */
8329 damage[boardY][boardX] = True;
8331 /* This prevents weird things happening with fast successive
8332 clicks which on my Sun at least can cause motion events
8333 without corresponding press/release. */
8334 player.dragActive = False;
8337 /* Handle expose event while piece being dragged */
8342 if (!player.dragActive || appData.blindfold)
8345 /* What we're doing: logically, the move hasn't been made yet,
8346 so the piece is still in it's original square. But visually
8347 it's being dragged around the board. So we erase the square
8348 that the piece is on and draw it at the last known drag point. */
8349 BlankSquare(player.startSquare.x, player.startSquare.y,
8350 player.startColor, EmptySquare, xBoardWindow);
8351 AnimationFrame(&player, &player.prevFrame, player.dragPiece);
8352 damage[player.startBoardY][player.startBoardX] = TRUE;
8356 SetProgramStats( FrontEndProgramStats * stats )
8359 // [HGM] done, but perhaps backend should call this directly?
8360 EngineOutputUpdate( stats );