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 ||
4199 (x == BOARD_LEFT-2 && y < BOARD_HEIGHT-gameInfo.holdingsSize ) ||
4200 (x == BOARD_RGHT+1 && y >= gameInfo.holdingsSize)) )
4204 if (event->type == ButtonPress) {
4206 if (OKToStartUserMove(x, y)) {
4210 DragPieceBegin(event->xbutton.x, event->xbutton.y);
4211 if (appData.highlightDragging) {
4212 SetHighlights(x, y, -1, -1);
4220 if (event->type == ButtonPress && gameMode != EditPosition &&
4225 /* Check if clicking again on the same color piece */
4226 fromP = boards[currentMove][fromY][fromX];
4227 toP = boards[currentMove][y][x];
4228 if ((WhitePawn <= fromP && fromP < WhiteKing && // [HGM] this test should go, as UserMoveTest now does it.
4229 WhitePawn <= toP && toP <= WhiteKing) || // For now I made it less critical by exempting King
4230 (BlackPawn <= fromP && fromP < BlackKing && // moves, to not interfere with FRC castlings.
4231 BlackPawn <= toP && toP <= BlackKing)) {
4232 /* Clicked again on same color piece -- changed his mind */
4233 second = (x == fromX && y == fromY);
4234 if (appData.highlightDragging) {
4235 SetHighlights(x, y, -1, -1);
4239 if (OKToStartUserMove(x, y)) {
4242 DragPieceBegin(event->xbutton.x, event->xbutton.y);
4248 if (event->type == ButtonRelease && x == fromX && y == fromY) {
4249 DragPieceEnd(event->xbutton.x, event->xbutton.y);
4250 if (appData.animateDragging) {
4251 /* Undo animation damage if any */
4252 DrawPosition(FALSE, NULL);
4255 /* Second up/down in same square; just abort move */
4260 ClearPremoveHighlights();
4262 /* First upclick in same square; start click-click mode */
4263 SetHighlights(x, y, -1, -1);
4268 /* Completed move */
4271 saveAnimate = appData.animate;
4272 if (event->type == ButtonPress) {
4273 /* Finish clickclick move */
4274 if (appData.animate || appData.highlightLastMove) {
4275 SetHighlights(fromX, fromY, toX, toY);
4280 /* Finish drag move */
4281 if (appData.highlightLastMove) {
4282 SetHighlights(fromX, fromY, toX, toY);
4286 DragPieceEnd(event->xbutton.x, event->xbutton.y);
4287 /* Don't animate move and drag both */
4288 appData.animate = FALSE;
4290 if (IsPromotion(fromX, fromY, toX, toY)) {
4291 if (appData.alwaysPromoteToQueen) {
4292 UserMoveEvent(fromX, fromY, toX, toY, 'q');
4293 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
4294 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
4297 SetHighlights(fromX, fromY, toX, toY);
4301 UserMoveEvent(fromX, fromY, toX, toY, NULLCHAR);
4302 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
4303 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
4306 appData.animate = saveAnimate;
4307 if (appData.animate || appData.animateDragging) {
4308 /* Undo animation damage if needed */
4309 DrawPosition(FALSE, NULL);
4313 void AnimateUserMove (Widget w, XEvent * event,
4314 String * params, Cardinal * nParams)
4316 DragPieceMove(event->xmotion.x, event->xmotion.y);
4319 Widget CommentCreate(name, text, mutable, callback, lines)
4321 int /*Boolean*/ mutable;
4322 XtCallbackProc callback;
4326 Widget shell, layout, form, edit, b_ok, b_cancel, b_clear, b_close, b_edit;
4331 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4332 XtGetValues(boardWidget, args, j);
4335 XtSetArg(args[j], XtNresizable, True); j++;
4338 XtCreatePopupShell(name, topLevelShellWidgetClass,
4339 shellWidget, args, j);
4342 XtCreatePopupShell(name, transientShellWidgetClass,
4343 shellWidget, args, j);
4346 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
4347 layoutArgs, XtNumber(layoutArgs));
4349 XtCreateManagedWidget("form", formWidgetClass, layout,
4350 formArgs, XtNumber(formArgs));
4354 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
4355 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
4357 XtSetArg(args[j], XtNstring, text); j++;
4358 XtSetArg(args[j], XtNtop, XtChainTop); j++;
4359 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4360 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4361 XtSetArg(args[j], XtNright, XtChainRight); j++;
4362 XtSetArg(args[j], XtNresizable, True); j++;
4363 XtSetArg(args[j], XtNwidth, bw_width); j++; /*force wider than buttons*/
4365 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
4367 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
4368 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
4370 XtSetArg(args[j], XtNautoFill, True); j++;
4371 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
4373 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
4377 XtSetArg(args[j], XtNfromVert, edit); j++;
4378 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4379 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4380 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4381 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4383 XtCreateManagedWidget(_("ok"), commandWidgetClass, form, args, j);
4384 XtAddCallback(b_ok, XtNcallback, callback, (XtPointer) 0);
4387 XtSetArg(args[j], XtNfromVert, edit); j++;
4388 XtSetArg(args[j], XtNfromHoriz, b_ok); j++;
4389 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4390 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4391 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4392 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4394 XtCreateManagedWidget(_("cancel"), commandWidgetClass, form, args, j);
4395 XtAddCallback(b_cancel, XtNcallback, callback, (XtPointer) 0);
4398 XtSetArg(args[j], XtNfromVert, edit); j++;
4399 XtSetArg(args[j], XtNfromHoriz, b_cancel); j++;
4400 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4401 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4402 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4403 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4405 XtCreateManagedWidget(_("clear"), commandWidgetClass, form, args, j);
4406 XtAddCallback(b_clear, XtNcallback, callback, (XtPointer) 0);
4409 XtSetArg(args[j], XtNfromVert, edit); j++;
4410 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4411 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4412 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4413 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4415 XtCreateManagedWidget(_("close"), commandWidgetClass, form, args, j);
4416 XtAddCallback(b_close, XtNcallback, callback, (XtPointer) 0);
4419 XtSetArg(args[j], XtNfromVert, edit); j++;
4420 XtSetArg(args[j], XtNfromHoriz, b_close); j++;
4421 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4422 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4423 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4424 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4426 XtCreateManagedWidget(_("edit"), commandWidgetClass, form, args, j);
4427 XtAddCallback(b_edit, XtNcallback, callback, (XtPointer) 0);
4430 XtRealizeWidget(shell);
4432 if (commentX == -1) {
4435 Dimension pw_height;
4436 Dimension ew_height;
4439 XtSetArg(args[j], XtNheight, &ew_height); j++;
4440 XtGetValues(edit, args, j);
4443 XtSetArg(args[j], XtNheight, &pw_height); j++;
4444 XtGetValues(shell, args, j);
4445 commentH = pw_height + (lines - 1) * ew_height;
4446 commentW = bw_width - 16;
4448 XSync(xDisplay, False);
4450 /* This code seems to tickle an X bug if it is executed too soon
4451 after xboard starts up. The coordinates get transformed as if
4452 the main window was positioned at (0, 0).
4454 XtTranslateCoords(shellWidget,
4455 (bw_width - commentW) / 2, 0 - commentH / 2,
4456 &commentX, &commentY);
4458 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
4459 RootWindowOfScreen(XtScreen(shellWidget)),
4460 (bw_width - commentW) / 2, 0 - commentH / 2,
4465 if (commentY < 0) commentY = 0; /*avoid positioning top offscreen*/
4468 XtSetArg(args[j], XtNheight, commentH); j++;
4469 XtSetArg(args[j], XtNwidth, commentW); j++;
4470 XtSetArg(args[j], XtNx, commentX); j++;
4471 XtSetArg(args[j], XtNy, commentY); j++;
4472 XtSetValues(shell, args, j);
4473 XtSetKeyboardFocus(shell, edit);
4478 /* Used for analysis window and ICS input window */
4479 Widget MiscCreate(name, text, mutable, callback, lines)
4481 int /*Boolean*/ mutable;
4482 XtCallbackProc callback;
4486 Widget shell, layout, form, edit;
4488 Dimension bw_width, pw_height, ew_height, w, h;
4494 XtSetArg(args[j], XtNresizable, True); j++;
4497 XtCreatePopupShell(name, topLevelShellWidgetClass,
4498 shellWidget, args, j);
4501 XtCreatePopupShell(name, transientShellWidgetClass,
4502 shellWidget, args, j);
4505 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
4506 layoutArgs, XtNumber(layoutArgs));
4508 XtCreateManagedWidget("form", formWidgetClass, layout,
4509 formArgs, XtNumber(formArgs));
4513 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
4514 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
4516 XtSetArg(args[j], XtNstring, text); j++;
4517 XtSetArg(args[j], XtNtop, XtChainTop); j++;
4518 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4519 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4520 XtSetArg(args[j], XtNright, XtChainRight); j++;
4521 XtSetArg(args[j], XtNresizable, True); j++;
4523 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
4525 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
4526 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
4528 XtSetArg(args[j], XtNautoFill, True); j++;
4529 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
4531 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
4533 XtRealizeWidget(shell);
4536 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4537 XtGetValues(boardWidget, args, j);
4540 XtSetArg(args[j], XtNheight, &ew_height); j++;
4541 XtGetValues(edit, args, j);
4544 XtSetArg(args[j], XtNheight, &pw_height); j++;
4545 XtGetValues(shell, args, j);
4546 h = pw_height + (lines - 1) * ew_height;
4549 XSync(xDisplay, False);
4551 /* This code seems to tickle an X bug if it is executed too soon
4552 after xboard starts up. The coordinates get transformed as if
4553 the main window was positioned at (0, 0).
4555 XtTranslateCoords(shellWidget, (bw_width - w) / 2, 0 - h / 2, &x, &y);
4557 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
4558 RootWindowOfScreen(XtScreen(shellWidget)),
4559 (bw_width - w) / 2, 0 - h / 2, &xx, &yy, &junk);
4563 if (y < 0) y = 0; /*avoid positioning top offscreen*/
4566 XtSetArg(args[j], XtNheight, h); j++;
4567 XtSetArg(args[j], XtNwidth, w); j++;
4568 XtSetArg(args[j], XtNx, x); j++;
4569 XtSetArg(args[j], XtNy, y); j++;
4570 XtSetValues(shell, args, j);
4576 static int savedIndex; /* gross that this is global */
4578 void EditCommentPopUp(index, title, text)
4587 if (text == NULL) text = "";
4589 if (editShell == NULL) {
4591 CommentCreate(title, text, True, EditCommentCallback, 4);
4592 XtRealizeWidget(editShell);
4593 CatchDeleteWindow(editShell, "EditCommentPopDown");
4595 edit = XtNameToWidget(editShell, "*form.text");
4597 XtSetArg(args[j], XtNstring, text); j++;
4598 XtSetValues(edit, args, j);
4600 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4601 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4602 XtSetValues(editShell, args, j);
4605 XtPopup(editShell, XtGrabNone);
4609 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
4610 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
4614 void EditCommentCallback(w, client_data, call_data)
4616 XtPointer client_data, call_data;
4624 XtSetArg(args[j], XtNlabel, &name); j++;
4625 XtGetValues(w, args, j);
4627 if (strcmp(name, _("ok")) == 0) {
4628 edit = XtNameToWidget(editShell, "*form.text");
4630 XtSetArg(args[j], XtNstring, &val); j++;
4631 XtGetValues(edit, args, j);
4632 ReplaceComment(savedIndex, val);
4633 EditCommentPopDown();
4634 } else if (strcmp(name, _("cancel")) == 0) {
4635 EditCommentPopDown();
4636 } else if (strcmp(name, _("clear")) == 0) {
4637 edit = XtNameToWidget(editShell, "*form.text");
4638 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
4639 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
4643 void EditCommentPopDown()
4648 if (!editUp) return;
4650 XtSetArg(args[j], XtNx, &commentX); j++;
4651 XtSetArg(args[j], XtNy, &commentY); j++;
4652 XtSetArg(args[j], XtNheight, &commentH); j++;
4653 XtSetArg(args[j], XtNwidth, &commentW); j++;
4654 XtGetValues(editShell, args, j);
4655 XtPopdown(editShell);
4658 XtSetArg(args[j], XtNleftBitmap, None); j++;
4659 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
4663 void ICSInputBoxPopUp()
4668 char *title = _("ICS Input");
4671 if (ICSInputShell == NULL) {
4672 ICSInputShell = MiscCreate(title, "", True, NULL, 1);
4673 tr = XtParseTranslationTable(ICSInputTranslations);
4674 edit = XtNameToWidget(ICSInputShell, "*form.text");
4675 XtOverrideTranslations(edit, tr);
4676 XtRealizeWidget(ICSInputShell);
4677 CatchDeleteWindow(ICSInputShell, "ICSInputBoxPopDown");
4680 edit = XtNameToWidget(ICSInputShell, "*form.text");
4682 XtSetArg(args[j], XtNstring, ""); j++;
4683 XtSetValues(edit, args, j);
4685 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4686 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4687 XtSetValues(ICSInputShell, args, j);
4690 XtPopup(ICSInputShell, XtGrabNone);
4691 XtSetKeyboardFocus(ICSInputShell, edit);
4693 ICSInputBoxUp = True;
4695 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
4696 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
4700 void ICSInputSendText()
4707 edit = XtNameToWidget(ICSInputShell, "*form.text");
4709 XtSetArg(args[j], XtNstring, &val); j++;
4710 XtGetValues(edit, args, j);
4711 SendMultiLineToICS(val);
4712 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
4713 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
4716 void ICSInputBoxPopDown()
4721 if (!ICSInputBoxUp) return;
4723 XtPopdown(ICSInputShell);
4724 ICSInputBoxUp = False;
4726 XtSetArg(args[j], XtNleftBitmap, None); j++;
4727 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
4731 void CommentPopUp(title, text)
4738 if (commentShell == NULL) {
4740 CommentCreate(title, text, False, CommentCallback, 4);
4741 XtRealizeWidget(commentShell);
4742 CatchDeleteWindow(commentShell, "CommentPopDown");
4744 edit = XtNameToWidget(commentShell, "*form.text");
4746 XtSetArg(args[j], XtNstring, text); j++;
4747 XtSetValues(edit, args, j);
4749 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4750 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4751 XtSetValues(commentShell, args, j);
4754 XtPopup(commentShell, XtGrabNone);
4755 XSync(xDisplay, False);
4760 void AnalysisPopUp(title, text)
4767 if (analysisShell == NULL) {
4768 analysisShell = MiscCreate(title, text, False, NULL, 4);
4769 XtRealizeWidget(analysisShell);
4770 CatchDeleteWindow(analysisShell, "AnalysisPopDown");
4773 edit = XtNameToWidget(analysisShell, "*form.text");
4775 XtSetArg(args[j], XtNstring, text); j++;
4776 XtSetValues(edit, args, j);
4778 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4779 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4780 XtSetValues(analysisShell, args, j);
4784 XtPopup(analysisShell, XtGrabNone);
4786 XSync(xDisplay, False);
4791 void CommentCallback(w, client_data, call_data)
4793 XtPointer client_data, call_data;
4800 XtSetArg(args[j], XtNlabel, &name); j++;
4801 XtGetValues(w, args, j);
4803 if (strcmp(name, _("close")) == 0) {
4805 } else if (strcmp(name, _("edit")) == 0) {
4812 void CommentPopDown()
4817 if (!commentUp) return;
4819 XtSetArg(args[j], XtNx, &commentX); j++;
4820 XtSetArg(args[j], XtNy, &commentY); j++;
4821 XtSetArg(args[j], XtNwidth, &commentW); j++;
4822 XtSetArg(args[j], XtNheight, &commentH); j++;
4823 XtGetValues(commentShell, args, j);
4824 XtPopdown(commentShell);
4825 XSync(xDisplay, False);
4829 void AnalysisPopDown()
4831 if (!analysisUp) return;
4832 XtPopdown(analysisShell);
4833 XSync(xDisplay, False);
4835 if (appData.icsEngineAnalyze) ExitAnalyzeMode(); /* [DM] icsEngineAnalyze */
4839 void FileNamePopUp(label, def, proc, openMode)
4846 Widget popup, layout, dialog, edit;
4852 fileProc = proc; /* I can't see a way not */
4853 fileOpenMode = openMode; /* to use globals here */
4856 XtSetArg(args[i], XtNresizable, True); i++;
4857 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
4858 XtSetArg(args[i], XtNtitle, XtNewString(_("File name prompt"))); i++;
4859 fileNameShell = popup =
4860 XtCreatePopupShell("File name prompt", transientShellWidgetClass,
4861 shellWidget, args, i);
4864 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
4865 layoutArgs, XtNumber(layoutArgs));
4868 XtSetArg(args[i], XtNlabel, label); i++;
4869 XtSetArg(args[i], XtNvalue, def); i++;
4870 XtSetArg(args[i], XtNborderWidth, 0); i++;
4871 dialog = XtCreateManagedWidget("fileName", dialogWidgetClass,
4874 XawDialogAddButton(dialog, _("ok"), FileNameCallback, (XtPointer) dialog);
4875 XawDialogAddButton(dialog, _("cancel"), FileNameCallback,
4876 (XtPointer) dialog);
4878 XtRealizeWidget(popup);
4879 CatchDeleteWindow(popup, "FileNamePopDown");
4881 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
4882 &x, &y, &win_x, &win_y, &mask);
4884 XtSetArg(args[0], XtNx, x - 10);
4885 XtSetArg(args[1], XtNy, y - 30);
4886 XtSetValues(popup, args, 2);
4888 XtPopup(popup, XtGrabExclusive);
4891 edit = XtNameToWidget(dialog, "*value");
4892 XtSetKeyboardFocus(popup, edit);
4895 void FileNamePopDown()
4897 if (!filenameUp) return;
4898 XtPopdown(fileNameShell);
4899 XtDestroyWidget(fileNameShell);
4904 void FileNameCallback(w, client_data, call_data)
4906 XtPointer client_data, call_data;
4911 XtSetArg(args[0], XtNlabel, &name);
4912 XtGetValues(w, args, 1);
4914 if (strcmp(name, _("cancel")) == 0) {
4919 FileNameAction(w, NULL, NULL, NULL);
4922 void FileNameAction(w, event, prms, nprms)
4934 name = XawDialogGetValueString(w = XtParent(w));
4936 if ((name != NULL) && (*name != NULLCHAR)) {
4938 XtPopdown(w = XtParent(XtParent(w)));
4942 p = strrchr(buf, ' ');
4949 fullname = ExpandPathName(buf);
4951 ErrorPopUp(_("Error"), _("Can't open file"), FALSE);
4954 f = fopen(fullname, fileOpenMode);
4956 DisplayError(_("Failed to open file"), errno);
4958 (void) (*fileProc)(f, index, buf);
4965 XtPopdown(w = XtParent(XtParent(w)));
4971 void PromotionPopUp()
4974 Widget dialog, layout;
4976 Dimension bw_width, pw_width;
4980 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4981 XtGetValues(boardWidget, args, j);
4984 XtSetArg(args[j], XtNresizable, True); j++;
4985 XtSetArg(args[j], XtNtitle, XtNewString(_("Promotion"))); j++;
4987 XtCreatePopupShell("Promotion", transientShellWidgetClass,
4988 shellWidget, args, j);
4990 XtCreateManagedWidget(layoutName, formWidgetClass, promotionShell,
4991 layoutArgs, XtNumber(layoutArgs));
4994 XtSetArg(args[j], XtNlabel, _("Promote to what?")); j++;
4995 XtSetArg(args[j], XtNborderWidth, 0); j++;
4996 dialog = XtCreateManagedWidget("promotion", dialogWidgetClass,
4999 if(gameInfo.variant != VariantShogi) {
5000 XawDialogAddButton(dialog, _("Queen"), PromotionCallback,
5001 (XtPointer) dialog);
5002 XawDialogAddButton(dialog, _("Rook"), PromotionCallback,
5003 (XtPointer) dialog);
5004 XawDialogAddButton(dialog, _("Bishop"), PromotionCallback,
5005 (XtPointer) dialog);
5006 XawDialogAddButton(dialog, _("Knight"), PromotionCallback,
5007 (XtPointer) dialog);
5008 if (!appData.testLegality || gameInfo.variant == VariantSuicide ||
5009 gameInfo.variant == VariantGiveaway) {
5010 XawDialogAddButton(dialog, _("King"), PromotionCallback,
5011 (XtPointer) dialog);
5013 if(gameInfo.variant == VariantCapablanca ||
5014 gameInfo.variant == VariantGothic ||
5015 gameInfo.variant == VariantCapaRandom) {
5016 XawDialogAddButton(dialog, _("Archbishop"), PromotionCallback,
5017 (XtPointer) dialog);
5018 XawDialogAddButton(dialog, _("Chancellor"), PromotionCallback,
5019 (XtPointer) dialog);
5021 } else // [HGM] shogi
5023 XawDialogAddButton(dialog, _("Promote"), PromotionCallback,
5024 (XtPointer) dialog);
5025 XawDialogAddButton(dialog, _("Defer"), PromotionCallback,
5026 (XtPointer) dialog);
5028 XawDialogAddButton(dialog, _("cancel"), PromotionCallback,
5029 (XtPointer) dialog);
5031 XtRealizeWidget(promotionShell);
5032 CatchDeleteWindow(promotionShell, "PromotionPopDown");
5035 XtSetArg(args[j], XtNwidth, &pw_width); j++;
5036 XtGetValues(promotionShell, args, j);
5038 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
5039 lineGap + squareSize/3 +
5040 ((toY == BOARD_HEIGHT-1) ^ (flipView) ?
5041 0 : 6*(squareSize + lineGap)), &x, &y);
5044 XtSetArg(args[j], XtNx, x); j++;
5045 XtSetArg(args[j], XtNy, y); j++;
5046 XtSetValues(promotionShell, args, j);
5048 XtPopup(promotionShell, XtGrabNone);
5053 void PromotionPopDown()
5055 if (!promotionUp) return;
5056 XtPopdown(promotionShell);
5057 XtDestroyWidget(promotionShell);
5058 promotionUp = False;
5061 void PromotionCallback(w, client_data, call_data)
5063 XtPointer client_data, call_data;
5069 XtSetArg(args[0], XtNlabel, &name);
5070 XtGetValues(w, args, 1);
5074 if (fromX == -1) return;
5076 if (strcmp(name, _("cancel")) == 0) {
5080 } else if (strcmp(name, _("Knight")) == 0) {
5082 } else if (strcmp(name, _("Promote")) == 0) {
5084 } else if (strcmp(name, _("Defer")) == 0) {
5087 promoChar = ToLower(name[0]);
5090 UserMoveEvent(fromX, fromY, toX, toY, promoChar);
5092 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
5093 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
5098 void ErrorCallback(w, client_data, call_data)
5100 XtPointer client_data, call_data;
5103 XtPopdown(w = XtParent(XtParent(XtParent(w))));
5105 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5111 if (!errorUp) return;
5115 gtk_widget_destroy(GTK_WIDGET(GUI_Error));
5117 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5122 void ErrorPopUp(title, label, modal)
5123 char *title, *label;
5126 GUI_Error = gtk_message_dialog_new(GTK_WINDOW(GUI_Window),
5127 GTK_DIALOG_DESTROY_WITH_PARENT,
5132 gtk_window_set_title(GTK_WINDOW(GUI_Error),(gchar *) title);
5135 gtk_dialog_run(GTK_DIALOG(GUI_Error));
5136 gtk_widget_destroy(GTK_WIDGET(GUI_Error));
5140 g_signal_connect_swapped (GUI_Error, "response",
5141 G_CALLBACK (ErrorPopDownProc),
5144 gtk_widget_show(GTK_WIDGET(GUI_Error));
5150 /* Disable all user input other than deleting the window */
5151 static int frozen = 0;
5155 /* Grab by a widget that doesn't accept input */
5156 // XtAddGrab(messageWidget, TRUE, FALSE);
5160 /* Undo a FreezeUI */
5163 if (!frozen) return;
5164 // XtRemoveGrab(messageWidget);
5168 char *ModeToWidgetName(mode)
5172 case BeginningOfGame:
5173 if (appData.icsActive)
5174 return "menuMode.ICS Client";
5175 else if (appData.noChessProgram ||
5176 *appData.cmailGameName != NULLCHAR)
5177 return "menuMode.Edit Game";
5179 return "menuMode.Machine Black";
5180 case MachinePlaysBlack:
5181 return "menuMode.Machine Black";
5182 case MachinePlaysWhite:
5183 return "menuMode.Machine White";
5185 return "menuMode.Analysis Mode";
5187 return "menuMode.Analyze File";
5188 case TwoMachinesPlay:
5189 return "menuMode.Two Machines";
5191 return "menuMode.Edit Game";
5192 case PlayFromGameFile:
5193 return "menuFile.Load Game";
5195 return "menuMode.Edit Position";
5197 return "menuMode.Training";
5198 case IcsPlayingWhite:
5199 case IcsPlayingBlack:
5203 return "menuMode.ICS Client";
5210 void ModeHighlight()
5212 static int oldPausing = FALSE;
5213 static GameMode oldmode = (GameMode) -1;
5216 // todo this toggling of the pause button doesn't seem to work?
5217 // e.g. select pause from buttonbar doesn't activate menumode.pause
5219 // if (!boardWidget || !XtIsRealized(boardWidget)) return;
5221 if (pausing != oldPausing) {
5222 oldPausing = pausing;
5223 gtk_button_set_relief(GTK_BUTTON (gtk_builder_get_object (builder, "menuMode.Pause")),pausing?GTK_RELIEF_NORMAL:GTK_RELIEF_NONE);
5224 /* toggle background color in showbuttonbar */
5225 if (appData.showButtonBar) {
5227 gtk_button_pressed(GTK_BUTTON (gtk_builder_get_object (builder, "buttonbar.Pause")));
5229 gtk_button_released(GTK_BUTTON (gtk_builder_get_object (builder, "buttonbar.Pause")));
5234 wname = ModeToWidgetName(oldmode);
5236 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, wname)),True);
5240 /* Maybe all the enables should be handled here, not just this one */
5241 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuMode.Training")),
5242 gameMode == Training || gameMode == PlayFromGameFile);
5247 * Button/menu procedures
5250 int LoadGamePopUp(f, gameNumber, title)
5255 cmailMsgLoaded = FALSE;
5256 if (gameNumber == 0) {
5257 int error = GameListBuild(f);
5259 DisplayError(_("Cannot build game list"), error);
5260 } else if (!ListEmpty(&gameList) &&
5261 ((ListGame *) gameList.tailPred)->number > 1) {
5262 GameListPopUp(f, title);
5268 return LoadGame(f, gameNumber, title, FALSE);
5272 void LoadNextPositionProc(w, event, prms, nprms)
5281 void LoadPrevPositionProc(w, event, prms, nprms)
5290 void ReloadPositionProc(w, event, prms, nprms)
5299 void LoadPositionProc(w, event, prms, nprms)
5305 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
5308 FileNamePopUp(_("Load position file name?"), "", LoadPosition, "rb");
5311 void SaveGameProc(w, event, prms, nprms)
5317 FileNamePopUp(_("Save game file name?"),
5318 DefaultFileName(appData.oldSaveStyle ? "game" : "pgn"),
5322 void SavePositionProc(w, event, prms, nprms)
5328 FileNamePopUp(_("Save position file name?"),
5329 DefaultFileName(appData.oldSaveStyle ? "pos" : "fen"),
5333 void ReloadCmailMsgProc(w, event, prms, nprms)
5339 ReloadCmailMsgEvent(FALSE);
5342 void MailMoveProc(w, event, prms, nprms)
5351 /* this variable is shared between CopyPositionProc and SendPositionSelection */
5352 static char *selected_fen_position=NULL;
5355 SendPositionSelection(Widget w, Atom *selection, Atom *target,
5356 Atom *type_return, XtPointer *value_return,
5357 unsigned long *length_return, int *format_return)
5359 char *selection_tmp;
5361 if (!selected_fen_position) return False; /* should never happen */
5362 if (*target == XA_STRING){
5363 /* note: since no XtSelectionDoneProc was registered, Xt will
5364 * automatically call XtFree on the value returned. So have to
5365 * make a copy of it allocated with XtMalloc */
5366 selection_tmp= XtMalloc(strlen(selected_fen_position)+16);
5367 strcpy(selection_tmp, selected_fen_position);
5369 *value_return=selection_tmp;
5370 *length_return=strlen(selection_tmp);
5371 *type_return=XA_STRING;
5372 *format_return = 8; /* bits per byte */
5379 /* note: when called from menu all parameters are NULL, so no clue what the
5380 * Widget which was clicked on was, or what the click event was
5382 void CopyPositionProc(w, event, prms, nprms)
5390 if (selected_fen_position) free(selected_fen_position);
5391 selected_fen_position = (char *)PositionToFEN(currentMove, NULL);
5392 if (!selected_fen_position) return;
5393 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
5395 SendPositionSelection,
5396 NULL/* lose_ownership_proc */ ,
5397 NULL/* transfer_done_proc */);
5399 free(selected_fen_position);
5400 selected_fen_position=NULL;
5404 /* function called when the data to Paste is ready */
5406 PastePositionCB(Widget w, XtPointer client_data, Atom *selection,
5407 Atom *type, XtPointer value, unsigned long *len, int *format)
5410 if (value==NULL || *len==0) return; /* nothing had been selected to copy */
5411 fenstr[*len]='\0'; /* normally this string is terminated, but be safe */
5412 EditPositionPasteFEN(fenstr);
5416 /* called when Paste Position button is pressed,
5417 * all parameters will be NULL */
5418 void PastePositionProc(w, event, prms, nprms)
5424 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
5425 /* (XtSelectionCallbackProc) */ PastePositionCB,
5426 NULL, /* client_data passed to PastePositionCB */
5428 /* better to use the time field from the event that triggered the
5429 * call to this function, but that isn't trivial to get
5437 SendGameSelection(Widget w, Atom *selection, Atom *target,
5438 Atom *type_return, XtPointer *value_return,
5439 unsigned long *length_return, int *format_return)
5441 char *selection_tmp;
5443 if (*target == XA_STRING){
5444 FILE* f = fopen(gameCopyFilename, "r");
5447 if (f == NULL) return False;
5451 selection_tmp = XtMalloc(len + 1);
5452 count = fread(selection_tmp, 1, len, f);
5454 XtFree(selection_tmp);
5457 selection_tmp[len] = NULLCHAR;
5458 *value_return = selection_tmp;
5459 *length_return = len;
5460 *type_return = XA_STRING;
5461 *format_return = 8; /* bits per byte */
5468 /* note: when called from menu all parameters are NULL, so no clue what the
5469 * Widget which was clicked on was, or what the click event was
5471 void CopyGameProc(w, event, prms, nprms)
5479 ret = SaveGameToFile(gameCopyFilename, FALSE);
5482 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
5485 NULL/* lose_ownership_proc */ ,
5486 NULL/* transfer_done_proc */);
5489 /* function called when the data to Paste is ready */
5491 PasteGameCB(Widget w, XtPointer client_data, Atom *selection,
5492 Atom *type, XtPointer value, unsigned long *len, int *format)
5495 if (value == NULL || *len == 0) {
5496 return; /* nothing had been selected to copy */
5498 f = fopen(gamePasteFilename, "w");
5500 DisplayError(_("Can't open temp file"), errno);
5503 fwrite(value, 1, *len, f);
5506 LoadGameFromFile(gamePasteFilename, 0, gamePasteFilename, TRUE);
5509 /* called when Paste Game button is pressed,
5510 * all parameters will be NULL */
5511 void PasteGameProc(w, event, prms, nprms)
5517 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
5518 /* (XtSelectionCallbackProc) */ PasteGameCB,
5519 NULL, /* client_data passed to PasteGameCB */
5521 /* better to use the time field from the event that triggered the
5522 * call to this function, but that isn't trivial to get
5532 SaveGameProc(NULL, NULL, NULL, NULL);
5535 void MachineBlackProc(w, event, prms, nprms)
5541 MachineBlackEvent();
5544 void MachineWhiteProc(w, event, prms, nprms)
5550 MachineWhiteEvent();
5553 void AnalyzeModeProc(w, event, prms, nprms)
5561 if (!first.analysisSupport) {
5562 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
5563 DisplayError(buf, 0);
5566 /* [DM] icsEngineAnalyze [HGM] This is horrible code; reverse the gameMode and isEngineAnalyze tests! */
5567 if (appData.icsActive) {
5568 if (gameMode != IcsObserving) {
5569 sprintf(buf,_("You are not observing a game"));
5570 DisplayError(buf, 0);
5572 if (appData.icsEngineAnalyze) {
5573 if (appData.debugMode)
5574 fprintf(debugFP, _("Found unexpected active ICS engine analyze \n"));
5580 /* if enable, use want disable icsEngineAnalyze */
5581 if (appData.icsEngineAnalyze) {
5586 appData.icsEngineAnalyze = TRUE;
5587 if (appData.debugMode)
5588 fprintf(debugFP, _("ICS engine analyze starting... \n"));
5590 if (!appData.showThinking)
5591 ShowThinkingProc(w,event,prms,nprms);
5596 void AnalyzeFileProc(w, event, prms, nprms)
5602 if (!first.analysisSupport) {
5604 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
5605 DisplayError(buf, 0);
5610 if (!appData.showThinking)
5611 ShowThinkingProc(w,event,prms,nprms);
5614 FileNamePopUp(_("File to analyze"), "", LoadGamePopUp, "rb");
5615 AnalysisPeriodicEvent(1);
5618 void TwoMachinesProc(w, event, prms, nprms)
5627 void IcsClientProc(w, event, prms, nprms)
5636 void EditGameProc(w, event, prms, nprms)
5645 void EditPositionProc(w, event, prms, nprms)
5651 EditPositionEvent();
5654 void TrainingProc(w, event, prms, nprms)
5663 void EditCommentProc(w, event, prms, nprms)
5670 EditCommentPopDown();
5676 void IcsInputBoxProc(w, event, prms, nprms)
5682 if (ICSInputBoxUp) {
5683 ICSInputBoxPopDown();
5689 void AcceptProc(w, event, prms, nprms)
5698 void DeclineProc(w, event, prms, nprms)
5707 void RematchProc(w, event, prms, nprms)
5716 void CallFlagProc(w, event, prms, nprms)
5725 void DrawProc(w, event, prms, nprms)
5734 void AbortProc(w, event, prms, nprms)
5743 void AdjournProc(w, event, prms, nprms)
5752 void ResignProc(w, event, prms, nprms)
5761 void AdjuWhiteProc(w, event, prms, nprms)
5767 UserAdjudicationEvent(+1);
5770 void AdjuBlackProc(w, event, prms, nprms)
5776 UserAdjudicationEvent(-1);
5779 void AdjuDrawProc(w, event, prms, nprms)
5785 UserAdjudicationEvent(0);
5788 void EnterKeyProc(w, event, prms, nprms)
5794 if (ICSInputBoxUp == True)
5798 void StopObservingProc(w, event, prms, nprms)
5804 StopObservingEvent();
5807 void StopExaminingProc(w, event, prms, nprms)
5813 StopExaminingEvent();
5817 void ForwardProc(w, event, prms, nprms)
5827 void BackwardProc(w, event, prms, nprms)
5836 void ToStartProc(w, event, prms, nprms)
5845 void ToEndProc(w, event, prms, nprms)
5854 void RevertProc(w, event, prms, nprms)
5863 void TruncateGameProc(w, event, prms, nprms)
5869 TruncateGameEvent();
5871 void RetractMoveProc(w, event, prms, nprms)
5880 void MoveNowProc(w, event, prms, nprms)
5890 void AlwaysQueenProc(w, event, prms, nprms)
5898 appData.alwaysPromoteToQueen = !appData.alwaysPromoteToQueen;
5900 if (appData.alwaysPromoteToQueen) {
5901 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5903 XtSetArg(args[0], XtNleftBitmap, None);
5905 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
5909 void AnimateDraggingProc(w, event, prms, nprms)
5917 appData.animateDragging = !appData.animateDragging;
5919 if (appData.animateDragging) {
5920 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5923 XtSetArg(args[0], XtNleftBitmap, None);
5925 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Dragging"),
5929 void AnimateMovingProc(w, event, prms, nprms)
5937 appData.animate = !appData.animate;
5939 if (appData.animate) {
5940 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5943 XtSetArg(args[0], XtNleftBitmap, None);
5945 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
5949 void AutocommProc(w, event, prms, nprms)
5957 appData.autoComment = !appData.autoComment;
5959 if (appData.autoComment) {
5960 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5962 XtSetArg(args[0], XtNleftBitmap, None);
5964 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
5969 void AutoflagProc(w, event, prms, nprms)
5977 appData.autoCallFlag = !appData.autoCallFlag;
5979 if (appData.autoCallFlag) {
5980 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5982 XtSetArg(args[0], XtNleftBitmap, None);
5984 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
5988 void AutoflipProc(w, event, prms, nprms)
5996 appData.autoFlipView = !appData.autoFlipView;
5998 if (appData.autoFlipView) {
5999 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6001 XtSetArg(args[0], XtNleftBitmap, None);
6003 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flip View"),
6007 void AutobsProc(w, event, prms, nprms)
6015 appData.autoObserve = !appData.autoObserve;
6017 if (appData.autoObserve) {
6018 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6020 XtSetArg(args[0], XtNleftBitmap, None);
6022 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
6026 void AutoraiseProc(w, event, prms, nprms)
6034 appData.autoRaiseBoard = !appData.autoRaiseBoard;
6036 if (appData.autoRaiseBoard) {
6037 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6039 XtSetArg(args[0], XtNleftBitmap, None);
6041 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Raise Board"),
6045 void AutosaveProc(w, event, prms, nprms)
6053 appData.autoSaveGames = !appData.autoSaveGames;
6055 if (appData.autoSaveGames) {
6056 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6058 XtSetArg(args[0], XtNleftBitmap, None);
6060 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
6064 void BlindfoldProc(w, event, prms, nprms)
6072 appData.blindfold = !appData.blindfold;
6074 if (appData.blindfold) {
6075 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6077 XtSetArg(args[0], XtNleftBitmap, None);
6079 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Blindfold"),
6082 DrawPosition(True, NULL);
6085 void TestLegalityProc(w, event, prms, nprms)
6093 appData.testLegality = !appData.testLegality;
6095 if (appData.testLegality) {
6096 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6098 XtSetArg(args[0], XtNleftBitmap, None);
6100 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Test Legality"),
6105 void FlashMovesProc(w, event, prms, nprms)
6113 if (appData.flashCount == 0) {
6114 appData.flashCount = 3;
6116 appData.flashCount = -appData.flashCount;
6119 if (appData.flashCount > 0) {
6120 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6122 XtSetArg(args[0], XtNleftBitmap, None);
6124 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flash Moves"),
6128 void FlipViewProc(w, event, prms, nprms)
6134 flipView = !flipView;
6135 DrawPosition(True, NULL);
6138 void GetMoveListProc(w, event, prms, nprms)
6146 appData.getMoveList = !appData.getMoveList;
6148 if (appData.getMoveList) {
6149 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6152 XtSetArg(args[0], XtNleftBitmap, None);
6154 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
6159 void HighlightDraggingProc(w, event, prms, nprms)
6167 appData.highlightDragging = !appData.highlightDragging;
6169 if (appData.highlightDragging) {
6170 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6172 XtSetArg(args[0], XtNleftBitmap, None);
6174 XtSetValues(XtNameToWidget(menuBarWidget,
6175 "menuOptions.Highlight Dragging"), args, 1);
6179 void HighlightLastMoveProc(w, event, prms, nprms)
6187 appData.highlightLastMove = !appData.highlightLastMove;
6189 if (appData.highlightLastMove) {
6190 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6192 XtSetArg(args[0], XtNleftBitmap, None);
6194 XtSetValues(XtNameToWidget(menuBarWidget,
6195 "menuOptions.Highlight Last Move"), args, 1);
6198 void IcsAlarmProc(w, event, prms, nprms)
6206 appData.icsAlarm = !appData.icsAlarm;
6208 if (appData.icsAlarm) {
6209 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6211 XtSetArg(args[0], XtNleftBitmap, None);
6213 XtSetValues(XtNameToWidget(menuBarWidget,
6214 "menuOptions.ICS Alarm"), args, 1);
6217 void MoveSoundProc(w, event, prms, nprms)
6225 appData.ringBellAfterMoves = !appData.ringBellAfterMoves;
6227 if (appData.ringBellAfterMoves) {
6228 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6230 XtSetArg(args[0], XtNleftBitmap, None);
6232 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
6237 void OldSaveStyleProc(w, event, prms, nprms)
6245 appData.oldSaveStyle = !appData.oldSaveStyle;
6247 if (appData.oldSaveStyle) {
6248 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6250 XtSetArg(args[0], XtNleftBitmap, None);
6252 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Old Save Style"),
6256 void PeriodicUpdatesProc(w, event, prms, nprms)
6264 PeriodicUpdatesEvent(!appData.periodicUpdates);
6266 if (appData.periodicUpdates) {
6267 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6269 XtSetArg(args[0], XtNleftBitmap, None);
6271 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Periodic Updates"),
6275 void PonderNextMoveProc(w, event, prms, nprms)
6283 PonderNextMoveEvent(!appData.ponderNextMove);
6285 if (appData.ponderNextMove) {
6286 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6288 XtSetArg(args[0], XtNleftBitmap, None);
6290 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Ponder Next Move"),
6294 void PopupExitMessageProc(w, event, prms, nprms)
6302 appData.popupExitMessage = !appData.popupExitMessage;
6304 if (appData.popupExitMessage) {
6305 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6307 XtSetArg(args[0], XtNleftBitmap, None);
6309 XtSetValues(XtNameToWidget(menuBarWidget,
6310 "menuOptions.Popup Exit Message"), args, 1);
6313 void PopupMoveErrorsProc(w, event, prms, nprms)
6321 appData.popupMoveErrors = !appData.popupMoveErrors;
6323 if (appData.popupMoveErrors) {
6324 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6326 XtSetArg(args[0], XtNleftBitmap, None);
6328 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Popup Move Errors"),
6332 void PremoveProc(w, event, prms, nprms)
6340 appData.premove = !appData.premove;
6342 if (appData.premove) {
6343 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6345 XtSetArg(args[0], XtNleftBitmap, None);
6347 XtSetValues(XtNameToWidget(menuBarWidget,
6348 "menuOptions.Premove"), args, 1);
6351 void QuietPlayProc(w, event, prms, nprms)
6359 appData.quietPlay = !appData.quietPlay;
6361 if (appData.quietPlay) {
6362 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6364 XtSetArg(args[0], XtNleftBitmap, None);
6366 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Quiet Play"),
6370 void ShowThinkingProc(w, event, prms, nprms)
6378 appData.showThinking = !appData.showThinking; // [HGM] thinking: tken out of ShowThinkingEvent
6379 ShowThinkingEvent();
6381 // [HGM] thinking: currently no suc menu item; replaced by Hide Thinking (From Human)
6382 if (appData.showThinking) {
6383 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6385 XtSetArg(args[0], XtNleftBitmap, None);
6387 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Thinking"),
6392 void HideThinkingProc(w, event, prms, nprms)
6400 appData.hideThinkingFromHuman = !appData.hideThinkingFromHuman; // [HGM] thinking: tken out of ShowThinkingEvent
6401 ShowThinkingEvent();
6403 if (appData.hideThinkingFromHuman) {
6404 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6406 XtSetArg(args[0], XtNleftBitmap, None);
6408 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
6412 void InfoProc(w, event, prms, nprms)
6419 snprintf(buf, sizeof(buf), "xterm -e info --directory %s --directory . -f %s &",
6424 void ManProc(w, event, prms, nprms)
6432 if (nprms && *nprms > 0)
6436 snprintf(buf, sizeof(buf), "xterm -e man %s &", name);
6440 void HintProc(w, event, prms, nprms)
6449 void BookProc(w, event, prms, nprms)
6458 void DebugProc(w, event, prms, nprms)
6464 appData.debugMode = !appData.debugMode;
6467 void AboutGameProc(w, event, prms, nprms)
6476 void NothingProc(w, event, prms, nprms)
6485 void Iconify(w, event, prms, nprms)
6494 XtSetArg(args[0], XtNiconic, True);
6495 XtSetValues(shellWidget, args, 1);
6498 void DisplayMessage(message, extMessage)
6499 gchar *message, *extMessage;
6506 snprintf(buf, sizeof(buf), "%s %s", message, extMessage);
6509 message = extMessage;
6512 gtk_label_set_text( GTK_LABEL(gtk_builder_get_object (builder, "Messages")),message);
6517 void DisplayTitle(text)
6520 gchar title[MSG_SIZ];
6522 if (text == NULL) text = "";
6524 if (appData.titleInWindow)
6529 if (*text != NULLCHAR)
6531 strcpy(title, text);
6533 else if (appData.icsActive)
6535 snprintf(title, sizeof(title), "%s: %s", programName, appData.icsHost);
6537 else if (appData.cmailGameName[0] != NULLCHAR)
6539 snprintf(title,sizeof(title), "%s: %s", programName, "CMail");
6541 // [HGM] license: This stuff should really be done in back-end, but WinBoard already had a pop-up for it
6543 else if (gameInfo.variant == VariantGothic)
6545 strcpy(title, GOTHIC);
6549 else if (gameInfo.variant == VariantFalcon)
6551 strcpy(title, FALCON);
6554 else if (appData.noChessProgram)
6556 strcpy(title, programName);
6560 snprintf(title,sizeof(title), "%s: %s", programName, first.tidy);
6562 gtk_window_set_title(GTK_WINDOW(GUI_Window),title);
6568 void DisplayError(message, error)
6575 if (appData.debugMode || appData.matchMode) {
6576 fprintf(stderr, "%s: %s\n", programName, message);
6579 if (appData.debugMode || appData.matchMode) {
6580 fprintf(stderr, "%s: %s: %s\n",
6581 programName, message, strerror(error));
6583 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
6586 ErrorPopUp(_("Error"), message, FALSE);
6590 void DisplayMoveError(message)
6595 DrawPosition(FALSE, NULL);
6596 if (appData.debugMode || appData.matchMode) {
6597 fprintf(stderr, "%s: %s\n", programName, message);
6599 if (appData.popupMoveErrors) {
6600 ErrorPopUp(_("Error"), message, FALSE);
6602 DisplayMessage(message, "");
6607 void DisplayFatalError(message, error, status)
6613 errorExitStatus = status;
6615 fprintf(stderr, "%s: %s\n", programName, message);
6617 fprintf(stderr, "%s: %s: %s\n",
6618 programName, message, strerror(error));
6619 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
6622 if (appData.popupExitMessage && boardWidget && XtIsRealized(boardWidget)) {
6623 ErrorPopUp(status ? _("Fatal Error") : _("Exiting"), message, TRUE);
6629 void DisplayInformation(message)
6633 ErrorPopUp(_("Information"), message, TRUE);
6636 void DisplayNote(message)
6640 ErrorPopUp(_("Note"), message, FALSE);
6644 NullXErrorCheck(dpy, error_event)
6646 XErrorEvent *error_event;
6651 void DisplayIcsInteractionTitle(message)
6654 if (oldICSInteractionTitle == NULL) {
6655 /* Magic to find the old window title, adapted from vim */
6656 char *wina = getenv("WINDOWID");
6658 Window win = (Window) atoi(wina);
6659 Window root, parent, *children;
6660 unsigned int nchildren;
6661 int (*oldHandler)() = XSetErrorHandler(NullXErrorCheck);
6663 if (XFetchName(xDisplay, win, &oldICSInteractionTitle)) break;
6664 if (!XQueryTree(xDisplay, win, &root, &parent,
6665 &children, &nchildren)) break;
6666 if (children) XFree((void *)children);
6667 if (parent == root || parent == 0) break;
6670 XSetErrorHandler(oldHandler);
6672 if (oldICSInteractionTitle == NULL) {
6673 oldICSInteractionTitle = "xterm";
6676 printf("\033]0;%s\007", message);
6680 char pendingReplyPrefix[MSG_SIZ];
6681 ProcRef pendingReplyPR;
6683 void AskQuestionProc(w, event, prms, nprms)
6690 fprintf(stderr, _("AskQuestionProc needed 4 parameters, got %d\n"),
6694 AskQuestionEvent(prms[0], prms[1], prms[2], prms[3]);
6697 void AskQuestionPopDown()
6699 if (!askQuestionUp) return;
6700 XtPopdown(askQuestionShell);
6701 XtDestroyWidget(askQuestionShell);
6702 askQuestionUp = False;
6705 void AskQuestionReplyAction(w, event, prms, nprms)
6715 reply = XawDialogGetValueString(w = XtParent(w));
6716 strcpy(buf, pendingReplyPrefix);
6717 if (*buf) strcat(buf, " ");
6720 OutputToProcess(pendingReplyPR, buf, strlen(buf), &err);
6721 AskQuestionPopDown();
6723 if (err) DisplayFatalError(_("Error writing to chess program"), err, 0);
6726 void AskQuestionCallback(w, client_data, call_data)
6728 XtPointer client_data, call_data;
6733 XtSetArg(args[0], XtNlabel, &name);
6734 XtGetValues(w, args, 1);
6736 if (strcmp(name, _("cancel")) == 0) {
6737 AskQuestionPopDown();
6739 AskQuestionReplyAction(w, NULL, NULL, NULL);
6743 void AskQuestion(title, question, replyPrefix, pr)
6744 char *title, *question, *replyPrefix;
6748 Widget popup, layout, dialog, edit;
6754 strcpy(pendingReplyPrefix, replyPrefix);
6755 pendingReplyPR = pr;
6758 XtSetArg(args[i], XtNresizable, True); i++;
6759 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
6760 askQuestionShell = popup =
6761 XtCreatePopupShell(title, transientShellWidgetClass,
6762 shellWidget, args, i);
6765 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
6766 layoutArgs, XtNumber(layoutArgs));
6769 XtSetArg(args[i], XtNlabel, question); i++;
6770 XtSetArg(args[i], XtNvalue, ""); i++;
6771 XtSetArg(args[i], XtNborderWidth, 0); i++;
6772 dialog = XtCreateManagedWidget("question", dialogWidgetClass,
6775 XawDialogAddButton(dialog, _("enter"), AskQuestionCallback,
6776 (XtPointer) dialog);
6777 XawDialogAddButton(dialog, _("cancel"), AskQuestionCallback,
6778 (XtPointer) dialog);
6780 XtRealizeWidget(popup);
6781 CatchDeleteWindow(popup, "AskQuestionPopDown");
6783 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
6784 &x, &y, &win_x, &win_y, &mask);
6786 XtSetArg(args[0], XtNx, x - 10);
6787 XtSetArg(args[1], XtNy, y - 30);
6788 XtSetValues(popup, args, 2);
6790 XtPopup(popup, XtGrabExclusive);
6791 askQuestionUp = True;
6793 edit = XtNameToWidget(dialog, "*value");
6794 XtSetKeyboardFocus(popup, edit);
6802 if (*name == NULLCHAR) {
6804 } else if (strcmp(name, "$") == 0) {
6805 putc(BELLCHAR, stderr);
6808 snprintf(buf, sizeof(buf), "%s '%s' &", appData.soundProgram, name);
6816 PlaySound(appData.soundMove);
6822 PlaySound(appData.soundIcsWin);
6828 PlaySound(appData.soundIcsLoss);
6834 PlaySound(appData.soundIcsDraw);
6838 PlayIcsUnfinishedSound()
6840 PlaySound(appData.soundIcsUnfinished);
6846 PlaySound(appData.soundIcsAlarm);
6852 system("stty echo");
6858 system("stty -echo");
6862 Colorize(cc, continuation)
6867 int count, outCount, error;
6869 if (textColors[(int)cc].bg > 0) {
6870 if (textColors[(int)cc].fg > 0) {
6871 sprintf(buf, "\033[0;%d;%d;%dm", textColors[(int)cc].attr,
6872 textColors[(int)cc].fg, textColors[(int)cc].bg);
6874 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
6875 textColors[(int)cc].bg);
6878 if (textColors[(int)cc].fg > 0) {
6879 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
6880 textColors[(int)cc].fg);
6882 sprintf(buf, "\033[0;%dm", textColors[(int)cc].attr);
6885 count = strlen(buf);
6886 outCount = OutputToProcess(NoProc, buf, count, &error);
6887 if (outCount < count) {
6888 DisplayFatalError(_("Error writing to display"), error, 1);
6891 if (continuation) return;
6894 PlaySound(appData.soundShout);
6897 PlaySound(appData.soundSShout);
6900 PlaySound(appData.soundChannel1);
6903 PlaySound(appData.soundChannel);
6906 PlaySound(appData.soundKibitz);
6909 PlaySound(appData.soundTell);
6911 case ColorChallenge:
6912 PlaySound(appData.soundChallenge);
6915 PlaySound(appData.soundRequest);
6918 PlaySound(appData.soundSeek);
6929 return getpwuid(getuid())->pw_name;
6932 static char *ExpandPathName(path)
6935 static char static_buf[2000];
6936 char *d, *s, buf[2000];
6942 while (*s && isspace(*s))
6951 if (*(s+1) == '/') {
6952 strcpy(d, getpwuid(getuid())->pw_dir);
6957 *strchr(buf, '/') = 0;
6958 pwd = getpwnam(buf);
6961 fprintf(stderr, _("ERROR: Unknown user %s (in path %s)\n"),
6965 strcpy(d, pwd->pw_dir);
6966 strcat(d, strchr(s+1, '/'));
6977 static char host_name[MSG_SIZ];
6979 #if HAVE_GETHOSTNAME
6980 gethostname(host_name, MSG_SIZ);
6982 #else /* not HAVE_GETHOSTNAME */
6983 # if HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H
6984 sysinfo(SI_HOSTNAME, host_name, MSG_SIZ);
6986 # else /* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
6988 # endif/* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
6989 #endif /* not HAVE_GETHOSTNAME */
6992 gint delayedEventTimerTag = 0;
6993 DelayedEventCallback delayedEventCallback = 0;
6996 FireDelayedEvent(data)
6999 delayedEventTimerTag = 0;
7000 delayedEventCallback();
7004 ScheduleDelayedEvent(cb, millisec)
7005 DelayedEventCallback cb; long millisec;
7007 delayedEventCallback = cb;
7008 delayedEventTimerTag = 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;
7036 gint loadGameTimerTag = 0;
7038 int LoadGameTimerRunning()
7040 return loadGameTimerTag != 0;
7043 int StopLoadGameTimer()
7045 if (loadGameTimerTag != 0) {
7046 gtk_timeout_remove(loadGameTimerTag);
7047 loadGameTimerTag = 0;
7055 LoadGameTimerCallback(data)
7058 loadGameTimerTag = 0;
7063 StartLoadGameTimer(millisec)
7067 gtk_timeout_add( millisec, (GtkFunction) LoadGameTimerCallback, NULL);
7070 gint analysisClockTag = 0;
7073 AnalysisClockCallback(data)
7076 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile
7077 || appData.icsEngineAnalyze)
7079 AnalysisPeriodicEvent(0);
7080 StartAnalysisClock();
7085 StartAnalysisClock()
7088 gtk_timeout_add( 2000,(GtkFunction) AnalysisClockCallback, NULL);
7091 gint clockTimerTag = 0;
7093 int ClockTimerRunning()
7095 return clockTimerTag != 0;
7098 int StopClockTimer()
7100 if (clockTimerTag != 0)
7102 gtk_timeout_remove(clockTimerTag);
7113 ClockTimerCallback(data)
7122 StartClockTimer(millisec)
7125 clockTimerTag = gtk_timeout_add(millisec,(GtkFunction) ClockTimerCallback,NULL);
7130 DisplayTimerLabel(w, color, timer, highlight)
7139 if (appData.clockMode) {
7140 sprintf(buf, "%s: %s", color, TimeString(timer));
7142 sprintf(buf, "%s ", color);
7144 gtk_label_set_text(GTK_LABEL(w),buf);
7146 /* check for low time warning */
7147 // Pixel foregroundOrWarningColor = timerForegroundPixel;
7150 // appData.lowTimeWarning &&
7151 // (timer / 1000) < appData.icsAlarmTime)
7152 // foregroundOrWarningColor = lowTimeWarningColor;
7154 // if (appData.clockMode) {
7155 // sprintf(buf, "%s: %s", color, TimeString(timer));
7156 // XtSetArg(args[0], XtNlabel, buf);
7158 // sprintf(buf, "%s ", color);
7159 // XtSetArg(args[0], XtNlabel, buf);
7164 // XtSetArg(args[1], XtNbackground, foregroundOrWarningColor);
7165 // XtSetArg(args[2], XtNforeground, timerBackgroundPixel);
7167 // XtSetArg(args[1], XtNbackground, timerBackgroundPixel);
7168 // XtSetArg(args[2], XtNforeground, foregroundOrWarningColor);
7171 // XtSetValues(w, args, 3);
7176 DisplayWhiteClock(timeRemaining, highlight)
7180 if(appData.noGUI) return;
7182 DisplayTimerLabel(GUI_Whiteclock, _("White"), timeRemaining, highlight);
7183 if (highlight && WindowIcon == BlackIcon)
7185 WindowIcon = WhiteIcon;
7186 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
7191 DisplayBlackClock(timeRemaining, highlight)
7195 if(appData.noGUI) return;
7197 DisplayTimerLabel(GUI_Blackclock, _("Black"), timeRemaining, highlight);
7198 if (highlight && WindowIcon == WhiteIcon)
7200 WindowIcon = BlackIcon;
7201 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
7219 int StartChildProcess(cmdLine, dir, pr)
7226 int to_prog[2], from_prog[2];
7230 if (appData.debugMode) {
7231 fprintf(stderr, "StartChildProcess (dir=\"%s\") %s\n",dir, cmdLine);
7234 /* We do NOT feed the cmdLine to the shell; we just
7235 parse it into blank-separated arguments in the
7236 most simple-minded way possible.
7239 strcpy(buf, cmdLine);
7244 if (p == NULL) break;
7249 SetUpChildIO(to_prog, from_prog);
7251 if ((pid = fork()) == 0) {
7253 // [HGM] PSWBTM: made order resistant against case where fd of created pipe was 0 or 1
7254 close(to_prog[1]); // first close the unused pipe ends
7255 close(from_prog[0]);
7256 dup2(to_prog[0], 0); // to_prog was created first, nd is the only one to use 0 or 1
7257 dup2(from_prog[1], 1);
7258 if(to_prog[0] >= 2) close(to_prog[0]); // if 0 or 1, the dup2 already cosed the original
7259 close(from_prog[1]); // and closing again loses one of the pipes!
7260 if(fileno(stderr) >= 2) // better safe than sorry...
7261 dup2(1, fileno(stderr)); /* force stderr to the pipe */
7263 if (dir[0] != NULLCHAR && chdir(dir) != 0) {
7268 nice(appData.niceEngines); // [HGM] nice: adjust priority of engine proc
7270 execvp(argv[0], argv);
7272 /* If we get here, exec failed */
7277 /* Parent process */
7279 close(from_prog[1]);
7281 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7284 cp->fdFrom = from_prog[0];
7285 cp->fdTo = to_prog[1];
7290 // [HGM] kill: implement the 'hard killing' of AS's Winboard_x
7291 static RETSIGTYPE AlarmCallBack(int n)
7297 DestroyChildProcess(pr, signalType)
7301 ChildProc *cp = (ChildProc *) pr;
7303 if (cp->kind != CPReal) return;
7305 if (signalType == 10) { // [HGM] kill: if it does not terminate in 3 sec, kill
7306 signal(SIGALRM, AlarmCallBack);
7308 if(wait((int *) 0) == -1) { // process does not terminate on its own accord
7309 kill(cp->pid, SIGKILL); // kill it forcefully
7310 wait((int *) 0); // and wait again
7314 kill(cp->pid, signalType == 9 ? SIGKILL : SIGTERM); // [HGM] kill: use hard kill if so requested
7316 /* Process is exiting either because of the kill or because of
7317 a quit command sent by the backend; either way, wait for it to die.
7326 InterruptChildProcess(pr)
7329 ChildProc *cp = (ChildProc *) pr;
7331 if (cp->kind != CPReal) return;
7332 (void) kill(cp->pid, SIGINT); /* stop it thinking */
7335 int OpenTelnet(host, port, pr)
7340 char cmdLine[MSG_SIZ];
7342 if (port[0] == NULLCHAR) {
7343 snprintf(cmdLine, sizeof(cmdLine), "%s %s", appData.telnetProgram, host);
7345 snprintf(cmdLine, sizeof(cmdLine), "%s %s %s", appData.telnetProgram, host, port);
7347 return StartChildProcess(cmdLine, "", pr);
7350 int OpenTCP(host, port, pr)
7356 DisplayFatalError(_("Socket support is not configured in"), 0, 2);
7357 #else /* !OMIT_SOCKETS */
7359 struct sockaddr_in sa;
7361 unsigned short uport;
7364 if ((s = socket(AF_INET, SOCK_STREAM, 6)) < 0) {
7368 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
7369 sa.sin_family = AF_INET;
7370 sa.sin_addr.s_addr = INADDR_ANY;
7371 uport = (unsigned short) 0;
7372 sa.sin_port = htons(uport);
7373 if (bind(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)) < 0) {
7377 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
7378 if (!(hp = gethostbyname(host))) {
7380 if (sscanf(host, "%d.%d.%d.%d", &b0, &b1, &b2, &b3) == 4) {
7381 hp = (struct hostent *) calloc(1, sizeof(struct hostent));
7382 hp->h_addrtype = AF_INET;
7384 hp->h_addr_list = (char **) calloc(2, sizeof(char *));
7385 hp->h_addr_list[0] = (char *) malloc(4);
7386 hp->h_addr_list[0][0] = b0;
7387 hp->h_addr_list[0][1] = b1;
7388 hp->h_addr_list[0][2] = b2;
7389 hp->h_addr_list[0][3] = b3;
7394 sa.sin_family = hp->h_addrtype;
7395 uport = (unsigned short) atoi(port);
7396 sa.sin_port = htons(uport);
7397 memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);
7399 if (connect(s, (struct sockaddr *) &sa,
7400 sizeof(struct sockaddr_in)) < 0) {
7404 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7411 #endif /* !OMIT_SOCKETS */
7416 int OpenCommPort(name, pr)
7423 fd = open(name, 2, 0);
7424 if (fd < 0) return errno;
7426 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7436 int OpenLoopback(pr)
7442 SetUpChildIO(to, from);
7444 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7447 cp->fdFrom = to[0]; /* note not from[0]; we are doing a loopback */
7454 int OpenRcmd(host, user, cmd, pr)
7455 char *host, *user, *cmd;
7458 DisplayFatalError(_("internal rcmd not implemented for Unix"), 0, 1);
7462 #define INPUT_SOURCE_BUF_SIZE 8192
7471 char buf[INPUT_SOURCE_BUF_SIZE];
7476 DoInputCallback(closure, source, xid)
7481 InputSource *is = (InputSource *) closure;
7486 if (is->lineByLine) {
7487 count = read(is->fd, is->unused,
7488 INPUT_SOURCE_BUF_SIZE - (is->unused - is->buf));
7490 (is->func)(is, is->closure, is->buf, count, count ? errno : 0);
7493 is->unused += count;
7495 while (p < is->unused) {
7496 q = memchr(p, '\n', is->unused - p);
7497 if (q == NULL) break;
7499 (is->func)(is, is->closure, p, q - p, 0);
7503 while (p < is->unused) {
7508 count = read(is->fd, is->buf, INPUT_SOURCE_BUF_SIZE);
7513 (is->func)(is, is->closure, is->buf, count, error);
7517 InputSourceRef AddInputSource(pr, lineByLine, func, closure)
7524 ChildProc *cp = (ChildProc *) pr;
7526 is = (InputSource *) calloc(1, sizeof(InputSource));
7527 is->lineByLine = lineByLine;
7531 is->fd = fileno(stdin);
7533 is->kind = cp->kind;
7534 is->fd = cp->fdFrom;
7537 is->unused = is->buf;
7540 is->xid = XtAppAddInput(appContext, is->fd,
7541 (XtPointer) (XtInputReadMask),
7542 (XtInputCallbackProc) DoInputCallback,
7544 is->closure = closure;
7545 return (InputSourceRef) is;
7549 RemoveInputSource(isr)
7552 InputSource *is = (InputSource *) isr;
7554 if (is->xid == 0) return;
7555 XtRemoveInput(is->xid);
7559 int OutputToProcess(pr, message, count, outError)
7565 ChildProc *cp = (ChildProc *) pr;
7569 outCount = fwrite(message, 1, count, stdout);
7571 outCount = write(cp->fdTo, message, count);
7581 /* Output message to process, with "ms" milliseconds of delay
7582 between each character. This is needed when sending the logon
7583 script to ICC, which for some reason doesn't like the
7584 instantaneous send. */
7585 int OutputToProcessDelayed(pr, message, count, outError, msdelay)
7592 ChildProc *cp = (ChildProc *) pr;
7597 r = write(cp->fdTo, message++, 1);
7610 /**** Animation code by Hugh Fisher, DCS, ANU.
7612 Known problem: if a window overlapping the board is
7613 moved away while a piece is being animated underneath,
7614 the newly exposed area won't be updated properly.
7615 I can live with this.
7617 Known problem: if you look carefully at the animation
7618 of pieces in mono mode, they are being drawn as solid
7619 shapes without interior detail while moving. Fixing
7620 this would be a major complication for minimal return.
7623 /* Masks for XPM pieces. Black and white pieces can have
7624 different shapes, but in the interest of retaining my
7625 sanity pieces must have the same outline on both light
7626 and dark squares, and all pieces must use the same
7627 background square colors/images. */
7629 static int xpmDone = 0;
7632 CreateAnimMasks (pieceDepth)
7639 unsigned long plane;
7642 /* just return for gtk at the moment */
7645 /* Need a bitmap just to get a GC with right depth */
7646 buf = XCreatePixmap(xDisplay, xBoardWindow,
7648 values.foreground = 1;
7649 values.background = 0;
7650 /* Don't use XtGetGC, not read only */
7651 maskGC = XCreateGC(xDisplay, buf,
7652 GCForeground | GCBackground, &values);
7653 XFreePixmap(xDisplay, buf);
7655 buf = XCreatePixmap(xDisplay, xBoardWindow,
7656 squareSize, squareSize, pieceDepth);
7657 values.foreground = XBlackPixel(xDisplay, xScreen);
7658 values.background = XWhitePixel(xDisplay, xScreen);
7659 bufGC = XCreateGC(xDisplay, buf,
7660 GCForeground | GCBackground, &values);
7662 for (piece = WhitePawn; piece <= BlackKing; piece++) {
7663 /* Begin with empty mask */
7664 if(!xpmDone) // [HGM] pieces: keep using existing
7665 xpmMask[piece] = XCreatePixmap(xDisplay, xBoardWindow,
7666 squareSize, squareSize, 1);
7667 XSetFunction(xDisplay, maskGC, GXclear);
7668 XFillRectangle(xDisplay, xpmMask[piece], maskGC,
7669 0, 0, squareSize, squareSize);
7671 /* Take a copy of the piece */
7676 XSetFunction(xDisplay, bufGC, GXcopy);
7677 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn],
7679 0, 0, squareSize, squareSize, 0, 0);
7681 /* XOR the background (light) over the piece */
7682 XSetFunction(xDisplay, bufGC, GXxor);
7684 XCopyArea(xDisplay, xpmLightSquare, buf, bufGC,
7685 0, 0, squareSize, squareSize, 0, 0);
7687 XSetForeground(xDisplay, bufGC, lightSquareColor);
7688 XFillRectangle(xDisplay, buf, bufGC, 0, 0, squareSize, squareSize);
7691 /* We now have an inverted piece image with the background
7692 erased. Construct mask by just selecting all the non-zero
7693 pixels - no need to reconstruct the original image. */
7694 XSetFunction(xDisplay, maskGC, GXor);
7696 /* Might be quicker to download an XImage and create bitmap
7697 data from it rather than this N copies per piece, but it
7698 only takes a fraction of a second and there is a much
7699 longer delay for loading the pieces. */
7700 for (n = 0; n < pieceDepth; n ++) {
7701 XCopyPlane(xDisplay, buf, xpmMask[piece], maskGC,
7702 0, 0, squareSize, squareSize,
7708 XFreePixmap(xDisplay, buf);
7709 XFreeGC(xDisplay, bufGC);
7710 XFreeGC(xDisplay, maskGC);
7714 InitAnimState (anim, info)
7716 XWindowAttributes * info;
7721 /* Each buffer is square size, same depth as window */
7722 // anim->saveBuf = XCreatePixmap(xDisplay, xBoardWindow,
7723 // squareSize, squareSize, info->depth);
7724 // anim->newBuf = XCreatePixmap(xDisplay, xBoardWindow,
7725 // squareSize, squareSize, info->depth);
7727 // /* Create a plain GC for blitting */
7728 // mask = GCForeground | GCBackground | GCFunction |
7729 // GCPlaneMask | GCGraphicsExposures;
7730 // values.foreground = XBlackPixel(xDisplay, xScreen);
7731 // values.background = XWhitePixel(xDisplay, xScreen);
7732 // values.function = GXcopy;
7733 // values.plane_mask = AllPlanes;
7734 // values.graphics_exposures = False;
7735 // anim->blitGC = XCreateGC(xDisplay, xBoardWindow, mask, &values);
7737 // /* Piece will be copied from an existing context at
7738 // the start of each new animation/drag. */
7739 // anim->pieceGC = XCreateGC(xDisplay, xBoardWindow, 0, &values);
7741 // /* Outline will be a read-only copy of an existing */
7742 // anim->outlineGC = None;
7748 static VariantClass old = (VariantClass) -1; // [HGM] pieces: redo every time variant changes
7749 XWindowAttributes info;
7751 /* for gtk at the moment just ... */
7754 if (xpmDone && gameInfo.variant == old) return;
7755 if(xpmDone) old = gameInfo.variant; // first time pieces might not be created yet
7756 // XGetWindowAttributes(xDisplay, xBoardWindow, &info);
7758 // InitAnimState(&game, &info);
7759 // InitAnimState(&player, &info);
7761 /* For XPM pieces, we need bitmaps to use as masks. */
7763 // CreateAnimMasks(info.depth);
7769 static Boolean frameWaiting;
7771 static RETSIGTYPE FrameAlarm (sig)
7774 frameWaiting = False;
7775 /* In case System-V style signals. Needed?? */
7776 signal(SIGALRM, FrameAlarm);
7783 struct itimerval delay;
7785 XSync(xDisplay, False);
7788 frameWaiting = True;
7789 signal(SIGALRM, FrameAlarm);
7790 delay.it_interval.tv_sec =
7791 delay.it_value.tv_sec = time / 1000;
7792 delay.it_interval.tv_usec =
7793 delay.it_value.tv_usec = (time % 1000) * 1000;
7794 setitimer(ITIMER_REAL, &delay, NULL);
7796 /* Ugh -- busy-wait! --tpm */
7797 while (frameWaiting);
7799 while (frameWaiting) pause();
7801 delay.it_interval.tv_sec = delay.it_value.tv_sec = 0;
7802 delay.it_interval.tv_usec = delay.it_value.tv_usec = 0;
7803 setitimer(ITIMER_REAL, &delay, NULL);
7813 // XSync(xDisplay, False);
7815 usleep(time * 1000);
7820 /* Convert board position to corner of screen rect and color */
7823 ScreenSquare(column, row, pt, color)
7824 int column; int row; XPoint * pt; int * color;
7827 pt->x = lineGap + ((BOARD_WIDTH-1)-column) * (squareSize + lineGap);
7828 pt->y = lineGap + row * (squareSize + lineGap);
7830 pt->x = lineGap + column * (squareSize + lineGap);
7831 pt->y = lineGap + ((BOARD_HEIGHT-1)-row) * (squareSize + lineGap);
7833 *color = SquareColor(row, column);
7836 /* Convert window coords to square */
7839 BoardSquare(x, y, column, row)
7840 int x; int y; int * column; int * row;
7842 *column = EventToSquare(x, BOARD_WIDTH);
7843 if (flipView && *column >= 0)
7844 *column = BOARD_WIDTH - 1 - *column;
7845 *row = EventToSquare(y, BOARD_HEIGHT);
7846 if (!flipView && *row >= 0)
7847 *row = BOARD_HEIGHT - 1 - *row;
7852 #undef Max /* just in case */
7854 #define Max(a, b) ((a) > (b) ? (a) : (b))
7855 #define Min(a, b) ((a) < (b) ? (a) : (b))
7858 SetRect(rect, x, y, width, height)
7859 XRectangle * rect; int x; int y; int width; int height;
7863 rect->width = width;
7864 rect->height = height;
7867 /* Test if two frames overlap. If they do, return
7868 intersection rect within old and location of
7869 that rect within new. */
7872 Intersect(old, new, size, area, pt)
7873 XPoint * old; XPoint * new;
7874 int size; XRectangle * area; XPoint * pt;
7876 if (old->x > new->x + size || new->x > old->x + size ||
7877 old->y > new->y + size || new->y > old->y + size) {
7880 SetRect(area, Max(new->x - old->x, 0), Max(new->y - old->y, 0),
7881 size - abs(old->x - new->x), size - abs(old->y - new->y));
7882 pt->x = Max(old->x - new->x, 0);
7883 pt->y = Max(old->y - new->y, 0);
7888 /* For two overlapping frames, return the rect(s)
7889 in the old that do not intersect with the new. */
7892 CalcUpdateRects(old, new, size, update, nUpdates)
7893 XPoint * old; XPoint * new; int size;
7894 XRectangle update[]; int * nUpdates;
7898 /* If old = new (shouldn't happen) then nothing to draw */
7899 if (old->x == new->x && old->y == new->y) {
7903 /* Work out what bits overlap. Since we know the rects
7904 are the same size we don't need a full intersect calc. */
7906 /* Top or bottom edge? */
7907 if (new->y > old->y) {
7908 SetRect(&(update[count]), old->x, old->y, size, new->y - old->y);
7910 } else if (old->y > new->y) {
7911 SetRect(&(update[count]), old->x, old->y + size - (old->y - new->y),
7912 size, old->y - new->y);
7915 /* Left or right edge - don't overlap any update calculated above. */
7916 if (new->x > old->x) {
7917 SetRect(&(update[count]), old->x, Max(new->y, old->y),
7918 new->x - old->x, size - abs(new->y - old->y));
7920 } else if (old->x > new->x) {
7921 SetRect(&(update[count]), new->x + size, Max(new->y, old->y),
7922 old->x - new->x, size - abs(new->y - old->y));
7929 /* Generate a series of frame coords from start->mid->finish.
7930 The movement rate doubles until the half way point is
7931 reached, then halves back down to the final destination,
7932 which gives a nice slow in/out effect. The algorithmn
7933 may seem to generate too many intermediates for short
7934 moves, but remember that the purpose is to attract the
7935 viewers attention to the piece about to be moved and
7936 then to where it ends up. Too few frames would be less
7940 Tween(start, mid, finish, factor, frames, nFrames)
7941 XPoint * start; XPoint * mid;
7942 XPoint * finish; int factor;
7943 XPoint frames[]; int * nFrames;
7945 int fraction, n, count;
7949 /* Slow in, stepping 1/16th, then 1/8th, ... */
7951 for (n = 0; n < factor; n++)
7953 for (n = 0; n < factor; n++) {
7954 frames[count].x = start->x + (mid->x - start->x) / fraction;
7955 frames[count].y = start->y + (mid->y - start->y) / fraction;
7957 fraction = fraction / 2;
7961 frames[count] = *mid;
7964 /* Slow out, stepping 1/2, then 1/4, ... */
7966 for (n = 0; n < factor; n++) {
7967 frames[count].x = finish->x - (finish->x - mid->x) / fraction;
7968 frames[count].y = finish->y - (finish->y - mid->y) / fraction;
7970 fraction = fraction * 2;
7975 /* Draw a piece on the screen without disturbing what's there */
7978 SelectGCMask(piece, clip, outline, mask)
7979 ChessSquare piece; GC * clip; GC * outline; Pixmap * mask;
7983 /* Bitmap for piece being moved. */
7984 if (appData.monoMode) {
7985 *mask = *pieceToSolid(piece);
7986 } else if (useImages) {
7988 *mask = xpmMask[piece];
7990 *mask = ximMaskPm[piece];
7993 *mask = *pieceToSolid(piece);
7996 /* GC for piece being moved. Square color doesn't matter, but
7997 since it gets modified we make a copy of the original. */
7999 if (appData.monoMode)
8004 if (appData.monoMode)
8009 // XCopyGC(xDisplay, source, 0xFFFFFFFF, *clip);
8011 /* Outline only used in mono mode and is not modified */
8013 *outline = bwPieceGC;
8015 *outline = wbPieceGC;
8019 OverlayPiece(piece, clip, outline, dest)
8020 ChessSquare piece; GC clip; GC outline; Drawable dest;
8025 /* Draw solid rectangle which will be clipped to shape of piece */
8026 // XFillRectangle(xDisplay, dest, clip,
8027 // 0, 0, squareSize, squareSize)
8029 if (appData.monoMode)
8030 /* Also draw outline in contrasting color for black
8031 on black / white on white cases */
8032 // XCopyPlane(xDisplay, *pieceToOutline(piece), dest, outline,
8033 // 0, 0, squareSize, squareSize, 0, 0, 1)
8036 /* Copy the piece */
8041 // XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
8043 // 0, 0, squareSize, squareSize,
8048 /* Animate the movement of a single piece */
8051 BeginAnimation(anim, piece, startColor, start)
8059 /* The old buffer is initialised with the start square (empty) */
8060 BlankSquare(0, 0, startColor, EmptySquare, anim->saveBuf);
8061 anim->prevFrame = *start;
8063 /* The piece will be drawn using its own bitmap as a matte */
8064 // SelectGCMask(piece, &anim->pieceGC, &anim->outlineGC, &mask);
8065 // XSetClipMask(xDisplay, anim->pieceGC, mask);
8069 AnimationFrame(anim, frame, piece)
8074 XRectangle updates[4];
8079 /* Save what we are about to draw into the new buffer */
8080 // XCopyArea(xDisplay, xBoardWindow, anim->newBuf, anim->blitGC,
8081 // frame->x, frame->y, squareSize, squareSize,
8084 /* Erase bits of the previous frame */
8085 if (Intersect(&anim->prevFrame, frame, squareSize, &overlap, &pt)) {
8086 /* Where the new frame overlapped the previous,
8087 the contents in newBuf are wrong. */
8088 // XCopyArea(xDisplay, anim->saveBuf, anim->newBuf, anim->blitGC,
8089 // overlap.x, overlap.y,
8090 // overlap.width, overlap.height,
8092 /* Repaint the areas in the old that don't overlap new */
8093 CalcUpdateRects(&anim->prevFrame, frame, squareSize, updates, &count);
8094 for (i = 0; i < count; i++)
8095 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
8096 // updates[i].x - anim->prevFrame.x,
8097 // updates[i].y - anim->prevFrame.y,
8098 // updates[i].width, updates[i].height,
8099 // updates[i].x, updates[i].y)
8102 /* Easy when no overlap */
8103 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
8104 // 0, 0, squareSize, squareSize,
8105 // anim->prevFrame.x, anim->prevFrame.y);
8108 /* Save this frame for next time round */
8109 // XCopyArea(xDisplay, anim->newBuf, anim->saveBuf, anim->blitGC,
8110 // 0, 0, squareSize, squareSize,
8112 anim->prevFrame = *frame;
8114 /* Draw piece over original screen contents, not current,
8115 and copy entire rect. Wipes out overlapping piece images. */
8116 OverlayPiece(piece, anim->pieceGC, anim->outlineGC, anim->newBuf);
8117 // XCopyArea(xDisplay, anim->newBuf, xBoardWindow, anim->blitGC,
8118 // 0, 0, squareSize, squareSize,
8119 // frame->x, frame->y);
8123 EndAnimation (anim, finish)
8127 XRectangle updates[4];
8132 /* The main code will redraw the final square, so we
8133 only need to erase the bits that don't overlap. */
8134 if (Intersect(&anim->prevFrame, finish, squareSize, &overlap, &pt)) {
8135 CalcUpdateRects(&anim->prevFrame, finish, squareSize, updates, &count);
8136 for (i = 0; i < count; i++)
8137 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
8138 // updates[i].x - anim->prevFrame.x,
8139 // updates[i].y - anim->prevFrame.y,
8140 // updates[i].width, updates[i].height,
8141 // updates[i].x, updates[i].y)
8144 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
8145 // 0, 0, squareSize, squareSize,
8146 // anim->prevFrame.x, anim->prevFrame.y);
8151 FrameSequence(anim, piece, startColor, start, finish, frames, nFrames)
8153 ChessSquare piece; int startColor;
8154 XPoint * start; XPoint * finish;
8155 XPoint frames[]; int nFrames;
8159 BeginAnimation(anim, piece, startColor, start);
8160 for (n = 0; n < nFrames; n++) {
8161 AnimationFrame(anim, &(frames[n]), piece);
8162 FrameDelay(appData.animSpeed);
8164 EndAnimation(anim, finish);
8167 /* Main control logic for deciding what to animate and how */
8170 AnimateMove(board, fromX, fromY, toX, toY)
8179 XPoint start, finish, mid;
8180 XPoint frames[kFactor * 2 + 1];
8181 int nFrames, startColor, endColor;
8183 /* Are we animating? */
8184 if (!appData.animate || appData.blindfold)
8187 if(board[toY][toX] == WhiteRook && board[fromY][fromX] == WhiteKing ||
8188 board[toY][toX] == BlackRook && board[fromY][fromX] == BlackKing)
8189 return; // [HGM] FRC: no animtion of FRC castlings, as to-square is not true to-square
8191 if (fromY < 0 || fromX < 0 || toX < 0 || toY < 0) return;
8192 piece = board[fromY][fromX];
8193 if (piece >= EmptySquare) return;
8198 hop = (piece == WhiteKnight || piece == BlackKnight);
8201 if (appData.debugMode) {
8202 fprintf(debugFP, hop ? _("AnimateMove: piece %d hops from %d,%d to %d,%d \n") :
8203 _("AnimateMove: piece %d slides from %d,%d to %d,%d \n"),
8204 piece, fromX, fromY, toX, toY); }
8206 ScreenSquare(fromX, fromY, &start, &startColor);
8207 ScreenSquare(toX, toY, &finish, &endColor);
8210 /* Knight: make diagonal movement then straight */
8211 if (abs(toY - fromY) < abs(toX - fromX)) {
8212 mid.x = start.x + (finish.x - start.x) / 2;
8216 mid.y = start.y + (finish.y - start.y) / 2;
8219 mid.x = start.x + (finish.x - start.x) / 2;
8220 mid.y = start.y + (finish.y - start.y) / 2;
8223 /* Don't use as many frames for very short moves */
8224 if (abs(toY - fromY) + abs(toX - fromX) <= 2)
8225 Tween(&start, &mid, &finish, kFactor - 1, frames, &nFrames);
8227 Tween(&start, &mid, &finish, kFactor, frames, &nFrames);
8228 FrameSequence(&game, piece, startColor, &start, &finish, frames, nFrames);
8230 /* Be sure end square is redrawn */
8231 damage[toY][toX] = True;
8235 DragPieceBegin(x, y)
8238 int boardX, boardY, color;
8241 /* Are we animating? */
8242 if (!appData.animateDragging || appData.blindfold)
8245 /* Figure out which square we start in and the
8246 mouse position relative to top left corner. */
8247 BoardSquare(x, y, &boardX, &boardY);
8248 player.startBoardX = boardX;
8249 player.startBoardY = boardY;
8250 ScreenSquare(boardX, boardY, &corner, &color);
8251 player.startSquare = corner;
8252 player.startColor = color;
8254 /* Start from exactly where the piece is. This can be confusing
8255 if you start dragging far from the center of the square; most
8256 or all of the piece can be over a different square from the one
8257 the mouse pointer is in. */
8258 player.mouseDelta.x = x - corner.x;
8259 player.mouseDelta.y = y - corner.y;
8261 /* As soon as we start dragging, the piece will jump slightly to
8262 be centered over the mouse pointer. */
8263 player.mouseDelta.x = squareSize/2;
8264 player.mouseDelta.y = squareSize/2;
8266 /* Initialise animation */
8267 player.dragPiece = PieceForSquare(boardX, boardY);
8269 if (player.dragPiece >= 0 && player.dragPiece < EmptySquare) {
8270 player.dragActive = True;
8271 BeginAnimation(&player, player.dragPiece, color, &corner);
8272 /* Mark this square as needing to be redrawn. Note that
8273 we don't remove the piece though, since logically (ie
8274 as seen by opponent) the move hasn't been made yet. */
8275 if(boardX == BOARD_RGHT+1 && PieceForSquare(boardX-1, boardY) > 1 ||
8276 boardX == BOARD_LEFT-2 && PieceForSquare(boardX+1, boardY) > 1)
8277 // XCopyArea(xDisplay, xBoardWindow, player.saveBuf, player.blitGC,
8278 // corner.x, corner.y, squareSize, squareSize,
8279 // 0, 0); // [HGM] zh: unstack in stead of grab
8280 damage[boardY][boardX] = True;
8282 player.dragActive = False;
8292 /* Are we animating? */
8293 if (!appData.animateDragging || appData.blindfold)
8297 if (! player.dragActive)
8299 /* Move piece, maintaining same relative position
8300 of mouse within square */
8301 corner.x = x - player.mouseDelta.x;
8302 corner.y = y - player.mouseDelta.y;
8303 AnimationFrame(&player, &corner, player.dragPiece);
8305 if (appData.highlightDragging) {
8307 BoardSquare(x, y, &boardX, &boardY);
8308 SetHighlights(fromX, fromY, boardX, boardY);
8317 int boardX, boardY, color;
8320 /* Are we animating? */
8321 if (!appData.animateDragging || appData.blindfold)
8325 if (! player.dragActive)
8327 /* Last frame in sequence is square piece is
8328 placed on, which may not match mouse exactly. */
8329 BoardSquare(x, y, &boardX, &boardY);
8330 ScreenSquare(boardX, boardY, &corner, &color);
8331 EndAnimation(&player, &corner);
8333 /* Be sure end square is redrawn */
8334 damage[boardY][boardX] = True;
8336 /* This prevents weird things happening with fast successive
8337 clicks which on my Sun at least can cause motion events
8338 without corresponding press/release. */
8339 player.dragActive = False;
8342 /* Handle expose event while piece being dragged */
8347 if (!player.dragActive || appData.blindfold)
8350 /* What we're doing: logically, the move hasn't been made yet,
8351 so the piece is still in it's original square. But visually
8352 it's being dragged around the board. So we erase the square
8353 that the piece is on and draw it at the last known drag point. */
8354 BlankSquare(player.startSquare.x, player.startSquare.y,
8355 player.startColor, EmptySquare, xBoardWindow);
8356 AnimationFrame(&player, &player.prevFrame, player.dragPiece);
8357 damage[player.startBoardY][player.startBoardX] = TRUE;
8361 SetProgramStats( FrontEndProgramStats * stats )
8364 // [HGM] done, but perhaps backend should call this directly?
8365 EngineOutputUpdate( stats );